diff --git a/scene_builder.json b/scene_builder.json index d140240..1a0c563 100644 --- a/scene_builder.json +++ b/scene_builder.json @@ -14,7 +14,7 @@ "w": 4 }, "name": "ARM0", - "nDOF": 1, + "nDOF": 6, "toolType": "RBS_GRIPPER", "jointPosition": [ 1.1, diff --git a/server/src/core/controllers/http_controller.ts b/server/src/core/controllers/http_controller.ts index 1ee352b..5b5832d 100644 --- a/server/src/core/controllers/http_controller.ts +++ b/server/src/core/controllers/http_controller.ts @@ -34,11 +34,11 @@ export abstract class CallbackStrategyWithFilesUploads { abstract call(files: File[]): ResponseBase; } -interface ISubSetFeatureRouter { +interface ISubSetFeatureRouter { method: HttpMethodType; subUrl: string; fn: - | CallbackStrategyWithValidationModel + | CallbackStrategyWithValidationModel | CallbackStrategyWithEmpty | CallbackStrategyWithIdQuery | CallBackStrategyWithQueryPage @@ -179,7 +179,7 @@ export class CoreHttpController implements ICoreHttpController { router: this.router, }; } - public put(usecase: CallbackStrategyWithValidationModel) { + public put(usecase: any) { this.routes["PUT"] = usecase; } public delete(usecase: CallbackStrategyWithValidationModel) { diff --git a/server/src/core/models/static_files.ts b/server/src/core/models/static_files.ts index c60ee6a..ea87521 100644 --- a/server/src/core/models/static_files.ts +++ b/server/src/core/models/static_files.ts @@ -2,5 +2,7 @@ export enum StaticFiles { robossembler_assets = "robossembler_assets.json", assets = "/assets/assets.json", parts = '/assets/parts.json', - robots = '/robots/' + robots = '/robots/', + scenes = '/scenes/', + behaviorTrees = 'behavior_trees' } diff --git a/server/src/features/behavior_trees/domain/get_bt_skills_templates_usecase.ts b/server/src/features/behavior_trees/domain/get_bt_skills_templates_usecase.ts index 558f95f..eb7f3ce 100644 --- a/server/src/features/behavior_trees/domain/get_bt_skills_templates_usecase.ts +++ b/server/src/features/behavior_trees/domain/get_bt_skills_templates_usecase.ts @@ -5,6 +5,35 @@ export class GetBehaviorTreeSkillsTemplatesUseCase extends CallbackStrategyWithE call = async (): ResponseBase => { return Result.ok({ 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" }, Module: { name: "PoseEstimation", description: "Pose Estimation skill with DOPE" }, @@ -20,12 +49,12 @@ export class GetBehaviorTreeSkillsTemplatesUseCase extends CallbackStrategyWithE }, { type: "camera", - dependency: {} + dependency: {}, }, { type: "topic", - dependency: {} - } + dependency: {}, + }, ], result: ["POSE"], }, @@ -46,28 +75,6 @@ export class GetBehaviorTreeSkillsTemplatesUseCase extends CallbackStrategyWithE { 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: [] - } - ], }); }; diff --git a/server/src/features/behavior_trees/models/behavior_tree_database_model.ts b/server/src/features/behavior_trees/models/behavior_tree_database_model.ts index f44d0f8..8297b58 100644 --- a/server/src/features/behavior_trees/models/behavior_tree_database_model.ts +++ b/server/src/features/behavior_trees/models/behavior_tree_database_model.ts @@ -12,6 +12,10 @@ export const BehaviorTreeSchema = new Schema({ name: { type: String, }, + scene: { + type: Schema.Types.Mixed, + default: [], + }, local_path: { type: String, }, @@ -29,9 +33,8 @@ export const BehaviorTreeSchema = new Schema({ skills: { type: Schema.Types.Mixed, }, - scene: { - type: Array, - default: null, + sceneId: { + type: String, }, project: { type: Schema.Types.ObjectId, diff --git a/server/src/features/scene/create_new_scene_scenario.ts b/server/src/features/scene/create_new_scene_scenario.ts new file mode 100644 index 0000000..bcc8351 --- /dev/null +++ b/server/src/features/scene/create_new_scene_scenario.ts @@ -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 { + validationModel: SceneModel = SceneModel; + + call = async (model: SceneModel): ResponseBase => + ( + await new SearchManyDataBaseModelUseCase(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")) + ); + }); +} diff --git a/server/src/features/scene/edit_scene_scenario.ts b/server/src/features/scene/edit_scene_scenario.ts new file mode 100644 index 0000000..862cbdf --- /dev/null +++ b/server/src/features/scene/edit_scene_scenario.ts @@ -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 { + validationModel: SceneValidationModel; + call = async (model: SceneValidationModel): ResponseBase => + ( + await new SearchManyDataBaseModelUseCase(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")); + }); +} diff --git a/server/src/features/scene/read_scene_scenario.ts b/server/src/features/scene/read_scene_scenario.ts new file mode 100644 index 0000000..1d70060 --- /dev/null +++ b/server/src/features/scene/read_scene_scenario.ts @@ -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(SceneDBModel).call(id)).map(async (model) => + ( + await new SearchManyDataBaseModelUseCase(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) + ); + }) + ); +} diff --git a/server/src/features/scene/scene_presentation.ts b/server/src/features/scene/scene_presentation.ts index e25d0b9..a885669 100644 --- a/server/src/features/scene/scene_presentation.ts +++ b/server/src/features/scene/scene_presentation.ts @@ -1,5 +1,11 @@ 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 { EditSceneScenario } from "./edit_scene_scenario"; +import { ReadSceneScenario } from "./read_scene_scenario"; import { SceneDBModel } from "./scene_database_model"; import { SceneValidationModel } from "./scene_validation_model"; @@ -10,10 +16,17 @@ export class ScenePresentation extends CrudController - + - + - robossembler: pipeline + Robossembler diff --git a/ui/public/logo.ico b/ui/public/logo.ico new file mode 100644 index 0000000..23f6a83 Binary files /dev/null and b/ui/public/logo.ico differ diff --git a/ui/public/logo.png b/ui/public/logo.png new file mode 100644 index 0000000..d049b1e Binary files /dev/null and b/ui/public/logo.png differ diff --git a/ui/public/logo192.png b/ui/public/logo192.png deleted file mode 100644 index fc44b0a..0000000 Binary files a/ui/public/logo192.png and /dev/null differ diff --git a/ui/public/logo512.png b/ui/public/logo512.png deleted file mode 100644 index a4e47a6..0000000 Binary files a/ui/public/logo512.png and /dev/null differ diff --git a/ui/src/core/extensions/object.ts b/ui/src/core/extensions/object.ts index acca8fd..69317fb 100644 --- a/ui/src/core/extensions/object.ts +++ b/ui/src/core/extensions/object.ts @@ -1,7 +1,9 @@ -/* eslint-disable no-extend-native */ - export const ObjectExtensionsIsKeyExists = (obj: any, keys: string[]): boolean => { return true; }; - -// {"objectThatSticksName":"cube2","objectThatSticksNamePoints":[{"x":25,"y":4.987889622413917,"z":10.504078531217838}],"objectsToWhichItSticksName":"cube1","objectsToWhichItSticksPoints":[{"x":5,"y":3.0783236330074963,"z":1.1333166084347885}]} +export const ObjectIsNotEmpty = (obj: Object | undefined) => { + if (obj === undefined) { + return false; + } + return Object.keys(obj).length !== 0; +}; diff --git a/ui/src/core/hook/key_listner.tsx b/ui/src/core/hook/key_listner.tsx deleted file mode 100644 index 7c7bb60..0000000 --- a/ui/src/core/hook/key_listner.tsx +++ /dev/null @@ -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 []; -}; diff --git a/ui/src/core/model/camera_model.ts b/ui/src/core/model/camera_model.ts index 4b6bebc..01b0e99 100644 --- a/ui/src/core/model/camera_model.ts +++ b/ui/src/core/model/camera_model.ts @@ -9,6 +9,7 @@ export enum CameraTypes { } export class CameraModel implements Instance { type = SceneModelsTypes.CAMERA; + jointType = 'fixed'; constructor( public quaternion: number[], public vector3: Vector3, diff --git a/ui/src/core/model/core_vector3.ts b/ui/src/core/model/core_vector3.ts deleted file mode 100644 index c6e2b08..0000000 --- a/ui/src/core/model/core_vector3.ts +++ /dev/null @@ -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)); - } -} diff --git a/ui/src/core/model/database_model.ts b/ui/src/core/model/database_model.ts index d2e7f7a..b69b6ca 100644 --- a/ui/src/core/model/database_model.ts +++ b/ui/src/core/model/database_model.ts @@ -1,3 +1,3 @@ -export interface DatabaseModel { +export interface DatabaseModelId { _id?: string; } diff --git a/ui/src/core/model/point_model.ts b/ui/src/core/model/point_model.ts index 458df1a..c77e71f 100644 --- a/ui/src/core/model/point_model.ts +++ b/ui/src/core/model/point_model.ts @@ -4,6 +4,8 @@ import { SceneModelsTypes } from "./scene_models_type"; import { Instance } from "./scene_asset"; import { CoreThreeRepository } from "../repository/core_three_repository"; 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 { type = SceneModelsTypes.POINT; @@ -11,7 +13,7 @@ export class PointModel implements Instance { @Type(() => Vector3) vector3: Vector3; color: string = "#E91E63"; - size: number = 0.5; + size: number = 0.01; quaternion: number[]; icon: string = "Point"; @@ -25,10 +27,30 @@ export class PointModel implements Instance { this.color, 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 { return Result.ok(); } + static empty() { return new PointModel(); } diff --git a/ui/src/core/model/robot_model.ts b/ui/src/core/model/robot_model.ts index 27c9c0d..41960fd 100644 --- a/ui/src/core/model/robot_model.ts +++ b/ui/src/core/model/robot_model.ts @@ -16,7 +16,7 @@ interface RobotJoint { lower: Number; upper: Number; }; - angel: Number; + angle: Number; name: string; } @@ -50,24 +50,23 @@ export class RobotModel implements Instance { icon: string = "Robot"; toSceneItems = (sceneMangerStore: SceneMangerStore): SceneItems => { return { - fn: () => { }, + fn: () => {}, name: this.name, isSelected: false, icon: "Robot", }; }; toWebGl = (coreThreeRepository: CoreThreeRepository) => { - console.log(JSON.stringify(this)); coreThreeRepository.loadUrdfRobot(this); }; - update(coreThreeRepository: CoreThreeRepository): any { + update = (coreThreeRepository: CoreThreeRepository) => { const robot = coreThreeRepository.scene.getObjectByName(this.name) as URDFRobot; robot.position.copy(this.vector3); robot.quaternion.copy(new Quaternion().fromArray(this.quaternion)); this.jointPosition.forEach((el) => { - robot.setJointValue(el.name, el.angel); + robot.setJointValue(el.name, el.angle); }); - } + }; isValid(): Result { return Result.ok(this); } diff --git a/ui/src/core/model/scene_asset.ts b/ui/src/core/model/scene_asset.ts index e8bbea6..0a87c1e 100644 --- a/ui/src/core/model/scene_asset.ts +++ b/ui/src/core/model/scene_asset.ts @@ -9,8 +9,10 @@ import { ZoneModel } from "./zone_model"; import { CoreThreeRepository } from "../repository/core_three_repository"; import { LightModel } from "./light_model"; import { Vector3 } from "three"; +import { SceneItems } from "../../features/scene_manager/presentation/scene_manager_store"; export abstract class Instance { + type: string; abstract icon: string; @Type(() => Vector3) vector3: Vector3; @@ -21,6 +23,7 @@ export abstract class Instance { } export class SceneAsset { + name: string; @IsArray() @Type(() => Instance, { discriminator: { @@ -37,4 +40,27 @@ export class SceneAsset { keepDiscriminatorProperty: true, }) 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 = (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; + }; } diff --git a/ui/src/core/model/skill_model.ts b/ui/src/core/model/skill_model.ts index 8056bce..394dfef 100644 --- a/ui/src/core/model/skill_model.ts +++ b/ui/src/core/model/skill_model.ts @@ -198,7 +198,7 @@ export class SkillModel implements ISkill { } export class SkillDependency implements IDependency { - constructor(public skills: ISkillDependency[]) { } + constructor(public skills: ISkillDependency[]) {} static empty() { return new SkillDependency([]); } @@ -320,7 +320,7 @@ export class Skills { if (skill.sid?.isEqual(sid)) { skill.BTAction.map((action) => { action.param.map((param) => { - if (param.type.isEqual(skillType)) { + if (param.type.isEqualR(skillType)) { acc.push(param.dependency); } return param; diff --git a/ui/src/core/model/solid_model.ts b/ui/src/core/model/solid_model.ts index e9d54de..6a94874 100644 --- a/ui/src/core/model/solid_model.ts +++ b/ui/src/core/model/solid_model.ts @@ -1,26 +1,68 @@ -import { Quaternion, Scene, Vector3 } from "three"; +import { Object3D, Object3DEventMap, Quaternion, Vector3 } from "three"; import { SceneModelsTypes } from "./scene_models_type"; import { Instance } from "./scene_asset"; import { CoreThreeRepository } from "../repository/core_three_repository"; 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 { + icon: string = "Solid"; type = SceneModelsTypes.SOLID; @Type(() => Vector3) public vector3: Vector3; constructor( - vector3:Vector3, + vector3: Vector3, public quaternion: number[], public name: string, public solidType: 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) - icon: string = "Solid"; - toWebGl = (coreThreeRepository: CoreThreeRepository) => coreThreeRepository.loader(this.mesh, () => {}, this.name); + toSceneItems = (): SceneItems => { + return { + 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; + 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), [], "", "", "", "", ""); } diff --git a/ui/src/core/model/trigger_model.ts b/ui/src/core/model/trigger_model.ts index 5ea29e5..277bf7e 100644 --- a/ui/src/core/model/trigger_model.ts +++ b/ui/src/core/model/trigger_model.ts @@ -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; description: string; value: string[]; diff --git a/ui/src/core/repository/babylon_repository.ts b/ui/src/core/repository/babylon_repository.ts deleted file mode 100644 index f156a9a..0000000 --- a/ui/src/core/repository/babylon_repository.ts +++ /dev/null @@ -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) => { -// }); - -// } -// } \ No newline at end of file diff --git a/ui/src/core/repository/core_three_repository.ts b/ui/src/core/repository/core_three_repository.ts index 7fa3b2d..1d81c26 100644 --- a/ui/src/core/repository/core_three_repository.ts +++ b/ui/src/core/repository/core_three_repository.ts @@ -34,7 +34,6 @@ import { TransformControls } from "three/examples/jsm/controls/TransformControls import { SceneMode } from "../../features/scene_manager/model/scene_view"; import { UrdfTransforms, coordsToQuaternion } from "../../features/simulations/tranforms_model"; import { ISpawnHelper, SceneItems } from "../../features/scene_manager/presentation/scene_manager_store"; -import { CameraModel } from "../model/camera_model"; import { SolidModel } from "../model/solid_model"; import { Instance, SceneAsset } from "../model/scene_asset"; import { ZoneModel } from "../model/zone_model"; @@ -64,7 +63,6 @@ interface IEmissiveCache { type SceneFrames = { [K in string]: URDFLink }; export class CoreThreeRepository extends TypedEvent { - scene = new Scene(); camera: PerspectiveCamera; webGlRender: WebGLRenderer; @@ -190,14 +188,18 @@ export class CoreThreeRepository extends TypedEvent { this.urdfLoader.load(robotModel.httpUrl, (robot) => { robot.userData[UserData.selectedObject] = true; 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)); - // robot.setJointValue("ee_link_joint", 4); + if (robotModel.jointPosition.isNotEmpty()) { + robotModel.jointPosition.forEach((el) => { + robot.setJointValue(el.name, el.angle); + }); + } if (robotModel.jointPosition.isEmpty()) { Object.entries(robot.joints).forEach(([name, uRDFJoint]) => { if (uRDFJoint.jointType !== "fixed") { robotModel.jointPosition.push({ - angel: uRDFJoint.angle, + angle: uRDFJoint.angle, limit: { lower: uRDFJoint.limit.lower, upper: uRDFJoint.limit.upper, @@ -208,8 +210,6 @@ export class CoreThreeRepository extends TypedEvent { }); } - // Object.entries(robot.joints).forEach(([k, v]) => robot.setJointValue(k, 1)); - this.scene.add(robot); // @ts-expect-error @@ -229,21 +229,6 @@ export class CoreThreeRepository extends TypedEvent { this.sceneFrame = robot.frames; }); - solidSpawn = ( - solidSpawn: ISpawnHelper, - loadCallback?: (obj: Object3D | 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) { this.loader( path, @@ -271,8 +256,6 @@ export class CoreThreeRepository extends TypedEvent { } } - addSceneCamera = (cameraModel: CameraModel) => cameraModel.toWebGl(this); - updateSolidBody = (solidBodyModel: SolidModel) => { const mesh = this.scene.getObjectByName(solidBodyModel.name); mesh?.position.copy(solidBodyModel.vector3); @@ -445,6 +428,7 @@ export class CoreThreeRepository extends TypedEvent { if (position) result.scene.position.copy(position); if (quaternion) result.scene.quaternion.copy(quaternion); this.scene.add(result.scene); + callBack(); }, (err) => console.log(err) ); diff --git a/ui/src/core/repository/http_repository.ts b/ui/src/core/repository/http_repository.ts index 84ddcca..4ba9435 100644 --- a/ui/src/core/repository/http_repository.ts +++ b/ui/src/core/repository/http_repository.ts @@ -2,6 +2,8 @@ import { ClassConstructor, plainToInstance } from "class-transformer"; import { Result } from "../helper/result"; import { Parts } from "../../features/details/details_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 { GET = "GET", @@ -100,7 +102,12 @@ export class CoreHttpRepository extends HttpRepository { getAssetsActiveProject = async (): Promise> => { return this._jsonRequest(HttpMethod.GET, "/projects/assets"); }; + getSceneAsset = (id: string) => + this._jsonToClassInstanceRequest(HttpMethod.GET, `/scenes/by_id?id=${id}`, SceneAsset) as Promise< + Result + >; async getActiveProjectId() { return this._jsonRequest(HttpMethod.GET, "/projects/get/active/project/id"); } + getAllScenes = () => this._jsonRequest(HttpMethod.GET, "/scenes"); } diff --git a/ui/src/core/store/base_store.ts b/ui/src/core/store/base_store.ts index 98893a9..c3b8111 100644 --- a/ui/src/core/store/base_store.ts +++ b/ui/src/core/store/base_store.ts @@ -118,7 +118,7 @@ export abstract class FormState extends UiErrorState { //@ts-ignore this.viewModel = Object.assign(this.viewModel, value); } - loadDependency = (viewModel: V) => { - this.viewModel = viewModel; + loadDependency = (viewModel: V | undefined) => { + if (viewModel) this.viewModel = viewModel; }; } diff --git a/ui/src/core/ui/form_builder/form_builder.tsx b/ui/src/core/ui/form_builder/form_builder.tsx index ac2dd7b..34dffb2 100644 --- a/ui/src/core/ui/form_builder/form_builder.tsx +++ b/ui/src/core/ui/form_builder/form_builder.tsx @@ -51,6 +51,7 @@ export const FormBuilder = observer((props: IFormBuilder) => { ); } if (element.type.isEqual(InputType.ARRAY)) { + return (
{ + const [isOpen, setOpen] = useState(props.isOpen); + return ( +
+
setOpen(!isOpen)} + > + + +
+ {isOpen ? props.child : <>} +
+ ); +}; diff --git a/ui/src/features/behavior_tree_builder/data/behavior_tree_builder_repository.ts b/ui/src/features/behavior_tree_builder/data/behavior_tree_builder_repository.ts index 31f4e32..0efa507 100644 --- a/ui/src/features/behavior_tree_builder/data/behavior_tree_builder_repository.ts +++ b/ui/src/features/behavior_tree_builder/data/behavior_tree_builder_repository.ts @@ -5,6 +5,7 @@ import { BehaviorTreeModel } from "../model/behavior_tree_model"; import { BehaviorTreeViewModel } from "../model/behavior_tree_view_model"; export class BehaviorTreeBuilderHttpRepository extends CoreHttpRepository { + getAllBtInstances = async () => this._jsonRequest(HttpMethod.GET, "/behavior/trees"); getBtSkills = async (): Promise> => { return (await this._jsonToClassInstanceRequest( diff --git a/ui/src/features/behavior_tree_builder/model/behavior_tree_model.ts b/ui/src/features/behavior_tree_builder/model/behavior_tree_model.ts index 0025418..266a07c 100644 --- a/ui/src/features/behavior_tree_builder/model/behavior_tree_model.ts +++ b/ui/src/features/behavior_tree_builder/model/behavior_tree_model.ts @@ -3,12 +3,15 @@ import { Result } from "../../../core/helper/result"; import { Skills } from "../../../core/model/skill_model"; import { NodeBehaviorTree } from "./node_behavior_tree"; import { IsOptional } from "class-validator"; +import { BehaviorTreeBuilderHttpRepository } from "../data/behavior_tree_builder_repository"; +import { message } from "antd"; export class BehaviorTreeModel { @IsOptional() @Type(() => Skills) + public sceneId: string; public skills?: Skills; - public scene: NodeBehaviorTree[]; + public scene: NodeBehaviorTree[] = []; public xml: string; public name: string; public project: string; @@ -26,6 +29,16 @@ export class BehaviorTreeModel { this.scene = scene; this.xml = xml; } + getSceneDependency = async (behaviorTreeBuilderHttpRepository: BehaviorTreeBuilderHttpRepository) => + (await behaviorTreeBuilderHttpRepository.getSceneAsset(this.sceneId)).fold( + (s) => { + + }, + (e) => { + message.error('Get Scene Dependency error') + } + ); + static empty() { return new BehaviorTreeModel(Skills.empty(), [], "", "", "", ""); } diff --git a/ui/src/features/behavior_tree_builder/model/behavior_tree_view_model.ts b/ui/src/features/behavior_tree_builder/model/behavior_tree_view_model.ts index 208fe6c..0960242 100644 --- a/ui/src/features/behavior_tree_builder/model/behavior_tree_view_model.ts +++ b/ui/src/features/behavior_tree_builder/model/behavior_tree_view_model.ts @@ -1,11 +1,11 @@ import { Result } from "../../../core/helper/result"; export class BehaviorTreeViewModel { - constructor(public name: string, public project: string) {} + constructor(public name: string, public project: string, public sceneId: string) {} static empty() { - return new BehaviorTreeViewModel("", ""); + return new BehaviorTreeViewModel("", "", ""); } - + valid(): Result { if (this.project.isEmpty()) { return Result.error("project is empty"); diff --git a/ui/src/features/behavior_tree_builder/model/editor_view.ts b/ui/src/features/behavior_tree_builder/model/editor_view.ts index a227a50..3e42a7e 100644 --- a/ui/src/features/behavior_tree_builder/model/editor_view.ts +++ b/ui/src/features/behavior_tree_builder/model/editor_view.ts @@ -25,6 +25,8 @@ export interface IUpdateEvent { export class NodeRerenderObserver extends TypedEvent {} export class ReteForceUpdateObserver extends TypedEvent {} export class BehaviorTreeBuilderModel { + public static btRootTag: string = '${bt}'; + public static result = ""; static fromReteScene( editor: NodeEditor, @@ -33,8 +35,6 @@ export class BehaviorTreeBuilderModel { ): Result { try { this.result = ""; - - // eslint-disable-next-line array-callback-return this.getFirstSequence(editor).map((sortedSequence) => { const firstNodeId = sortedSequence.getKeyFromValueIsExists(1) as string; this.findSequence(firstNodeId, editor, sortedSequence, 2); @@ -42,25 +42,7 @@ export class BehaviorTreeBuilderModel { this.toXML(sortedSequence as Map, editor, area, firstNodeId, skills); this.result += ``; }); - - return Result.ok( - xmlFormat(` - - - ${this.result} - - - - - - - - - - - - `) - ); + return Result.ok(xmlFormat(this.btRootTag.replace("${bt}", this.result))); } catch (error) { return Result.error("BtBuilderModel fromReteScene error"); } @@ -68,9 +50,9 @@ export class BehaviorTreeBuilderModel { public static getNodeLabelAtId(editor: NodeEditor, id: string, skills?: Skills) { 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 - }" sid=${id} server_name="rbs_interface" server_timeout="1000"`; + }" sid=${id}"`; } return editor.getNode(id).label; } diff --git a/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_screen.tsx b/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_screen.tsx index ca9c39e..d132ec8 100644 --- a/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_screen.tsx +++ b/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_screen.tsx @@ -13,6 +13,7 @@ import { CoreInput } from "../../../core/ui/input/input"; import { CoreText, CoreTextType } from "../../../core/ui/text/text"; import { useNavigate, useParams } from "react-router-dom"; import { IForms, forms } from "./ui/forms/forms"; +import { CoreSelect } from "../../../core/ui/select/select"; export const behaviorTreeBuilderScreenPath = "behavior/tree/screen/path"; export interface DOMReact { @@ -131,6 +132,14 @@ export const BehaviorTreeBuilderScreen = observer(() => {
store.updateForm({ name: text })} /> + el.name) ?? []} + value={""} + label={"Сцена"} + onChange={(text) => + store.updateForm({ sceneId: store.scenes?.filter((el) => el.name.isEqual(text)).at(0)?._id }) + } + />
store.createNewBehaviorTree()} /> @@ -150,10 +159,11 @@ export const BehaviorTreeBuilderScreen = observer(() => { {store.skillTemplates?.getForms(store.selected ?? "").map((formType, index) => forms( store.filledOutTemplates?.getDependencyBySkillLabelAndType( - forms(null, () => {}).find((form) => form.name.isEqual(formType))?.name ?? "", + forms(null, () => {}, store).find((form) => form.name.isEqual(formType))?.name ?? "", store.selectedSid ?? "" ), - (dependency) => store.formUpdateDependency(dependency, formType) + (dependency) => store.formUpdateDependency(dependency, formType), + store ) .rFind((form) => form.name.isEqual(formType)) .fold( @@ -169,4 +179,3 @@ export const BehaviorTreeBuilderScreen = observer(() => { /> ); }); - \ No newline at end of file diff --git a/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_store.tsx b/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_store.tsx index 09b4b17..ef50682 100644 --- a/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_store.tsx +++ b/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_store.tsx @@ -24,7 +24,8 @@ import { behaviorTreeBuilderStore } from "./behavior_tree_builder_screen"; import clone from "just-clone"; import { BehaviorTreeModel } from "../model/behavior_tree_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 { x: number; @@ -43,10 +44,11 @@ export enum StoreUIType { ViewBehaviorTree, } - export class BehaviorTreeBuilderStore extends UiDrawerFormState { type: StoreUIType = StoreUIType.ViewBehaviorTree; + sceneAsset?: SceneAsset; viewModel: BehaviorTreeViewModel = BehaviorTreeViewModel.empty(); + scenes?: SceneModel[]; behaviorTreeModel: BehaviorTreeModel = BehaviorTreeModel.empty(); skillTemplates: Skills = Skills.empty(); filledOutTemplates: Skills = Skills.empty(); @@ -74,7 +76,6 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState, area: AreaPlugin) => { @@ -92,7 +93,7 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState { }; + errorHandingStrategy = (_: CoreError) => {}; dragEnd = (e: EventTarget) => { if (this.canRun) { @@ -123,8 +124,7 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState { - const model = clone(m); - const modelSetId = model.setSid(sid); + const modelSetId = clone(m).setSid(sid); modelSetId.BTAction = m.BTAction.filter((el) => el.name.isEqual(name)); this.filledOutTemplates?.skills.push(modelSetId); @@ -150,6 +150,7 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState console.log(e) ); @@ -180,16 +181,22 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState { + async (model) => { this.nodeBehaviorTree = model.scene; this.behaviorTreeModel = model; if (model.skills) this.filledOutTemplates = model.skills; + + await this.mapOk("sceneAsset", this.behaviorTreeBuilderHttpRepository.getSceneAsset(model.sceneId)); + this.isLoading = false; this.reteForceUpdateObserver?.emit(""); }, - () => this.errors.push(new UiBaseError(`не найдено дерево с id:${id}`)) + async () => { + this.errors.push(new UiBaseError(`не найдено дерево с id:${id}`)); + } ); } else { + await this.mapOk("scenes", this.behaviorTreeBuilderHttpRepository.getAllScenes()); this.type = StoreUIType.SelectBehaviorTree; } }; @@ -202,8 +209,8 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState { }); - document.removeEventListener("keydown", () => { }); + document.removeEventListener("keyup", () => {}); + document.removeEventListener("keydown", () => {}); } onClickSaveBehaviorTree = async (): Promise => { this.filledOutTemplates.validation().fold( @@ -233,7 +240,7 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState message.error(`Дерево поведения не заполнено`) ); }; - validateBt() { } + validateBt() {} createNewBehaviorTree = async () => { this.viewModel.project = this.activeProject; this.viewModel.valid().fold( @@ -282,7 +289,6 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState console.log("UNKNOWN SID: " + this.selectedSid) ); @@ -319,9 +325,12 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState ); } - 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) { - const result = this.primitiveViewModel.getPrimitiveAtLabel(name) + const result = this.primitiveViewModel.getPrimitiveAtLabel(name); if (result) { return { input: result.input ? "a" : null, @@ -329,13 +338,12 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState {}; } diff --git a/ui/src/features/behavior_tree_builder/presentation/ui/editor/editor.tsx b/ui/src/features/behavior_tree_builder/presentation/ui/editor/editor.tsx index 3f66821..e25f459 100644 --- a/ui/src/features/behavior_tree_builder/presentation/ui/editor/editor.tsx +++ b/ui/src/features/behavior_tree_builder/presentation/ui/editor/editor.tsx @@ -14,6 +14,7 @@ import { UpdateEvent, } from "../../../model/editor_view"; import { v4 } from "uuid"; +import constructWithOptions from "styled-components/dist/constructors/constructWithOptions"; export type Schemes = GetSchemes>; export type AreaExtra = ReactArea2D; diff --git a/ui/src/features/behavior_tree_builder/presentation/ui/forms/forms.tsx b/ui/src/features/behavior_tree_builder/presentation/ui/forms/forms.tsx index d7050af..3957ff7 100644 --- a/ui/src/features/behavior_tree_builder/presentation/ui/forms/forms.tsx +++ b/ui/src/features/behavior_tree_builder/presentation/ui/forms/forms.tsx @@ -1,10 +1,13 @@ +import { BehaviorTreeBuilderStore } from "../../behavior_tree_builder_store"; 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 { TopicsForm } from "./topics_form/topics_form"; import { WeightsForm } from "./weights_form/weights_form"; export interface IPropsForm { dependency: T; + store: BehaviorTreeBuilderStore; onChange: (dependency: Object) => void; } @@ -17,10 +20,17 @@ export enum Form { robotName = "robot_name", cameraDeviceForm = "camera", 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: }, - { name: Form.robotName, component: }, - { name: Form.cameraDeviceForm, component: }, - { name: Form.topic, component: }, + { name: Form.robotName, component: }, + { name: Form.cameraDeviceForm, component: }, + { name: Form.topic, component: }, + { name: Form.moveToPose, component: }, ]; diff --git a/ui/src/features/behavior_tree_builder/presentation/ui/forms/move_to_pose/move_to_pose_form.tsx b/ui/src/features/behavior_tree_builder/presentation/ui/forms/move_to_pose/move_to_pose_form.tsx new file mode 100644 index 0000000..0357e8f --- /dev/null +++ b/ui/src/features/behavior_tree_builder/presentation/ui/forms/move_to_pose/move_to_pose_form.tsx @@ -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) => { + const [store] = React.useState(() => new MoveToPoseStore(props.store)); + React.useEffect(() => { + if (ObjectIsNotEmpty(props.dependency)) store.loadDependency(props.dependency); + store.init(); + }, [store]); + return ( +
+ store.updateForm({ robot_name: text })} + /> + + store.updateForm({ pose: props.store.sceneAsset?.getElementByName(text).toDependency() }) + } + value={store.viewModel?.pose?.name ?? ""} + /> + { + store.viewModel.valid().fold( + (s) => { + props.onChange(s); + }, + (e) => message.error(e) + ); + }} + /> +
+ ); +}); diff --git a/ui/src/features/behavior_tree_builder/presentation/ui/forms/move_to_pose/move_to_pose_robot_model.ts b/ui/src/features/behavior_tree_builder/presentation/ui/forms/move_to_pose/move_to_pose_robot_model.ts new file mode 100644 index 0000000..e1a2e0c --- /dev/null +++ b/ui/src/features/behavior_tree_builder/presentation/ui/forms/move_to_pose/move_to_pose_robot_model.ts @@ -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 { + 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; + } +} diff --git a/ui/src/features/behavior_tree_builder/presentation/ui/forms/move_to_pose/move_to_pose_store.ts b/ui/src/features/behavior_tree_builder/presentation/ui/forms/move_to_pose/move_to_pose_store.ts new file mode 100644 index 0000000..4c57400 --- /dev/null +++ b/ui/src/features/behavior_tree_builder/presentation/ui/forms/move_to_pose/move_to_pose_store.ts @@ -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 { + behaviorTreeBuilderStore: BehaviorTreeBuilderStore; + + constructor(behaviorTreeBuilderStore: BehaviorTreeBuilderStore) { + super(); + this.behaviorTreeBuilderStore = behaviorTreeBuilderStore; + makeAutoObservable(this); + } + viewModel: MoveToPoseRobotModel = MoveToPoseRobotModel.empty(); + errorHandingStrategy = (error: CoreError) => {}; + init = async (navigate?: NavigateFunction | undefined) => {}; +} diff --git a/ui/src/features/scene_manager/data/scene_http_repository.ts b/ui/src/features/scene_manager/data/scene_http_repository.ts index 3c83540..2a87468 100644 --- a/ui/src/features/scene_manager/data/scene_http_repository.ts +++ b/ui/src/features/scene_manager/data/scene_http_repository.ts @@ -1,105 +1,16 @@ -import { plainToInstance } from "class-transformer"; 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 { SceneModel } from "../model/scene_model"; import { SceneViewModel } from "../model/scene_view_model"; import { SceneAsset } from "../../../core/model/scene_asset"; export class SceneHttpRepository extends CoreHttpRepository { - getScene = () => { - 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, - // }, + editScene = (scene: SceneAsset) => this._jsonRequest(HttpMethod.PUT, "/scenes", scene); + - // { - // 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(HttpMethod.GET, "/scenes"); newScene = (sceneViewModel: SceneViewModel) => this._jsonRequest(HttpMethod.POST, "/scenes", sceneViewModel) as unknown as Promise>; -} +} \ No newline at end of file diff --git a/ui/src/features/scene_manager/presentation/components/coords_form.tsx b/ui/src/features/scene_manager/presentation/components/coords_form.tsx index 2a1898f..cee0915 100644 --- a/ui/src/features/scene_manager/presentation/components/coords_form.tsx +++ b/ui/src/features/scene_manager/presentation/components/coords_form.tsx @@ -1,59 +1,105 @@ import { FormState } from "../../../../core/store/base_store"; import { CoreInput } from "../../../../core/ui/input/input"; import { CoreText, CoreTextType } from "../../../../core/ui/text/text"; +import { Toggle } from "../../../../core/ui/toggle/toggle"; export const CoordsForm = ({ store, update }: { store: FormState; update: Function }) => { return ( <> - - { - store.updateForm({ vector3: store.viewModel.vector3.setX(Number(text)) }); - update(); - }} - /> - { - store.updateForm({ vector3: store.viewModel.vector3.setY(Number(text)) }); - update(); - }} - /> - { - store.updateForm({ vector3: store.viewModel.vector3.setZ(Number(text)) }); - update(); - }} - /> - - { - store.updateForm({ vector3: store.viewModel.vector3.setX(Number(text)) }); - update(); - }} - /> - { - store.updateForm({ vector3: store.viewModel.vector3.setY(Number(text)) }); - update(); - }} - /> - { - store.updateForm({ vector3: store.viewModel.vector3.setZ(Number(text)) }); - update(); - }} + + + + { + store.updateForm({ vector3: store.viewModel.vector3.setX(Number(text)) }); + update(); + }} + /> + { + store.updateForm({ vector3: store.viewModel.vector3.setY(Number(text)) }); + update(); + }} + /> + { + store.updateForm({ vector3: store.viewModel.vector3.setZ(Number(text)) }); + update(); + }} + /> + + { + store.updateForm({ + quaternion: store.viewModel.quaternion.map((el: any, i: number) => { + if (i === 1) { + return Number(text); + } + return el; + }), + }); + update(); + }} + /> + { + store.updateForm({ + quaternion: store.viewModel.quaternion.map((el: any, i: number) => { + if (i === 2) { + return Number(text); + } + return el; + }), + }); + update(); + }} + /> + { + store.updateForm({ + quaternion: store.viewModel.quaternion.map((el: any, i: number) => { + if (i === 3) { + return Number(text); + } + return el; + }), + }); + update(); + }} + /> + { + store.updateForm({ + quaternion: store.viewModel.quaternion.map((el: any, i: number) => { + if (i === 4) { + return Number(text); + } + return el; + }), + }); + update(); + }} + /> +
+ } + isOpen={false} /> ); diff --git a/ui/src/features/scene_manager/presentation/forms/camera/camera_form.tsx b/ui/src/features/scene_manager/presentation/forms/camera/camera_form.tsx index 8a88ee4..98c47fd 100644 --- a/ui/src/features/scene_manager/presentation/forms/camera/camera_form.tsx +++ b/ui/src/features/scene_manager/presentation/forms/camera/camera_form.tsx @@ -1,17 +1,13 @@ import React from "react"; -import { message } from "antd"; import { CoreButton } from "../../../../../core/ui/button/button"; import { IDefaultSceneManagerFormProps, isPreviewMode } from "../scene_manager_forms"; import { CoreInput } from "../../../../../core/ui/input/input"; import { CoreText, CoreTextType } from "../../../../../core/ui/text/text"; import { CoreSelect } from "../../../../../core/ui/select/select"; import { CameraFormStore } from "./camera_store"; -import { Loader } from "../../../../../core/ui/loader/loader"; import { observer } from "mobx-react-lite"; import { CameraTypes } from "../../../../../core/model/camera_model"; - - export const CameraForm = observer((props: IDefaultSceneManagerFormProps) => { 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 })} />
- { - store.viewModel.validate().fold( - (model) => { - props.store.addNewCamera(model); - }, - (error) => message.error(error) - ); - }} - /> + + {store.type !== "preview" ? ( + store.clickNewCamera()} /> + ) : null}
+ +
); }); diff --git a/ui/src/features/scene_manager/presentation/forms/camera/camera_store.tsx b/ui/src/features/scene_manager/presentation/forms/camera/camera_store.tsx index f0c7f81..8702bd4 100644 --- a/ui/src/features/scene_manager/presentation/forms/camera/camera_store.tsx +++ b/ui/src/features/scene_manager/presentation/forms/camera/camera_store.tsx @@ -4,6 +4,7 @@ import { FormState, CoreError } from "../../../../../core/store/base_store"; import { SceneMangerStore } from "../../scene_manager_store"; import { isPreviewMode } from "../scene_manager_forms"; import { CameraModel } from "../../../../../core/model/camera_model"; +import { message } from "antd"; export class CameraFormStore extends FormState { viewModel: CameraModel = CameraModel.empty(); @@ -18,6 +19,16 @@ export class CameraFormStore extends FormState { errorHandingStrategy = (error: CoreError) => {}; updateCameraScene = () => 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) => { isPreviewMode(this.sceneMangerStore.activeFormDependency).map(() => diff --git a/ui/src/features/scene_manager/presentation/forms/point/point_form.tsx b/ui/src/features/scene_manager/presentation/forms/point/point_form.tsx index 71bd807..a50f2ef 100644 --- a/ui/src/features/scene_manager/presentation/forms/point/point_form.tsx +++ b/ui/src/features/scene_manager/presentation/forms/point/point_form.tsx @@ -7,11 +7,15 @@ import { CoreInput } from "../../../../../core/ui/input/input"; import { CoreButton } from "../../../../../core/ui/button/button"; import { match } from "ts-pattern"; import { SpawnPositionTypesForm } from "../../components/spawn_position_types"; +import { CoordsForm } from "../../components/coords_form"; export const PointForm = observer((props: IDefaultSceneManagerFormProps) => { const [store] = React.useState(() => new PointStore(props.store)); React.useEffect(() => { store.init(); + return () => { + store.dispose(); + }; }, [store]); return ( @@ -21,22 +25,7 @@ export const PointForm = observer((props: IDefaultSceneManagerFormProps) => { <> - - (store.updateForm({ vector3: store.viewModel.vector3.setX(Number(text)) }), store.updateWebGl())} - /> - (store.updateForm({ vector3: store.viewModel.vector3.setY(Number(text)) }),store.updateWebGl())} - /> - (store.updateForm({ vector3: store.viewModel.vector3.setZ(Number(text)) }), store.updateWebGl())} - /> + )) .with(PointStoreType.initNewPoint, () => ( @@ -54,6 +43,11 @@ export const PointForm = observer((props: IDefaultSceneManagerFormProps) => { )) + .with(PointStoreType.awaitClick, () => ( + <> + + + )) .otherwise(() => ( <> ))} diff --git a/ui/src/features/scene_manager/presentation/forms/point/point_http_repository.ts b/ui/src/features/scene_manager/presentation/forms/point/point_http_repository.ts deleted file mode 100644 index 500d45c..0000000 --- a/ui/src/features/scene_manager/presentation/forms/point/point_http_repository.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { HttpRepository } from "../../../../../core/repository/http_repository"; - - -export class PointHttpRepository extends HttpRepository { - -} diff --git a/ui/src/features/scene_manager/presentation/forms/point/point_store.ts b/ui/src/features/scene_manager/presentation/forms/point/point_store.ts index a2f1ecd..a486604 100644 --- a/ui/src/features/scene_manager/presentation/forms/point/point_store.ts +++ b/ui/src/features/scene_manager/presentation/forms/point/point_store.ts @@ -1,7 +1,6 @@ import makeAutoObservable from "mobx-store-inheritance"; import { NavigateFunction } from "react-router-dom"; import { PointModel } from "../../../../../core/model/point_model"; -import { PointHttpRepository } from "./point_http_repository"; import { FormState, CoreError } from "../../../../../core/store/base_store"; import { SpawnPositionTypes } from "../../../../../core/model/spawn_position_types"; import { isPreviewMode } from "../scene_manager_forms"; @@ -11,22 +10,42 @@ export enum PointStoreType { makeSceneSolidAndEditPosition = "makeSceneSolidAndEditPosition", initNewPoint = "initNewPoint", previewPoint = "previewPoint", + awaitClick = "awaitClick", } export class PointStore extends FormState { viewModel: PointModel = PointModel.empty(); - cameraDeviceHttpRepository: PointHttpRepository = new PointHttpRepository(); storeType: PointStoreType = PointStoreType.initNewPoint; spawnPositionTypes: SpawnPositionTypes; sceneMangerStore: SceneMangerStore; + listener: Function; + constructor(sceneMangerStore: SceneMangerStore) { super(); makeAutoObservable(this); 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) => { this.spawnPositionTypes = type; + this.storeType = PointStoreType.awaitClick; + setTimeout(() => window.addEventListener("click", this.clickLister), 1000); }; + dispose = () => window.removeEventListener("click", this.clickLister); updateWebGl = () => this.storeType .isEqualR(PointStoreType.previewPoint) diff --git a/ui/src/features/scene_manager/presentation/forms/robot_form/robot_form.tsx b/ui/src/features/scene_manager/presentation/forms/robot_form/robot_form.tsx index 085b644..b700967 100644 --- a/ui/src/features/scene_manager/presentation/forms/robot_form/robot_form.tsx +++ b/ui/src/features/scene_manager/presentation/forms/robot_form/robot_form.tsx @@ -16,6 +16,9 @@ export const RobotForm = observer((props: IDefaultSceneManagerFormProps) => { const [store] = React.useState(() => new RobotFormStore(props.store)); React.useEffect(() => { store.init(); + return () => { + store.dispose(); + }; }, []); return (
@@ -56,10 +59,7 @@ export const RobotForm = observer((props: IDefaultSceneManagerFormProps) => { )) .with(RobotStoreType.previewRobot, () => ( <> - store.updateScene()} /> - -
- + {store.viewModel.jointPosition.map((el, i) => (
{ jointPosition: store.viewModel.jointPosition.map((element, index) => index.isEqualR(i).fold( () => { - element.angel = value; + element.angle = value; return element; }, () => element @@ -87,6 +87,9 @@ export const RobotForm = observer((props: IDefaultSceneManagerFormProps) => {
))}
+ store.updateScene()} /> +
+ )) .otherwise(() => ( diff --git a/ui/src/features/scene_manager/presentation/forms/robot_form/robot_form_store.ts b/ui/src/features/scene_manager/presentation/forms/robot_form/robot_form_store.ts index c68b555..5e5def0 100644 --- a/ui/src/features/scene_manager/presentation/forms/robot_form/robot_form_store.ts +++ b/ui/src/features/scene_manager/presentation/forms/robot_form/robot_form_store.ts @@ -6,8 +6,6 @@ import { RobotModel } from "../../../../../core/model/robot_model"; import { SceneMangerStore } from "../../scene_manager_store"; import { isPreviewMode } from "../scene_manager_forms"; import { message } from "antd"; -import { SceneModelsTypes } from "../../../../../core/model/scene_models_type"; -import { Vector3 } from "three"; export enum RobotStoreType { previewRobot = "previewRobot", @@ -28,9 +26,10 @@ export class RobotFormStore extends FormState { this.viewModel.vector3 = vector3; 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) + this.sceneMangerStore.sceneItems.push(this.viewModel.toSceneItems(this.sceneMangerStore)); + this.sceneMangerStore.scene.push(this.viewModel); window.removeEventListener("click", this.clickLister); + this.sceneMangerStore.visibleSaveButton(); }) ); @@ -50,7 +49,12 @@ export class RobotFormStore extends FormState { updateScene = () => this.storeType .isEqualR(RobotStoreType.previewRobot) - .map(() => this.viewModel.update(this.sceneMangerStore.coreThreeRepository!)); + .map( + () => ( + this.viewModel.update(this.sceneMangerStore.coreThreeRepository!), + this.sceneMangerStore.visibleSaveButton() + ) + ); createNewRobot = () => this.viewModel.isValid().fold( async (s) => diff --git a/ui/src/features/scene_manager/presentation/forms/solid_body/solid_body_form.tsx b/ui/src/features/scene_manager/presentation/forms/solid_body/solid_body_form.tsx index 917515c..0cd3c40 100644 --- a/ui/src/features/scene_manager/presentation/forms/solid_body/solid_body_form.tsx +++ b/ui/src/features/scene_manager/presentation/forms/solid_body/solid_body_form.tsx @@ -7,6 +7,7 @@ import { CoreButton } from "../../../../../core/ui/button/button"; import { match } from "ts-pattern"; import { SpawnPositionTypesForm } from "../../components/spawn_position_types"; import { CoreInput } from "../../../../../core/ui/input/input"; +import { CoordsForm } from "../../components/coords_form"; export const SolidBodyForm = observer((props: IDefaultSceneManagerFormProps) => { const [store] = React.useState(() => new SolidBodyStore(props.store)); @@ -20,31 +21,8 @@ export const SolidBodyForm = observer((props: IDefaultSceneManagerFormProps) => {match(store.solidBodyStoreType) .with(SolidBodyStoreType.previewSolid, () => ( <> - - ( - store.updateForm({ vector3: store.viewModel.vector3.setX(Number(text)) }), - store.updateBodySimulation() - )} - /> - ( - store.updateForm({ vector3: store.viewModel.vector3.setY(Number(text)) }), - store.updateBodySimulation() - )} - /> - ( - store.updateForm({ vector3: store.viewModel.vector3.setZ(Number(text)) }), - store.updateBodySimulation() - )} - /> + + )) @@ -68,11 +46,7 @@ export const SolidBodyForm = observer((props: IDefaultSceneManagerFormProps) => )) .with(SolidBodyStoreType.spawn2DVector, () => ( <> - {props.store.mousePosition ? ( - "" - ) : ( - - )} + )) .otherwise(() => ( diff --git a/ui/src/features/scene_manager/presentation/forms/solid_body/solid_body_store.tsx b/ui/src/features/scene_manager/presentation/forms/solid_body/solid_body_store.tsx index 4a303e3..39e9d45 100644 --- a/ui/src/features/scene_manager/presentation/forms/solid_body/solid_body_store.tsx +++ b/ui/src/features/scene_manager/presentation/forms/solid_body/solid_body_store.tsx @@ -7,7 +7,7 @@ import { SceneMangerStore } from "../../scene_manager_store"; import { SpawnPositionTypes } from "../../../../../core/model/spawn_position_types"; import { isPreviewMode } from "../scene_manager_forms"; import { SolidModel } from "../../../../../core/model/solid_model"; -import { SceneModelsTypes } from "../../../../../core/model/scene_models_type"; + export enum SolidBodyStoreType { selectBody = "selectBody", selectSpawnPositionType = "selectSpawnPositionType", @@ -52,20 +52,27 @@ export class SolidBodyStore extends FormState { }; errorHandingStrategy = (error: CoreError) => {}; - dispose = () => {}; - selectSpawnType = (type: string) => { - 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; + dispose = () => { + window.removeEventListener("click", this.clickLister); }; + 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 = () => this.solidBodyStoreType .isEqualR(SolidBodyStoreType.previewSolid) @@ -73,5 +80,6 @@ export class SolidBodyStore extends FormState { clickSelectBody = (el: Parts) => { this.selectBody = el; this.solidBodyStoreType = SolidBodyStoreType.selectSpawnPositionType; + this.viewModel = this.viewModel.fromParts(el); }; } diff --git a/ui/src/features/scene_manager/presentation/forms/zone/zone_http_repository.ts b/ui/src/features/scene_manager/presentation/forms/zone/zone_http_repository.ts deleted file mode 100644 index dcb397d..0000000 --- a/ui/src/features/scene_manager/presentation/forms/zone/zone_http_repository.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { HttpRepository } from "../../../../../core/repository/http_repository"; - -export class ZoneHttpRepository extends HttpRepository {} diff --git a/ui/src/features/scene_manager/presentation/forms/zone/zone_store.ts b/ui/src/features/scene_manager/presentation/forms/zone/zone_store.ts index 2927f3b..aa58db3 100644 --- a/ui/src/features/scene_manager/presentation/forms/zone/zone_store.ts +++ b/ui/src/features/scene_manager/presentation/forms/zone/zone_store.ts @@ -1,7 +1,7 @@ import makeAutoObservable from "mobx-store-inheritance"; import { NavigateFunction } from "react-router-dom"; import { ZoneModel } from "../../../../../core/model/zone_model"; -import { ZoneHttpRepository } from "./zone_http_repository"; + import { FormState, CoreError } from "../../../../../core/store/base_store"; import { isPreviewMode } from "../scene_manager_forms"; import { SceneMangerStore } from "../../scene_manager_store"; @@ -9,7 +9,6 @@ export enum ZoneStoreType { preview = "preview", } export class ZoneStore extends FormState { - constructor(sceneMangerStore: SceneMangerStore) { super(); this.sceneMangerStore = sceneMangerStore; @@ -18,9 +17,8 @@ export class ZoneStore extends FormState { storeType: ZoneStoreType; sceneMangerStore: SceneMangerStore; viewModel: ZoneModel = ZoneModel.empty(); - cameraDeviceHttpRepository: ZoneHttpRepository = new ZoneHttpRepository(); - errorHandingStrategy = (error: CoreError) => {}; - init = async (navigate?: NavigateFunction | undefined) => { + errorHandingStrategy = (_error: CoreError) => {}; + init = async (_navigate?: NavigateFunction | undefined) => { isPreviewMode(this.sceneMangerStore.activeFormDependency).map(() => this.sceneMangerStore.scene .rFind((el) => el.name.isEqual(this.sceneMangerStore.selectedItemName ?? "")) @@ -38,5 +36,8 @@ export class ZoneStore extends FormState { ) ); }; - 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)); } diff --git a/ui/src/features/scene_manager/presentation/scene_manager_store.ts b/ui/src/features/scene_manager/presentation/scene_manager_store.ts index dc5b86c..3f1c1bf 100644 --- a/ui/src/features/scene_manager/presentation/scene_manager_store.ts +++ b/ui/src/features/scene_manager/presentation/scene_manager_store.ts @@ -1,5 +1,5 @@ import makeAutoObservable from "mobx-store-inheritance"; -import { Object3D, Object3DEventMap, Vector2, Vector3 } from "three"; +import { Object3D, Vector2, Vector3 } from "three"; import { message } from "antd"; import { CoreThreeRepository } from "../../../core/repository/core_three_repository"; import { HttpError } from "../../../core/repository/http_repository"; @@ -43,8 +43,11 @@ export interface SceneItems { isSelected: boolean; icon: string; } + + export class SceneMangerStore extends UiDrawerFormState { activeFormType?: string; + activeSceneId?: string; selectedItemName?: string; activeFormDependency: Object = {}; viewModel: SceneViewModel = SceneViewModel.empty(); @@ -60,7 +63,6 @@ export class SceneMangerStore extends UiDrawerFormState this.createNewForm(SceneManagerForms.capturePoints, true) }, ]; canvasOffsetX?: number; + sceneName?: string; constructor() { super(DrawersSceneManager); makeAutoObservable(this); @@ -94,9 +97,8 @@ export class SceneMangerStore extends UiDrawerFormState { - console.log(JSON.stringify(this.scene)); - }; + sceneSave = () => this.sceneHttpRepository.editScene(SceneAsset.newScene(this.scene, this.sceneName ?? "")); + iconToSceneManagerForm = (icon: string): SceneManagerForms => { if (icon.isEqual("Camera")) { this.activeFormDependency = { @@ -153,7 +155,6 @@ export class SceneMangerStore extends UiDrawerFormState { this.activeFormDependency = Object.assign(this.activeFormDependency, { store: this }); @@ -183,31 +184,20 @@ export class SceneMangerStore extends UiDrawerFormState { 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.scene.push(model); - this.coreThreeRepository?.addSceneCamera(model); + model.toWebGl(this.coreThreeRepository!); 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); - sceneModeWatcher() {} - init = async () => {}; initParam = (id: string | undefined) => { if (id) { + this.activeSceneId = id; this.storeMode = StoreMode.sceneInstance; } else { this.storeMode = StoreMode.allScenes; @@ -220,13 +210,9 @@ export class SceneMangerStore extends UiDrawerFormState { this.canvasRef = canvasRef; this.storeMode.isEqualR(StoreMode.sceneInstance).map(() => this.loadWebGl(canvasRef)); - // await this.mapOk("robossemblerAssets", this.sceneHttpRepository.getRobossemblerAssets()); - // if (this.robossemblerAssets) { - // this.coreThreeRepository?.loadInstances(this.robossemblerAssets); - // } }; - loadWebGl(canvasRef: HTMLCanvasElement): void { + loadWebGl = async (canvasRef: HTMLCanvasElement): Promise => { this.coreThreeRepository = new CoreThreeRepository(canvasRef as HTMLCanvasElement, this.watcherSceneEditorObject); this.coreThreeRepository.render(); @@ -234,18 +220,16 @@ export class SceneMangerStore extends UiDrawerFormState this.clickLister(event, canvasRef.getBoundingClientRect().x)); - const sceneAssets = this.sceneHttpRepository.getScene(); - this.coreThreeRepository?.loadScene(sceneAssets); - this.sceneItems = sceneAssets.scene.map((el) => { - return { - fn: () => {}, - name: el.name, - icon: el.icon, - isSelected: false, - }; - }); - this.scene = sceneAssets.scene; - } + (await this.sceneHttpRepository.getSceneAsset(this.activeSceneId ?? "")).fold( + (sceneAssets) => { + this.sceneName = sceneAssets.name; + this.coreThreeRepository?.loadScene(sceneAssets); + this.sceneItems = sceneAssets.toSceneItems(); + this.scene = sceneAssets.scene; + }, + () => {} + ); + }; clickScene = (event: MouseEvent, offset: number = 0): Result => { const vector = new Vector2(); const boundingRect = this.canvasRef!.getBoundingClientRect(); @@ -260,25 +244,7 @@ export class SceneMangerStore extends UiDrawerFormState { - this.coreThreeRepository?.solidSpawn( - this.spawnHelper as ISpawnHelper, - (obj: Object3D | 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)) { return; } diff --git a/ui/src/index.tsx b/ui/src/index.tsx index 2332018..01eff66 100644 --- a/ui/src/index.tsx +++ b/ui/src/index.tsx @@ -10,7 +10,9 @@ import { configure } from "mobx"; configure({ enforceActions: "never", }); + extensions(); + const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement); root.render( diff --git a/ui/tsconfig.json b/ui/tsconfig.json index 12b2984..f4d06b3 100644 --- a/ui/tsconfig.json +++ b/ui/tsconfig.json @@ -21,6 +21,5 @@ "strictPropertyInitialization": false, "sourceMap": true }, - "types": ["babylonjs", "babylonjs-loaders"], "include": ["src"] } diff --git a/web_p/train_Dope.py b/web_p/train_Dope.py index f9908bc..c4fdc1f 100644 --- a/web_p/train_Dope.py +++ b/web_p/train_Dope.py @@ -540,3 +540,6 @@ if __name__ == "__main__": args = parser.parse_args() train_Dope_i(args.path, args.name, args.datasetName, args.outpath, args.epoch, args.pretrain) + + + \ No newline at end of file