progress
This commit is contained in:
parent
d8b5018cb2
commit
318d0a7893
60 changed files with 746 additions and 524 deletions
|
@ -14,7 +14,7 @@
|
||||||
"w": 4
|
"w": 4
|
||||||
},
|
},
|
||||||
"name": "ARM0",
|
"name": "ARM0",
|
||||||
"nDOF": 1,
|
"nDOF": 6,
|
||||||
"toolType": "RBS_GRIPPER",
|
"toolType": "RBS_GRIPPER",
|
||||||
"jointPosition": [
|
"jointPosition": [
|
||||||
1.1,
|
1.1,
|
||||||
|
|
|
@ -34,11 +34,11 @@ export abstract class CallbackStrategyWithFilesUploads {
|
||||||
abstract call(files: File[]): ResponseBase;
|
abstract call(files: File[]): ResponseBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ISubSetFeatureRouter<T> {
|
interface ISubSetFeatureRouter<A> {
|
||||||
method: HttpMethodType;
|
method: HttpMethodType;
|
||||||
subUrl: string;
|
subUrl: string;
|
||||||
fn:
|
fn:
|
||||||
| CallbackStrategyWithValidationModel<T>
|
| CallbackStrategyWithValidationModel<A>
|
||||||
| CallbackStrategyWithEmpty
|
| CallbackStrategyWithEmpty
|
||||||
| CallbackStrategyWithIdQuery
|
| CallbackStrategyWithIdQuery
|
||||||
| CallBackStrategyWithQueryPage
|
| CallBackStrategyWithQueryPage
|
||||||
|
@ -179,7 +179,7 @@ export class CoreHttpController<V> implements ICoreHttpController {
|
||||||
router: this.router,
|
router: this.router,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
public put(usecase: CallbackStrategyWithValidationModel<V>) {
|
public put(usecase: any) {
|
||||||
this.routes["PUT"] = usecase;
|
this.routes["PUT"] = usecase;
|
||||||
}
|
}
|
||||||
public delete(usecase: CallbackStrategyWithValidationModel<V>) {
|
public delete(usecase: CallbackStrategyWithValidationModel<V>) {
|
||||||
|
|
|
@ -2,5 +2,7 @@ export enum StaticFiles {
|
||||||
robossembler_assets = "robossembler_assets.json",
|
robossembler_assets = "robossembler_assets.json",
|
||||||
assets = "/assets/assets.json",
|
assets = "/assets/assets.json",
|
||||||
parts = '/assets/parts.json',
|
parts = '/assets/parts.json',
|
||||||
robots = '/robots/'
|
robots = '/robots/',
|
||||||
|
scenes = '/scenes/',
|
||||||
|
behaviorTrees = 'behavior_trees'
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,35 @@ export class GetBehaviorTreeSkillsTemplatesUseCase extends CallbackStrategyWithE
|
||||||
call = async (): ResponseBase => {
|
call = async (): ResponseBase => {
|
||||||
return Result.ok({
|
return Result.ok({
|
||||||
skills: [
|
skills: [
|
||||||
|
{
|
||||||
|
SkillPackage: { name: "Robossembler", version: "1.0", format: "1" },
|
||||||
|
Module: { name: "MoveToPose", description: "Move to Pose skill with cartesian controllers" },
|
||||||
|
Launch: { package: "rbss_movetopose", executable: "mtp_cartesian.py", name: "mtp_cartesian" },
|
||||||
|
BTAction: [
|
||||||
|
{
|
||||||
|
name: "move",
|
||||||
|
type: "action",
|
||||||
|
param: [
|
||||||
|
{
|
||||||
|
type: "move_to_pose",
|
||||||
|
dependency: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Interface: {
|
||||||
|
Input: [
|
||||||
|
{ name: "robotName", type: "ROBOT" },
|
||||||
|
{ name: "pose", type: "POSE" },
|
||||||
|
],
|
||||||
|
Output: [],
|
||||||
|
},
|
||||||
|
Settings: [
|
||||||
|
{ name: "topicServer", value: "cartesian_move_to_pose" },
|
||||||
|
{ name: "end_effector_velocity", value: 1.0 },
|
||||||
|
{ name: "end_effector_acceleration", value: 1.0 },
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
SkillPackage: { name: "Robossembler", version: "1.0", format: "1", type: "Action" },
|
SkillPackage: { name: "Robossembler", version: "1.0", format: "1", type: "Action" },
|
||||||
Module: { name: "PoseEstimation", description: "Pose Estimation skill with DOPE" },
|
Module: { name: "PoseEstimation", description: "Pose Estimation skill with DOPE" },
|
||||||
|
@ -20,12 +49,12 @@ export class GetBehaviorTreeSkillsTemplatesUseCase extends CallbackStrategyWithE
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "camera",
|
type: "camera",
|
||||||
dependency: {}
|
dependency: {},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "topic",
|
type: "topic",
|
||||||
dependency: {}
|
dependency: {},
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
result: ["POSE"],
|
result: ["POSE"],
|
||||||
},
|
},
|
||||||
|
@ -46,28 +75,6 @@ export class GetBehaviorTreeSkillsTemplatesUseCase extends CallbackStrategyWithE
|
||||||
{ name: "mesh_scale", value: 0.001 },
|
{ name: "mesh_scale", value: 0.001 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
SkillPackage: { name: "Robossembler", version: "1.0", format: "1" },
|
|
||||||
Module: { name: "MoveToPose", description: "Move to Pose skill with ? controllers" },
|
|
||||||
Launch: { package: "rbss_movetopose", executable: "movetopose.py", name: "skill_move" },
|
|
||||||
BTAction: [
|
|
||||||
{
|
|
||||||
name: "move",
|
|
||||||
type: "action",
|
|
||||||
param: [{ type: "topic", dependency: { } }],
|
|
||||||
result: []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
Interface: {
|
|
||||||
Input: [
|
|
||||||
{ name: "robotName", type: "ROBOT" },
|
|
||||||
{ name: "pose", type: "POSE" }
|
|
||||||
],
|
|
||||||
Output: []
|
|
||||||
},
|
|
||||||
Settings: []
|
|
||||||
}
|
|
||||||
|
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,6 +12,10 @@ export const BehaviorTreeSchema = new Schema({
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
|
scene: {
|
||||||
|
type: Schema.Types.Mixed,
|
||||||
|
default: [],
|
||||||
|
},
|
||||||
local_path: {
|
local_path: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
|
@ -29,9 +33,8 @@ export const BehaviorTreeSchema = new Schema({
|
||||||
skills: {
|
skills: {
|
||||||
type: Schema.Types.Mixed,
|
type: Schema.Types.Mixed,
|
||||||
},
|
},
|
||||||
scene: {
|
sceneId: {
|
||||||
type: Array,
|
type: String,
|
||||||
default: null,
|
|
||||||
},
|
},
|
||||||
project: {
|
project: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
|
|
46
server/src/features/scene/create_new_scene_scenario.ts
Normal file
46
server/src/features/scene/create_new_scene_scenario.ts
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import { IsString } from "class-validator";
|
||||||
|
import { CallbackStrategyWithValidationModel, ResponseBase } from "../../core/controllers/http_controller";
|
||||||
|
import { Result } from "../../core/helpers/result";
|
||||||
|
import { CreateFileUseCase } from "../../core/usecases/create_file_usecase";
|
||||||
|
import { GetActiveProjectIdScenario } from "../projects/domain/get_active_project_id_scenario";
|
||||||
|
import { model } from "mongoose";
|
||||||
|
import { SearchManyDataBaseModelUseCase } from "../../core/usecases/search_many_database_model_usecase";
|
||||||
|
import { IProjectModel, ProjectDBModel } from "../projects/models/project_model_database_model";
|
||||||
|
import { StaticFiles } from "../../core/models/static_files";
|
||||||
|
import { CreateDataBaseModelUseCase } from "../../core/usecases/create_database_model_usecase";
|
||||||
|
import { SceneDBModel } from "./scene_database_model";
|
||||||
|
import { SceneValidationModel } from "./scene_validation_model";
|
||||||
|
export class SceneModel {
|
||||||
|
@IsString()
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
export class SceneAssets {
|
||||||
|
name: string;
|
||||||
|
scene: [] = [];
|
||||||
|
constructor(name: string) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
static empty = () => new SceneAssets("");
|
||||||
|
}
|
||||||
|
export class CreateNewSceneScenario extends CallbackStrategyWithValidationModel<SceneModel> {
|
||||||
|
validationModel: SceneModel = SceneModel;
|
||||||
|
|
||||||
|
call = async (model: SceneModel): ResponseBase =>
|
||||||
|
(
|
||||||
|
await new SearchManyDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call(
|
||||||
|
{ isActive: true },
|
||||||
|
"is dont active projects"
|
||||||
|
)
|
||||||
|
).map(async (projectModel) => {
|
||||||
|
const { rootDir } = projectModel[0];
|
||||||
|
|
||||||
|
return (
|
||||||
|
await new CreateFileUseCase().call(
|
||||||
|
`${rootDir}${StaticFiles.scenes}${model.name}.json`,
|
||||||
|
Buffer.from(JSON.stringify(new SceneAssets(model.name)))
|
||||||
|
)
|
||||||
|
).map(async () =>
|
||||||
|
(await new CreateDataBaseModelUseCase(SceneDBModel).call(model)).map(() => Result.ok("Create"))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
28
server/src/features/scene/edit_scene_scenario.ts
Normal file
28
server/src/features/scene/edit_scene_scenario.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { CallbackStrategyWithValidationModel, ResponseBase } from "../../core/controllers/http_controller";
|
||||||
|
import { Result } from "../../core/helpers/result";
|
||||||
|
import { StaticFiles } from "../../core/models/static_files";
|
||||||
|
import { CreateFileUseCase } from "../../core/usecases/create_file_usecase";
|
||||||
|
import { SearchManyDataBaseModelUseCase } from "../../core/usecases/search_many_database_model_usecase";
|
||||||
|
import { IProjectModel, ProjectDBModel } from "../projects/models/project_model_database_model";
|
||||||
|
import { SceneAssets } from "./create_new_scene_scenario";
|
||||||
|
import { SceneValidationModel } from "./scene_validation_model";
|
||||||
|
|
||||||
|
export class EditSceneScenario extends CallbackStrategyWithValidationModel<SceneValidationModel> {
|
||||||
|
validationModel: SceneValidationModel;
|
||||||
|
call = async (model: SceneValidationModel): ResponseBase =>
|
||||||
|
(
|
||||||
|
await new SearchManyDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call(
|
||||||
|
{ isActive: true },
|
||||||
|
"is dont active projects"
|
||||||
|
)
|
||||||
|
).map(async (projectModel) => {
|
||||||
|
const { rootDir } = projectModel[0];
|
||||||
|
|
||||||
|
return (
|
||||||
|
await new CreateFileUseCase().call(
|
||||||
|
`${rootDir}${StaticFiles.scenes}${model.name}.json`,
|
||||||
|
Buffer.from(JSON.stringify(model))
|
||||||
|
)
|
||||||
|
).map(async () => Result.ok("Edit"));
|
||||||
|
});
|
||||||
|
}
|
31
server/src/features/scene/read_scene_scenario.ts
Normal file
31
server/src/features/scene/read_scene_scenario.ts
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import { CallbackStrategyWithIdQuery, ResponseBase } from "../../core/controllers/http_controller";
|
||||||
|
import { Result } from "../../core/helpers/result";
|
||||||
|
import { StaticFiles } from "../../core/models/static_files";
|
||||||
|
import { CreateFileUseCase } from "../../core/usecases/create_file_usecase";
|
||||||
|
import { ReadByIdDataBaseModelUseCase } from "../../core/usecases/read_by_id_database_model_usecase";
|
||||||
|
import { ReadFileAndParseJsonUseCase } from "../../core/usecases/read_file_and_parse_json";
|
||||||
|
import { SearchManyDataBaseModelUseCase } from "../../core/usecases/search_many_database_model_usecase";
|
||||||
|
import { CoreValidation } from "../../core/validations/core_validation";
|
||||||
|
import { MongoIdValidation } from "../../core/validations/mongo_id_validation";
|
||||||
|
import { IProjectModel, ProjectDBModel } from "../projects/models/project_model_database_model";
|
||||||
|
import { SceneAssets, SceneModel } from "./create_new_scene_scenario";
|
||||||
|
import { SceneDBModel } from "./scene_database_model";
|
||||||
|
|
||||||
|
export class ReadSceneScenario extends CallbackStrategyWithIdQuery {
|
||||||
|
idValidationExpression: CoreValidation = new MongoIdValidation();
|
||||||
|
call = async (id: string): ResponseBase =>
|
||||||
|
(await new ReadByIdDataBaseModelUseCase<SceneModel>(SceneDBModel).call(id)).map(async (model) =>
|
||||||
|
(
|
||||||
|
await new SearchManyDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call(
|
||||||
|
{ isActive: true },
|
||||||
|
"is dont active projects"
|
||||||
|
)
|
||||||
|
).map(async (projectModel) => {
|
||||||
|
const { rootDir } = projectModel[0];
|
||||||
|
|
||||||
|
return (await new ReadFileAndParseJsonUseCase().call(`${rootDir}${StaticFiles.scenes}${model.name}.json`)).map(
|
||||||
|
async (sceneAsset) => Result.ok(sceneAsset)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,5 +1,11 @@
|
||||||
import { CrudController } from "../../core/controllers/crud_controller";
|
import { CrudController } from "../../core/controllers/crud_controller";
|
||||||
|
import { ReadByIdDataBaseModelScenario } from "../../core/scenarios/read_by_id_database_model_scenario";
|
||||||
|
import { BehaviorTreeDBModel } from "../behavior_trees/models/behavior_tree_database_model";
|
||||||
|
import { BehaviorTreeValidationModel } from "../behavior_trees/models/behavior_tree_validation_model";
|
||||||
|
import { CreateNewSceneScenario } from "./create_new_scene_scenario";
|
||||||
import { CreateRobotScenario } from "./create_robot_scenario";
|
import { CreateRobotScenario } from "./create_robot_scenario";
|
||||||
|
import { EditSceneScenario } from "./edit_scene_scenario";
|
||||||
|
import { ReadSceneScenario } from "./read_scene_scenario";
|
||||||
import { SceneDBModel } from "./scene_database_model";
|
import { SceneDBModel } from "./scene_database_model";
|
||||||
import { SceneValidationModel } from "./scene_validation_model";
|
import { SceneValidationModel } from "./scene_validation_model";
|
||||||
|
|
||||||
|
@ -10,10 +16,17 @@ export class ScenePresentation extends CrudController<SceneValidationModel, type
|
||||||
validationModel: SceneValidationModel,
|
validationModel: SceneValidationModel,
|
||||||
databaseModel: SceneDBModel,
|
databaseModel: SceneDBModel,
|
||||||
});
|
});
|
||||||
|
super.post(new CreateNewSceneScenario().call);
|
||||||
|
super.put(new EditSceneScenario().call);
|
||||||
this.subRoutes.push({
|
this.subRoutes.push({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
subUrl: "create/robot",
|
subUrl: "create/robot",
|
||||||
fn: new CreateRobotScenario(),
|
fn: new CreateRobotScenario(),
|
||||||
});
|
});
|
||||||
|
this.subRoutes.push({
|
||||||
|
method: "GET",
|
||||||
|
subUrl: "by_id",
|
||||||
|
fn: new ReadSceneScenario(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.8 KiB |
|
@ -3,13 +3,13 @@
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
<link rel="icon" href="%PUBLIC_URL%/logo.ico" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<meta name="description" content="Web site created using create-react-app" />
|
<meta name="description" content="Web site created using create-react-app" />
|
||||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo.png" />
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||||
<title>robossembler: pipeline </title>
|
<title>Robossembler </title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
BIN
ui/public/logo.ico
Normal file
BIN
ui/public/logo.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
BIN
ui/public/logo.png
Normal file
BIN
ui/public/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 818 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB |
|
@ -1,7 +1,9 @@
|
||||||
/* eslint-disable no-extend-native */
|
|
||||||
|
|
||||||
export const ObjectExtensionsIsKeyExists = (obj: any, keys: string[]): boolean => {
|
export const ObjectExtensionsIsKeyExists = (obj: any, keys: string[]): boolean => {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
export const ObjectIsNotEmpty = (obj: Object | undefined) => {
|
||||||
// {"objectThatSticksName":"cube2","objectThatSticksNamePoints":[{"x":25,"y":4.987889622413917,"z":10.504078531217838}],"objectsToWhichItSticksName":"cube1","objectsToWhichItSticksPoints":[{"x":5,"y":3.0783236330074963,"z":1.1333166084347885}]}
|
if (obj === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Object.keys(obj).length !== 0;
|
||||||
|
};
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
export const useKeyLister = (fn: Function) => {
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
const pressed = new Map();
|
|
||||||
|
|
||||||
const registerKeyPress = React.useCallback(
|
|
||||||
(event: KeyboardEvent, codes: string[], callBack: Function) => {
|
|
||||||
if (codes.hasIncludeElement(event.code)) {
|
|
||||||
pressed.addValueOrMakeCallback(event.code, event.type, (e) => {
|
|
||||||
if (Array.from(pressed.values()).equals(["keydown", "keydown"], false)) {
|
|
||||||
callBack();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[pressed]
|
|
||||||
);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
window.addEventListener("keyup", (e) => registerKeyPress(e, ["KeyQ", "KeyW"], () => fn));
|
|
||||||
window.addEventListener("keydown", (e) => registerKeyPress(e, ["KeyQ", "KeyW"], () => {}));
|
|
||||||
}, [fn, registerKeyPress]);
|
|
||||||
|
|
||||||
return [];
|
|
||||||
};
|
|
|
@ -9,6 +9,7 @@ export enum CameraTypes {
|
||||||
}
|
}
|
||||||
export class CameraModel implements Instance {
|
export class CameraModel implements Instance {
|
||||||
type = SceneModelsTypes.CAMERA;
|
type = SceneModelsTypes.CAMERA;
|
||||||
|
jointType = 'fixed';
|
||||||
constructor(
|
constructor(
|
||||||
public quaternion: number[],
|
public quaternion: number[],
|
||||||
public vector3: Vector3,
|
public vector3: Vector3,
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
import { Vector3 } from "three";
|
|
||||||
|
|
||||||
export class CoreVector3 {
|
|
||||||
vector: Vector3;
|
|
||||||
constructor(vector: Vector3) {
|
|
||||||
this.vector = vector;
|
|
||||||
}
|
|
||||||
|
|
||||||
static divideLineIntoEqualSegments(beginPoint: Vector3, endPoint: Vector3, segments: number): Vector3[] {
|
|
||||||
return Number(segments)
|
|
||||||
.fromArray()
|
|
||||||
.map((el) => new Vector3().lerpVectors(beginPoint, endPoint, (el * 1) / segments));
|
|
||||||
}
|
|
||||||
add(vector: Vector3) {
|
|
||||||
return new CoreVector3(new Vector3(this.vector.x + vector.x, this.vector.y + vector.y, this.vector.z + vector.z));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +1,3 @@
|
||||||
export interface DatabaseModel {
|
export interface DatabaseModelId {
|
||||||
_id?: string;
|
_id?: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ import { SceneModelsTypes } from "./scene_models_type";
|
||||||
import { Instance } from "./scene_asset";
|
import { Instance } from "./scene_asset";
|
||||||
import { CoreThreeRepository } from "../repository/core_three_repository";
|
import { CoreThreeRepository } from "../repository/core_three_repository";
|
||||||
import { Type } from "class-transformer";
|
import { Type } from "class-transformer";
|
||||||
|
import { SceneItems, SceneMangerStore } from "../../features/scene_manager/presentation/scene_manager_store";
|
||||||
|
import { Pose } from "../../features/behavior_tree_builder/presentation/ui/forms/move_to_pose/move_to_pose_robot_model";
|
||||||
|
|
||||||
export class PointModel implements Instance {
|
export class PointModel implements Instance {
|
||||||
type = SceneModelsTypes.POINT;
|
type = SceneModelsTypes.POINT;
|
||||||
|
@ -11,7 +13,7 @@ export class PointModel implements Instance {
|
||||||
@Type(() => Vector3)
|
@Type(() => Vector3)
|
||||||
vector3: Vector3;
|
vector3: Vector3;
|
||||||
color: string = "#E91E63";
|
color: string = "#E91E63";
|
||||||
size: number = 0.5;
|
size: number = 0.01;
|
||||||
quaternion: number[];
|
quaternion: number[];
|
||||||
icon: string = "Point";
|
icon: string = "Point";
|
||||||
|
|
||||||
|
@ -25,10 +27,30 @@ export class PointModel implements Instance {
|
||||||
this.color,
|
this.color,
|
||||||
this.size
|
this.size
|
||||||
);
|
);
|
||||||
|
toSceneItems = (sceneMangerStore: SceneMangerStore): SceneItems => {
|
||||||
|
return {
|
||||||
|
fn: () => {},
|
||||||
|
name: this.name,
|
||||||
|
isSelected: false,
|
||||||
|
icon: this.icon,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
toDependency = (): Pose => {
|
||||||
|
return {
|
||||||
|
name: this.name,
|
||||||
|
position: this.vector3,
|
||||||
|
orientation: {
|
||||||
|
x: this.quaternion[0],
|
||||||
|
y: this.quaternion[1],
|
||||||
|
z: this.quaternion[2],
|
||||||
|
w: this.quaternion[3],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
isValid(): Result<string, PointModel> {
|
isValid(): Result<string, PointModel> {
|
||||||
return Result.ok();
|
return Result.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
static empty() {
|
static empty() {
|
||||||
return new PointModel();
|
return new PointModel();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ interface RobotJoint {
|
||||||
lower: Number;
|
lower: Number;
|
||||||
upper: Number;
|
upper: Number;
|
||||||
};
|
};
|
||||||
angel: Number;
|
angle: Number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,24 +50,23 @@ export class RobotModel implements Instance {
|
||||||
icon: string = "Robot";
|
icon: string = "Robot";
|
||||||
toSceneItems = (sceneMangerStore: SceneMangerStore): SceneItems => {
|
toSceneItems = (sceneMangerStore: SceneMangerStore): SceneItems => {
|
||||||
return {
|
return {
|
||||||
fn: () => { },
|
fn: () => {},
|
||||||
name: this.name,
|
name: this.name,
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
icon: "Robot",
|
icon: "Robot",
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
toWebGl = (coreThreeRepository: CoreThreeRepository) => {
|
toWebGl = (coreThreeRepository: CoreThreeRepository) => {
|
||||||
console.log(JSON.stringify(this));
|
|
||||||
coreThreeRepository.loadUrdfRobot(this);
|
coreThreeRepository.loadUrdfRobot(this);
|
||||||
};
|
};
|
||||||
update(coreThreeRepository: CoreThreeRepository): any {
|
update = (coreThreeRepository: CoreThreeRepository) => {
|
||||||
const robot = coreThreeRepository.scene.getObjectByName(this.name) as URDFRobot;
|
const robot = coreThreeRepository.scene.getObjectByName(this.name) as URDFRobot;
|
||||||
robot.position.copy(this.vector3);
|
robot.position.copy(this.vector3);
|
||||||
robot.quaternion.copy(new Quaternion().fromArray(this.quaternion));
|
robot.quaternion.copy(new Quaternion().fromArray(this.quaternion));
|
||||||
this.jointPosition.forEach((el) => {
|
this.jointPosition.forEach((el) => {
|
||||||
robot.setJointValue(el.name, el.angel);
|
robot.setJointValue(el.name, el.angle);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
isValid(): Result<string, RobotModel> {
|
isValid(): Result<string, RobotModel> {
|
||||||
return Result.ok(this);
|
return Result.ok(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,10 @@ import { ZoneModel } from "./zone_model";
|
||||||
import { CoreThreeRepository } from "../repository/core_three_repository";
|
import { CoreThreeRepository } from "../repository/core_three_repository";
|
||||||
import { LightModel } from "./light_model";
|
import { LightModel } from "./light_model";
|
||||||
import { Vector3 } from "three";
|
import { Vector3 } from "three";
|
||||||
|
import { SceneItems } from "../../features/scene_manager/presentation/scene_manager_store";
|
||||||
|
|
||||||
export abstract class Instance {
|
export abstract class Instance {
|
||||||
|
type: string;
|
||||||
abstract icon: string;
|
abstract icon: string;
|
||||||
@Type(() => Vector3)
|
@Type(() => Vector3)
|
||||||
vector3: Vector3;
|
vector3: Vector3;
|
||||||
|
@ -21,6 +23,7 @@ export abstract class Instance {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SceneAsset {
|
export class SceneAsset {
|
||||||
|
name: string;
|
||||||
@IsArray()
|
@IsArray()
|
||||||
@Type(() => Instance, {
|
@Type(() => Instance, {
|
||||||
discriminator: {
|
discriminator: {
|
||||||
|
@ -37,4 +40,27 @@ export class SceneAsset {
|
||||||
keepDiscriminatorProperty: true,
|
keepDiscriminatorProperty: true,
|
||||||
})
|
})
|
||||||
scene: (Instance | SolidModel | CameraModel | RobotModel | PointModel | ZoneModel)[];
|
scene: (Instance | SolidModel | CameraModel | RobotModel | PointModel | ZoneModel)[];
|
||||||
|
toSceneItems = (): SceneItems[] => {
|
||||||
|
return this.scene.map((el) => {
|
||||||
|
return {
|
||||||
|
fn: () => {},
|
||||||
|
name: el.name,
|
||||||
|
icon: el.icon,
|
||||||
|
isSelected: false,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
getElementByName = <T>(name: string) => this.scene.filter((el) => el.name.isEqual(name)).at(0) as T;
|
||||||
|
getAllRobotsTopics = () => this.scene.filter((el) => el.type.isEqual(SceneModelsTypes.ROBOT)).map((el) => el.name);
|
||||||
|
getAllCameraTopics = () => {};
|
||||||
|
getAllPoints = () => this.scene.filter((el) => el.type.isEqual(SceneModelsTypes.POINT)).map((el) => el.name);
|
||||||
|
static newScene = (
|
||||||
|
scene: (Instance | SolidModel | CameraModel | RobotModel | PointModel | ZoneModel)[],
|
||||||
|
name: string
|
||||||
|
) => {
|
||||||
|
const sceneAsset = new SceneAsset();
|
||||||
|
sceneAsset.scene = scene;
|
||||||
|
sceneAsset.name = name;
|
||||||
|
return sceneAsset;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,7 +198,7 @@ export class SkillModel implements ISkill {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SkillDependency implements IDependency {
|
export class SkillDependency implements IDependency {
|
||||||
constructor(public skills: ISkillDependency[]) { }
|
constructor(public skills: ISkillDependency[]) {}
|
||||||
static empty() {
|
static empty() {
|
||||||
return new SkillDependency([]);
|
return new SkillDependency([]);
|
||||||
}
|
}
|
||||||
|
@ -320,7 +320,7 @@ export class Skills {
|
||||||
if (skill.sid?.isEqual(sid)) {
|
if (skill.sid?.isEqual(sid)) {
|
||||||
skill.BTAction.map((action) => {
|
skill.BTAction.map((action) => {
|
||||||
action.param.map((param) => {
|
action.param.map((param) => {
|
||||||
if (param.type.isEqual(skillType)) {
|
if (param.type.isEqualR(skillType)) {
|
||||||
acc.push(param.dependency);
|
acc.push(param.dependency);
|
||||||
}
|
}
|
||||||
return param;
|
return param;
|
||||||
|
|
|
@ -1,26 +1,68 @@
|
||||||
import { Quaternion, Scene, Vector3 } from "three";
|
import { Object3D, Object3DEventMap, Quaternion, Vector3 } from "three";
|
||||||
import { SceneModelsTypes } from "./scene_models_type";
|
import { SceneModelsTypes } from "./scene_models_type";
|
||||||
import { Instance } from "./scene_asset";
|
import { Instance } from "./scene_asset";
|
||||||
import { CoreThreeRepository } from "../repository/core_three_repository";
|
import { CoreThreeRepository } from "../repository/core_three_repository";
|
||||||
import { Type } from "class-transformer";
|
import { Type } from "class-transformer";
|
||||||
|
import { SceneItems } from "../../features/scene_manager/presentation/scene_manager_store";
|
||||||
|
import { Parts } from "../../features/details/details_http_repository";
|
||||||
|
|
||||||
export class SolidModel implements Instance {
|
export class SolidModel implements Instance {
|
||||||
|
icon: string = "Solid";
|
||||||
type = SceneModelsTypes.SOLID;
|
type = SceneModelsTypes.SOLID;
|
||||||
@Type(() => Vector3)
|
@Type(() => Vector3)
|
||||||
public vector3: Vector3;
|
public vector3: Vector3;
|
||||||
constructor(
|
constructor(
|
||||||
vector3:Vector3,
|
vector3: Vector3,
|
||||||
public quaternion: number[],
|
public quaternion: number[],
|
||||||
public name: string,
|
public name: string,
|
||||||
public solidType: string,
|
public solidType: string,
|
||||||
public mesh: string,
|
public mesh: string,
|
||||||
public collisionMesh: string
|
public collisionMesh: string,
|
||||||
|
public spawnType: string
|
||||||
) {
|
) {
|
||||||
this.vector3 = vector3
|
this.vector3 = vector3;
|
||||||
}
|
}
|
||||||
update = (coreThreeRepository: CoreThreeRepository) => this.toWebGl(coreThreeRepository)
|
toSceneItems = (): SceneItems => {
|
||||||
icon: string = "Solid";
|
return {
|
||||||
toWebGl = (coreThreeRepository: CoreThreeRepository) => coreThreeRepository.loader(this.mesh, () => {}, this.name);
|
fn: () => {},
|
||||||
|
name: this.name,
|
||||||
|
isSelected: false,
|
||||||
|
icon: "Solid",
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
static empty = () => new SolidModel(new Vector3(0, 0, 0), [], "", "", "", "");
|
update = (coreThreeRepository: CoreThreeRepository) => {
|
||||||
|
const object = coreThreeRepository.getObjectsAtName(this.name) as Object3D<Object3DEventMap>;
|
||||||
|
object.position.copy(this.vector3)
|
||||||
|
object.quaternion.copy(new Quaternion().fromArray(this.quaternion))
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
toWebGl = (coreThreeRepository: CoreThreeRepository) => {
|
||||||
|
this.spawnType.isEqualR("BoundBox").fold(
|
||||||
|
() =>
|
||||||
|
coreThreeRepository.loader(
|
||||||
|
this.mesh,
|
||||||
|
() => (
|
||||||
|
coreThreeRepository.raiseAnObjectAboveZeroVector(this.name),
|
||||||
|
(this.quaternion = coreThreeRepository.scene.getObjectByName(this.name)!.quaternion.toArray()),
|
||||||
|
(this.vector3 = coreThreeRepository.scene.getObjectByName(this.name)!.position)
|
||||||
|
),
|
||||||
|
|
||||||
|
this.name,
|
||||||
|
this.vector3
|
||||||
|
),
|
||||||
|
() => console.log("UNKNOWN SPAWN TYPE SOLID MODEL")
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
fromParts = (parts: Parts): SolidModel => {
|
||||||
|
const solidModel = SolidModel.empty();
|
||||||
|
solidModel.mesh = parts.daeUrl;
|
||||||
|
solidModel.name = parts.name;
|
||||||
|
solidModel.solidType = parts.solidType;
|
||||||
|
return solidModel;
|
||||||
|
};
|
||||||
|
|
||||||
|
static empty = () => new SolidModel(new Vector3(0, 0, 0), [], "", "", "", "", "");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { DatabaseModel } from "./database_model";
|
import { DatabaseModelId } from "./database_model";
|
||||||
|
|
||||||
export interface ITriggerModel extends DatabaseModel {
|
export interface ITriggerModel extends DatabaseModelId {
|
||||||
type: string;
|
type: string;
|
||||||
description: string;
|
description: string;
|
||||||
value: string[];
|
value: string[];
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
// import { Scene, Engine, MeshBuilder, FreeCamera, HemisphericLight, Vector3, SceneLoader } from 'babylonjs';
|
|
||||||
// import { GLTFFileLoader } from 'babylonjs-loaders';
|
|
||||||
|
|
||||||
|
|
||||||
// export class BabylonRepository {
|
|
||||||
// engine: Engine;
|
|
||||||
// canvas: HTMLCanvasElement;
|
|
||||||
// scene: Scene;
|
|
||||||
// sceneLoader: SceneLoader
|
|
||||||
// constructor(canvas: HTMLCanvasElement) {
|
|
||||||
// this.sceneLoader = new SceneLoader();
|
|
||||||
// this.engine = new Engine(canvas, true);
|
|
||||||
// this.scene = new Scene(this.engine);
|
|
||||||
// this.engine.runRenderLoop(() => {
|
|
||||||
// this.scene.render();
|
|
||||||
// });
|
|
||||||
// this.scene.createDefaultCameraOrLight(true, true, true);
|
|
||||||
// new HemisphericLight("hemiLight", new Vector3(0, 1, 0));
|
|
||||||
// SceneLoader.RegisterPlugin(new GLTFFileLoader())
|
|
||||||
// SceneLoader.ImportMeshAsync("",
|
|
||||||
// "http://localhost:4001/1dfc4e1a-9c1a-4fa2-96b2-19c86acb6ea4/assets/libs/objects/",
|
|
||||||
// "sol_gear.glb", this.scene)
|
|
||||||
|
|
||||||
// }
|
|
||||||
// deleteAllObjectsScene = () => this.scene.meshes.forEach((el) => this.scene.removeMesh(el, true))
|
|
||||||
|
|
||||||
// loadHttp = (url: string) => {
|
|
||||||
// const divide = url.divideByIndex(url.lastIndexOf('/'))
|
|
||||||
|
|
||||||
// SceneLoader.ImportMeshAsync("",
|
|
||||||
// `${divide.at(0)}/`,
|
|
||||||
// `${divide.at(1)}`, this.scene).then((frame) => {
|
|
||||||
// });
|
|
||||||
|
|
||||||
// }
|
|
||||||
// }
|
|
|
@ -34,7 +34,6 @@ import { TransformControls } from "three/examples/jsm/controls/TransformControls
|
||||||
import { SceneMode } from "../../features/scene_manager/model/scene_view";
|
import { SceneMode } from "../../features/scene_manager/model/scene_view";
|
||||||
import { UrdfTransforms, coordsToQuaternion } from "../../features/simulations/tranforms_model";
|
import { UrdfTransforms, coordsToQuaternion } from "../../features/simulations/tranforms_model";
|
||||||
import { ISpawnHelper, SceneItems } from "../../features/scene_manager/presentation/scene_manager_store";
|
import { ISpawnHelper, SceneItems } from "../../features/scene_manager/presentation/scene_manager_store";
|
||||||
import { CameraModel } from "../model/camera_model";
|
|
||||||
import { SolidModel } from "../model/solid_model";
|
import { SolidModel } from "../model/solid_model";
|
||||||
import { Instance, SceneAsset } from "../model/scene_asset";
|
import { Instance, SceneAsset } from "../model/scene_asset";
|
||||||
import { ZoneModel } from "../model/zone_model";
|
import { ZoneModel } from "../model/zone_model";
|
||||||
|
@ -64,7 +63,6 @@ interface IEmissiveCache {
|
||||||
type SceneFrames = { [K in string]: URDFLink };
|
type SceneFrames = { [K in string]: URDFLink };
|
||||||
|
|
||||||
export class CoreThreeRepository extends TypedEvent<any> {
|
export class CoreThreeRepository extends TypedEvent<any> {
|
||||||
|
|
||||||
scene = new Scene();
|
scene = new Scene();
|
||||||
camera: PerspectiveCamera;
|
camera: PerspectiveCamera;
|
||||||
webGlRender: WebGLRenderer;
|
webGlRender: WebGLRenderer;
|
||||||
|
@ -190,14 +188,18 @@ export class CoreThreeRepository extends TypedEvent<any> {
|
||||||
this.urdfLoader.load(robotModel.httpUrl, (robot) => {
|
this.urdfLoader.load(robotModel.httpUrl, (robot) => {
|
||||||
robot.userData[UserData.selectedObject] = true;
|
robot.userData[UserData.selectedObject] = true;
|
||||||
robot.name = robotModel.name;
|
robot.name = robotModel.name;
|
||||||
if (robotModel.vector3) robot.position.copy(new Vector3(0, 0, 0));
|
if (robotModel.vector3) robot.position.copy(robotModel.vector3);
|
||||||
if (robotModel.quaternion) robot.quaternion.copy(new Quaternion().fromArray(robotModel.quaternion));
|
if (robotModel.quaternion) robot.quaternion.copy(new Quaternion().fromArray(robotModel.quaternion));
|
||||||
// robot.setJointValue("ee_link_joint", 4);
|
if (robotModel.jointPosition.isNotEmpty()) {
|
||||||
|
robotModel.jointPosition.forEach((el) => {
|
||||||
|
robot.setJointValue(el.name, el.angle);
|
||||||
|
});
|
||||||
|
}
|
||||||
if (robotModel.jointPosition.isEmpty()) {
|
if (robotModel.jointPosition.isEmpty()) {
|
||||||
Object.entries(robot.joints).forEach(([name, uRDFJoint]) => {
|
Object.entries(robot.joints).forEach(([name, uRDFJoint]) => {
|
||||||
if (uRDFJoint.jointType !== "fixed") {
|
if (uRDFJoint.jointType !== "fixed") {
|
||||||
robotModel.jointPosition.push({
|
robotModel.jointPosition.push({
|
||||||
angel: uRDFJoint.angle,
|
angle: uRDFJoint.angle,
|
||||||
limit: {
|
limit: {
|
||||||
lower: uRDFJoint.limit.lower,
|
lower: uRDFJoint.limit.lower,
|
||||||
upper: uRDFJoint.limit.upper,
|
upper: uRDFJoint.limit.upper,
|
||||||
|
@ -208,8 +210,6 @@ export class CoreThreeRepository extends TypedEvent<any> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Object.entries(robot.joints).forEach(([k, v]) => robot.setJointValue(k, 1));
|
|
||||||
|
|
||||||
this.scene.add(robot);
|
this.scene.add(robot);
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
|
@ -229,21 +229,6 @@ export class CoreThreeRepository extends TypedEvent<any> {
|
||||||
this.sceneFrame = robot.frames;
|
this.sceneFrame = robot.frames;
|
||||||
});
|
});
|
||||||
|
|
||||||
solidSpawn = (
|
|
||||||
solidSpawn: ISpawnHelper,
|
|
||||||
loadCallback?: (obj: Object3D<Object3DEventMap> | undefined) => void,
|
|
||||||
vector3?: Vector3
|
|
||||||
) =>
|
|
||||||
this.loader(
|
|
||||||
solidSpawn.url,
|
|
||||||
() => {
|
|
||||||
this.raiseAnObjectAboveZeroVector(solidSpawn.name);
|
|
||||||
if (loadCallback) loadCallback(this.scene.getObjectByName(solidSpawn.name));
|
|
||||||
},
|
|
||||||
solidSpawn.name,
|
|
||||||
vector3
|
|
||||||
);
|
|
||||||
|
|
||||||
loadHttpAndPreview(path: string, name: string, loadCallback?: Function) {
|
loadHttpAndPreview(path: string, name: string, loadCallback?: Function) {
|
||||||
this.loader(
|
this.loader(
|
||||||
path,
|
path,
|
||||||
|
@ -271,8 +256,6 @@ export class CoreThreeRepository extends TypedEvent<any> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addSceneCamera = (cameraModel: CameraModel) => cameraModel.toWebGl(this);
|
|
||||||
|
|
||||||
updateSolidBody = (solidBodyModel: SolidModel) => {
|
updateSolidBody = (solidBodyModel: SolidModel) => {
|
||||||
const mesh = this.scene.getObjectByName(solidBodyModel.name);
|
const mesh = this.scene.getObjectByName(solidBodyModel.name);
|
||||||
mesh?.position.copy(solidBodyModel.vector3);
|
mesh?.position.copy(solidBodyModel.vector3);
|
||||||
|
@ -445,6 +428,7 @@ export class CoreThreeRepository extends TypedEvent<any> {
|
||||||
if (position) result.scene.position.copy(position);
|
if (position) result.scene.position.copy(position);
|
||||||
if (quaternion) result.scene.quaternion.copy(quaternion);
|
if (quaternion) result.scene.quaternion.copy(quaternion);
|
||||||
this.scene.add(result.scene);
|
this.scene.add(result.scene);
|
||||||
|
callBack();
|
||||||
},
|
},
|
||||||
(err) => console.log(err)
|
(err) => console.log(err)
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,6 +2,8 @@ import { ClassConstructor, plainToInstance } from "class-transformer";
|
||||||
import { Result } from "../helper/result";
|
import { Result } from "../helper/result";
|
||||||
import { Parts } from "../../features/details/details_http_repository";
|
import { Parts } from "../../features/details/details_http_repository";
|
||||||
import { UUID } from "../../features/all_projects/data/project_http_repository";
|
import { UUID } from "../../features/all_projects/data/project_http_repository";
|
||||||
|
import { SceneModel } from "../../features/scene_manager/model/scene_model";
|
||||||
|
import { SceneAsset } from "../model/scene_asset";
|
||||||
|
|
||||||
export enum HttpMethod {
|
export enum HttpMethod {
|
||||||
GET = "GET",
|
GET = "GET",
|
||||||
|
@ -100,7 +102,12 @@ export class CoreHttpRepository extends HttpRepository {
|
||||||
getAssetsActiveProject = async (): Promise<Result<HttpError, Parts[]>> => {
|
getAssetsActiveProject = async (): Promise<Result<HttpError, Parts[]>> => {
|
||||||
return this._jsonRequest<Parts[]>(HttpMethod.GET, "/projects/assets");
|
return this._jsonRequest<Parts[]>(HttpMethod.GET, "/projects/assets");
|
||||||
};
|
};
|
||||||
|
getSceneAsset = (id: string) =>
|
||||||
|
this._jsonToClassInstanceRequest(HttpMethod.GET, `/scenes/by_id?id=${id}`, SceneAsset) as Promise<
|
||||||
|
Result<HttpError, SceneAsset>
|
||||||
|
>;
|
||||||
async getActiveProjectId() {
|
async getActiveProjectId() {
|
||||||
return this._jsonRequest<UUID>(HttpMethod.GET, "/projects/get/active/project/id");
|
return this._jsonRequest<UUID>(HttpMethod.GET, "/projects/get/active/project/id");
|
||||||
}
|
}
|
||||||
|
getAllScenes = () => this._jsonRequest<SceneModel[]>(HttpMethod.GET, "/scenes");
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ export abstract class FormState<V, E> extends UiErrorState<E> {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
this.viewModel = Object.assign(this.viewModel, value);
|
this.viewModel = Object.assign(this.viewModel, value);
|
||||||
}
|
}
|
||||||
loadDependency = (viewModel: V) => {
|
loadDependency = (viewModel: V | undefined) => {
|
||||||
this.viewModel = viewModel;
|
if (viewModel) this.viewModel = viewModel;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ export const FormBuilder = observer((props: IFormBuilder) => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (element.type.isEqual(InputType.ARRAY)) {
|
if (element.type.isEqual(InputType.ARRAY)) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ border: "1px black solid", margin: 20 }}>
|
<div style={{ border: "1px black solid", margin: 20 }}>
|
||||||
<div
|
<div
|
||||||
|
|
30
ui/src/core/ui/toggle/toggle.tsx
Normal file
30
ui/src/core/ui/toggle/toggle.tsx
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Icon } from "../icons/icons";
|
||||||
|
import { CoreText, CoreTextType } from "../text/text";
|
||||||
|
import { set } from "ts-pattern/dist/patterns";
|
||||||
|
interface IToggleProps {
|
||||||
|
name: string;
|
||||||
|
child: React.ReactNode;
|
||||||
|
isOpen: boolean;
|
||||||
|
}
|
||||||
|
export const Toggle = (props: IToggleProps) => {
|
||||||
|
const [isOpen, setOpen] = useState(props.isOpen);
|
||||||
|
return (
|
||||||
|
<div style={{ border: "1px black solid" }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
margin: 0,
|
||||||
|
padding:5,
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
onClick={() => setOpen(!isOpen)}
|
||||||
|
>
|
||||||
|
<CoreText style={{ height: 33 }} text={props.name} type={CoreTextType.large} />
|
||||||
|
<Icon type="PlusCircle" style={{ width: 33 }} />
|
||||||
|
</div>
|
||||||
|
{isOpen ? props.child : <></>}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -5,6 +5,7 @@ import { BehaviorTreeModel } from "../model/behavior_tree_model";
|
||||||
import { BehaviorTreeViewModel } from "../model/behavior_tree_view_model";
|
import { BehaviorTreeViewModel } from "../model/behavior_tree_view_model";
|
||||||
|
|
||||||
export class BehaviorTreeBuilderHttpRepository extends CoreHttpRepository {
|
export class BehaviorTreeBuilderHttpRepository extends CoreHttpRepository {
|
||||||
|
|
||||||
getAllBtInstances = async () => this._jsonRequest<BehaviorTreeModel[]>(HttpMethod.GET, "/behavior/trees");
|
getAllBtInstances = async () => this._jsonRequest<BehaviorTreeModel[]>(HttpMethod.GET, "/behavior/trees");
|
||||||
getBtSkills = async (): Promise<Result<HttpError, Skills>> => {
|
getBtSkills = async (): Promise<Result<HttpError, Skills>> => {
|
||||||
return (await this._jsonToClassInstanceRequest<Skills>(
|
return (await this._jsonToClassInstanceRequest<Skills>(
|
||||||
|
|
|
@ -3,12 +3,15 @@ import { Result } from "../../../core/helper/result";
|
||||||
import { Skills } from "../../../core/model/skill_model";
|
import { Skills } from "../../../core/model/skill_model";
|
||||||
import { NodeBehaviorTree } from "./node_behavior_tree";
|
import { NodeBehaviorTree } from "./node_behavior_tree";
|
||||||
import { IsOptional } from "class-validator";
|
import { IsOptional } from "class-validator";
|
||||||
|
import { BehaviorTreeBuilderHttpRepository } from "../data/behavior_tree_builder_repository";
|
||||||
|
import { message } from "antd";
|
||||||
|
|
||||||
export class BehaviorTreeModel {
|
export class BehaviorTreeModel {
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@Type(() => Skills)
|
@Type(() => Skills)
|
||||||
|
public sceneId: string;
|
||||||
public skills?: Skills;
|
public skills?: Skills;
|
||||||
public scene: NodeBehaviorTree[];
|
public scene: NodeBehaviorTree[] = [];
|
||||||
public xml: string;
|
public xml: string;
|
||||||
public name: string;
|
public name: string;
|
||||||
public project: string;
|
public project: string;
|
||||||
|
@ -26,6 +29,16 @@ export class BehaviorTreeModel {
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
this.xml = xml;
|
this.xml = xml;
|
||||||
}
|
}
|
||||||
|
getSceneDependency = async (behaviorTreeBuilderHttpRepository: BehaviorTreeBuilderHttpRepository) =>
|
||||||
|
(await behaviorTreeBuilderHttpRepository.getSceneAsset(this.sceneId)).fold(
|
||||||
|
(s) => {
|
||||||
|
|
||||||
|
},
|
||||||
|
(e) => {
|
||||||
|
message.error('Get Scene Dependency error')
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
static empty() {
|
static empty() {
|
||||||
return new BehaviorTreeModel(Skills.empty(), [], "", "", "", "");
|
return new BehaviorTreeModel(Skills.empty(), [], "", "", "", "");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { Result } from "../../../core/helper/result";
|
import { Result } from "../../../core/helper/result";
|
||||||
|
|
||||||
export class BehaviorTreeViewModel {
|
export class BehaviorTreeViewModel {
|
||||||
constructor(public name: string, public project: string) {}
|
constructor(public name: string, public project: string, public sceneId: string) {}
|
||||||
static empty() {
|
static empty() {
|
||||||
return new BehaviorTreeViewModel("", "");
|
return new BehaviorTreeViewModel("", "", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
valid(): Result<string, BehaviorTreeViewModel> {
|
valid(): Result<string, BehaviorTreeViewModel> {
|
||||||
if (this.project.isEmpty()) {
|
if (this.project.isEmpty()) {
|
||||||
return Result.error("project is empty");
|
return Result.error("project is empty");
|
||||||
|
|
|
@ -25,6 +25,8 @@ export interface IUpdateEvent {
|
||||||
export class NodeRerenderObserver extends TypedEvent<IUpdateEvent> {}
|
export class NodeRerenderObserver extends TypedEvent<IUpdateEvent> {}
|
||||||
export class ReteForceUpdateObserver extends TypedEvent<any> {}
|
export class ReteForceUpdateObserver extends TypedEvent<any> {}
|
||||||
export class BehaviorTreeBuilderModel {
|
export class BehaviorTreeBuilderModel {
|
||||||
|
public static btRootTag: string = '<root BTCPP_format="4"><BehaviorTree ID="Main">${bt}</BehaviorTree></root>';
|
||||||
|
|
||||||
public static result = "";
|
public static result = "";
|
||||||
static fromReteScene(
|
static fromReteScene(
|
||||||
editor: NodeEditor<Schemes>,
|
editor: NodeEditor<Schemes>,
|
||||||
|
@ -33,8 +35,6 @@ export class BehaviorTreeBuilderModel {
|
||||||
): Result<string, string> {
|
): Result<string, string> {
|
||||||
try {
|
try {
|
||||||
this.result = "";
|
this.result = "";
|
||||||
|
|
||||||
// eslint-disable-next-line array-callback-return
|
|
||||||
this.getFirstSequence(editor).map((sortedSequence) => {
|
this.getFirstSequence(editor).map((sortedSequence) => {
|
||||||
const firstNodeId = sortedSequence.getKeyFromValueIsExists(1) as string;
|
const firstNodeId = sortedSequence.getKeyFromValueIsExists(1) as string;
|
||||||
this.findSequence(firstNodeId, editor, sortedSequence, 2);
|
this.findSequence(firstNodeId, editor, sortedSequence, 2);
|
||||||
|
@ -42,25 +42,7 @@ export class BehaviorTreeBuilderModel {
|
||||||
this.toXML(sortedSequence as Map<string, number>, editor, area, firstNodeId, skills);
|
this.toXML(sortedSequence as Map<string, number>, editor, area, firstNodeId, skills);
|
||||||
this.result += `</${this.getNodeLabelAtId(editor, firstNodeId, skills)}>`;
|
this.result += `</${this.getNodeLabelAtId(editor, firstNodeId, skills)}>`;
|
||||||
});
|
});
|
||||||
|
return Result.ok(xmlFormat(this.btRootTag.replace("${bt}", this.result)));
|
||||||
return Result.ok(
|
|
||||||
xmlFormat(`<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<root main_tree_to_execute="Main">
|
|
||||||
<BehaviorTree ID="Main">
|
|
||||||
${this.result}
|
|
||||||
</BehaviorTree>
|
|
||||||
|
|
||||||
<TreeNodesModel>
|
|
||||||
<Action ID="RbsBtAction">
|
|
||||||
<input_port name="do" />
|
|
||||||
<input_port name="command" />
|
|
||||||
<input_port name="server_name" />
|
|
||||||
<input_port name="server_timeout" />
|
|
||||||
</Action>
|
|
||||||
</TreeNodesModel>
|
|
||||||
|
|
||||||
</root>`)
|
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return Result.error("BtBuilderModel fromReteScene error");
|
return Result.error("BtBuilderModel fromReteScene error");
|
||||||
}
|
}
|
||||||
|
@ -68,9 +50,9 @@ export class BehaviorTreeBuilderModel {
|
||||||
|
|
||||||
public static getNodeLabelAtId(editor: NodeEditor<Schemes>, id: string, skills?: Skills) {
|
public static getNodeLabelAtId(editor: NodeEditor<Schemes>, id: string, skills?: Skills) {
|
||||||
if (skills?.getSkillsNames().find((el) => el.name.isEqual(editor.getNode(id).label))) {
|
if (skills?.getSkillsNames().find((el) => el.name.isEqual(editor.getNode(id).label))) {
|
||||||
return `Action ID="RbsBtAction" do="${skills.getSkillDo(editor.getNode(id).label)}" command="${
|
return `Action ID="RbsAction" do="${skills.getSkillDo(editor.getNode(id).label)}" command="${
|
||||||
editor.getNode(id).label
|
editor.getNode(id).label
|
||||||
}" sid=${id} server_name="rbs_interface" server_timeout="1000"`;
|
}" sid=${id}"`;
|
||||||
}
|
}
|
||||||
return editor.getNode(id).label;
|
return editor.getNode(id).label;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { CoreInput } from "../../../core/ui/input/input";
|
||||||
import { CoreText, CoreTextType } from "../../../core/ui/text/text";
|
import { CoreText, CoreTextType } from "../../../core/ui/text/text";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { IForms, forms } from "./ui/forms/forms";
|
import { IForms, forms } from "./ui/forms/forms";
|
||||||
|
import { CoreSelect } from "../../../core/ui/select/select";
|
||||||
|
|
||||||
export const behaviorTreeBuilderScreenPath = "behavior/tree/screen/path";
|
export const behaviorTreeBuilderScreenPath = "behavior/tree/screen/path";
|
||||||
export interface DOMReact {
|
export interface DOMReact {
|
||||||
|
@ -131,6 +132,14 @@ export const BehaviorTreeBuilderScreen = observer(() => {
|
||||||
<div style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", height: "100%" }}>
|
<div style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", height: "100%" }}>
|
||||||
<div>
|
<div>
|
||||||
<CoreInput label="Имя дерева" onChange={(text) => store.updateForm({ name: text })} />
|
<CoreInput label="Имя дерева" onChange={(text) => store.updateForm({ name: text })} />
|
||||||
|
<CoreSelect
|
||||||
|
items={store.scenes?.map((el) => el.name) ?? []}
|
||||||
|
value={""}
|
||||||
|
label={"Сцена"}
|
||||||
|
onChange={(text) =>
|
||||||
|
store.updateForm({ sceneId: store.scenes?.filter((el) => el.name.isEqual(text)).at(0)?._id })
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: "flex" }}>
|
<div style={{ display: "flex" }}>
|
||||||
<CoreButton text="Сохранить" filled={true} onClick={() => store.createNewBehaviorTree()} />
|
<CoreButton text="Сохранить" filled={true} onClick={() => store.createNewBehaviorTree()} />
|
||||||
|
@ -150,10 +159,11 @@ export const BehaviorTreeBuilderScreen = observer(() => {
|
||||||
{store.skillTemplates?.getForms(store.selected ?? "").map((formType, index) =>
|
{store.skillTemplates?.getForms(store.selected ?? "").map((formType, index) =>
|
||||||
forms(
|
forms(
|
||||||
store.filledOutTemplates?.getDependencyBySkillLabelAndType(
|
store.filledOutTemplates?.getDependencyBySkillLabelAndType(
|
||||||
forms(null, () => {}).find((form) => form.name.isEqual(formType))?.name ?? "",
|
forms(null, () => {}, store).find((form) => form.name.isEqual(formType))?.name ?? "",
|
||||||
store.selectedSid ?? ""
|
store.selectedSid ?? ""
|
||||||
),
|
),
|
||||||
(dependency) => store.formUpdateDependency(dependency, formType)
|
(dependency) => store.formUpdateDependency(dependency, formType),
|
||||||
|
store
|
||||||
)
|
)
|
||||||
.rFind<IForms>((form) => form.name.isEqual(formType))
|
.rFind<IForms>((form) => form.name.isEqual(formType))
|
||||||
.fold(
|
.fold(
|
||||||
|
@ -169,4 +179,3 @@ export const BehaviorTreeBuilderScreen = observer(() => {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,7 +24,8 @@ import { behaviorTreeBuilderStore } from "./behavior_tree_builder_screen";
|
||||||
import clone from "just-clone";
|
import clone from "just-clone";
|
||||||
import { BehaviorTreeModel } from "../model/behavior_tree_model";
|
import { BehaviorTreeModel } from "../model/behavior_tree_model";
|
||||||
import { PrimitiveViewModel, SystemPrimitive } from "../model/primitive_view_model";
|
import { PrimitiveViewModel, SystemPrimitive } from "../model/primitive_view_model";
|
||||||
|
import { SceneModel } from "../../scene_manager/model/scene_model";
|
||||||
|
import { SceneAsset } from "../../../core/model/scene_asset";
|
||||||
|
|
||||||
interface I2DArea {
|
interface I2DArea {
|
||||||
x: number;
|
x: number;
|
||||||
|
@ -43,10 +44,11 @@ export enum StoreUIType {
|
||||||
ViewBehaviorTree,
|
ViewBehaviorTree,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeViewModel, CoreError> {
|
export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeViewModel, CoreError> {
|
||||||
type: StoreUIType = StoreUIType.ViewBehaviorTree;
|
type: StoreUIType = StoreUIType.ViewBehaviorTree;
|
||||||
|
sceneAsset?: SceneAsset;
|
||||||
viewModel: BehaviorTreeViewModel = BehaviorTreeViewModel.empty();
|
viewModel: BehaviorTreeViewModel = BehaviorTreeViewModel.empty();
|
||||||
|
scenes?: SceneModel[];
|
||||||
behaviorTreeModel: BehaviorTreeModel = BehaviorTreeModel.empty();
|
behaviorTreeModel: BehaviorTreeModel = BehaviorTreeModel.empty();
|
||||||
skillTemplates: Skills = Skills.empty();
|
skillTemplates: Skills = Skills.empty();
|
||||||
filledOutTemplates: Skills = Skills.empty();
|
filledOutTemplates: Skills = Skills.empty();
|
||||||
|
@ -74,7 +76,6 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeView
|
||||||
name: "Действия",
|
name: "Действия",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,8 +84,8 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeView
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
this.type = StoreUIType.SelectBehaviorTree;
|
this.type = StoreUIType.SelectBehaviorTree;
|
||||||
|
|
||||||
this.primitiveViewModel = new PrimitiveViewModel()
|
this.primitiveViewModel = new PrimitiveViewModel();
|
||||||
this.skillTree.children?.push({ name: "Примитивы BT", children: this.primitiveViewModel.toSkillView() })
|
this.skillTree.children?.push({ name: "Примитивы BT", children: this.primitiveViewModel.toSkillView() });
|
||||||
}
|
}
|
||||||
|
|
||||||
syncScene = async (editor: NodeEditor<Schemes>, area: AreaPlugin<Schemes, AreaExtra>) => {
|
syncScene = async (editor: NodeEditor<Schemes>, area: AreaPlugin<Schemes, AreaExtra>) => {
|
||||||
|
@ -92,7 +93,7 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeView
|
||||||
this.areaPlugin = area;
|
this.areaPlugin = area;
|
||||||
};
|
};
|
||||||
|
|
||||||
errorHandingStrategy = (_: CoreError) => { };
|
errorHandingStrategy = (_: CoreError) => {};
|
||||||
|
|
||||||
dragEnd = (e: EventTarget) => {
|
dragEnd = (e: EventTarget) => {
|
||||||
if (this.canRun) {
|
if (this.canRun) {
|
||||||
|
@ -123,8 +124,7 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeView
|
||||||
if (!name.isEqualMany(Object.keys(SystemPrimitive))) {
|
if (!name.isEqualMany(Object.keys(SystemPrimitive))) {
|
||||||
this.skillTemplates?.getSkill(name).fold(
|
this.skillTemplates?.getSkill(name).fold(
|
||||||
(m) => {
|
(m) => {
|
||||||
const model = clone(m);
|
const modelSetId = clone(m).setSid(sid);
|
||||||
const modelSetId = model.setSid(sid);
|
|
||||||
modelSetId.BTAction = m.BTAction.filter((el) => el.name.isEqual(name));
|
modelSetId.BTAction = m.BTAction.filter((el) => el.name.isEqual(name));
|
||||||
|
|
||||||
this.filledOutTemplates?.skills.push(modelSetId);
|
this.filledOutTemplates?.skills.push(modelSetId);
|
||||||
|
@ -150,6 +150,7 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeView
|
||||||
}
|
}
|
||||||
return el;
|
return el;
|
||||||
});
|
});
|
||||||
|
// this.sceneAsset = this.behaviorTreeBuilderHttpRepository.getScene()
|
||||||
},
|
},
|
||||||
(e) => console.log(e)
|
(e) => console.log(e)
|
||||||
);
|
);
|
||||||
|
@ -180,16 +181,22 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeView
|
||||||
this.type = StoreUIType.ViewBehaviorTree;
|
this.type = StoreUIType.ViewBehaviorTree;
|
||||||
if (id) {
|
if (id) {
|
||||||
(await this.behaviorTreeBuilderHttpRepository.getBtById(id)).fold(
|
(await this.behaviorTreeBuilderHttpRepository.getBtById(id)).fold(
|
||||||
(model) => {
|
async (model) => {
|
||||||
this.nodeBehaviorTree = model.scene;
|
this.nodeBehaviorTree = model.scene;
|
||||||
this.behaviorTreeModel = model;
|
this.behaviorTreeModel = model;
|
||||||
if (model.skills) this.filledOutTemplates = model.skills;
|
if (model.skills) this.filledOutTemplates = model.skills;
|
||||||
|
|
||||||
|
await this.mapOk("sceneAsset", this.behaviorTreeBuilderHttpRepository.getSceneAsset(model.sceneId));
|
||||||
|
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
this.reteForceUpdateObserver?.emit("");
|
this.reteForceUpdateObserver?.emit("");
|
||||||
},
|
},
|
||||||
() => this.errors.push(new UiBaseError(`не найдено дерево с id:${id}`))
|
async () => {
|
||||||
|
this.errors.push(new UiBaseError(`не найдено дерево с id:${id}`));
|
||||||
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
await this.mapOk("scenes", this.behaviorTreeBuilderHttpRepository.getAllScenes());
|
||||||
this.type = StoreUIType.SelectBehaviorTree;
|
this.type = StoreUIType.SelectBehaviorTree;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -202,8 +209,8 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeView
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
dispose(): void {
|
dispose(): void {
|
||||||
document.removeEventListener("keyup", () => { });
|
document.removeEventListener("keyup", () => {});
|
||||||
document.removeEventListener("keydown", () => { });
|
document.removeEventListener("keydown", () => {});
|
||||||
}
|
}
|
||||||
onClickSaveBehaviorTree = async (): Promise<void> => {
|
onClickSaveBehaviorTree = async (): Promise<void> => {
|
||||||
this.filledOutTemplates.validation().fold(
|
this.filledOutTemplates.validation().fold(
|
||||||
|
@ -233,7 +240,7 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeView
|
||||||
async () => message.error(`Дерево поведения не заполнено`)
|
async () => message.error(`Дерево поведения не заполнено`)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
validateBt() { }
|
validateBt() {}
|
||||||
createNewBehaviorTree = async () => {
|
createNewBehaviorTree = async () => {
|
||||||
this.viewModel.project = this.activeProject;
|
this.viewModel.project = this.activeProject;
|
||||||
this.viewModel.valid().fold(
|
this.viewModel.valid().fold(
|
||||||
|
@ -282,7 +289,6 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeView
|
||||||
});
|
});
|
||||||
|
|
||||||
this.filledOutTemplates.updateSkill(model);
|
this.filledOutTemplates.updateSkill(model);
|
||||||
console.log(this.filledOutTemplates)
|
|
||||||
},
|
},
|
||||||
() => console.log("UNKNOWN SID: " + this.selectedSid)
|
() => console.log("UNKNOWN SID: " + this.selectedSid)
|
||||||
);
|
);
|
||||||
|
@ -319,9 +325,12 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeView
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
isFilledInput = (type: string, sid: string): boolean => this.filledOutTemplates?.dependencyIsFilled(type, sid);
|
isFilledInput = (type: string, sid: string): boolean => {
|
||||||
|
console.log(this.filledOutTemplates?.dependencyIsFilled)
|
||||||
|
return this.filledOutTemplates?.dependencyIsFilled(type, sid) ?? false;
|
||||||
|
};
|
||||||
getInputs(name: string) {
|
getInputs(name: string) {
|
||||||
const result = this.primitiveViewModel.getPrimitiveAtLabel(name)
|
const result = this.primitiveViewModel.getPrimitiveAtLabel(name);
|
||||||
if (result) {
|
if (result) {
|
||||||
return {
|
return {
|
||||||
input: result.input ? "a" : null,
|
input: result.input ? "a" : null,
|
||||||
|
@ -329,13 +338,12 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeView
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
input: 'a',
|
input: "a",
|
||||||
output: null
|
output: null,
|
||||||
}
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
getStylesByLabelNode(label: string): React.CSSProperties | undefined {
|
getStylesByLabelNode(label: string): React.CSSProperties | undefined {
|
||||||
const result = this.primitiveViewModel.getPrimitiveAtLabel(label)
|
const result = this.primitiveViewModel.getPrimitiveAtLabel(label);
|
||||||
if (result) {
|
if (result) {
|
||||||
return clone(result.css as Object);
|
return clone(result.css as Object);
|
||||||
}
|
}
|
||||||
|
@ -357,4 +365,5 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeView
|
||||||
background: "rgba(153, 195, 234, 1)",
|
background: "rgba(153, 195, 234, 1)",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
changeSceneViewModel = (text: string) => {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import {
|
||||||
UpdateEvent,
|
UpdateEvent,
|
||||||
} from "../../../model/editor_view";
|
} from "../../../model/editor_view";
|
||||||
import { v4 } from "uuid";
|
import { v4 } from "uuid";
|
||||||
|
import constructWithOptions from "styled-components/dist/constructors/constructWithOptions";
|
||||||
|
|
||||||
export type Schemes = GetSchemes<ClassicPreset.Node, ClassicPreset.Connection<ClassicPreset.Node, ClassicPreset.Node>>;
|
export type Schemes = GetSchemes<ClassicPreset.Node, ClassicPreset.Connection<ClassicPreset.Node, ClassicPreset.Node>>;
|
||||||
export type AreaExtra = ReactArea2D<Schemes>;
|
export type AreaExtra = ReactArea2D<Schemes>;
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
|
import { BehaviorTreeBuilderStore } from "../../behavior_tree_builder_store";
|
||||||
import { CameraDeviceForm } from "./camera_device_form/camera_device_form_form";
|
import { CameraDeviceForm } from "./camera_device_form/camera_device_form_form";
|
||||||
|
import { MoveToPose } from "./move_to_pose/move_to_pose_form";
|
||||||
import { RobotDeviceForm } from "./robot_device_form/robot_device_form_form";
|
import { RobotDeviceForm } from "./robot_device_form/robot_device_form_form";
|
||||||
import { TopicsForm } from "./topics_form/topics_form";
|
import { TopicsForm } from "./topics_form/topics_form";
|
||||||
import { WeightsForm } from "./weights_form/weights_form";
|
import { WeightsForm } from "./weights_form/weights_form";
|
||||||
|
|
||||||
export interface IPropsForm<T> {
|
export interface IPropsForm<T> {
|
||||||
dependency: T;
|
dependency: T;
|
||||||
|
store: BehaviorTreeBuilderStore;
|
||||||
onChange: (dependency: Object) => void;
|
onChange: (dependency: Object) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,10 +20,17 @@ export enum Form {
|
||||||
robotName = "robot_name",
|
robotName = "robot_name",
|
||||||
cameraDeviceForm = "camera",
|
cameraDeviceForm = "camera",
|
||||||
topic = "topic",
|
topic = "topic",
|
||||||
|
moveToPose = "move_to_pose",
|
||||||
}
|
}
|
||||||
export const forms = (props: any, onChange: (dependency: Object) => void): IForms[] => [
|
|
||||||
|
export const forms = (
|
||||||
|
props: any,
|
||||||
|
onChange: (dependency: Object) => void,
|
||||||
|
store: BehaviorTreeBuilderStore
|
||||||
|
): IForms[] => [
|
||||||
{ name: Form.weights, component: <WeightsForm dependency={props} onChange={onChange} /> },
|
{ name: Form.weights, component: <WeightsForm dependency={props} onChange={onChange} /> },
|
||||||
{ name: Form.robotName, component: <RobotDeviceForm dependency={props} onChange={onChange} /> },
|
{ name: Form.robotName, component: <RobotDeviceForm store={store} dependency={props} onChange={onChange} /> },
|
||||||
{ name: Form.cameraDeviceForm, component: <CameraDeviceForm dependency={props} onChange={onChange} /> },
|
{ name: Form.cameraDeviceForm, component: <CameraDeviceForm store={store} dependency={props} onChange={onChange} /> },
|
||||||
{ name: Form.topic, component: <TopicsForm dependency={props} onChange={onChange} /> },
|
{ name: Form.topic, component: <TopicsForm store={store} dependency={props} onChange={onChange} /> },
|
||||||
|
{ name: Form.moveToPose, component: <MoveToPose store={store} dependency={props} onChange={onChange} /> },
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
import React from "react";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { MoveToPoseStore } from "./move_to_pose_store";
|
||||||
|
import { IPropsForm } from "../forms";
|
||||||
|
import { MoveToPoseRobotModel } from "./move_to_pose_robot_model";
|
||||||
|
import { CoreSelect } from "../../../../../../core/ui/select/select";
|
||||||
|
import { PointModel } from "../../../../../../core/model/point_model";
|
||||||
|
import { ObjectIsNotEmpty } from "../../../../../../core/extensions/object";
|
||||||
|
import { CoreButton } from "../../../../../../core/ui/button/button";
|
||||||
|
import { message } from "antd";
|
||||||
|
|
||||||
|
export const MoveToPose = observer((props: IPropsForm<MoveToPoseRobotModel | undefined>) => {
|
||||||
|
const [store] = React.useState(() => new MoveToPoseStore(props.store));
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (ObjectIsNotEmpty(props.dependency)) store.loadDependency(props.dependency);
|
||||||
|
store.init();
|
||||||
|
}, [store]);
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<CoreSelect
|
||||||
|
items={props.store.sceneAsset?.getAllRobotsTopics() ?? ["ERROR"]}
|
||||||
|
value={store.viewModel.robot_name ?? ""}
|
||||||
|
label={"Робот"}
|
||||||
|
onChange={(text) => store.updateForm({ robot_name: text })}
|
||||||
|
/>
|
||||||
|
<CoreSelect
|
||||||
|
items={props.store.sceneAsset?.getAllPoints() ?? ["ERROR"]}
|
||||||
|
label={"Точка"}
|
||||||
|
onChange={(text) =>
|
||||||
|
store.updateForm({ pose: props.store.sceneAsset?.getElementByName<PointModel>(text).toDependency() })
|
||||||
|
}
|
||||||
|
value={store.viewModel?.pose?.name ?? ""}
|
||||||
|
/>
|
||||||
|
<CoreButton
|
||||||
|
style={{ margin: 10, width: 100 }}
|
||||||
|
text="OK"
|
||||||
|
onClick={() => {
|
||||||
|
store.viewModel.valid().fold(
|
||||||
|
(s) => {
|
||||||
|
props.onChange(s);
|
||||||
|
},
|
||||||
|
(e) => message.error(e)
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { Vector3 } from "three";
|
||||||
|
import { Result } from "../../../../../../core/helper/result";
|
||||||
|
export interface IMoveToPoseRobotModel {
|
||||||
|
robot_name: string;
|
||||||
|
pose: Pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Pose {
|
||||||
|
name: string;
|
||||||
|
position: Vector3;
|
||||||
|
orientation: Orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Orientation {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
z: number;
|
||||||
|
w: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MoveToPoseRobotModel implements IMoveToPoseRobotModel {
|
||||||
|
robot_name: string;
|
||||||
|
pose: Pose;
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
valid(): Result<string, MoveToPoseRobotModel> {
|
||||||
|
return Result.ok(this);
|
||||||
|
}
|
||||||
|
static empty() {
|
||||||
|
const moveToPoseRobotModel = new MoveToPoseRobotModel();
|
||||||
|
moveToPoseRobotModel.robot_name = "";
|
||||||
|
moveToPoseRobotModel.pose = {
|
||||||
|
name: "",
|
||||||
|
position: new Vector3(0, 0, 0),
|
||||||
|
orientation: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0,
|
||||||
|
w: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return moveToPoseRobotModel;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
import makeAutoObservable from "mobx-store-inheritance";
|
||||||
|
import { NavigateFunction } from "react-router-dom";
|
||||||
|
import { MoveToPoseRobotModel } from "./move_to_pose_robot_model";
|
||||||
|
import { FormState, CoreError } from "../../../../../../core/store/base_store";
|
||||||
|
import { BehaviorTreeBuilderStore } from "../../../behavior_tree_builder_store";
|
||||||
|
|
||||||
|
export class MoveToPoseStore extends FormState<MoveToPoseRobotModel, CoreError> {
|
||||||
|
behaviorTreeBuilderStore: BehaviorTreeBuilderStore;
|
||||||
|
|
||||||
|
constructor(behaviorTreeBuilderStore: BehaviorTreeBuilderStore) {
|
||||||
|
super();
|
||||||
|
this.behaviorTreeBuilderStore = behaviorTreeBuilderStore;
|
||||||
|
makeAutoObservable(this);
|
||||||
|
}
|
||||||
|
viewModel: MoveToPoseRobotModel = MoveToPoseRobotModel.empty();
|
||||||
|
errorHandingStrategy = (error: CoreError) => {};
|
||||||
|
init = async (navigate?: NavigateFunction | undefined) => {};
|
||||||
|
}
|
|
@ -1,105 +1,16 @@
|
||||||
import { plainToInstance } from "class-transformer";
|
|
||||||
import { Result } from "../../../core/helper/result";
|
import { Result } from "../../../core/helper/result";
|
||||||
import { HttpMethod, CoreHttpRepository } from "../../../core/repository/http_repository";
|
import { HttpMethod, CoreHttpRepository, HttpError } from "../../../core/repository/http_repository";
|
||||||
import { CoreError } from "../../../core/store/base_store";
|
import { CoreError } from "../../../core/store/base_store";
|
||||||
import { SceneModel } from "../model/scene_model";
|
import { SceneModel } from "../model/scene_model";
|
||||||
import { SceneViewModel } from "../model/scene_view_model";
|
import { SceneViewModel } from "../model/scene_view_model";
|
||||||
import { SceneAsset } from "../../../core/model/scene_asset";
|
import { SceneAsset } from "../../../core/model/scene_asset";
|
||||||
|
|
||||||
export class SceneHttpRepository extends CoreHttpRepository {
|
export class SceneHttpRepository extends CoreHttpRepository {
|
||||||
getScene = () => {
|
editScene = (scene: SceneAsset) => this._jsonRequest(HttpMethod.PUT, "/scenes", scene);
|
||||||
return plainToInstance(SceneAsset, {
|
|
||||||
scene: [
|
|
||||||
// {
|
|
||||||
// quaternion: [0, 0, 0, 1],
|
|
||||||
// vector3: { x: 1, y: 1, z: 1 },
|
|
||||||
// name: "body_down",
|
|
||||||
// solidType: "active",
|
|
||||||
// mesh: "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/body_down.dae",
|
|
||||||
// collisionMesh: "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/assets/libs/objects/body_down.dae",
|
|
||||||
// type: "SOLID",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// quaternion: [0.3797976276673656, 0.5269410603416079, 0.6168038601812418, 0.44456706919183975],
|
|
||||||
// vector3: { x: 60, y: 20.000000000000004, z: 9.999999999999993 },
|
|
||||||
// name: "231",
|
|
||||||
// cameraType: "RGB",
|
|
||||||
// width: 0,
|
|
||||||
// updateRate: 0,
|
|
||||||
// fov: 50,
|
|
||||||
// near: 0.1,
|
|
||||||
// far: 2000,
|
|
||||||
// height: 0,
|
|
||||||
// topic: "231",
|
|
||||||
// type: "CAMERA",
|
|
||||||
// aspect: 0.48721804511278194,
|
|
||||||
// },
|
|
||||||
|
|
||||||
// {
|
|
||||||
// type: "POINT",
|
|
||||||
// name: "POINT 1",
|
|
||||||
// quaternion: [0, 0, 0, 1],
|
|
||||||
// vector3: { x: 0.504300334422403, y: 0.66062343475878, z: 1 },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// type: "ZONE",
|
|
||||||
// name: "ZONE 1",
|
|
||||||
// quaternion: [0, 0, 0, 1],
|
|
||||||
// vector3: { x: 0, y: 0, z: 0 },
|
|
||||||
// width: 100,
|
|
||||||
// height: 100,
|
|
||||||
// length: 10,
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
quaternion: [0, 0, 0, 1],
|
|
||||||
vector3: { x: 0, y: 10, z: 0 },
|
|
||||||
name: "ARM0",
|
|
||||||
nDof: 6,
|
|
||||||
httpUrl: "http://localhost:4001/d370204b-205b-44bb-9698-3bf083b4b7a7/robots/124/robot.xml",
|
|
||||||
toolType: "",
|
|
||||||
jointPosition: [],
|
|
||||||
type: "ROBOT",
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// type: "LIGHT",
|
|
||||||
// name:"light1S",
|
|
||||||
|
|
||||||
// typeLight: "SPOT",
|
|
||||||
// color: "0xffffff",
|
|
||||||
// intensity: 100,
|
|
||||||
// distance: 100,
|
|
||||||
// angle: 100,
|
|
||||||
// penumbra: 100,
|
|
||||||
// decay: 100,
|
|
||||||
// quaternion: [0, 0, 0, 1],
|
|
||||||
// vector3: { x: 0, y: 0, z: 0 },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// type: "LIGHT",
|
|
||||||
// name:"light1P",
|
|
||||||
|
|
||||||
// typeLight: "POINT",
|
|
||||||
// color: "0xffffff",
|
|
||||||
// intensity: 100,
|
|
||||||
// distance: 100,
|
|
||||||
// decay: 100,
|
|
||||||
// quaternion: [0, 0, 0, 1],
|
|
||||||
// vector3: { x: 0, y: 0, z: 0 },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name:"light1D",
|
|
||||||
// type: "LIGHT",
|
|
||||||
// typeLight: "DIRECTIONAL",
|
|
||||||
// color: "0xffffff",
|
|
||||||
// intensity: 100,
|
|
||||||
// quaternion: [0, 0, 0, 1],
|
|
||||||
// vector3: { x: 0, y: 0, z: 0 },
|
|
||||||
// },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
getAllScenes = () => this._jsonRequest<SceneModel[]>(HttpMethod.GET, "/scenes");
|
|
||||||
|
|
||||||
newScene = (sceneViewModel: SceneViewModel) =>
|
newScene = (sceneViewModel: SceneViewModel) =>
|
||||||
this._jsonRequest(HttpMethod.POST, "/scenes", sceneViewModel) as unknown as Promise<Result<CoreError, void>>;
|
this._jsonRequest(HttpMethod.POST, "/scenes", sceneViewModel) as unknown as Promise<Result<CoreError, void>>;
|
||||||
}
|
}
|
|
@ -1,59 +1,105 @@
|
||||||
import { FormState } from "../../../../core/store/base_store";
|
import { FormState } from "../../../../core/store/base_store";
|
||||||
import { CoreInput } from "../../../../core/ui/input/input";
|
import { CoreInput } from "../../../../core/ui/input/input";
|
||||||
import { CoreText, CoreTextType } from "../../../../core/ui/text/text";
|
import { CoreText, CoreTextType } from "../../../../core/ui/text/text";
|
||||||
|
import { Toggle } from "../../../../core/ui/toggle/toggle";
|
||||||
|
|
||||||
export const CoordsForm = ({ store, update }: { store: FormState<any, any>; update: Function }) => {
|
export const CoordsForm = ({ store, update }: { store: FormState<any, any>; update: Function }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CoreText text="Координаты" type={CoreTextType.header} />
|
<Toggle
|
||||||
<CoreInput
|
name={"Координаты"}
|
||||||
value={String(store.viewModel.vector3.x)}
|
child={
|
||||||
label="Вектор X"
|
<div style={{margin:10}}>
|
||||||
onChange={(text) => {
|
<CoreText text="Позиция" type={CoreTextType.header} />
|
||||||
store.updateForm({ vector3: store.viewModel.vector3.setX(Number(text)) });
|
|
||||||
update();
|
<CoreInput
|
||||||
}}
|
value={String(store.viewModel.vector3.x)}
|
||||||
/>
|
label="X"
|
||||||
<CoreInput
|
onChange={(text) => {
|
||||||
value={String(store.viewModel.vector3.x)}
|
store.updateForm({ vector3: store.viewModel.vector3.setX(Number(text)) });
|
||||||
label="Вектор Y"
|
update();
|
||||||
onChange={(text) => {
|
}}
|
||||||
store.updateForm({ vector3: store.viewModel.vector3.setY(Number(text)) });
|
/>
|
||||||
update();
|
<CoreInput
|
||||||
}}
|
value={String(store.viewModel.vector3.x)}
|
||||||
/>
|
label="Y"
|
||||||
<CoreInput
|
onChange={(text) => {
|
||||||
value={String(store.viewModel.vector3.x)}
|
store.updateForm({ vector3: store.viewModel.vector3.setY(Number(text)) });
|
||||||
label="Вектор Z"
|
update();
|
||||||
onChange={(text) => {
|
}}
|
||||||
store.updateForm({ vector3: store.viewModel.vector3.setZ(Number(text)) });
|
/>
|
||||||
update();
|
<CoreInput
|
||||||
}}
|
value={String(store.viewModel.vector3.x)}
|
||||||
/>
|
label="Z"
|
||||||
<CoreText text="Координаты" type={CoreTextType.header} />
|
onChange={(text) => {
|
||||||
<CoreInput
|
store.updateForm({ vector3: store.viewModel.vector3.setZ(Number(text)) });
|
||||||
value={String(store.viewModel.vector3.x)}
|
update();
|
||||||
label="Вектор X"
|
}}
|
||||||
onChange={(text) => {
|
/>
|
||||||
store.updateForm({ vector3: store.viewModel.vector3.setX(Number(text)) });
|
<CoreText text="Кватернион" type={CoreTextType.header} />
|
||||||
update();
|
<CoreInput
|
||||||
}}
|
value={String(store.viewModel.quaternion[0])}
|
||||||
/>
|
label="X"
|
||||||
<CoreInput
|
onChange={(text) => {
|
||||||
value={String(store.viewModel.vector3.x)}
|
store.updateForm({
|
||||||
label="Вектор Y"
|
quaternion: store.viewModel.quaternion.map((el: any, i: number) => {
|
||||||
onChange={(text) => {
|
if (i === 1) {
|
||||||
store.updateForm({ vector3: store.viewModel.vector3.setY(Number(text)) });
|
return Number(text);
|
||||||
update();
|
}
|
||||||
}}
|
return el;
|
||||||
/>
|
}),
|
||||||
<CoreInput
|
});
|
||||||
value={String(store.viewModel.vector3.x)}
|
update();
|
||||||
label="Вектор Z"
|
}}
|
||||||
onChange={(text) => {
|
/>
|
||||||
store.updateForm({ vector3: store.viewModel.vector3.setZ(Number(text)) });
|
<CoreInput
|
||||||
update();
|
value={String(store.viewModel.quaternion[1])}
|
||||||
}}
|
label="Y"
|
||||||
|
onChange={(text) => {
|
||||||
|
store.updateForm({
|
||||||
|
quaternion: store.viewModel.quaternion.map((el: any, i: number) => {
|
||||||
|
if (i === 2) {
|
||||||
|
return Number(text);
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
update();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<CoreInput
|
||||||
|
value={String(store.viewModel.quaternion[2])}
|
||||||
|
label="Z"
|
||||||
|
onChange={(text) => {
|
||||||
|
store.updateForm({
|
||||||
|
quaternion: store.viewModel.quaternion.map((el: any, i: number) => {
|
||||||
|
if (i === 3) {
|
||||||
|
return Number(text);
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
update();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<CoreInput
|
||||||
|
value={String(store.viewModel.quaternion[3])}
|
||||||
|
label="W"
|
||||||
|
onChange={(text) => {
|
||||||
|
store.updateForm({
|
||||||
|
quaternion: store.viewModel.quaternion.map((el: any, i: number) => {
|
||||||
|
if (i === 4) {
|
||||||
|
return Number(text);
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
update();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
isOpen={false}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { message } from "antd";
|
|
||||||
import { CoreButton } from "../../../../../core/ui/button/button";
|
import { CoreButton } from "../../../../../core/ui/button/button";
|
||||||
import { IDefaultSceneManagerFormProps, isPreviewMode } from "../scene_manager_forms";
|
import { IDefaultSceneManagerFormProps, isPreviewMode } from "../scene_manager_forms";
|
||||||
import { CoreInput } from "../../../../../core/ui/input/input";
|
import { CoreInput } from "../../../../../core/ui/input/input";
|
||||||
import { CoreText, CoreTextType } from "../../../../../core/ui/text/text";
|
import { CoreText, CoreTextType } from "../../../../../core/ui/text/text";
|
||||||
import { CoreSelect } from "../../../../../core/ui/select/select";
|
import { CoreSelect } from "../../../../../core/ui/select/select";
|
||||||
import { CameraFormStore } from "./camera_store";
|
import { CameraFormStore } from "./camera_store";
|
||||||
import { Loader } from "../../../../../core/ui/loader/loader";
|
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { CameraTypes } from "../../../../../core/model/camera_model";
|
import { CameraTypes } from "../../../../../core/model/camera_model";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const CameraForm = observer((props: IDefaultSceneManagerFormProps) => {
|
export const CameraForm = observer((props: IDefaultSceneManagerFormProps) => {
|
||||||
const [store] = React.useState(() => new CameraFormStore(props.store));
|
const [store] = React.useState(() => new CameraFormStore(props.store));
|
||||||
|
|
||||||
|
@ -67,19 +63,13 @@ export const CameraForm = observer((props: IDefaultSceneManagerFormProps) => {
|
||||||
onChange={(text) => store.updateForm({ cameraType: text as CameraTypes })}
|
onChange={(text) => store.updateForm({ cameraType: text as CameraTypes })}
|
||||||
/>
|
/>
|
||||||
<div style={{ height: 10 }} />
|
<div style={{ height: 10 }} />
|
||||||
<CoreButton
|
|
||||||
text="Создать"
|
{store.type !== "preview" ? (
|
||||||
style={{ width: 96 }}
|
<CoreButton text="Создать" style={{ width: 96 }} onClick={() => store.clickNewCamera()} />
|
||||||
onClick={() => {
|
) : null}
|
||||||
store.viewModel.validate().fold(
|
|
||||||
(model) => {
|
|
||||||
props.store.addNewCamera(model);
|
|
||||||
},
|
|
||||||
(error) => message.error(error)
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div style={{ height: 50 }} />
|
<div style={{ height: 50 }} />
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { FormState, CoreError } from "../../../../../core/store/base_store";
|
||||||
import { SceneMangerStore } from "../../scene_manager_store";
|
import { SceneMangerStore } from "../../scene_manager_store";
|
||||||
import { isPreviewMode } from "../scene_manager_forms";
|
import { isPreviewMode } from "../scene_manager_forms";
|
||||||
import { CameraModel } from "../../../../../core/model/camera_model";
|
import { CameraModel } from "../../../../../core/model/camera_model";
|
||||||
|
import { message } from "antd";
|
||||||
|
|
||||||
export class CameraFormStore extends FormState<CameraModel, CoreError> {
|
export class CameraFormStore extends FormState<CameraModel, CoreError> {
|
||||||
viewModel: CameraModel = CameraModel.empty();
|
viewModel: CameraModel = CameraModel.empty();
|
||||||
|
@ -18,6 +19,16 @@ export class CameraFormStore extends FormState<CameraModel, CoreError> {
|
||||||
errorHandingStrategy = (error: CoreError) => {};
|
errorHandingStrategy = (error: CoreError) => {};
|
||||||
updateCameraScene = () =>
|
updateCameraScene = () =>
|
||||||
this.type?.isNotEmptyR().map(() => this.viewModel.toWebGl(this.sceneMangerStore.coreThreeRepository!));
|
this.type?.isNotEmptyR().map(() => this.viewModel.toWebGl(this.sceneMangerStore.coreThreeRepository!));
|
||||||
|
clickNewCamera = () =>
|
||||||
|
this.viewModel.validate().fold(
|
||||||
|
(model) => {
|
||||||
|
this.sceneMangerStore.addNewCamera(model);
|
||||||
|
this.sceneMangerStore.activeFormType = undefined;
|
||||||
|
this.sceneMangerStore.visibleSaveButton()
|
||||||
|
|
||||||
|
},
|
||||||
|
(error) => message.error(error)
|
||||||
|
);
|
||||||
|
|
||||||
init = async (navigate?: NavigateFunction | undefined) => {
|
init = async (navigate?: NavigateFunction | undefined) => {
|
||||||
isPreviewMode(this.sceneMangerStore.activeFormDependency).map(() =>
|
isPreviewMode(this.sceneMangerStore.activeFormDependency).map(() =>
|
||||||
|
|
|
@ -7,11 +7,15 @@ import { CoreInput } from "../../../../../core/ui/input/input";
|
||||||
import { CoreButton } from "../../../../../core/ui/button/button";
|
import { CoreButton } from "../../../../../core/ui/button/button";
|
||||||
import { match } from "ts-pattern";
|
import { match } from "ts-pattern";
|
||||||
import { SpawnPositionTypesForm } from "../../components/spawn_position_types";
|
import { SpawnPositionTypesForm } from "../../components/spawn_position_types";
|
||||||
|
import { CoordsForm } from "../../components/coords_form";
|
||||||
|
|
||||||
export const PointForm = observer((props: IDefaultSceneManagerFormProps) => {
|
export const PointForm = observer((props: IDefaultSceneManagerFormProps) => {
|
||||||
const [store] = React.useState(() => new PointStore(props.store));
|
const [store] = React.useState(() => new PointStore(props.store));
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
store.init();
|
store.init();
|
||||||
|
return () => {
|
||||||
|
store.dispose();
|
||||||
|
};
|
||||||
}, [store]);
|
}, [store]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -21,22 +25,7 @@ export const PointForm = observer((props: IDefaultSceneManagerFormProps) => {
|
||||||
<>
|
<>
|
||||||
<CoreText text="Точка" type={CoreTextType.header} />
|
<CoreText text="Точка" type={CoreTextType.header} />
|
||||||
<CoreText text={store.viewModel.name} type={CoreTextType.medium} />
|
<CoreText text={store.viewModel.name} type={CoreTextType.medium} />
|
||||||
<CoreText text="Позиция" type={CoreTextType.header} />
|
<CoordsForm store={store} update={store.updateWebGl} />
|
||||||
<CoreInput
|
|
||||||
label="X"
|
|
||||||
value={String(store.viewModel.vector3.x)}
|
|
||||||
onChange={(text) => (store.updateForm({ vector3: store.viewModel.vector3.setX(Number(text)) }), store.updateWebGl())}
|
|
||||||
/>
|
|
||||||
<CoreInput
|
|
||||||
label="Y"
|
|
||||||
value={String(store.viewModel.vector3.y)}
|
|
||||||
onChange={(text) => (store.updateForm({ vector3: store.viewModel.vector3.setY(Number(text)) }),store.updateWebGl())}
|
|
||||||
/>
|
|
||||||
<CoreInput
|
|
||||||
label="Z"
|
|
||||||
value={String(store.viewModel.vector3.z)}
|
|
||||||
onChange={(text) => (store.updateForm({ vector3: store.viewModel.vector3.setZ(Number(text)) }), store.updateWebGl())}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
))
|
))
|
||||||
.with(PointStoreType.initNewPoint, () => (
|
.with(PointStoreType.initNewPoint, () => (
|
||||||
|
@ -54,6 +43,11 @@ export const PointForm = observer((props: IDefaultSceneManagerFormProps) => {
|
||||||
<SpawnPositionTypesForm onClick={store.selectSpawnType} />
|
<SpawnPositionTypesForm onClick={store.selectSpawnType} />
|
||||||
</>
|
</>
|
||||||
))
|
))
|
||||||
|
.with(PointStoreType.awaitClick, () => (
|
||||||
|
<>
|
||||||
|
<CoreText type={CoreTextType.medium} text="Ожидание клика мыши" />
|
||||||
|
</>
|
||||||
|
))
|
||||||
.otherwise(() => (
|
.otherwise(() => (
|
||||||
<></>
|
<></>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
import { HttpRepository } from "../../../../../core/repository/http_repository";
|
|
||||||
|
|
||||||
|
|
||||||
export class PointHttpRepository extends HttpRepository {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,7 +1,6 @@
|
||||||
import makeAutoObservable from "mobx-store-inheritance";
|
import makeAutoObservable from "mobx-store-inheritance";
|
||||||
import { NavigateFunction } from "react-router-dom";
|
import { NavigateFunction } from "react-router-dom";
|
||||||
import { PointModel } from "../../../../../core/model/point_model";
|
import { PointModel } from "../../../../../core/model/point_model";
|
||||||
import { PointHttpRepository } from "./point_http_repository";
|
|
||||||
import { FormState, CoreError } from "../../../../../core/store/base_store";
|
import { FormState, CoreError } from "../../../../../core/store/base_store";
|
||||||
import { SpawnPositionTypes } from "../../../../../core/model/spawn_position_types";
|
import { SpawnPositionTypes } from "../../../../../core/model/spawn_position_types";
|
||||||
import { isPreviewMode } from "../scene_manager_forms";
|
import { isPreviewMode } from "../scene_manager_forms";
|
||||||
|
@ -11,22 +10,42 @@ export enum PointStoreType {
|
||||||
makeSceneSolidAndEditPosition = "makeSceneSolidAndEditPosition",
|
makeSceneSolidAndEditPosition = "makeSceneSolidAndEditPosition",
|
||||||
initNewPoint = "initNewPoint",
|
initNewPoint = "initNewPoint",
|
||||||
previewPoint = "previewPoint",
|
previewPoint = "previewPoint",
|
||||||
|
awaitClick = "awaitClick",
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PointStore extends FormState<PointModel, CoreError> {
|
export class PointStore extends FormState<PointModel, CoreError> {
|
||||||
viewModel: PointModel = PointModel.empty();
|
viewModel: PointModel = PointModel.empty();
|
||||||
cameraDeviceHttpRepository: PointHttpRepository = new PointHttpRepository();
|
|
||||||
storeType: PointStoreType = PointStoreType.initNewPoint;
|
storeType: PointStoreType = PointStoreType.initNewPoint;
|
||||||
spawnPositionTypes: SpawnPositionTypes;
|
spawnPositionTypes: SpawnPositionTypes;
|
||||||
sceneMangerStore: SceneMangerStore;
|
sceneMangerStore: SceneMangerStore;
|
||||||
|
listener: Function;
|
||||||
|
|
||||||
constructor(sceneMangerStore: SceneMangerStore) {
|
constructor(sceneMangerStore: SceneMangerStore) {
|
||||||
super();
|
super();
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
this.sceneMangerStore = sceneMangerStore;
|
this.sceneMangerStore = sceneMangerStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clickLister = (event: MouseEvent) =>
|
||||||
|
this.storeType.isEqualR(PointStoreType.awaitClick).map(() =>
|
||||||
|
this.sceneMangerStore!.clickScene(event, this.sceneMangerStore!.canvasOffsetX).map((vector3) => {
|
||||||
|
this.viewModel.vector3 = vector3;
|
||||||
|
this.viewModel.quaternion = [0, 0, 0, 1];
|
||||||
|
this.viewModel.toWebGl(this.sceneMangerStore.coreThreeRepository!);
|
||||||
|
this.sceneMangerStore.activeFormType = undefined;
|
||||||
|
this.sceneMangerStore.sceneItems.push(this.viewModel.toSceneItems(this.sceneMangerStore));
|
||||||
|
this.sceneMangerStore.scene.push(this.viewModel);
|
||||||
|
window.removeEventListener("click", this.clickLister);
|
||||||
|
this.sceneMangerStore.visibleSaveButton();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
selectSpawnType = (type: SpawnPositionTypes) => {
|
selectSpawnType = (type: SpawnPositionTypes) => {
|
||||||
this.spawnPositionTypes = type;
|
this.spawnPositionTypes = type;
|
||||||
|
this.storeType = PointStoreType.awaitClick;
|
||||||
|
setTimeout(() => window.addEventListener("click", this.clickLister), 1000);
|
||||||
};
|
};
|
||||||
|
dispose = () => window.removeEventListener("click", this.clickLister);
|
||||||
updateWebGl = () =>
|
updateWebGl = () =>
|
||||||
this.storeType
|
this.storeType
|
||||||
.isEqualR(PointStoreType.previewPoint)
|
.isEqualR(PointStoreType.previewPoint)
|
||||||
|
|
|
@ -16,6 +16,9 @@ export const RobotForm = observer((props: IDefaultSceneManagerFormProps) => {
|
||||||
const [store] = React.useState(() => new RobotFormStore(props.store));
|
const [store] = React.useState(() => new RobotFormStore(props.store));
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
store.init();
|
store.init();
|
||||||
|
return () => {
|
||||||
|
store.dispose();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
return (
|
return (
|
||||||
<div style={{ overflowY: "scroll", height: "100%" }}>
|
<div style={{ overflowY: "scroll", height: "100%" }}>
|
||||||
|
@ -56,10 +59,7 @@ export const RobotForm = observer((props: IDefaultSceneManagerFormProps) => {
|
||||||
))
|
))
|
||||||
.with(RobotStoreType.previewRobot, () => (
|
.with(RobotStoreType.previewRobot, () => (
|
||||||
<>
|
<>
|
||||||
<CoordsForm store={store} update={() => store.updateScene()} />
|
<CoreText text="Управление соединениями" type={CoreTextType.small} />
|
||||||
|
|
||||||
<div style={{ height: 40 }} />
|
|
||||||
<CoreText text="Управление соединениями" type={CoreTextType.header} />
|
|
||||||
{store.viewModel.jointPosition.map((el, i) => (
|
{store.viewModel.jointPosition.map((el, i) => (
|
||||||
<div>
|
<div>
|
||||||
<CoreInputNumber
|
<CoreInputNumber
|
||||||
|
@ -73,7 +73,7 @@ export const RobotForm = observer((props: IDefaultSceneManagerFormProps) => {
|
||||||
jointPosition: store.viewModel.jointPosition.map((element, index) =>
|
jointPosition: store.viewModel.jointPosition.map((element, index) =>
|
||||||
index.isEqualR(i).fold(
|
index.isEqualR(i).fold(
|
||||||
() => {
|
() => {
|
||||||
element.angel = value;
|
element.angle = value;
|
||||||
return element;
|
return element;
|
||||||
},
|
},
|
||||||
() => element
|
() => element
|
||||||
|
@ -87,6 +87,9 @@ export const RobotForm = observer((props: IDefaultSceneManagerFormProps) => {
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
<div style={{ height: 40 }} />
|
<div style={{ height: 40 }} />
|
||||||
|
<CoordsForm store={store} update={() => store.updateScene()} />
|
||||||
|
<div style={{ height: 40 }} />
|
||||||
|
|
||||||
</>
|
</>
|
||||||
))
|
))
|
||||||
.otherwise(() => (
|
.otherwise(() => (
|
||||||
|
|
|
@ -6,8 +6,6 @@ import { RobotModel } from "../../../../../core/model/robot_model";
|
||||||
import { SceneMangerStore } from "../../scene_manager_store";
|
import { SceneMangerStore } from "../../scene_manager_store";
|
||||||
import { isPreviewMode } from "../scene_manager_forms";
|
import { isPreviewMode } from "../scene_manager_forms";
|
||||||
import { message } from "antd";
|
import { message } from "antd";
|
||||||
import { SceneModelsTypes } from "../../../../../core/model/scene_models_type";
|
|
||||||
import { Vector3 } from "three";
|
|
||||||
|
|
||||||
export enum RobotStoreType {
|
export enum RobotStoreType {
|
||||||
previewRobot = "previewRobot",
|
previewRobot = "previewRobot",
|
||||||
|
@ -28,9 +26,10 @@ export class RobotFormStore extends FormState<RobotModel, CoreError> {
|
||||||
this.viewModel.vector3 = vector3;
|
this.viewModel.vector3 = vector3;
|
||||||
this.viewModel.toWebGl(this.sceneMangerStore.coreThreeRepository!);
|
this.viewModel.toWebGl(this.sceneMangerStore.coreThreeRepository!);
|
||||||
this.sceneMangerStore.activeFormType = undefined;
|
this.sceneMangerStore.activeFormType = undefined;
|
||||||
this.sceneMangerStore.sceneItems.push(this.viewModel.toSceneItems(this.sceneMangerStore))
|
this.sceneMangerStore.sceneItems.push(this.viewModel.toSceneItems(this.sceneMangerStore));
|
||||||
this.sceneMangerStore.scene.push(this.viewModel)
|
this.sceneMangerStore.scene.push(this.viewModel);
|
||||||
window.removeEventListener("click", this.clickLister);
|
window.removeEventListener("click", this.clickLister);
|
||||||
|
this.sceneMangerStore.visibleSaveButton();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -50,7 +49,12 @@ export class RobotFormStore extends FormState<RobotModel, CoreError> {
|
||||||
updateScene = () =>
|
updateScene = () =>
|
||||||
this.storeType
|
this.storeType
|
||||||
.isEqualR(RobotStoreType.previewRobot)
|
.isEqualR(RobotStoreType.previewRobot)
|
||||||
.map(() => this.viewModel.update(this.sceneMangerStore.coreThreeRepository!));
|
.map(
|
||||||
|
() => (
|
||||||
|
this.viewModel.update(this.sceneMangerStore.coreThreeRepository!),
|
||||||
|
this.sceneMangerStore.visibleSaveButton()
|
||||||
|
)
|
||||||
|
);
|
||||||
createNewRobot = () =>
|
createNewRobot = () =>
|
||||||
this.viewModel.isValid().fold(
|
this.viewModel.isValid().fold(
|
||||||
async (s) =>
|
async (s) =>
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { CoreButton } from "../../../../../core/ui/button/button";
|
||||||
import { match } from "ts-pattern";
|
import { match } from "ts-pattern";
|
||||||
import { SpawnPositionTypesForm } from "../../components/spawn_position_types";
|
import { SpawnPositionTypesForm } from "../../components/spawn_position_types";
|
||||||
import { CoreInput } from "../../../../../core/ui/input/input";
|
import { CoreInput } from "../../../../../core/ui/input/input";
|
||||||
|
import { CoordsForm } from "../../components/coords_form";
|
||||||
|
|
||||||
export const SolidBodyForm = observer((props: IDefaultSceneManagerFormProps) => {
|
export const SolidBodyForm = observer((props: IDefaultSceneManagerFormProps) => {
|
||||||
const [store] = React.useState(() => new SolidBodyStore(props.store));
|
const [store] = React.useState(() => new SolidBodyStore(props.store));
|
||||||
|
@ -20,31 +21,8 @@ export const SolidBodyForm = observer((props: IDefaultSceneManagerFormProps) =>
|
||||||
{match(store.solidBodyStoreType)
|
{match(store.solidBodyStoreType)
|
||||||
.with(SolidBodyStoreType.previewSolid, () => (
|
.with(SolidBodyStoreType.previewSolid, () => (
|
||||||
<>
|
<>
|
||||||
<CoreText text={"Твердое тело"} type={CoreTextType.header} />
|
<CoreText text={"Твердое тело"} type={CoreTextType.header} />
|
||||||
<CoreInput
|
<CoordsForm store={store} update={store.updateBodySimulation} />
|
||||||
value={String(store.viewModel.vector3.x)}
|
|
||||||
label="Вектор X"
|
|
||||||
onChange={(text) => (
|
|
||||||
store.updateForm({ vector3: store.viewModel.vector3.setX(Number(text)) }),
|
|
||||||
store.updateBodySimulation()
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<CoreInput
|
|
||||||
value={String(store.viewModel.vector3.x)}
|
|
||||||
label="Вектор Y"
|
|
||||||
onChange={(text) => (
|
|
||||||
store.updateForm({ vector3: store.viewModel.vector3.setY(Number(text)) }),
|
|
||||||
store.updateBodySimulation()
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<CoreInput
|
|
||||||
value={String(store.viewModel.vector3.x)}
|
|
||||||
label="Вектор Z"
|
|
||||||
onChange={(text) => (
|
|
||||||
store.updateForm({ vector3: store.viewModel.vector3.setZ(Number(text)) }),
|
|
||||||
store.updateBodySimulation()
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<CoreText text={"Тип твердого тела: " + store.viewModel.solidType} type={CoreTextType.header} />
|
<CoreText text={"Тип твердого тела: " + store.viewModel.solidType} type={CoreTextType.header} />
|
||||||
</>
|
</>
|
||||||
))
|
))
|
||||||
|
@ -68,11 +46,7 @@ export const SolidBodyForm = observer((props: IDefaultSceneManagerFormProps) =>
|
||||||
))
|
))
|
||||||
.with(SolidBodyStoreType.spawn2DVector, () => (
|
.with(SolidBodyStoreType.spawn2DVector, () => (
|
||||||
<>
|
<>
|
||||||
{props.store.mousePosition ? (
|
<CoreText text={"Выберите точку размещения"} type={CoreTextType.header} />
|
||||||
""
|
|
||||||
) : (
|
|
||||||
<CoreText text={"Выберите точку размещения"} type={CoreTextType.header} />
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
))
|
))
|
||||||
.otherwise(() => (
|
.otherwise(() => (
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { SceneMangerStore } from "../../scene_manager_store";
|
||||||
import { SpawnPositionTypes } from "../../../../../core/model/spawn_position_types";
|
import { SpawnPositionTypes } from "../../../../../core/model/spawn_position_types";
|
||||||
import { isPreviewMode } from "../scene_manager_forms";
|
import { isPreviewMode } from "../scene_manager_forms";
|
||||||
import { SolidModel } from "../../../../../core/model/solid_model";
|
import { SolidModel } from "../../../../../core/model/solid_model";
|
||||||
import { SceneModelsTypes } from "../../../../../core/model/scene_models_type";
|
|
||||||
export enum SolidBodyStoreType {
|
export enum SolidBodyStoreType {
|
||||||
selectBody = "selectBody",
|
selectBody = "selectBody",
|
||||||
selectSpawnPositionType = "selectSpawnPositionType",
|
selectSpawnPositionType = "selectSpawnPositionType",
|
||||||
|
@ -52,20 +52,27 @@ export class SolidBodyStore extends FormState<SolidModel, CoreError> {
|
||||||
};
|
};
|
||||||
errorHandingStrategy = (error: CoreError) => {};
|
errorHandingStrategy = (error: CoreError) => {};
|
||||||
|
|
||||||
dispose = () => {};
|
dispose = () => {
|
||||||
selectSpawnType = (type: string) => {
|
window.removeEventListener("click", this.clickLister);
|
||||||
this.spawnType = type;
|
|
||||||
this.solidBodyStoreType = SolidBodyStoreType.spawn2DVector;
|
|
||||||
this.sceneMangerStore.mousePositionAwait = true;
|
|
||||||
this.sceneMangerStore.spawnHelper = {
|
|
||||||
url: this.selectBody.daeUrl,
|
|
||||||
name: this.selectBody.name,
|
|
||||||
spawn: SceneModelsTypes.SOLID,
|
|
||||||
isFinished: false,
|
|
||||||
type: this.spawnType,
|
|
||||||
};
|
|
||||||
this.sceneMangerStore.activeFormType = undefined;
|
|
||||||
};
|
};
|
||||||
|
selectSpawnType = () => {
|
||||||
|
this.solidBodyStoreType = SolidBodyStoreType.spawn2DVector;
|
||||||
|
|
||||||
|
setTimeout(() => window.addEventListener("click", this.clickLister), 1000);
|
||||||
|
};
|
||||||
|
clickLister = (event: MouseEvent) =>
|
||||||
|
this.solidBodyStoreType.isEqualR(SolidBodyStoreType.spawn2DVector).map(() =>
|
||||||
|
this.sceneMangerStore!.clickScene(event, this.sceneMangerStore!.canvasOffsetX).map((vector3) => {
|
||||||
|
this.viewModel.vector3 = vector3;
|
||||||
|
this.viewModel.spawnType = "BoundBox";
|
||||||
|
this.viewModel.toWebGl(this.sceneMangerStore.coreThreeRepository!);
|
||||||
|
this.sceneMangerStore.sceneItems.push(this.viewModel.toSceneItems());
|
||||||
|
this.sceneMangerStore.scene.push(this.viewModel);
|
||||||
|
window.removeEventListener("click", this.clickLister);
|
||||||
|
this.sceneMangerStore.activeFormType = undefined;
|
||||||
|
this.sceneMangerStore.visibleSaveButton()
|
||||||
|
})
|
||||||
|
);
|
||||||
updateBodySimulation = () =>
|
updateBodySimulation = () =>
|
||||||
this.solidBodyStoreType
|
this.solidBodyStoreType
|
||||||
.isEqualR(SolidBodyStoreType.previewSolid)
|
.isEqualR(SolidBodyStoreType.previewSolid)
|
||||||
|
@ -73,5 +80,6 @@ export class SolidBodyStore extends FormState<SolidModel, CoreError> {
|
||||||
clickSelectBody = (el: Parts) => {
|
clickSelectBody = (el: Parts) => {
|
||||||
this.selectBody = el;
|
this.selectBody = el;
|
||||||
this.solidBodyStoreType = SolidBodyStoreType.selectSpawnPositionType;
|
this.solidBodyStoreType = SolidBodyStoreType.selectSpawnPositionType;
|
||||||
|
this.viewModel = this.viewModel.fromParts(el);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
import { HttpRepository } from "../../../../../core/repository/http_repository";
|
|
||||||
|
|
||||||
export class ZoneHttpRepository extends HttpRepository {}
|
|
|
@ -1,7 +1,7 @@
|
||||||
import makeAutoObservable from "mobx-store-inheritance";
|
import makeAutoObservable from "mobx-store-inheritance";
|
||||||
import { NavigateFunction } from "react-router-dom";
|
import { NavigateFunction } from "react-router-dom";
|
||||||
import { ZoneModel } from "../../../../../core/model/zone_model";
|
import { ZoneModel } from "../../../../../core/model/zone_model";
|
||||||
import { ZoneHttpRepository } from "./zone_http_repository";
|
|
||||||
import { FormState, CoreError } from "../../../../../core/store/base_store";
|
import { FormState, CoreError } from "../../../../../core/store/base_store";
|
||||||
import { isPreviewMode } from "../scene_manager_forms";
|
import { isPreviewMode } from "../scene_manager_forms";
|
||||||
import { SceneMangerStore } from "../../scene_manager_store";
|
import { SceneMangerStore } from "../../scene_manager_store";
|
||||||
|
@ -9,7 +9,6 @@ export enum ZoneStoreType {
|
||||||
preview = "preview",
|
preview = "preview",
|
||||||
}
|
}
|
||||||
export class ZoneStore extends FormState<ZoneModel, CoreError> {
|
export class ZoneStore extends FormState<ZoneModel, CoreError> {
|
||||||
|
|
||||||
constructor(sceneMangerStore: SceneMangerStore) {
|
constructor(sceneMangerStore: SceneMangerStore) {
|
||||||
super();
|
super();
|
||||||
this.sceneMangerStore = sceneMangerStore;
|
this.sceneMangerStore = sceneMangerStore;
|
||||||
|
@ -18,9 +17,8 @@ export class ZoneStore extends FormState<ZoneModel, CoreError> {
|
||||||
storeType: ZoneStoreType;
|
storeType: ZoneStoreType;
|
||||||
sceneMangerStore: SceneMangerStore;
|
sceneMangerStore: SceneMangerStore;
|
||||||
viewModel: ZoneModel = ZoneModel.empty();
|
viewModel: ZoneModel = ZoneModel.empty();
|
||||||
cameraDeviceHttpRepository: ZoneHttpRepository = new ZoneHttpRepository();
|
errorHandingStrategy = (_error: CoreError) => {};
|
||||||
errorHandingStrategy = (error: CoreError) => {};
|
init = async (_navigate?: NavigateFunction | undefined) => {
|
||||||
init = async (navigate?: NavigateFunction | undefined) => {
|
|
||||||
isPreviewMode(this.sceneMangerStore.activeFormDependency).map(() =>
|
isPreviewMode(this.sceneMangerStore.activeFormDependency).map(() =>
|
||||||
this.sceneMangerStore.scene
|
this.sceneMangerStore.scene
|
||||||
.rFind<ZoneModel>((el) => el.name.isEqual(this.sceneMangerStore.selectedItemName ?? ""))
|
.rFind<ZoneModel>((el) => el.name.isEqual(this.sceneMangerStore.selectedItemName ?? ""))
|
||||||
|
@ -38,5 +36,8 @@ export class ZoneStore extends FormState<ZoneModel, CoreError> {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
updateWebGl = () => this.storeType.isEqualR(ZoneStoreType.preview).map(() => this.sceneMangerStore.coreThreeRepository!.updateInstance(this.viewModel))
|
updateWebGl = () =>
|
||||||
|
this.storeType
|
||||||
|
.isEqualR(ZoneStoreType.preview)
|
||||||
|
.map(() => this.sceneMangerStore.coreThreeRepository!.updateInstance(this.viewModel));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import makeAutoObservable from "mobx-store-inheritance";
|
import makeAutoObservable from "mobx-store-inheritance";
|
||||||
import { Object3D, Object3DEventMap, Vector2, Vector3 } from "three";
|
import { Object3D, Vector2, Vector3 } from "three";
|
||||||
import { message } from "antd";
|
import { message } from "antd";
|
||||||
import { CoreThreeRepository } from "../../../core/repository/core_three_repository";
|
import { CoreThreeRepository } from "../../../core/repository/core_three_repository";
|
||||||
import { HttpError } from "../../../core/repository/http_repository";
|
import { HttpError } from "../../../core/repository/http_repository";
|
||||||
|
@ -43,8 +43,11 @@ export interface SceneItems {
|
||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
icon: string;
|
icon: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpError> {
|
export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpError> {
|
||||||
activeFormType?: string;
|
activeFormType?: string;
|
||||||
|
activeSceneId?: string;
|
||||||
selectedItemName?: string;
|
selectedItemName?: string;
|
||||||
activeFormDependency: Object = {};
|
activeFormDependency: Object = {};
|
||||||
viewModel: SceneViewModel = SceneViewModel.empty();
|
viewModel: SceneViewModel = SceneViewModel.empty();
|
||||||
|
@ -60,7 +63,6 @@ export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpErro
|
||||||
scenes: SceneModel[] = [];
|
scenes: SceneModel[] = [];
|
||||||
storeMode: StoreMode;
|
storeMode: StoreMode;
|
||||||
canvasRef?: HTMLCanvasElement;
|
canvasRef?: HTMLCanvasElement;
|
||||||
mousePositionAwait: boolean = false;
|
|
||||||
mousePosition?: Vector2;
|
mousePosition?: Vector2;
|
||||||
spawnHelper?: ISpawnHelper;
|
spawnHelper?: ISpawnHelper;
|
||||||
selectSceneObject?: Object;
|
selectSceneObject?: Object;
|
||||||
|
@ -87,6 +89,7 @@ export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpErro
|
||||||
{ name: "Точки захвата", fn: () => this.createNewForm(SceneManagerForms.capturePoints, true) },
|
{ name: "Точки захвата", fn: () => this.createNewForm(SceneManagerForms.capturePoints, true) },
|
||||||
];
|
];
|
||||||
canvasOffsetX?: number;
|
canvasOffsetX?: number;
|
||||||
|
sceneName?: string;
|
||||||
constructor() {
|
constructor() {
|
||||||
super(DrawersSceneManager);
|
super(DrawersSceneManager);
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
|
@ -94,9 +97,8 @@ export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpErro
|
||||||
this.sceneHttpRepository = new SceneHttpRepository();
|
this.sceneHttpRepository = new SceneHttpRepository();
|
||||||
this.sceneMode = SceneMode.Select;
|
this.sceneMode = SceneMode.Select;
|
||||||
}
|
}
|
||||||
sceneSave = () => {
|
sceneSave = () => this.sceneHttpRepository.editScene(SceneAsset.newScene(this.scene, this.sceneName ?? ""));
|
||||||
console.log(JSON.stringify(this.scene));
|
|
||||||
};
|
|
||||||
iconToSceneManagerForm = (icon: string): SceneManagerForms => {
|
iconToSceneManagerForm = (icon: string): SceneManagerForms => {
|
||||||
if (icon.isEqual("Camera")) {
|
if (icon.isEqual("Camera")) {
|
||||||
this.activeFormDependency = {
|
this.activeFormDependency = {
|
||||||
|
@ -153,7 +155,6 @@ export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpErro
|
||||||
});
|
});
|
||||||
this.sceneMode = mode;
|
this.sceneMode = mode;
|
||||||
this.coreThreeRepository?.setTransformMode(this.sceneMode);
|
this.coreThreeRepository?.setTransformMode(this.sceneMode);
|
||||||
this.sceneModeWatcher();
|
|
||||||
};
|
};
|
||||||
createNewForm = (formType: SceneManagerForms | undefined, isNeedClearDependency?: boolean) => {
|
createNewForm = (formType: SceneManagerForms | undefined, isNeedClearDependency?: boolean) => {
|
||||||
this.activeFormDependency = Object.assign(this.activeFormDependency, { store: this });
|
this.activeFormDependency = Object.assign(this.activeFormDependency, { store: this });
|
||||||
|
@ -183,31 +184,20 @@ export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpErro
|
||||||
|
|
||||||
addNewCamera = (model: CameraModel) => {
|
addNewCamera = (model: CameraModel) => {
|
||||||
model.vector3 = this.coreThreeRepository!.camera.position;
|
model.vector3 = this.coreThreeRepository!.camera.position;
|
||||||
// model.quaternion = this.coreThreeRepository!.camera.quaternion;
|
model.quaternion = this.coreThreeRepository!.camera.quaternion.toArray();
|
||||||
|
model.aspect = this.coreThreeRepository!.camera.aspect;
|
||||||
this.sceneItems.push({ name: model.name, icon: "Camera", fn: () => {}, isSelected: false });
|
this.sceneItems.push({ name: model.name, icon: "Camera", fn: () => {}, isSelected: false });
|
||||||
this.scene.push(model);
|
this.scene.push(model);
|
||||||
this.coreThreeRepository?.addSceneCamera(model);
|
model.toWebGl(this.coreThreeRepository!);
|
||||||
this.visibleSaveButton();
|
this.visibleSaveButton();
|
||||||
};
|
};
|
||||||
|
|
||||||
loaderWatcher = () => {};
|
|
||||||
|
|
||||||
loadSceneRobossemblerAsset = (name: string) => {
|
|
||||||
try {
|
|
||||||
// this.coreThreeRepository?.loader(assetPath, this.loaderWatcher, name);
|
|
||||||
// this.visibleSaveButton();
|
|
||||||
} catch (error) {
|
|
||||||
message.error(String(error));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
hiddenMenu = () => (this.isSceneMenuShow = false);
|
hiddenMenu = () => (this.isSceneMenuShow = false);
|
||||||
|
|
||||||
sceneModeWatcher() {}
|
|
||||||
|
|
||||||
init = async () => {};
|
init = async () => {};
|
||||||
initParam = (id: string | undefined) => {
|
initParam = (id: string | undefined) => {
|
||||||
if (id) {
|
if (id) {
|
||||||
|
this.activeSceneId = id;
|
||||||
this.storeMode = StoreMode.sceneInstance;
|
this.storeMode = StoreMode.sceneInstance;
|
||||||
} else {
|
} else {
|
||||||
this.storeMode = StoreMode.allScenes;
|
this.storeMode = StoreMode.allScenes;
|
||||||
|
@ -220,13 +210,9 @@ export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpErro
|
||||||
loadScene = (canvasRef: HTMLCanvasElement) => {
|
loadScene = (canvasRef: HTMLCanvasElement) => {
|
||||||
this.canvasRef = canvasRef;
|
this.canvasRef = canvasRef;
|
||||||
this.storeMode.isEqualR(StoreMode.sceneInstance).map(() => this.loadWebGl(canvasRef));
|
this.storeMode.isEqualR(StoreMode.sceneInstance).map(() => this.loadWebGl(canvasRef));
|
||||||
// await this.mapOk<RobossemblerAssets>("robossemblerAssets", this.sceneHttpRepository.getRobossemblerAssets());
|
|
||||||
// if (this.robossemblerAssets) {
|
|
||||||
// this.coreThreeRepository?.loadInstances(this.robossemblerAssets);
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
loadWebGl(canvasRef: HTMLCanvasElement): void {
|
loadWebGl = async (canvasRef: HTMLCanvasElement): Promise<void> => {
|
||||||
this.coreThreeRepository = new CoreThreeRepository(canvasRef as HTMLCanvasElement, this.watcherSceneEditorObject);
|
this.coreThreeRepository = new CoreThreeRepository(canvasRef as HTMLCanvasElement, this.watcherSceneEditorObject);
|
||||||
|
|
||||||
this.coreThreeRepository.render();
|
this.coreThreeRepository.render();
|
||||||
|
@ -234,18 +220,16 @@ export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpErro
|
||||||
this.canvasOffsetX = canvasRef.getBoundingClientRect().x;
|
this.canvasOffsetX = canvasRef.getBoundingClientRect().x;
|
||||||
canvasRef.addEventListener("click", (event) => this.clickLister(event, canvasRef.getBoundingClientRect().x));
|
canvasRef.addEventListener("click", (event) => this.clickLister(event, canvasRef.getBoundingClientRect().x));
|
||||||
|
|
||||||
const sceneAssets = this.sceneHttpRepository.getScene();
|
(await this.sceneHttpRepository.getSceneAsset(this.activeSceneId ?? "")).fold(
|
||||||
this.coreThreeRepository?.loadScene(sceneAssets);
|
(sceneAssets) => {
|
||||||
this.sceneItems = sceneAssets.scene.map((el) => {
|
this.sceneName = sceneAssets.name;
|
||||||
return {
|
this.coreThreeRepository?.loadScene(sceneAssets);
|
||||||
fn: () => {},
|
this.sceneItems = sceneAssets.toSceneItems();
|
||||||
name: el.name,
|
this.scene = sceneAssets.scene;
|
||||||
icon: el.icon,
|
},
|
||||||
isSelected: false,
|
() => {}
|
||||||
};
|
);
|
||||||
});
|
};
|
||||||
this.scene = sceneAssets.scene;
|
|
||||||
}
|
|
||||||
clickScene = (event: MouseEvent, offset: number = 0): Result<void, Vector3> => {
|
clickScene = (event: MouseEvent, offset: number = 0): Result<void, Vector3> => {
|
||||||
const vector = new Vector2();
|
const vector = new Vector2();
|
||||||
const boundingRect = this.canvasRef!.getBoundingClientRect();
|
const boundingRect = this.canvasRef!.getBoundingClientRect();
|
||||||
|
@ -260,25 +244,7 @@ export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpErro
|
||||||
|
|
||||||
vector.x = ((event.clientX - offset) / boundingRect.width) * 2 - 1;
|
vector.x = ((event.clientX - offset) / boundingRect.width) * 2 - 1;
|
||||||
vector.y = -(event.clientY / boundingRect.height) * 2 + 1;
|
vector.y = -(event.clientY / boundingRect.height) * 2 + 1;
|
||||||
if (this.mousePositionAwait && this.spawnHelper) {
|
|
||||||
this.mousePositionAwait = false;
|
|
||||||
this.mousePosition = vector;
|
|
||||||
this.coreThreeRepository?.setRayCastAndGetFirstObjectAndPointToObject(vector).map((v3) => {
|
|
||||||
this.coreThreeRepository?.solidSpawn(
|
|
||||||
this.spawnHelper as ISpawnHelper,
|
|
||||||
(obj: Object3D<Object3DEventMap> | undefined) => {
|
|
||||||
this.sceneItems.push({
|
|
||||||
name: String(this.spawnHelper?.name),
|
|
||||||
icon: "Solid",
|
|
||||||
isSelected: false,
|
|
||||||
fn: () => this.createNewForm(SceneManagerForms.solidBody),
|
|
||||||
});
|
|
||||||
this.visibleSaveButton();
|
|
||||||
},
|
|
||||||
v3
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (this.sceneMode.isEqual(SceneMode.Select)) {
|
if (this.sceneMode.isEqual(SceneMode.Select)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,9 @@ import { configure } from "mobx";
|
||||||
configure({
|
configure({
|
||||||
enforceActions: "never",
|
enforceActions: "never",
|
||||||
});
|
});
|
||||||
|
|
||||||
extensions();
|
extensions();
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
|
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
|
||||||
|
|
||||||
root.render(
|
root.render(
|
||||||
|
|
|
@ -21,6 +21,5 @@
|
||||||
"strictPropertyInitialization": false,
|
"strictPropertyInitialization": false,
|
||||||
"sourceMap": true
|
"sourceMap": true
|
||||||
},
|
},
|
||||||
"types": ["babylonjs", "babylonjs-loaders"],
|
|
||||||
"include": ["src"]
|
"include": ["src"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -540,3 +540,6 @@ if __name__ == "__main__":
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
train_Dope_i(args.path, args.name, args.datasetName, args.outpath, args.epoch, args.pretrain)
|
train_Dope_i(args.path, args.name, args.datasetName, args.outpath, args.epoch, args.pretrain)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue