diff --git a/ui/src/core/model/point_model.ts b/ui/src/core/model/point_model.ts index 3ea2c58..f431880 100644 --- a/ui/src/core/model/point_model.ts +++ b/ui/src/core/model/point_model.ts @@ -4,8 +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"; +import { SceneBuilderStore, SceneItems } from "../../features/scene_builder/presentation/scene_builder_store"; export class PointModel implements Instance { type = SceneModelsTypes.POINT; @@ -27,7 +27,7 @@ export class PointModel implements Instance { this.color, this.size ); - toSceneItems = (sceneMangerStore: SceneMangerStore): SceneItems => { + toSceneItems = (sceneMangerStore: SceneBuilderStore): SceneItems => { return { fn: () => {}, name: this.name, diff --git a/ui/src/core/model/robot_model.ts b/ui/src/core/model/robot_model.ts index 4a52bc4..4fe5dbd 100644 --- a/ui/src/core/model/robot_model.ts +++ b/ui/src/core/model/robot_model.ts @@ -5,7 +5,7 @@ import { Instance } from "./scene_asset"; import { CoreThreeRepository } from "../repository/core_three_repository"; import { Type } from "class-transformer"; import { URDFRobot } from "urdf-loader"; -import { SceneItems, SceneMangerStore } from "../../features/scene_manager/presentation/scene_manager_store"; +import { SceneBuilderStore, SceneItems } from "../../features/scene_builder/presentation/scene_builder_store"; export enum ToolTypes { RBS_GRIPPER = "RBS_GRIPPER", @@ -48,7 +48,7 @@ export class RobotModel implements Instance { this.jointPosition = jointPosition; } icon: string = "Robot"; - toSceneItems = (sceneMangerStore: SceneMangerStore): SceneItems => { + toSceneItems = (sceneBuilderStore: SceneBuilderStore): SceneItems => { return { fn: () => {}, name: this.name, diff --git a/ui/src/core/model/scene_asset.ts b/ui/src/core/model/scene_asset.ts index cecbee0..1bfb7cd 100644 --- a/ui/src/core/model/scene_asset.ts +++ b/ui/src/core/model/scene_asset.ts @@ -9,7 +9,7 @@ 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"; +import { SceneItems } from "../../features/scene_builder/presentation/scene_builder_store"; export abstract class Instance { type: string; diff --git a/ui/src/core/model/solid_model.ts b/ui/src/core/model/solid_model.ts index 539f37d..42158ab 100644 --- a/ui/src/core/model/solid_model.ts +++ b/ui/src/core/model/solid_model.ts @@ -3,8 +3,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 } from "../../features/scene_manager/presentation/scene_manager_store"; import { Parts } from "../../features/details/details_http_repository"; +import { SceneItems } from "../../features/scene_builder/presentation/scene_builder_store"; export class SolidModel implements Instance { icon: string = "Solid"; diff --git a/ui/src/core/repository/core_three_repository.ts b/ui/src/core/repository/core_three_repository.ts index b85c2c7..d7f6bc0 100644 --- a/ui/src/core/repository/core_three_repository.ts +++ b/ui/src/core/repository/core_three_repository.ts @@ -33,13 +33,13 @@ import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; 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 { SceneItems } from "../../features/scene_manager/presentation/scene_manager_store"; import { SolidModel } from "../model/solid_model"; import { Instance, SceneAsset } from "../model/scene_asset"; import { ZoneModel } from "../model/zone_model"; import { TypedEvent } from "../helper/typed_event"; import { Result } from "../helper/result"; import { RobotModel } from "../model/robot_model"; +import { SceneItems } from "../../features/scene_builder/presentation/scene_builder_store"; Object3D.DEFAULT_UP = new Vector3(0, 0, 1); diff --git a/ui/src/core/routers/routers.tsx b/ui/src/core/routers/routers.tsx index c3e3a4e..8b45f7f 100644 --- a/ui/src/core/routers/routers.tsx +++ b/ui/src/core/routers/routers.tsx @@ -19,6 +19,7 @@ import { TopicsScreen, TopicsScreenPath } from "../../features/topics/topics_scr import { SkillsScreen, SkillsScreenPath } from "../../features/skills/skills_screen"; import { CalculationsTemplateScreenPath } from "../../features/calculations_template/calculations_template_screen"; import { BehaviorTreeManagerScreen, BehaviorTreeManagerScreenPath } from "../../features/behavior_tree_manager/behavior_tree_manager_screen"; +import { SceneBuilderScreenPath, SceneBuilderScreen } from "../../features/scene_builder/presentation/scene_builder_screen"; const idURL = ":id"; export const router = createBrowserRouter([ @@ -26,6 +27,10 @@ export const router = createBrowserRouter([ path: AllProjectScreenPath, element: , }, + { + path:SceneBuilderScreenPath + idURL, + element: + }, { path: SceneManagerPath + idURL, element: , diff --git a/ui/src/features/scene_builder/data/scene_builder_repository.ts b/ui/src/features/scene_builder/data/scene_builder_repository.ts new file mode 100644 index 0000000..ca76314 --- /dev/null +++ b/ui/src/features/scene_builder/data/scene_builder_repository.ts @@ -0,0 +1,6 @@ +import { SceneAsset } from "../../../core/model/scene_asset"; +import { CoreHttpRepository, HttpMethod } from "../../../core/repository/core_http_repository"; + +export class SceneBuilderHttpRepository extends CoreHttpRepository { + editScene = (scene: SceneAsset) => this._jsonRequest(HttpMethod.PUT, "/scenes", scene); +} diff --git a/ui/src/features/scene_manager/presentation/forms/camera/camera_form.tsx b/ui/src/features/scene_builder/forms/camera/camera_form.tsx similarity index 89% rename from ui/src/features/scene_manager/presentation/forms/camera/camera_form.tsx rename to ui/src/features/scene_builder/forms/camera/camera_form.tsx index 11b5642..a99d5d3 100644 --- a/ui/src/features/scene_manager/presentation/forms/camera/camera_form.tsx +++ b/ui/src/features/scene_builder/forms/camera/camera_form.tsx @@ -1,12 +1,12 @@ import React from "react"; -import { CoreButton } from "../../../../../core/ui/button/button"; +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 { 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 { 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) => { const [store] = React.useState(() => new CameraFormStore(props.store)); diff --git a/ui/src/features/scene_manager/presentation/forms/camera/camera_store.tsx b/ui/src/features/scene_builder/forms/camera/camera_store.tsx similarity index 54% rename from ui/src/features/scene_manager/presentation/forms/camera/camera_store.tsx rename to ui/src/features/scene_builder/forms/camera/camera_store.tsx index 8702bd4..02b8795 100644 --- a/ui/src/features/scene_manager/presentation/forms/camera/camera_store.tsx +++ b/ui/src/features/scene_builder/forms/camera/camera_store.tsx @@ -1,39 +1,39 @@ import makeAutoObservable from "mobx-store-inheritance"; import { NavigateFunction } from "react-router-dom"; -import { FormState, CoreError } from "../../../../../core/store/base_store"; -import { SceneMangerStore } from "../../scene_manager_store"; +import { FormState, CoreError } from "../../../../core/store/base_store"; import { isPreviewMode } from "../scene_manager_forms"; -import { CameraModel } from "../../../../../core/model/camera_model"; +import { CameraModel } from "../../../../core/model/camera_model"; import { message } from "antd"; +import { SceneBuilderStore } from "../../presentation/scene_builder_store"; export class CameraFormStore extends FormState { viewModel: CameraModel = CameraModel.empty(); - sceneMangerStore: SceneMangerStore; + sceneBuilderStore: SceneBuilderStore; type?: string; - constructor(sceneMangerStore: SceneMangerStore) { + constructor(sceneBuilderStore: SceneBuilderStore) { super(); makeAutoObservable(this); - this.sceneMangerStore = sceneMangerStore; + this.sceneBuilderStore = sceneBuilderStore; } errorHandingStrategy = (error: CoreError) => {}; updateCameraScene = () => - this.type?.isNotEmptyR().map(() => this.viewModel.toWebGl(this.sceneMangerStore.coreThreeRepository!)); + this.type?.isNotEmptyR().map(() => this.viewModel.toWebGl(this.sceneBuilderStore.coreThreeRepository!)); clickNewCamera = () => this.viewModel.validate().fold( (model) => { - this.sceneMangerStore.addNewCamera(model); - this.sceneMangerStore.activeFormType = undefined; - this.sceneMangerStore.visibleSaveButton() + this.sceneBuilderStore.addNewCamera(model); + this.sceneBuilderStore.activeFormType = undefined; + this.sceneBuilderStore.visibleSaveButton() }, (error) => message.error(error) ); init = async (navigate?: NavigateFunction | undefined) => { - isPreviewMode(this.sceneMangerStore.activeFormDependency).map(() => - this.sceneMangerStore.scene - .rFind((el) => el.name.isEqual(this.sceneMangerStore.selectedItemName ?? "")) + isPreviewMode(this.sceneBuilderStore.activeFormDependency).map(() => + this.sceneBuilderStore.scene + .rFind((el) => el.name.isEqual(this.sceneBuilderStore.selectedItemName ?? "")) .fold( (cameraModel) => { this.loadDependency(cameraModel); diff --git a/ui/src/features/scene_manager/presentation/forms/light/light_form.tsx b/ui/src/features/scene_builder/forms/light/light_form.tsx similarity index 100% rename from ui/src/features/scene_manager/presentation/forms/light/light_form.tsx rename to ui/src/features/scene_builder/forms/light/light_form.tsx diff --git a/ui/src/features/scene_manager/presentation/forms/light/light_store.tsx b/ui/src/features/scene_builder/forms/light/light_store.tsx similarity index 71% rename from ui/src/features/scene_manager/presentation/forms/light/light_store.tsx rename to ui/src/features/scene_builder/forms/light/light_store.tsx index 9017531..ea4e0e9 100644 --- a/ui/src/features/scene_manager/presentation/forms/light/light_store.tsx +++ b/ui/src/features/scene_builder/forms/light/light_store.tsx @@ -1,6 +1,6 @@ import { NavigateFunction } from "react-router-dom"; -import { FormState, CoreError } from "../../../../../core/store/base_store"; -import { LightModel } from "../../../../../core/model/light_model"; +import { FormState, CoreError } from "../../../../core/store/base_store"; +import { LightModel } from "../../../../core/model/light_model"; export class LightStore extends FormState { viewModel: LightModel = LightModel.empty(); diff --git a/ui/src/features/scene_manager/presentation/forms/point/point_form.tsx b/ui/src/features/scene_builder/forms/point/point_form.tsx similarity index 82% rename from ui/src/features/scene_manager/presentation/forms/point/point_form.tsx rename to ui/src/features/scene_builder/forms/point/point_form.tsx index a50f2ef..a6ffb25 100644 --- a/ui/src/features/scene_manager/presentation/forms/point/point_form.tsx +++ b/ui/src/features/scene_builder/forms/point/point_form.tsx @@ -2,12 +2,12 @@ import React from "react"; import { observer } from "mobx-react-lite"; import { PointStore, PointStoreType } from "./point_store"; import { IDefaultSceneManagerFormProps } from "../scene_manager_forms"; -import { CoreText, CoreTextType } from "../../../../../core/ui/text/text"; -import { CoreInput } from "../../../../../core/ui/input/input"; -import { CoreButton } from "../../../../../core/ui/button/button"; +import { CoreText, CoreTextType } from "../../../../core/ui/text/text"; +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"; +import { SpawnPositionTypesForm } from "../../presentation/components/spawn_position_types"; +import { CoordsForm } from "../../presentation/components/coords_form"; export const PointForm = observer((props: IDefaultSceneManagerFormProps) => { const [store] = React.useState(() => new PointStore(props.store)); diff --git a/ui/src/features/scene_manager/presentation/forms/point/point_store.ts b/ui/src/features/scene_builder/forms/point/point_store.ts similarity index 56% rename from ui/src/features/scene_manager/presentation/forms/point/point_store.ts rename to ui/src/features/scene_builder/forms/point/point_store.ts index cefad83..46d196b 100644 --- a/ui/src/features/scene_manager/presentation/forms/point/point_store.ts +++ b/ui/src/features/scene_builder/forms/point/point_store.ts @@ -1,10 +1,10 @@ import makeAutoObservable from "mobx-store-inheritance"; import { NavigateFunction } from "react-router-dom"; -import { PointModel } from "../../../../../core/model/point_model"; -import { FormState, CoreError } from "../../../../../core/store/base_store"; -import { SpawnPositionTypes } from "../../../../../core/model/spawn_position_types"; +import { PointModel } from "../../../../core/model/point_model"; +import { FormState, CoreError } from "../../../../core/store/base_store"; +import { SpawnPositionTypes } from "../../../../core/model/spawn_position_types"; import { isPreviewMode } from "../scene_manager_forms"; -import { SceneMangerStore } from "../../scene_manager_store"; +import { SceneBuilderStore } from "../../presentation/scene_builder_store"; export enum PointStoreType { makeSceneSolidAndEditPosition = "makeSceneSolidAndEditPosition", @@ -17,26 +17,26 @@ export class PointStore extends FormState { viewModel: PointModel = PointModel.empty(); storeType: PointStoreType = PointStoreType.initNewPoint; spawnPositionTypes: SpawnPositionTypes; - sceneMangerStore: SceneMangerStore; + sceneBuilderStore: SceneBuilderStore; listener: Function; - constructor(sceneMangerStore: SceneMangerStore) { + constructor(sceneBuilderStore: SceneBuilderStore) { super(); makeAutoObservable(this); - this.sceneMangerStore = sceneMangerStore; + this.sceneBuilderStore = sceneBuilderStore; } clickLister = (event: MouseEvent) => this.storeType.isEqualR(PointStoreType.awaitClick).map(() => - this.sceneMangerStore!.clickScene(event, this.sceneMangerStore!.canvasOffsetX).map((vector3) => { + this.sceneBuilderStore!.clickScene(event, this.sceneBuilderStore!.canvasOffsetX).map((vector3) => { this.viewModel.position = vector3; this.viewModel.orientation = [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); + this.viewModel.toWebGl(this.sceneBuilderStore.coreThreeRepository!); + this.sceneBuilderStore.activeFormType = undefined; + this.sceneBuilderStore.sceneItems.push(this.viewModel.toSceneItems(this.sceneBuilderStore)); + this.sceneBuilderStore.scene.push(this.viewModel); window.removeEventListener("click", this.clickLister); - this.sceneMangerStore.visibleSaveButton(); + this.sceneBuilderStore.visibleSaveButton(); }) ); @@ -49,14 +49,14 @@ export class PointStore extends FormState { updateWebGl = () => this.storeType .isEqualR(PointStoreType.previewPoint) - .map(() => this.sceneMangerStore.coreThreeRepository!.updateInstance(this.viewModel)); + .map(() => this.sceneBuilderStore.coreThreeRepository!.updateInstance(this.viewModel)); onClickNext = (pointStoreType: PointStoreType) => (this.storeType = pointStoreType); errorHandingStrategy = (error: CoreError) => {}; init = async (navigate?: NavigateFunction | undefined) => - isPreviewMode(this.sceneMangerStore.activeFormDependency).map(() => - this.sceneMangerStore.scene - .rFind((el) => el.name.isEqual(this.sceneMangerStore.selectedItemName ?? "")) + isPreviewMode(this.sceneBuilderStore.activeFormDependency).map(() => + this.sceneBuilderStore.scene + .rFind((el) => el.name.isEqual(this.sceneBuilderStore.selectedItemName ?? "")) .fold( (solidBodyModel) => { this.loadDependency(solidBodyModel); @@ -64,8 +64,8 @@ export class PointStore extends FormState { }, () => console.log( - `Unknown FormType ${this.sceneMangerStore.selectedItemName} : ${JSON.stringify( - this.sceneMangerStore.scene + `Unknown FormType ${this.sceneBuilderStore.selectedItemName} : ${JSON.stringify( + this.sceneBuilderStore.scene )}` ) ) diff --git a/ui/src/features/scene_manager/presentation/forms/robot_form/robot_form.tsx b/ui/src/features/scene_builder/forms/robot_form/robot_form.tsx similarity index 84% rename from ui/src/features/scene_manager/presentation/forms/robot_form/robot_form.tsx rename to ui/src/features/scene_builder/forms/robot_form/robot_form.tsx index b700967..5829f98 100644 --- a/ui/src/features/scene_manager/presentation/forms/robot_form/robot_form.tsx +++ b/ui/src/features/scene_builder/forms/robot_form/robot_form.tsx @@ -2,15 +2,15 @@ import React from "react"; import { observer } from "mobx-react-lite"; import { RobotFormStore, RobotStoreType } from "./robot_form_store"; import { IDefaultSceneManagerFormProps } from "../scene_manager_forms"; -import { CoreText, CoreTextType } from "../../../../../core/ui/text/text"; -import { CoreInputNumber } from "../../../../../core/ui/inputNumber/input_number"; -import { CoreInput, CoreInputType } from "../../../../../core/ui/input/input"; +import { CoreText, CoreTextType } from "../../../../core/ui/text/text"; +import { CoreInputNumber } from "../../../../core/ui/inputNumber/input_number"; +import { CoreInput, CoreInputType } from "../../../../core/ui/input/input"; import { match } from "ts-pattern"; -import { CoreSelect } from "../../../../../core/ui/select/select"; -import { ToolTypes } from "../../../../../core/model/robot_model"; -import { CoreButton } from "../../../../../core/ui/button/button"; -import { SpawnPositionTypesForm } from "../../components/spawn_position_types"; -import { CoordsForm } from "../../components/coords_form"; +import { CoreSelect } from "../../../../core/ui/select/select"; +import { ToolTypes } from "../../../../core/model/robot_model"; +import { CoreButton } from "../../../../core/ui/button/button"; +import { SpawnPositionTypesForm } from "../../presentation/components/spawn_position_types"; +import { CoordsForm } from "../../presentation/components/coords_form"; export const RobotForm = observer((props: IDefaultSceneManagerFormProps) => { const [store] = React.useState(() => new RobotFormStore(props.store)); diff --git a/ui/src/features/scene_manager/presentation/forms/robot_form/robot_form_http_repository.ts b/ui/src/features/scene_builder/forms/robot_form/robot_form_http_repository.ts similarity index 59% rename from ui/src/features/scene_manager/presentation/forms/robot_form/robot_form_http_repository.ts rename to ui/src/features/scene_builder/forms/robot_form/robot_form_http_repository.ts index 7c903e8..234e762 100644 --- a/ui/src/features/scene_manager/presentation/forms/robot_form/robot_form_http_repository.ts +++ b/ui/src/features/scene_builder/forms/robot_form/robot_form_http_repository.ts @@ -1,5 +1,5 @@ -import { RobotModel } from "../../../../../core/model/robot_model"; -import { HttpMethod, HttpRepository } from "../../../../../core/repository/core_http_repository"; +import { RobotModel } from "../../../../core/model/robot_model"; +import { HttpMethod, HttpRepository } from "../../../../core/repository/core_http_repository"; export interface RobotURL { robotUrl: string; } diff --git a/ui/src/features/scene_manager/presentation/forms/robot_form/robot_form_store.ts b/ui/src/features/scene_builder/forms/robot_form/robot_form_store.ts similarity index 63% rename from ui/src/features/scene_manager/presentation/forms/robot_form/robot_form_store.ts rename to ui/src/features/scene_builder/forms/robot_form/robot_form_store.ts index c346002..e9e1aec 100644 --- a/ui/src/features/scene_manager/presentation/forms/robot_form/robot_form_store.ts +++ b/ui/src/features/scene_builder/forms/robot_form/robot_form_store.ts @@ -1,11 +1,11 @@ import makeAutoObservable from "mobx-store-inheritance"; import { NavigateFunction } from "react-router-dom"; import { RobotFormHttpRepository } from "./robot_form_http_repository"; -import { FormState, CoreError } from "../../../../../core/store/base_store"; -import { RobotModel } from "../../../../../core/model/robot_model"; -import { SceneMangerStore } from "../../scene_manager_store"; +import { FormState, CoreError } from "../../../../core/store/base_store"; +import { RobotModel } from "../../../../core/model/robot_model"; import { isPreviewMode } from "../scene_manager_forms"; import { message } from "antd"; +import { SceneBuilderStore } from "../../presentation/scene_builder_store"; export enum RobotStoreType { previewRobot = "previewRobot", @@ -14,7 +14,7 @@ export enum RobotStoreType { awaitMouseClick = "awaitMouseClick", } export class RobotFormStore extends FormState { - sceneMangerStore: SceneMangerStore; + sceneBuilderStore: SceneBuilderStore; storeType: RobotStoreType = RobotStoreType.initNewRobot; viewModel: RobotModel = RobotModel.empty(); robotFormHttpRepository: RobotFormHttpRepository = new RobotFormHttpRepository(); @@ -22,14 +22,14 @@ export class RobotFormStore extends FormState { listener: Function; clickLister = (event: MouseEvent) => this.storeType.isEqualR(RobotStoreType.awaitMouseClick).map(() => - this.sceneMangerStore!.clickScene(event, this.sceneMangerStore!.canvasOffsetX).map((vector3) => { + this.sceneBuilderStore!.clickScene(event, this.sceneBuilderStore!.canvasOffsetX).map((vector3) => { this.viewModel.position = 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.viewModel.toWebGl(this.sceneBuilderStore.coreThreeRepository!); + this.sceneBuilderStore.activeFormType = undefined; + this.sceneBuilderStore.sceneItems.push(this.viewModel.toSceneItems(this.sceneBuilderStore)); + this.sceneBuilderStore.scene.push(this.viewModel); window.removeEventListener("click", this.clickLister); - this.sceneMangerStore.visibleSaveButton(); + this.sceneBuilderStore.visibleSaveButton(); }) ); @@ -41,18 +41,18 @@ export class RobotFormStore extends FormState { dispose = (): void => { window.removeEventListener("click", this.clickLister); }; - constructor(sceneMangerStore: SceneMangerStore) { + constructor(sceneBuilderStore: SceneBuilderStore) { super(); makeAutoObservable(this); - this.sceneMangerStore = sceneMangerStore; + this.sceneBuilderStore = sceneBuilderStore; } updateScene = () => this.storeType .isEqualR(RobotStoreType.previewRobot) .map( () => ( - this.viewModel.update(this.sceneMangerStore.coreThreeRepository!), - this.sceneMangerStore.visibleSaveButton() + this.viewModel.update(this.sceneBuilderStore.coreThreeRepository!), + this.sceneBuilderStore.visibleSaveButton() ) ); createNewRobot = () => @@ -71,9 +71,9 @@ export class RobotFormStore extends FormState { ); errorHandingStrategy = (error: CoreError) => {}; init = async (navigate?: NavigateFunction | undefined) => - isPreviewMode(this.sceneMangerStore.activeFormDependency).map(() => - this.sceneMangerStore.scene - .rFind((el) => el.name.isEqual(this.sceneMangerStore.selectedItemName ?? "")) + isPreviewMode(this.sceneBuilderStore.activeFormDependency).map(() => + this.sceneBuilderStore.scene + .rFind((el) => el.name.isEqual(this.sceneBuilderStore.selectedItemName ?? "")) .fold( (solidBodyModel) => { this.loadDependency(solidBodyModel); @@ -81,8 +81,8 @@ export class RobotFormStore extends FormState { }, () => console.log( - `Unknown FormType ${this.sceneMangerStore.selectedItemName} : ${JSON.stringify( - this.sceneMangerStore.scene + `Unknown FormType ${this.sceneBuilderStore.selectedItemName} : ${JSON.stringify( + this.sceneBuilderStore.scene )}` ) ) diff --git a/ui/src/features/scene_manager/presentation/forms/scene_manager_forms.tsx b/ui/src/features/scene_builder/forms/scene_manager_forms.tsx similarity index 83% rename from ui/src/features/scene_manager/presentation/forms/scene_manager_forms.tsx rename to ui/src/features/scene_builder/forms/scene_manager_forms.tsx index dfbdbf9..23d8f54 100644 --- a/ui/src/features/scene_manager/presentation/forms/scene_manager_forms.tsx +++ b/ui/src/features/scene_builder/forms/scene_manager_forms.tsx @@ -1,5 +1,6 @@ -import { Result } from "../../../../core/helper/result"; -import { SceneMangerStore } from "../scene_manager_store"; +import { Result } from "../../../core/helper/result"; +import { SceneBuilderStore } from "../presentation/scene_builder_store"; +import { SceneMangerStore } from "../../scene_manager/presentation/scene_manager_store"; import { CameraForm } from "./camera/camera_form"; import { LightForm } from "./light/light_form"; import { PointForm } from "./point/point_form"; @@ -25,13 +26,13 @@ interface IForms { } export interface IDefaultSceneManagerFormProps { dependency: Object; - store: SceneMangerStore; + store: SceneBuilderStore; } export const isPreviewMode = (dependency: Object): Result => { if (Object.hasOwn(dependency, "type")) return Result.ok(); return Result.error(undefined); }; -export const sceneManagerForms = (props: Object, store: SceneMangerStore): IForms[] => [ +export const sceneManagerForms = (props: Object, store: SceneBuilderStore): IForms[] => [ { name: SceneManagerForms.camera, component: }, { name: SceneManagerForms.robot, component: }, { name: SceneManagerForms.solidBody, component: }, diff --git a/ui/src/features/scene_manager/presentation/forms/solid_body/solid_body_form.tsx b/ui/src/features/scene_builder/forms/solid_body/solid_body_form.tsx similarity index 85% rename from ui/src/features/scene_manager/presentation/forms/solid_body/solid_body_form.tsx rename to ui/src/features/scene_builder/forms/solid_body/solid_body_form.tsx index 753abd1..0ca0f2b 100644 --- a/ui/src/features/scene_manager/presentation/forms/solid_body/solid_body_form.tsx +++ b/ui/src/features/scene_builder/forms/solid_body/solid_body_form.tsx @@ -1,13 +1,13 @@ import React from "react"; -import { CoreText, CoreTextType } from "../../../../../core/ui/text/text"; +import { CoreText, CoreTextType } from "../../../../core/ui/text/text"; import { IDefaultSceneManagerFormProps } from "../scene_manager_forms"; import { SolidBodyStore, SolidBodyStoreType } from "./solid_body_store"; import { observer } from "mobx-react-lite"; -import { CoreButton } from "../../../../../core/ui/button/button"; +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"; +import { SpawnPositionTypesForm } from "../../presentation/components/spawn_position_types"; +import { CoreInput } from "../../../../core/ui/input/input"; +import { CoordsForm } from "../../presentation/components/coords_form"; export const SolidBodyForm = observer((props: IDefaultSceneManagerFormProps) => { const [store] = React.useState(() => new SolidBodyStore(props.store)); diff --git a/ui/src/features/scene_manager/presentation/forms/solid_body/solid_body_store.tsx b/ui/src/features/scene_builder/forms/solid_body/solid_body_store.tsx similarity index 58% rename from ui/src/features/scene_manager/presentation/forms/solid_body/solid_body_store.tsx rename to ui/src/features/scene_builder/forms/solid_body/solid_body_store.tsx index 5c02027..fa71ca6 100644 --- a/ui/src/features/scene_manager/presentation/forms/solid_body/solid_body_store.tsx +++ b/ui/src/features/scene_builder/forms/solid_body/solid_body_store.tsx @@ -1,12 +1,12 @@ import makeAutoObservable from "mobx-store-inheritance"; -import { FormState, CoreError } from "../../../../../core/store/base_store"; -import { CoreHttpRepository } from "../../../../../core/repository/core_http_repository"; -import { Parts } from "../../../../details/details_http_repository"; +import { FormState, CoreError } from "../../../../core/store/base_store"; +import { CoreHttpRepository } from "../../../../core/repository/core_http_repository"; +import { Parts } from "../../../details/details_http_repository"; import { Vector2 } from "three"; -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 { SolidModel } from "../../../../../core/model/solid_model"; +import { SolidModel } from "../../../../core/model/solid_model"; +import { SceneBuilderStore } from "../../presentation/scene_builder_store"; export enum SolidBodyStoreType { selectBody = "selectBody", @@ -23,18 +23,18 @@ export class SolidBodyStore extends FormState { solidBodyStoreType: SolidBodyStoreType = SolidBodyStoreType.selectBody; selectBody: Parts; spawnType: string; - sceneMangerStore: SceneMangerStore; + sceneBuilderStore: SceneBuilderStore; vector2d?: Vector2; - constructor(sceneMangerStore: SceneMangerStore) { + constructor(sceneBuilderStore: SceneBuilderStore) { super(); - this.sceneMangerStore = sceneMangerStore; + this.sceneBuilderStore = sceneBuilderStore; makeAutoObservable(this); } init = async () => { - isPreviewMode(this.sceneMangerStore.activeFormDependency).map(() => - this.sceneMangerStore.scene - .rFind((el) => el.name.isEqual(this.sceneMangerStore.selectedItemName ?? "")) + isPreviewMode(this.sceneBuilderStore.activeFormDependency).map(() => + this.sceneBuilderStore.scene + .rFind((el) => el.name.isEqual(this.sceneBuilderStore.selectedItemName ?? "")) .fold( (solidBodyModel) => { this.loadDependency(solidBodyModel); @@ -42,8 +42,8 @@ export class SolidBodyStore extends FormState { }, () => console.log( - `Unknown FormType ${this.sceneMangerStore.selectedItemName} : ${JSON.stringify( - this.sceneMangerStore.scene + `Unknown FormType ${this.sceneBuilderStore.selectedItemName} : ${JSON.stringify( + this.sceneBuilderStore.scene )}` ) ) @@ -62,21 +62,21 @@ export class SolidBodyStore extends FormState { }; clickLister = (event: MouseEvent) => this.solidBodyStoreType.isEqualR(SolidBodyStoreType.spawn2DVector).map(() => - this.sceneMangerStore!.clickScene(event, this.sceneMangerStore!.canvasOffsetX).map((vector3) => { + this.sceneBuilderStore!.clickScene(event, this.sceneBuilderStore!.canvasOffsetX).map((vector3) => { this.viewModel.position = vector3; this.viewModel.spawnType = "BoundBox"; - this.viewModel.toWebGl(this.sceneMangerStore.coreThreeRepository!); - this.sceneMangerStore.sceneItems.push(this.viewModel.toSceneItems()); - this.sceneMangerStore.scene.push(this.viewModel); + this.viewModel.toWebGl(this.sceneBuilderStore.coreThreeRepository!); + this.sceneBuilderStore.sceneItems.push(this.viewModel.toSceneItems()); + this.sceneBuilderStore.scene.push(this.viewModel); window.removeEventListener("click", this.clickLister); - this.sceneMangerStore.activeFormType = undefined; - this.sceneMangerStore.visibleSaveButton() + this.sceneBuilderStore.activeFormType = undefined; + this.sceneBuilderStore.visibleSaveButton() }) ); updateBodySimulation = () => this.solidBodyStoreType .isEqualR(SolidBodyStoreType.previewSolid) - .map(() => this.viewModel.update(this.sceneMangerStore.coreThreeRepository!)); + .map(() => this.viewModel.update(this.sceneBuilderStore.coreThreeRepository!)); clickSelectBody = (el: Parts) => { this.selectBody = el; this.solidBodyStoreType = SolidBodyStoreType.selectSpawnPositionType; diff --git a/ui/src/features/scene_manager/presentation/forms/trajectory/trajectory_form.tsx b/ui/src/features/scene_builder/forms/trajectory/trajectory_form.tsx similarity index 100% rename from ui/src/features/scene_manager/presentation/forms/trajectory/trajectory_form.tsx rename to ui/src/features/scene_builder/forms/trajectory/trajectory_form.tsx diff --git a/ui/src/features/scene_builder/forms/trajectory/trajectory_http_repository.ts b/ui/src/features/scene_builder/forms/trajectory/trajectory_http_repository.ts new file mode 100644 index 0000000..526d21c --- /dev/null +++ b/ui/src/features/scene_builder/forms/trajectory/trajectory_http_repository.ts @@ -0,0 +1,3 @@ +import { HttpRepository } from "../../../../core/repository/core_http_repository"; + +export class TrajectoryHttpRepository extends HttpRepository {} diff --git a/ui/src/features/scene_manager/presentation/forms/trajectory/trajectory_store.ts b/ui/src/features/scene_builder/forms/trajectory/trajectory_store.ts similarity index 90% rename from ui/src/features/scene_manager/presentation/forms/trajectory/trajectory_store.ts rename to ui/src/features/scene_builder/forms/trajectory/trajectory_store.ts index 579bf85..5057382 100644 --- a/ui/src/features/scene_manager/presentation/forms/trajectory/trajectory_store.ts +++ b/ui/src/features/scene_builder/forms/trajectory/trajectory_store.ts @@ -2,7 +2,7 @@ import makeAutoObservable from "mobx-store-inheritance"; import { NavigateFunction } from "react-router-dom"; import { TrajectoryViewModel } from "./trajectory_view_model"; import { TrajectoryHttpRepository } from "./trajectory_http_repository"; -import { FormState, CoreError } from "../../../../../core/store/base_store"; +import { FormState, CoreError } from "../../../../core/store/base_store"; export class TrajectoryStore extends FormState { constructor() { diff --git a/ui/src/features/scene_manager/presentation/forms/trajectory/trajectory_view_model.ts b/ui/src/features/scene_builder/forms/trajectory/trajectory_view_model.ts similarity index 76% rename from ui/src/features/scene_manager/presentation/forms/trajectory/trajectory_view_model.ts rename to ui/src/features/scene_builder/forms/trajectory/trajectory_view_model.ts index 8d225c8..8b62bab 100644 --- a/ui/src/features/scene_manager/presentation/forms/trajectory/trajectory_view_model.ts +++ b/ui/src/features/scene_builder/forms/trajectory/trajectory_view_model.ts @@ -1,4 +1,4 @@ -import { Result } from "../../../../../core/helper/result"; +import { Result } from "../../../../core/helper/result"; export class TrajectoryViewModel { diff --git a/ui/src/features/scene_manager/presentation/forms/zone/zone_form.tsx b/ui/src/features/scene_builder/forms/zone/zone_form.tsx similarity index 89% rename from ui/src/features/scene_manager/presentation/forms/zone/zone_form.tsx rename to ui/src/features/scene_builder/forms/zone/zone_form.tsx index 4322ffe..f528e34 100644 --- a/ui/src/features/scene_manager/presentation/forms/zone/zone_form.tsx +++ b/ui/src/features/scene_builder/forms/zone/zone_form.tsx @@ -2,8 +2,8 @@ import React from "react"; import { observer } from "mobx-react-lite"; import { ZoneStore } from "./zone_store"; import { IDefaultSceneManagerFormProps } from "../scene_manager_forms"; -import { CoreText, CoreTextType } from "../../../../../core/ui/text/text"; -import { CoreInput } from "../../../../../core/ui/input/input"; +import { CoreText, CoreTextType } from "../../../../core/ui/text/text"; +import { CoreInput } from "../../../../core/ui/input/input"; export const ZoneForm = observer((props: IDefaultSceneManagerFormProps) => { const [store] = React.useState(() => new ZoneStore(props.store)); diff --git a/ui/src/features/scene_builder/forms/zone/zone_store.ts b/ui/src/features/scene_builder/forms/zone/zone_store.ts new file mode 100644 index 0000000..f67ad10 --- /dev/null +++ b/ui/src/features/scene_builder/forms/zone/zone_store.ts @@ -0,0 +1,44 @@ +import makeAutoObservable from "mobx-store-inheritance"; +import { NavigateFunction } from "react-router-dom"; +import { ZoneModel } from "../../../../core/model/zone_model"; + +import { FormState, CoreError } from "../../../../core/store/base_store"; +import { isPreviewMode } from "../scene_manager_forms"; +import { SceneMangerStore } from "../../../scene_manager/presentation/scene_manager_store"; +import { SceneBuilderStore } from "../../presentation/scene_builder_store"; +export enum ZoneStoreType { + preview = "preview", +} +export class ZoneStore extends FormState { + constructor(sceneBuilderStore: SceneBuilderStore) { + super(); + this.sceneBuilderStore = sceneBuilderStore; + makeAutoObservable(this); + } + storeType: ZoneStoreType; + sceneBuilderStore: SceneBuilderStore; + viewModel: ZoneModel = ZoneModel.empty(); + errorHandingStrategy = (_error: CoreError) => {}; + init = async (_navigate?: NavigateFunction | undefined) => { + isPreviewMode(this.sceneBuilderStore.activeFormDependency).map(() => + this.sceneBuilderStore.scene + .rFind((el) => el.name.isEqual(this.sceneBuilderStore.selectedItemName ?? "")) + .fold( + (zoneModel) => { + this.loadDependency(zoneModel); + this.storeType = ZoneStoreType.preview; + }, + () => + console.log( + `Unknown FormType ${this.sceneBuilderStore.selectedItemName} : ${JSON.stringify( + this.sceneBuilderStore.scene + )}` + ) + ) + ); + }; + updateWebGl = () => + this.storeType + .isEqualR(ZoneStoreType.preview) + .map(() => this.sceneBuilderStore.coreThreeRepository!.updateInstance(this.viewModel)); +} diff --git a/ui/src/features/scene_manager/presentation/components/coords_form.tsx b/ui/src/features/scene_builder/presentation/components/coords_form.tsx similarity index 100% rename from ui/src/features/scene_manager/presentation/components/coords_form.tsx rename to ui/src/features/scene_builder/presentation/components/coords_form.tsx diff --git a/ui/src/features/scene_manager/presentation/components/scene_menu.tsx b/ui/src/features/scene_builder/presentation/components/scene_menu.tsx similarity index 100% rename from ui/src/features/scene_manager/presentation/components/scene_menu.tsx rename to ui/src/features/scene_builder/presentation/components/scene_menu.tsx diff --git a/ui/src/features/scene_manager/presentation/components/scene_widget.tsx b/ui/src/features/scene_builder/presentation/components/scene_widget.tsx similarity index 100% rename from ui/src/features/scene_manager/presentation/components/scene_widget.tsx rename to ui/src/features/scene_builder/presentation/components/scene_widget.tsx diff --git a/ui/src/features/scene_manager/presentation/components/spawn_position_types.tsx b/ui/src/features/scene_builder/presentation/components/spawn_position_types.tsx similarity index 100% rename from ui/src/features/scene_manager/presentation/components/spawn_position_types.tsx rename to ui/src/features/scene_builder/presentation/components/spawn_position_types.tsx diff --git a/ui/src/features/scene_builder/presentation/scene_builder_screen.tsx b/ui/src/features/scene_builder/presentation/scene_builder_screen.tsx new file mode 100644 index 0000000..f9b9efe --- /dev/null +++ b/ui/src/features/scene_builder/presentation/scene_builder_screen.tsx @@ -0,0 +1,167 @@ +import React from "react"; +import { observer } from "mobx-react-lite"; +import { SceneBuilderStore } from "./scene_builder_store"; +import { useStore } from "../../../core/helper/use_store"; +import { useParams } from "react-router-dom"; +import { Popover } from "antd"; +import { CoreButton } from "../../../core/ui/button/button"; +import { Icon } from "../../../core/ui/icons/icons"; +import { MainPage } from "../../../core/ui/pages/main_page"; +import { CoreText, CoreTextType } from "../../../core/ui/text/text"; +import { SceneMode } from "../../scene_manager/model/scene_view"; +import { sceneManagerForms } from "../forms/scene_manager_forms"; + +export const SceneBuilderScreenPath = "/scene/builder/"; + +export const SceneBuilderScreen = observer(() => { + const store = useStore(SceneBuilderStore); + const canvasRef = React.useRef(null); + const id = useParams().id as string; + store.initParam(id); + + React.useEffect(() => { + store.loadScene(canvasRef.current!); + document.body.style.overflow = "hidden"; + return () => { + document.body.style.overflow = "scroll"; + store.dispose(); + }; + }, [id, store]); + return ( + +
+
+
+ + + {store.popoverItems.map((el, i) => ( +
el.fn()}> + +
+ ))} +
+ } + > + + + + +
+
+
+ {store.sceneHelperInstruments.map((el, i) => ( +
el.onClick()} + style={{ + marginTop: 4, + width: 50, + height: 50, + backgroundColor: el.isSelected ? "rgba(160, 132, 255, 1)" : "rgba(99, 81, 159, 1)", + border: "1px solid", + borderRadius: 5, + }} + > + +
+ ))} + {store.isVisibleSaveButton ? ( + <> +
store.sceneSave()} + style={{ + marginTop: 4, + width: 50, + height: 50, + backgroundColor: "rgba(99, 81, 159, 1)", + border: "1px solid", + borderRadius: 5, + }} + > + +
+ + ) : null} +
+
+
+
+
+
+ {store.sceneItems.map((el, index) => ( +
store.selectSceneItems(el.name, index, !el.isSelected, el.icon)} + > + +
+ + store.deleteSceneItem(el)} + style={{ marginRight: 10 }} + /> +
+ ))} +
+
+
+
+ {sceneManagerForms(store.activeFormDependency ?? {}, store).map((el, i) => + el.name.isEqualR(store.activeFormType ?? "").fold( + () => {el.component}, + () => + ) + )} +
+
+ + } + bodyChildren={ + <> + <> + + + + } + /> + ); +}); diff --git a/ui/src/features/scene_builder/presentation/scene_builder_store.ts b/ui/src/features/scene_builder/presentation/scene_builder_store.ts new file mode 100644 index 0000000..7581668 --- /dev/null +++ b/ui/src/features/scene_builder/presentation/scene_builder_store.ts @@ -0,0 +1,262 @@ +import { message } from "antd"; +import makeAutoObservable from "mobx-store-inheritance"; +import { Vector2, Vector3, Object3D } from "three"; +import { CameraModel } from "../../../core/model/camera_model"; +import { PointModel } from "../../../core/model/point_model"; +import { RobotModel } from "../../../core/model/robot_model"; +import { SceneAsset, Instance } from "../../../core/model/scene_asset"; +import { SolidModel } from "../../../core/model/solid_model"; +import { UiBaseError } from "../../../core/model/ui_base_error"; +import { ZoneModel } from "../../../core/model/zone_model"; +import { HttpError } from "../../../core/repository/core_http_repository"; +import { CoreThreeRepository } from "../../../core/repository/core_three_repository"; +import { SceneModel } from "../../scene_manager/model/scene_model"; +import { SceneMode } from "../../scene_manager/model/scene_view"; +import { SceneViewModel } from "../../scene_manager/model/scene_view_model"; +import { SceneManagerForms } from "../forms/scene_manager_forms"; +import { FormState } from "../../../core/store/base_store"; +import { Result } from "../../../core/helper/result"; +import { SceneBuilderHttpRepository } from "../data/scene_builder_repository"; +import { SceneModelsTypes } from "../../../core/model/scene_models_type"; +export enum StoreMode { + sceneInstance = "sceneInstance", + allScenes = "allScenes", +} +export interface ISpawnHelper { + url: string; + spawn: SceneModelsTypes; + name: string; + isFinished: boolean; + type: string; +} +export interface IPopoverItem { + name: string; + fn: Function; +} +export interface SceneItems { + fn: Function; + name: string; + isSelected: boolean; + icon: string; +} +export class SceneBuilderStore extends FormState { + activeFormType?: string; + activeSceneId: string = ""; + selectedItemName?: string; + activeFormDependency: Object = {}; + viewModel: SceneViewModel = SceneViewModel.empty(); + sceneMode: SceneMode; + sceneItems: SceneItems[] = []; + isVisibleSaveButton: boolean = false; + coreThreeRepository: null | CoreThreeRepository = null; + sceneBuilderHttpRepository: SceneBuilderHttpRepository; + isSceneMenuShow = false; + robossemblerAssets?: SceneAsset; + objectForMagnetism: string; + objectMagnetism: string; + scenes: SceneModel[] = []; + canvasRef?: HTMLCanvasElement; + mousePosition?: Vector2; + spawnHelper?: ISpawnHelper; + selectSceneObject?: Object; + isLoadingForm: boolean = false; + scene: (Instance | SolidModel | CameraModel | RobotModel | PointModel | ZoneModel)[] = []; + + sceneHelperInstruments: { + icon: string; + onClick: Function; + isSelected: boolean; + }[] = [ + { icon: SceneMode.Select, onClick: () => this.setMode(SceneMode.Select), isSelected: false }, + { icon: SceneMode.Move, onClick: () => this.setMode(SceneMode.Move), isSelected: false }, + { icon: SceneMode.Rotate, onClick: () => this.setMode(SceneMode.Rotate), isSelected: false }, + ]; + popoverItems: IPopoverItem[] = [ + { name: "Камера", fn: () => this.createNewForm(SceneManagerForms.camera, true) }, + { name: "Твердое тело", fn: () => this.createNewForm(SceneManagerForms.solidBody, true) }, + { name: "Источник света", fn: () => this.createNewForm(SceneManagerForms.light, true) }, + { name: "Робот", fn: () => this.createNewForm(SceneManagerForms.robot, true) }, + { name: "Точка", fn: () => this.createNewForm(SceneManagerForms.point, true) }, + { name: "Траектория", fn: () => this.createNewForm(SceneManagerForms.trajectory, true) }, + { name: "Зона", fn: () => this.createNewForm(SceneManagerForms.zone, true) }, + { name: "Точки захвата", fn: () => this.createNewForm(SceneManagerForms.capturePoints, true) }, + ]; + canvasOffsetX?: number; + sceneName?: string; + constructor() { + super(); + makeAutoObservable(this); + + this.sceneBuilderHttpRepository = new SceneBuilderHttpRepository(); + this.sceneMode = SceneMode.Select; + } + sceneSave = () => + this.messageHttp(this.sceneBuilderHttpRepository.editScene(SceneAsset.newScene(this.scene, this.sceneName ?? "")), { + successMessage: "Сцена сохранена", + }).then(() => (this.isVisibleSaveButton = false)); + + iconToSceneManagerForm = (icon: string): SceneManagerForms => { + if (icon.isEqual("Camera")) { + this.activeFormDependency = { + type: "Preview", + }; + return SceneManagerForms.camera; + } + if (icon.isEqual("Zone")) { + this.activeFormDependency = { + type: "Preview", + }; + return SceneManagerForms.zone; + } + if (icon.isEqual("Robot")) { + this.activeFormDependency = { + type: "Preview", + }; + return SceneManagerForms.robot; + } + if (icon.isEqual("Point")) { + this.activeFormDependency = { + type: "Preview", + }; + return SceneManagerForms.point; + } + + this.activeFormDependency = { + type: "Preview", + }; + return SceneManagerForms.solidBody; + }; + selectSceneItems = (name: string, index: number, selected: boolean, icon: string) => { + this.sceneItems.map((el) => { + el.isSelected = false; + return el; + }); + this.sceneItems.map((el, i) => i.isEqualR(index).map(() => (el.isSelected = selected))); + if (selected) { + this.createNewForm(this.iconToSceneManagerForm(icon)); + this.selectedItemName = name; + } + + if (!selected) { + this.createNewForm(undefined); + this.selectedItemName = undefined; + } + }; + + setMode = (mode: SceneMode) => { + this.sceneHelperInstruments.map((el) => { + el.isSelected = false; + el.icon.isEqualR(mode).map(() => (el.isSelected = true)); + return el; + }); + this.sceneMode = mode; + this.coreThreeRepository?.setTransformMode(this.sceneMode); + }; + createNewForm = (formType: SceneManagerForms | undefined, isNeedClearDependency?: boolean) => { + this.activeFormDependency = Object.assign(this.activeFormDependency, { store: this }); + if (isNeedClearDependency) this.activeFormDependency = { store: this }; + this.activeFormType = formType; + }; + + deleteSceneItem = (item: SceneItems) => { + this.sceneItems = this.sceneItems.filter((el) => !el.name.isEqual(item.name)); + + this.coreThreeRepository?.deleteSceneItem(item); + this.visibleSaveButton(); + }; + + visibleSaveButton = () => { + this.isVisibleSaveButton = true; + }; + + addNewCamera = (model: CameraModel) => { + model.position = this.coreThreeRepository!.camera.position; + model.orientation = 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); + model.toWebGl(this.coreThreeRepository!); + this.visibleSaveButton(); + }; + + hiddenMenu = () => (this.isSceneMenuShow = false); + + init = async () => {}; + initParam = (id: string | undefined) => { + if (id) this.activeSceneId = id; + }; + errorHandingStrategy = (error: HttpError) => + error.status.isEqualR(404).map(() => this.errors.push(new UiBaseError(`not found to project`))); + + loadScene = (canvasRef: HTMLCanvasElement) => { + this.canvasRef = canvasRef; + this.loadWebGl(canvasRef); + }; + + loadWebGl = async (canvasRef: HTMLCanvasElement): Promise => { + this.coreThreeRepository = new CoreThreeRepository(canvasRef as HTMLCanvasElement, this.watcherSceneEditorObject); + + this.coreThreeRepository.render(); + + this.canvasOffsetX = canvasRef.getBoundingClientRect().x; + canvasRef.addEventListener("click", (event) => this.clickLister(event, canvasRef.getBoundingClientRect().x)); + + (await this.sceneBuilderHttpRepository.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(); + + vector.x = ((event.clientX - offset) / boundingRect.width) * 2 - 1; + vector.y = -(event.clientY / boundingRect.height) * 2 + 1; + return this.coreThreeRepository!.setRayCastAndGetFirstObjectAndPointToObject(vector); + }; + clickLister = (event: MouseEvent, offset: number = 0) => { + const vector = new Vector2(); + const boundingRect = this.canvasRef!.getBoundingClientRect(); + + vector.x = ((event.clientX - offset) / boundingRect.width) * 2 - 1; + vector.y = -(event.clientY / boundingRect.height) * 2 + 1; + + if (this.sceneMode.isEqual(SceneMode.Select)) { + return; + } + + if (this.sceneMode.isEqualMany([SceneMode.Move, SceneMode.Rotate])) { + this.transformContollsCall(vector); + } + }; + + watcherSceneEditorObject = (mesh: Object3D) => ( + (this.scene = this.scene.map((el) => + el.name.isEqualR(mesh.name).fold( + () => { + el.position = mesh.position; + el.orientation = mesh.quaternion.toArray(); + return el; + }, + () => el + ) + )), + this.visibleSaveButton() + ); + + transformContollsCall = (vector: Vector2) => + // @ts-ignore + this.coreThreeRepository?.setRayCastAndGetFirstObject(vector).fold( + (object) => this.coreThreeRepository?.setTransformControlsAttach(object), + (_) => this.coreThreeRepository?.disposeTransformControlsMode() + ); + + dispose = () => { + window.removeEventListener("click", this.clickLister); + }; +} 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 709b826..fc1d750 100644 --- a/ui/src/features/scene_manager/data/scene_http_repository.ts +++ b/ui/src/features/scene_manager/data/scene_http_repository.ts @@ -2,10 +2,8 @@ import { Result } from "../../../core/helper/result"; import { HttpMethod, CoreHttpRepository } from "../../../core/repository/core_http_repository"; import { CoreError } from "../../../core/store/base_store"; import { SceneViewModel } from "../model/scene_view_model"; -import { SceneAsset } from "../../../core/model/scene_asset"; export class SceneHttpRepository extends CoreHttpRepository { - editScene = (scene: SceneAsset) => this._jsonRequest(HttpMethod.PUT, "/scenes", scene); deleteScene = (sceneId:string) => this._jsonRequest(HttpMethod.DELETE, '/scenes', ) newScene = (sceneViewModel: SceneViewModel) => this._jsonRequest(HttpMethod.POST, "/scenes", sceneViewModel) as unknown as Promise>; diff --git a/ui/src/features/scene_manager/presentation/forms/trajectory/trajectory_http_repository.ts b/ui/src/features/scene_manager/presentation/forms/trajectory/trajectory_http_repository.ts deleted file mode 100644 index f44ce3f..0000000 --- a/ui/src/features/scene_manager/presentation/forms/trajectory/trajectory_http_repository.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { HttpRepository } from "../../../../../core/repository/core_http_repository"; - -export class TrajectoryHttpRepository 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 deleted file mode 100644 index aa58db3..0000000 --- a/ui/src/features/scene_manager/presentation/forms/zone/zone_store.ts +++ /dev/null @@ -1,43 +0,0 @@ -import makeAutoObservable from "mobx-store-inheritance"; -import { NavigateFunction } from "react-router-dom"; -import { ZoneModel } from "../../../../../core/model/zone_model"; - -import { FormState, CoreError } from "../../../../../core/store/base_store"; -import { isPreviewMode } from "../scene_manager_forms"; -import { SceneMangerStore } from "../../scene_manager_store"; -export enum ZoneStoreType { - preview = "preview", -} -export class ZoneStore extends FormState { - constructor(sceneMangerStore: SceneMangerStore) { - super(); - this.sceneMangerStore = sceneMangerStore; - makeAutoObservable(this); - } - storeType: ZoneStoreType; - sceneMangerStore: SceneMangerStore; - viewModel: ZoneModel = ZoneModel.empty(); - errorHandingStrategy = (_error: CoreError) => {}; - init = async (_navigate?: NavigateFunction | undefined) => { - isPreviewMode(this.sceneMangerStore.activeFormDependency).map(() => - this.sceneMangerStore.scene - .rFind((el) => el.name.isEqual(this.sceneMangerStore.selectedItemName ?? "")) - .fold( - (zoneModel) => { - this.loadDependency(zoneModel); - this.storeType = ZoneStoreType.preview; - }, - () => - console.log( - `Unknown FormType ${this.sceneMangerStore.selectedItemName} : ${JSON.stringify( - this.sceneMangerStore.scene - )}` - ) - ) - ); - }; - updateWebGl = () => - this.storeType - .isEqualR(ZoneStoreType.preview) - .map(() => this.sceneMangerStore.coreThreeRepository!.updateInstance(this.viewModel)); -} diff --git a/ui/src/features/scene_manager/presentation/scene_manager.tsx b/ui/src/features/scene_manager/presentation/scene_manager.tsx index 6a25803..2da14c3 100644 --- a/ui/src/features/scene_manager/presentation/scene_manager.tsx +++ b/ui/src/features/scene_manager/presentation/scene_manager.tsx @@ -1,5 +1,5 @@ import * as React from "react"; -import { DrawersSceneManager, SceneMangerStore, StoreMode } from "./scene_manager_store"; +import { DrawersSceneManager, SceneMangerStore } from "./scene_manager_store"; import { observer } from "mobx-react-lite"; import { Drawer, Popover } from "antd"; import { useNavigate, useParams } from "react-router-dom"; @@ -9,258 +9,113 @@ import { CoreButton } from "../../../core/ui/button/button"; import { CoreInput } from "../../../core/ui/input/input"; import { DrawersDataset } from "../../dataset/dataset_store"; import { Icon } from "../../../core/ui/icons/icons"; -import { sceneManagerForms } from "./forms/scene_manager_forms"; +import { sceneManagerForms } from "../../scene_builder/forms/scene_manager_forms"; import { SceneMode } from "../model/scene_view"; import { useStore } from "../../../core/helper/use_store"; +import { SceneBuilderScreenPath } from "../../scene_builder/presentation/scene_builder_screen"; export const SceneManagerPath = "/scene/manager/"; export const SceneManger = observer(() => { - const canvasRef = React.useRef(null); const store = useStore(SceneMangerStore); - const id = useParams().id as string; const navigate = useNavigate(); - store.initParam(id); - - React.useEffect(() => { - store.loadScene(canvasRef.current!); - document.body.style.overflow = "hidden"; - return () => { - document.body.style.overflow = "scroll"; - store.dispose(); - }; - }, [id, store]); return ( "", - () => "none" - ), + display: "none", }} - panelChildren={ -
-
-
- - - {store.popoverItems.map((el, i) => ( -
el.fn()}> - -
- ))} -
- } - > - - - - -
-
-
- {store.sceneHelperInstruments.map((el, i) => ( -
el.onClick()} - style={{ - marginTop: 4, - width: 50, - height: 50, - backgroundColor: el.isSelected ? "rgba(160, 132, 255, 1)" : "rgba(99, 81, 159, 1)", - border: "1px solid", - borderRadius: 5, - }} - > - -
- ))} - {store.isVisibleSaveButton ? ( - <> -
store.sceneSave()} - style={{ - marginTop: 4, - width: 50, - height: 50, - backgroundColor: "rgba(99, 81, 159, 1)", - border: "1px solid", - borderRadius: 5, - }} - > - -
- - ) : null} -
-
-
-
-
-
- {store.sceneItems.map((el, index) => ( -
store.selectSceneItems(el.name, index, !el.isSelected, el.icon)} - > - -
- - store.deleteSceneItem(el)} - style={{ marginRight: 10 }} - /> -
- ))} -
-
-
-
- {sceneManagerForms(store.activeFormDependency ?? {}, store).map((el, i) => - el.name.isEqualR(store.activeFormType ?? "").fold( - () => {el.component}, - () => - ) - )} -
-
- } bodyChildren={ <> - {store.storeMode.isEqual(StoreMode.sceneInstance) ? ( - <> - - - ) : ( +
+
+
+ + store.editDrawer(DrawersSceneManager.NewScene, true)} + type={CoreTextType.small} + color="rgba(68, 142, 247, 1)" + style={{ cursor: "pointer" }} + /> + +
+ {store.scenes.map((el, i) => ( +
+ +
+ navigate(`${SceneBuilderScreenPath}${el._id}`)} + textStyle={{ color: "black", textAlign: "center" }} + style={{ marginRight: 10, backgroundColor: "white", width: 126 }} + /> + +
+
+ ))} +
+
+
+
+
+ store.editDrawer(DrawersSceneManager.NewScene, false)} + open={store.drawers.find((el) => el.name === DrawersSceneManager.NewScene)?.status} > -
-
- - store.editDrawer(DrawersSceneManager.NewScene, true)} - type={CoreTextType.small} - color="rgba(68, 142, 247, 1)" - style={{ cursor: "pointer" }} - /> - -
- {store.scenes.map((el, i) => ( -
- -
- { - navigate(`${SceneManagerPath}${el._id}`); - }} - textStyle={{ color: "black", textAlign: "center" }} - style={{ marginRight: 10, backgroundColor: "white", width: 126 }} - /> - -
-
- ))} -
-
-
-
-
- store.editDrawer(DrawersSceneManager.NewScene, false)} - open={store.drawers.find((el) => el.name === DrawersSceneManager.NewScene)?.status} + style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", height: "100%" }} > -
- store.updateForm({ name: text })} - /> + store.updateForm({ name: text })} + /> -
- store.createNewScene()} /> -
- store.editDrawer(DrawersDataset.NewDataset, false)} /> -
+
+ store.createNewScene()} /> +
+ store.editDrawer(DrawersDataset.NewDataset, false)} />
- -
- )} +
+ +
} /> 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 fc2e6dd..de75eed 100644 --- a/ui/src/features/scene_manager/presentation/scene_manager_store.ts +++ b/ui/src/features/scene_manager/presentation/scene_manager_store.ts @@ -1,57 +1,30 @@ import makeAutoObservable from "mobx-store-inheritance"; -import { Object3D, Vector2, Vector3 } from "three"; +import { Vector2 } from "three"; import { message } from "antd"; import { CoreThreeRepository } from "../../../core/repository/core_three_repository"; import { HttpError } from "../../../core/repository/core_http_repository"; import { UiDrawerFormState } from "../../../core/store/base_store"; import { UiBaseError } from "../../../core/model/ui_base_error"; -import { SceneMode } from "../model/scene_view"; import { SceneHttpRepository } from "../data/scene_http_repository"; import { Instance, SceneAsset } from "../../../core/model/scene_asset"; import { SceneViewModel } from "../model/scene_view_model"; import { SceneModel } from "../model/scene_model"; -import { SceneManagerForms } from "./forms/scene_manager_forms"; import { CameraModel } from "../../../core/model/camera_model"; import { SolidModel } from "../../../core/model/solid_model"; import { PointModel } from "../../../core/model/point_model"; import { RobotModel } from "../../../core/model/robot_model"; import { ZoneModel } from "../../../core/model/zone_model"; -import { SceneModelsTypes } from "../../../core/model/scene_models_type"; -import { Result } from "../../../core/helper/result"; + export enum DrawersSceneManager { NewScene = "Новая сцена", } -export enum StoreMode { - sceneInstance = "sceneInstance", - allScenes = "allScenes", -} -export interface ISpawnHelper { - url: string; - spawn: SceneModelsTypes; - name: string; - isFinished: boolean; - type: string; -} -interface IPopoverItem { - name: string; - fn: Function; -} -export interface SceneItems { - fn: Function; - name: string; - isSelected: boolean; - icon: string; -} export class SceneMangerStore extends UiDrawerFormState { activeFormType?: string; activeSceneId: string = ""; selectedItemName?: string; - activeFormDependency: Object = {}; viewModel: SceneViewModel = SceneViewModel.empty(); - sceneMode: SceneMode; - sceneItems: SceneItems[] = []; isVisibleSaveButton: boolean = false; coreThreeRepository: null | CoreThreeRepository = null; sceneHttpRepository: SceneHttpRepository; @@ -60,33 +33,12 @@ export class SceneMangerStore extends UiDrawerFormState this.setMode(SceneMode.Select), isSelected: false }, - { icon: SceneMode.Move, onClick: () => this.setMode(SceneMode.Move), isSelected: false }, - { icon: SceneMode.Rotate, onClick: () => this.setMode(SceneMode.Rotate), isSelected: false }, - ]; - popoverItems: IPopoverItem[] = [ - { name: "Камера", fn: () => this.createNewForm(SceneManagerForms.camera, true) }, - { name: "Твердое тело", fn: () => this.createNewForm(SceneManagerForms.solidBody, true) }, - { name: "Источник света", fn: () => this.createNewForm(SceneManagerForms.light, true) }, - { name: "Робот", fn: () => this.createNewForm(SceneManagerForms.robot, true) }, - { name: "Точка", fn: () => this.createNewForm(SceneManagerForms.point, true) }, - { name: "Траектория", fn: () => this.createNewForm(SceneManagerForms.trajectory, true) }, - { name: "Зона", fn: () => this.createNewForm(SceneManagerForms.zone, true) }, - { name: "Точки захвата", fn: () => this.createNewForm(SceneManagerForms.capturePoints, true) }, - ]; canvasOffsetX?: number; sceneName?: string; constructor() { @@ -94,75 +46,9 @@ export class SceneMangerStore extends UiDrawerFormState - this.messageHttp(this.sceneHttpRepository.editScene(SceneAsset.newScene(this.scene, this.sceneName ?? "")), { - successMessage: "Сцена сохранена", - }).then(() => (this.isVisibleSaveButton = false)); - iconToSceneManagerForm = (icon: string): SceneManagerForms => { - if (icon.isEqual("Camera")) { - this.activeFormDependency = { - type: "Preview", - }; - return SceneManagerForms.camera; - } - if (icon.isEqual("Zone")) { - this.activeFormDependency = { - type: "Preview", - }; - return SceneManagerForms.zone; - } - if (icon.isEqual("Robot")) { - this.activeFormDependency = { - type: "Preview", - }; - return SceneManagerForms.robot; - } - if (icon.isEqual("Point")) { - this.activeFormDependency = { - type: "Preview", - }; - return SceneManagerForms.point; - } - - this.activeFormDependency = { - type: "Preview", - }; - return SceneManagerForms.solidBody; - }; - selectSceneItems = (name: string, index: number, selected: boolean, icon: string) => { - this.sceneItems.map((el) => { - el.isSelected = false; - return el; - }); - this.sceneItems.map((el, i) => i.isEqualR(index).map(() => (el.isSelected = selected))); - if (selected) { - this.createNewForm(this.iconToSceneManagerForm(icon)); - this.selectedItemName = name; - } - - if (!selected) { - this.createNewForm(undefined); - this.selectedItemName = undefined; - } - }; - - setMode = (mode: SceneMode) => { - this.sceneHelperInstruments.map((el) => { - el.isSelected = false; - el.icon.isEqualR(mode).map(() => (el.isSelected = true)); - return el; - }); - this.sceneMode = mode; - this.coreThreeRepository?.setTransformMode(this.sceneMode); - }; - createNewForm = (formType: SceneManagerForms | undefined, isNeedClearDependency?: boolean) => { - this.activeFormDependency = Object.assign(this.activeFormDependency, { store: this }); - if (isNeedClearDependency) this.activeFormDependency = { store: this }; - this.activeFormType = formType; - }; + createNewScene = () => this.viewModel.valid().fold( async (s) => { @@ -173,42 +59,16 @@ export class SceneMangerStore extends UiDrawerFormState message.error(e) ); - deleteSceneItem = (item: SceneItems) => { - this.sceneItems = this.sceneItems.filter((el) => !el.name.isEqual(item.name)); - - this.coreThreeRepository?.deleteSceneItem(item); - this.visibleSaveButton(); - }; - visibleSaveButton = () => { this.isVisibleSaveButton = true; }; - addNewCamera = (model: CameraModel) => { - model.position = this.coreThreeRepository!.camera.position; - model.orientation = 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); - model.toWebGl(this.coreThreeRepository!); - this.visibleSaveButton(); - }; - hiddenMenu = () => (this.isSceneMenuShow = false); init = async () => { - this.storeMode - .isEqualR(StoreMode.allScenes) - .map(() => this.mapOk("scenes", this.sceneHttpRepository.getAllScenes())); - }; - initParam = (id: string | undefined) => { - if (id) { - this.activeSceneId = id; - this.storeMode = StoreMode.sceneInstance; - } else { - this.storeMode = StoreMode.allScenes; - } + this.mapOk("scenes", this.sceneHttpRepository.getAllScenes()); }; + errorHandingStrategy = (error: HttpError) => error.status.isEqualR(404).map(() => this.errors.push(new UiBaseError(`not found to project`))); @@ -218,76 +78,4 @@ export class SceneMangerStore extends UiDrawerFormState { - this.canvasRef = canvasRef; - this.storeMode.isEqualR(StoreMode.sceneInstance).map(() => this.loadWebGl(canvasRef)); - }; - - loadWebGl = async (canvasRef: HTMLCanvasElement): Promise => { - this.coreThreeRepository = new CoreThreeRepository(canvasRef as HTMLCanvasElement, this.watcherSceneEditorObject); - - this.coreThreeRepository.render(); - - this.canvasOffsetX = canvasRef.getBoundingClientRect().x; - canvasRef.addEventListener("click", (event) => this.clickLister(event, canvasRef.getBoundingClientRect().x)); - - (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(); - - vector.x = ((event.clientX - offset) / boundingRect.width) * 2 - 1; - vector.y = -(event.clientY / boundingRect.height) * 2 + 1; - return this.coreThreeRepository!.setRayCastAndGetFirstObjectAndPointToObject(vector); - }; - clickLister = (event: MouseEvent, offset: number = 0) => { - const vector = new Vector2(); - const boundingRect = this.canvasRef!.getBoundingClientRect(); - - vector.x = ((event.clientX - offset) / boundingRect.width) * 2 - 1; - vector.y = -(event.clientY / boundingRect.height) * 2 + 1; - - if (this.sceneMode.isEqual(SceneMode.Select)) { - return; - } - - if (this.sceneMode.isEqualMany([SceneMode.Move, SceneMode.Rotate])) { - this.transformContollsCall(vector); - } - }; - - watcherSceneEditorObject = (mesh: Object3D) => ( - (this.scene = this.scene.map((el) => - el.name.isEqualR(mesh.name).fold( - () => { - el.position = mesh.position; - el.orientation = mesh.quaternion.toArray(); - return el; - }, - () => el - ) - )), - this.visibleSaveButton() - ); - - transformContollsCall = (vector: Vector2) => - // @ts-ignore - this.coreThreeRepository?.setRayCastAndGetFirstObject(vector).fold( - (object) => this.coreThreeRepository?.setTransformControlsAttach(object), - (_) => this.coreThreeRepository?.disposeTransformControlsMode() - ); - - dispose = () => { - window.removeEventListener("click", this.clickLister); - }; }