progress scene builder
This commit is contained in:
parent
0a4eea19c5
commit
50d0c4c12b
64 changed files with 858 additions and 1315 deletions
|
@ -4,6 +4,7 @@ import { WeightsPresentation } from "../../features/weights/weights_presentation
|
|||
import { ProjectsPresentation } from "../../features/projects/projects_presentation";
|
||||
import { extensions } from "../extensions/extensions";
|
||||
import { Routes } from "../interfaces/router";
|
||||
import { ScenePresentation } from "../../features/scene/scene_presentation";
|
||||
|
||||
extensions();
|
||||
|
||||
|
@ -12,4 +13,5 @@ export const httpRoutes: Routes[] = [
|
|||
new DatasetsPresentation(),
|
||||
new BehaviorTreesPresentation(),
|
||||
new WeightsPresentation(),
|
||||
new ScenePresentation()
|
||||
].map((el) => el.call());
|
||||
|
|
|
@ -9,25 +9,37 @@ export interface Parts {
|
|||
name: string;
|
||||
part_path: string;
|
||||
material_path: string;
|
||||
stlUrl?: string;
|
||||
stlUrl: string;
|
||||
image: string;
|
||||
glUrl: string;
|
||||
}
|
||||
|
||||
export class RobossemblerAssetsNetworkMapperScenario extends CallbackStrategyWithEmpty {
|
||||
call = async (): ResponseBase => (await new SearchManyDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call({ isActive: true }, 'is dont active projects')).map((projectModel) => {
|
||||
const { rootDir } = projectModel[0];
|
||||
return new GetServerAddressUseCase().call().map(async (address) =>
|
||||
(
|
||||
await new ReadFileAndParseJsonUseCase().call<Parts[]>(
|
||||
rootDir + StaticFiles.parts
|
||||
)
|
||||
).map((model) => {
|
||||
call = async (): ResponseBase =>
|
||||
(
|
||||
await new SearchManyDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call(
|
||||
{ isActive: true },
|
||||
"is dont active projects"
|
||||
)
|
||||
).map((projectModel) => {
|
||||
const { rootDir } = projectModel[0];
|
||||
return new GetServerAddressUseCase().call().map(async (serverAddress) =>
|
||||
(await new ReadFileAndParseJsonUseCase().call<Parts[]>(rootDir + StaticFiles.parts)).map((model) => {
|
||||
const assetAddress =
|
||||
serverAddress +
|
||||
"/" +
|
||||
rootDir.match(new RegExp(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gm))[0] +
|
||||
"/assets/";
|
||||
model.map((el) => {
|
||||
const assetLibsAddress = assetAddress + "libs/objects/" + el.name;
|
||||
|
||||
model.map((el) => {
|
||||
el.stlUrl = address + '/' + rootDir.match(new RegExp(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gm))[0] + '/assets/' + el.part_path
|
||||
return el
|
||||
el.stlUrl = `${assetAddress}${el.part_path}`;
|
||||
el.glUrl = `${assetLibsAddress}.glb`;
|
||||
el.image = `${assetLibsAddress}.png`;
|
||||
return el;
|
||||
});
|
||||
return Result.ok(model);
|
||||
})
|
||||
return Result.ok(model);
|
||||
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -7,22 +7,24 @@ import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_
|
|||
import { UpdateDataBaseModelUseCase } from "../../../core/usecases/update_database_model_usecase";
|
||||
import { MongoIdValidation } from "../../../core/validations/mongo_id_validation";
|
||||
import { IProjectModel, ProjectDBModel } from "../models/project_model_database_model";
|
||||
|
||||
|
||||
export class SetActiveProjectScenario extends CallbackStrategyWithIdQuery {
|
||||
idValidationExpression = new MongoIdValidation();
|
||||
|
||||
call = async (id: string): ResponseBase => (await (await new ReadByIdDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call(id)).map(async (model) => await (
|
||||
await new CreateFolderUseCase().call(model.rootDir)
|
||||
).map(async () => {
|
||||
model.isActive = true;
|
||||
return (await new UpdateDataBaseModelUseCase(ProjectDBModel).call(model)).map(async (el) => {
|
||||
await ProjectDBModel.updateMany(
|
||||
{ _id: { $ne: el._id }, isActive: { $eq: true } },
|
||||
{ isActive: false }
|
||||
);
|
||||
await new SetLastActivePipelineToRealTimeServiceScenario().call();
|
||||
return Result.ok(`project ${id} is active`);
|
||||
});
|
||||
})))
|
||||
call = async (id: string): ResponseBase =>
|
||||
await (
|
||||
await new ReadByIdDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call(id)
|
||||
).map(
|
||||
async (model) =>
|
||||
await (
|
||||
await new CreateFolderUseCase().call(model.rootDir)
|
||||
).map(async () => {
|
||||
model.isActive = true;
|
||||
return (await new UpdateDataBaseModelUseCase(ProjectDBModel).call(model)).map(async (el) => {
|
||||
await ProjectDBModel.updateMany({ _id: { $ne: el._id }, isActive: { $eq: true } }, { isActive: false });
|
||||
await new SetLastActivePipelineToRealTimeServiceScenario().call();
|
||||
return Result.ok(`project ${id} is active`);
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
|
13
server/src/features/scene/scene_database_model.ts
Normal file
13
server/src/features/scene/scene_database_model.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { Schema, model } from "mongoose";
|
||||
export interface IScene {
|
||||
name: string;
|
||||
}
|
||||
export const SceneSchema = new Schema({
|
||||
name: {
|
||||
type: String,
|
||||
},
|
||||
}).plugin(require("mongoose-autopopulate"));
|
||||
|
||||
export const schemaSceneName = "Scene";
|
||||
|
||||
export const SceneDBModel = model<IScene>(schemaSceneName, SceneSchema);
|
13
server/src/features/scene/scene_presentation.ts
Normal file
13
server/src/features/scene/scene_presentation.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { CrudController } from "../../core/controllers/crud_controller";
|
||||
import { SceneDBModel } from "./scene_database_model";
|
||||
import { SceneValidationModel } from "./scene_validation_model";
|
||||
|
||||
export class ScenePresentation extends CrudController<SceneValidationModel, typeof SceneDBModel> {
|
||||
constructor() {
|
||||
super({
|
||||
url: "scenes",
|
||||
validationModel: SceneValidationModel,
|
||||
databaseModel: SceneDBModel,
|
||||
});
|
||||
}
|
||||
}
|
7
server/src/features/scene/scene_validation_model.ts
Normal file
7
server/src/features/scene/scene_validation_model.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { IsString } from "class-validator";
|
||||
import { IScene } from "./scene_database_model";
|
||||
|
||||
export class SceneValidationModel implements IScene {
|
||||
@IsString()
|
||||
public name: string;
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<div style="width: 100%; height: 100%" id="root"></div>
|
||||
|
||||
</body>
|
||||
<style>
|
||||
|
@ -24,6 +24,7 @@
|
|||
[contenteditable]:focus {
|
||||
outline: 0px solid transparent;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
</html>
|
|
@ -32,6 +32,8 @@ declare global {
|
|||
randRange(min: number, max: number): number;
|
||||
isPositive(): boolean;
|
||||
isNegative(): boolean;
|
||||
isEven(): boolean;
|
||||
isOdd(): boolean;
|
||||
}
|
||||
|
||||
interface String {
|
||||
|
@ -42,7 +44,7 @@ declare global {
|
|||
isEqualMany(str: string[]): boolean;
|
||||
hasPattern(pattern: string): boolean;
|
||||
hasNoPattern(pattern: string): boolean;
|
||||
divideByIndex(index: number): string[]
|
||||
divideByIndex(index: number): string[];
|
||||
}
|
||||
|
||||
interface Map<K, V> {
|
||||
|
|
|
@ -20,7 +20,7 @@ export const NumberExtensions = () => {
|
|||
return !isNaN(Number(str));
|
||||
};
|
||||
}
|
||||
if (Number().randRange === undefined) {
|
||||
if (Number().randRange === undefined) {
|
||||
Number.prototype.randRange = function (min, max) {
|
||||
return Math.random() * (max - min) + min;
|
||||
};
|
||||
|
@ -30,10 +30,19 @@ export const NumberExtensions = () => {
|
|||
return Math.sign(Number(this)) === 1;
|
||||
};
|
||||
}
|
||||
if(Number().isNegative === undefined){
|
||||
Number.prototype.isNegative = function (){
|
||||
return !this.isPositive()
|
||||
}
|
||||
if (Number().isNegative === undefined) {
|
||||
Number.prototype.isNegative = function () {
|
||||
return !this.isPositive();
|
||||
};
|
||||
}
|
||||
if (Number().isEven === undefined) {
|
||||
Number.prototype.isEven = function () {
|
||||
return Number(this) % 2 === 0;
|
||||
};
|
||||
}
|
||||
if (Number().isOdd === undefined) {
|
||||
Number.prototype.isOdd = function () {
|
||||
return !this.isEven();
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
@ -94,7 +94,7 @@ export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
|
|||
alpha: true,
|
||||
});
|
||||
const aspectCamera = this.htmlSceneWidth / this.htmlSceneHeight;
|
||||
this.camera = new PerspectiveCamera(800, aspectCamera, 0.1, 10000);
|
||||
this.camera = new PerspectiveCamera(100, aspectCamera, 0.1, 2000);
|
||||
this.camera.position.set(60, 20, 10);
|
||||
|
||||
this.webGlRender = renderer;
|
||||
|
@ -151,7 +151,7 @@ export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
|
|||
cube.position.copy(vector);
|
||||
}
|
||||
this.scene.add(cube);
|
||||
// this.scene.children.
|
||||
|
||||
}
|
||||
deleteSceneItem(item: BaseSceneItemModel) {
|
||||
const updateScene = this.scene;
|
||||
|
@ -159,7 +159,7 @@ export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
|
|||
}
|
||||
loadUrdf = (urlPath: string) => {
|
||||
this.urdfLoader.load(
|
||||
urlPath, // The path to the URDF within the package OR absolute
|
||||
urlPath,
|
||||
robot => {
|
||||
|
||||
this.scene.add(robot)
|
||||
|
@ -333,7 +333,7 @@ export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
|
|||
init() {
|
||||
this.light();
|
||||
this.addListeners();
|
||||
const floor = new GridHelper(100, 100, 0x888888, 0x444444);
|
||||
const floor = new GridHelper(1000, 100, 0x888888, 0x444444);
|
||||
floor.geometry.rotateX(Math.PI * 0.5)
|
||||
floor.userData = {};
|
||||
floor.userData[UserData.cameraInitialization] = true;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
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_repository";
|
||||
import { UUID } from "../../features/all_projects/data/project_http_repository";
|
||||
|
||||
export enum HttpMethod {
|
||||
GET = "GET",
|
||||
|
|
|
@ -1,21 +1,11 @@
|
|||
import { createBrowserRouter } from "react-router-dom";
|
||||
import { AllProjectScreen, AllProjectScreenPath } from "../../features/all_projects/presentation/all_projects_screen";
|
||||
import {
|
||||
PipelineInstanceScreen,
|
||||
PipelineInstanceScreenPath,
|
||||
} from "../../features/pipeline_instance_main_screen/pipeline_instance_screen";
|
||||
|
||||
import { CreateProjectScreen, CreateProjectScreenPath } from "../../features/create_project/create_project_screen";
|
||||
|
||||
import { SceneManger, SceneManagerPath } from "../../features/scene_manager/presentation/scene_manager";
|
||||
import {
|
||||
BehaviorTreeBuilderPath,
|
||||
BehaviorTreeBuilderScreen,
|
||||
} from "../../features/behavior_tree_builder/presentation/behavior_tree_builder_screen";
|
||||
import {
|
||||
StickObjectsMarkingScreen,
|
||||
StickObjectsMarkingScreenPath,
|
||||
} from "../../features/_stick_objects_marking/stick_objects_marking_screen";
|
||||
|
||||
import { DataSetScreen, DatasetsScreenPath } from "../../features/dataset/dataset_screen";
|
||||
import { AssemblesScreen, AssemblesScreenPath } from "../../features/assembles/assembles_screen";
|
||||
import { SimulationScreen, SimulationScreenPath } from "../../features/simulations/simulations_screen";
|
||||
|
@ -31,15 +21,9 @@ export const router = createBrowserRouter([
|
|||
element: <AllProjectScreen />,
|
||||
},
|
||||
{
|
||||
path: PipelineInstanceScreenPath + idURL,
|
||||
element: <PipelineInstanceScreen />,
|
||||
path: SceneManagerPath + idURL,
|
||||
element: <SceneManger />,
|
||||
},
|
||||
|
||||
{
|
||||
path: CreateProjectScreenPath,
|
||||
element: <CreateProjectScreen />,
|
||||
},
|
||||
|
||||
{
|
||||
path: SceneManagerPath,
|
||||
element: <SceneManger />,
|
||||
|
@ -52,10 +36,6 @@ export const router = createBrowserRouter([
|
|||
path: BehaviorTreeBuilderPath + idURL,
|
||||
element: <BehaviorTreeBuilderScreen />,
|
||||
},
|
||||
{
|
||||
path: StickObjectsMarkingScreenPath,
|
||||
element: <StickObjectsMarkingScreen />,
|
||||
},
|
||||
{
|
||||
path: DatasetsScreenPath,
|
||||
element: <DataSetScreen />,
|
||||
|
|
|
@ -59,11 +59,24 @@ export class SimpleErrorState extends UiLoader {
|
|||
};
|
||||
isError = false;
|
||||
}
|
||||
export class ModalStore extends SimpleErrorState {
|
||||
isModalOpen: boolean = false;
|
||||
showModal = () => {
|
||||
this.isModalOpen = true
|
||||
};
|
||||
|
||||
handleOk = () => {
|
||||
this.isModalOpen = false
|
||||
};
|
||||
|
||||
handleCancel = () => {
|
||||
this.isModalOpen = false
|
||||
};
|
||||
}
|
||||
export abstract class UiErrorState<T> extends UiLoader {
|
||||
abstract errorHandingStrategy: (error: T) => void;
|
||||
abstract init(navigate?: NavigateFunction): Promise<any>;
|
||||
dispose() {}
|
||||
dispose() { }
|
||||
errors: UiBaseError[] = [];
|
||||
}
|
||||
|
||||
|
@ -79,7 +92,7 @@ export abstract class DrawerState<E> extends UiErrorState<E> {
|
|||
};
|
||||
});
|
||||
}
|
||||
edtDrawer(drawerName: string, status: boolean): void {
|
||||
editDrawer(drawerName: string, status: boolean): void {
|
||||
this.titleDrawer = drawerName;
|
||||
this.drawers = this.drawers.map((el) => {
|
||||
if (el.name === drawerName) {
|
||||
|
@ -89,7 +102,7 @@ export abstract class DrawerState<E> extends UiErrorState<E> {
|
|||
});
|
||||
}
|
||||
}
|
||||
export abstract class UiFormState<V, E> extends DrawerState<E> {
|
||||
export abstract class UiDrawerFormState<V, E> extends DrawerState<E> {
|
||||
abstract viewModel: V;
|
||||
updateForm(value: Partial<V>) {
|
||||
//@ts-ignore
|
||||
|
|
|
@ -7,6 +7,7 @@ export interface IButtonProps extends IStyle {
|
|||
filled?: boolean;
|
||||
text?: string;
|
||||
onClick?: any;
|
||||
textStyle?:React.CSSProperties
|
||||
}
|
||||
|
||||
export function CoreButton(props: IButtonProps) {
|
||||
|
@ -29,6 +30,7 @@ export function CoreButton(props: IButtonProps) {
|
|||
<CoreText
|
||||
text={props.text ?? ""}
|
||||
type={CoreTextType.medium}
|
||||
style={props.textStyle}
|
||||
color={props.block ? "#1D1B20" : props.filled ? "white" : "rgba(103, 80, 164, 1)"}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -10,7 +10,7 @@ const { Title } = Typography;
|
|||
export interface IHeader {
|
||||
largeText?: string;
|
||||
minText?: string;
|
||||
path?: string;
|
||||
click?: Function;
|
||||
needBackButton?: undefined | any;
|
||||
}
|
||||
|
||||
|
@ -78,17 +78,17 @@ export const Header: React.FunctionComponent<IHeader> = (props: IHeader) => {
|
|||
)}
|
||||
</Row>
|
||||
|
||||
{props.minText !== undefined ? (
|
||||
{/* {props.minText !== undefined ? (
|
||||
<LinkTypography
|
||||
style={{
|
||||
marginBottom: "40px",
|
||||
}}
|
||||
path={props.path!}
|
||||
path={props.click!}
|
||||
text={props.minText}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
)} */}
|
||||
</Col>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -420,6 +420,46 @@ const getIconSvg = (type: string): Result<undefined, React.JSX.Element> => {
|
|||
</defs>
|
||||
</svg>
|
||||
);
|
||||
case "Play":
|
||||
return Result.ok(
|
||||
<svg width="16" height="18" viewBox="0 0 16 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15.0207 8.74021L0.00265907 17.106L0.0387473 0.309923L15.0207 8.74021Z" fill="white" />
|
||||
</svg>
|
||||
);
|
||||
case "Scene":
|
||||
return Result.ok(
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 256 256"
|
||||
style={{ width: 40, height: 20 }}
|
||||
enableBackground="new 0 0 256 256"
|
||||
xmlSpace="preserve"
|
||||
>
|
||||
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path
|
||||
fill="#000000"
|
||||
d="M25,35.7c-5.7,1.1-10.8,5.3-13.5,10.9L10,49.8V128v78.2l1.5,3.1c2.8,5.8,7.8,9.8,13.9,11c3.4,0.6,201.6,0.6,205,0c6.1-1.2,11.2-5.2,13.9-11l1.5-3.1l0.1-77.5c0.1-76.3,0.1-77.6-0.8-80.5c-1.2-3.8-3.6-7.1-7.2-9.6c-5.4-3.6,3-3.4-110.1-3.3C72,35.3,26.2,35.5,25,35.7z M230.7,47.4c1.8,0.9,3.6,3,4.2,4.8c0.4,1.2,0.5,15.1,0.5,50.3l0,48.7l-7.9-8.1c-4.3-4.4-17.6-18.1-29.4-30.5c-11.8-12.3-22-22.8-22.6-23.2c-1.5-1.1-4.1-1.1-5.7,0c-0.7,0.4-12.3,12.1-25.8,25.9c-13.5,13.8-26.6,27.3-29.3,30l-4.7,4.8l-15.6-15.7c-11.4-11.6-15.9-15.8-16.9-16c-3.5-0.8-2.8-1.3-30.1,26.5c-14.2,14.5-25.9,26.3-26.1,26.3c-0.2,0-0.4-26.6-0.4-59.1c0-66.2-0.2-61.6,3.4-64.2l1.8-1.3h101.7C214.4,46.8,229.7,46.8,230.7,47.4z M196.7,127.1c13.3,13.8,27.4,28.5,31.2,32.5l7,7.4l-0.1,19c-0.1,18.5-0.2,19-1.1,20.3c-0.5,0.7-1.7,1.8-2.5,2.4l-1.5,1H128.1c-110.9,0-102.8,0.2-105.4-2.6c-1.9-2.1-2.3-3.8-2.3-11.9v-7.5l27.6-28.2l27.6-28.2l15.4,15.5c8.4,8.5,15.7,15.7,16.2,16c0.5,0.2,1.7,0.5,2.8,0.5c1.6,0,2.2-0.3,4.1-2c1.2-1.2,14.7-15,30.1-30.7c15.4-15.7,28.1-28.6,28.2-28.5C172.4,101.9,183.4,113.2,196.7,127.1z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
case "Camera":
|
||||
return Result.ok(
|
||||
<svg width="18" height="14" viewBox="0 0 18 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M9 3.28047C6.69512 3.28047 4.82927 5.14632 4.82927 7.4512C4.82927 9.75608 6.69512 11.6219 9 11.6219C11.3049 11.6219 13.1707 9.75608 13.1707 7.4512C13.1707 5.16827 11.3049 3.28047 9 3.28047ZM9 10.7439C7.17805 10.7439 5.70732 9.27315 5.70732 7.4512C5.70732 5.62925 7.17805 4.15852 9 4.15852C10.822 4.15852 12.2927 5.62925 12.2927 7.4512C12.2927 9.27315 10.822 10.7439 9 10.7439ZM16.2439 2.40242L12.9512 2.42437L11.5683 0.404858C11.4805 0.295102 11.3488 0.229248 11.2171 0.229248H6.78293C6.65122 0.229248 6.51951 0.295102 6.43171 0.404858L5.04878 2.42437H1.7561C0.790244 2.42437 0 3.19266 0 4.15852V11.6439C0 12.6097 0.790244 13.4 1.7561 13.4H16.2439C17.2098 13.4 18 12.6097 18 11.6439V3.96096C18 2.9951 17.2098 2.40242 16.2439 2.40242ZM17.122 11.6439C17.122 12.1268 16.7268 12.5219 16.2439 12.5219H1.7561C1.27317 12.5219 0.878049 12.1268 0.878049 11.6439V4.15852C0.878049 3.67559 1.27317 3.30242 1.7561 3.30242H5.26829C5.4 3.30242 5.53171 3.23657 5.61951 3.12681L7.00244 1.1073H10.9976L12.3805 3.12681C12.4683 3.23657 12.6 3.30242 12.7317 3.30242L16.2439 3.28047C16.7268 3.28047 17.122 3.47803 17.122 3.96096V11.6439Z"
|
||||
fill="black"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
case "Settings":
|
||||
return Result.ok(
|
||||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
|
|
|
@ -17,7 +17,7 @@ export const LoadPage: React.FunctionComponent<ILoadPage> = observer(
|
|||
return (
|
||||
<>
|
||||
<Header
|
||||
path={props.path}
|
||||
click={props.click}
|
||||
largeText={props.largeText}
|
||||
minText={props.minText}
|
||||
needBackButton={props.needBackButton}
|
||||
|
|
|
@ -51,6 +51,7 @@ export interface IMainPageProps {
|
|||
bodyChildren?: JSX.Element;
|
||||
panelChildren?: JSX.Element;
|
||||
panelStyle?: React.CSSProperties;
|
||||
|
||||
isLoading?: boolean;
|
||||
maskLoader?: boolean;
|
||||
error?: UiBaseError[];
|
||||
|
@ -60,7 +61,7 @@ export const MainPage = (props: IMainPageProps) => {
|
|||
{ name: "Детали", path: DetailsScreenPath, icon: "Setting" },
|
||||
{ name: "Сборки", path: AssemblesScreenPath, icon: "Assembly" },
|
||||
{ name: "Датасеты", path: DatasetsScreenPath, icon: "Datasets" },
|
||||
{ name: "Сцена", path: SceneManagerPath, icon: "Layers" },
|
||||
{ name: "Сцена", path: SceneManagerPath, icon: "Scene" },
|
||||
{ name: "Навыки", path: SkillScreenPath, icon: "Layers" },
|
||||
{ name: "Поведение", path: BehaviorTreeBuilderPath, icon: "Rocket" },
|
||||
{ name: "Симуляция", path: SimulationScreenPath, icon: "Simulation" },
|
||||
|
|
61
ui/src/core/ui/pages/preview_page.tsx
Normal file
61
ui/src/core/ui/pages/preview_page.tsx
Normal file
|
@ -0,0 +1,61 @@
|
|||
import { IHeader } from "../header/header";
|
||||
import { CoreText, CoreTextType } from "../text/text";
|
||||
import { Spin } from "antd";
|
||||
|
||||
interface IPreviewPageProps extends IHeader {
|
||||
isLoading: boolean;
|
||||
isError: boolean;
|
||||
children?: JSX.Element | JSX.Element[];
|
||||
}
|
||||
export const PreviewPage = (props: IPreviewPageProps) => {
|
||||
return (
|
||||
<div style={{ width: "100%", height: "100%" }}>
|
||||
<div
|
||||
style={{
|
||||
width: "100%",
|
||||
marginTop: 10,
|
||||
textAlign: "center",
|
||||
position: "absolute",
|
||||
}}
|
||||
>
|
||||
<CoreText text={props.largeText ?? ""} type={CoreTextType.big} />
|
||||
<CoreText
|
||||
onClick={() => {
|
||||
console.log(200);
|
||||
if (props.click) props.click();
|
||||
}}
|
||||
text={props.minText ?? ""}
|
||||
type={CoreTextType.small}
|
||||
style={{ color: "rgba(68, 142, 247, 1)", cursor: "pointer" }}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
padding: 60,
|
||||
paddingTop: 100,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
borderRadius: 7,
|
||||
border: "1px solid #CAC4D0",
|
||||
background: "#FEF7FF",
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
overflowX: "auto",
|
||||
}}
|
||||
>
|
||||
{props.isLoading ? (
|
||||
<div style={{ width: "100%", height: "100%", justifyContent: "center", alignItems: "center" }}>
|
||||
<Spin />
|
||||
</div>
|
||||
) : (
|
||||
props.children
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -6,12 +6,14 @@ export enum CoreTextType {
|
|||
medium = 'medium',
|
||||
large = 'large',
|
||||
small = 'small',
|
||||
big = 'big'
|
||||
}
|
||||
|
||||
export interface ITextProps extends IStyle {
|
||||
text: string;
|
||||
type: CoreTextType;
|
||||
color?: string;
|
||||
onClick?: Function;
|
||||
}
|
||||
|
||||
const getStyle = (type: CoreTextType, color: string | undefined) => {
|
||||
|
@ -49,6 +51,15 @@ const getStyle = (type: CoreTextType, color: string | undefined) => {
|
|||
|
||||
fontSizeAdjust: 16,
|
||||
}
|
||||
if (type.isEqual(CoreTextType.big)) return {
|
||||
color: color ?? "#1D1B20",
|
||||
fontSize: 40,
|
||||
fontFamily: "Roboto",
|
||||
fontWeight: 500,
|
||||
textOverflow: "ellipsis",
|
||||
|
||||
fontSizeAdjust: 16,
|
||||
}
|
||||
return {
|
||||
color: color ?? "rgba(73, 69, 79, 1)",
|
||||
fontSize: 12,
|
||||
|
@ -64,6 +75,9 @@ const appendStyle = (type: CoreTextType, color: string | undefined, style: React
|
|||
export function CoreText(props: ITextProps) {
|
||||
return (
|
||||
<div
|
||||
onClick={() => {
|
||||
if (props.onClick) props.onClick()
|
||||
}}
|
||||
style={appendStyle(props.type, props.color, props.style)}
|
||||
>
|
||||
{props.text}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
export enum StickObjectsMarkingStoreMode {
|
||||
objectsToWhichItSticks = "objectsToWhichItSticks",
|
||||
objectThatSticks = "objectThatSticks",
|
||||
addPointsObjectsToWhichItSticks = "addPointsObjectsToWhichItSticks",
|
||||
addPointsObjectThatSticks = "addPointsObjectThatSticks",
|
||||
move = "move",
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
import { Vector3 } from "three";
|
||||
|
||||
export class StickyHelper {
|
||||
objectThatSticksName: string;
|
||||
objectThatSticksNamePoints: Vector3[] = [];
|
||||
objectsToWhichItSticksName: string;
|
||||
objectsToWhichItSticksPoints: Vector3[] = [];
|
||||
|
||||
constructor(
|
||||
objectThatSticksName: string,
|
||||
objectThatSticksNamePoints: Vector3[],
|
||||
objectsToWhichItSticksName: string,
|
||||
objectsToWhichItSticksPoints: Vector3[]
|
||||
) {
|
||||
this.objectThatSticksName = objectThatSticksName;
|
||||
this.objectThatSticksNamePoints = objectThatSticksNamePoints;
|
||||
this.objectsToWhichItSticksName = objectsToWhichItSticksName;
|
||||
this.objectsToWhichItSticksPoints = objectsToWhichItSticksPoints;
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
export enum StickyLoaderMode {
|
||||
IN = "IN",
|
||||
OUT = "OUT",
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
import * as React from "react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { Button } from "antd";
|
||||
import { StickObjectsMarkingStore } from "./stick_objects_marking_store";
|
||||
import { Vector3 } from "three";
|
||||
import { StickObjectsMarkingStoreMode } from "./model/stick_objects_marking_store_mode";
|
||||
import { StickyLoaderMode } from "./model/sticky_loader_mode";
|
||||
|
||||
export const StickObjectsMarking = "/stick/objects/marking";
|
||||
interface StickButtonsProps {
|
||||
isVisible: boolean;
|
||||
name: string;
|
||||
groupMode: StickObjectsMarkingStoreMode;
|
||||
storeMode: StickObjectsMarkingStoreMode;
|
||||
storeModePoints: StickObjectsMarkingStoreMode;
|
||||
setMode: Function;
|
||||
setPointMode: Function;
|
||||
points: Vector3[];
|
||||
body: string;
|
||||
}
|
||||
|
||||
export const StickButtons: React.FunctionComponent<StickButtonsProps> = observer((props) => {
|
||||
return (
|
||||
<>
|
||||
{props.isVisible ? (
|
||||
<>
|
||||
{props.name}
|
||||
<Button
|
||||
style={{
|
||||
backgroundColor: props.storeMode === props.storeModePoints ? "#ff7e1e" : "",
|
||||
}}
|
||||
onClick={() => props.setPointMode()}
|
||||
>
|
||||
add points
|
||||
</Button>
|
||||
{props.points.map((el) => {
|
||||
return (
|
||||
<>
|
||||
{el.x} {el.y} {el.z}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
) : (
|
||||
<Button
|
||||
style={{
|
||||
backgroundColor: props.groupMode === props.storeMode ? "#ff7e1e" : "",
|
||||
}}
|
||||
onClick={() => props.setMode(props.storeMode)}
|
||||
>
|
||||
{props.body}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
});
|
||||
export const StickObjectsMarkingScreenPath = "/sticky/objects/mark";
|
||||
export const StickObjectsMarkingScreen = observer(() => {
|
||||
const canvasRef = React.useRef<HTMLCanvasElement>(null);
|
||||
const [store] = React.useState(() => new StickObjectsMarkingStore());
|
||||
const id = useParams().id as string;
|
||||
|
||||
React.useEffect(() => {
|
||||
store.init();
|
||||
store.loadScene(canvasRef.current!);
|
||||
document.body.style.overflow = "hidden";
|
||||
return () => {
|
||||
document.body.style.overflow = "scroll";
|
||||
store.dispose();
|
||||
};
|
||||
}, [id, store]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<canvas ref={canvasRef} style={{ position: "absolute", overflow: "hidden" }} />
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignContent: "center",
|
||||
justifyContent: "space-between",
|
||||
position: "absolute",
|
||||
width: "100vw",
|
||||
}}
|
||||
>
|
||||
<div style={{ backgroundColor: "aqua", display: "flex", flexDirection: "column", padding: "5px" }}>
|
||||
{store.stickyObjects?.map((el) => {
|
||||
return (
|
||||
<div>
|
||||
<div style={{ display: "flex" }}>
|
||||
<Button onClick={() => store.loadAsset(el, StickyLoaderMode.IN)}>Sticky in</Button>
|
||||
<Button onClick={() => store.loadAsset(el, StickyLoaderMode.OUT)}>Sticky Out</Button>
|
||||
</div>
|
||||
<div>{el.name}</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{/* <div style={{ backgroundColor: "white", padding: "20px" }}>
|
||||
{Object.keys(store.points).map((el) => {
|
||||
// @ts-expect-error
|
||||
const v = store.points[el];
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
{el as string}:{v}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
<div>Marking objects for sticking</div>
|
||||
<div>
|
||||
<StickButtons
|
||||
storeMode={store.mode}
|
||||
setMode={() => store.setMode(StickObjectsMarkingStoreMode.objectThatSticks)}
|
||||
groupMode={StickObjectsMarkingStoreMode.objectThatSticks}
|
||||
name={store.objectThatSticksName}
|
||||
storeModePoints={StickObjectsMarkingStoreMode.addPointsObjectThatSticks}
|
||||
isVisible={store.objectThatSticksName !== undefined}
|
||||
setPointMode={() => store.setMode(StickObjectsMarkingStoreMode.addPointsObjectThatSticks)}
|
||||
points={store.objectThatSticksNamePoints}
|
||||
body="objectThatSticksName"
|
||||
/>
|
||||
<StickButtons
|
||||
body="objectsToWhichItSticksName"
|
||||
points={store.objectsToWhichItSticksPoints}
|
||||
storeMode={store.mode}
|
||||
setMode={() => store.setMode(StickObjectsMarkingStoreMode.objectsToWhichItSticks)}
|
||||
groupMode={StickObjectsMarkingStoreMode.objectsToWhichItSticks}
|
||||
name={store.objectsToWhichItSticksName}
|
||||
storeModePoints={StickObjectsMarkingStoreMode.addPointsObjectsToWhichItSticks}
|
||||
isVisible={store.objectsToWhichItSticksName !== undefined}
|
||||
setPointMode={() => store.setMode(StickObjectsMarkingStoreMode.addPointsObjectsToWhichItSticks)}
|
||||
/>
|
||||
<Button onClick={() => store.onSaveSticky()}>save</Button>
|
||||
<Button
|
||||
onClick={() => store.setMode(StickObjectsMarkingStoreMode.move)}
|
||||
style={{ backgroundColor: store.mode === StickObjectsMarkingStoreMode.move ? "#ff7e1e" : "" }}
|
||||
>
|
||||
run
|
||||
</Button>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
|
@ -1,120 +0,0 @@
|
|||
import makeAutoObservable from "mobx-store-inheritance";
|
||||
import { Box3, Vector2, Vector3 } from "three";
|
||||
import { UiErrorState } from "../../core/store/base_store";
|
||||
import { HttpError } from "../../core/repository/http_repository";
|
||||
import { UiBaseError } from "../../core/model/ui_base_error";
|
||||
import { RobossemblerFiles } from "../scene_manager/model/scene_assets";
|
||||
import { StickObjectsMarkingThreeRepository } from "./stick_objects_marking_three_repository";
|
||||
import { UserData } from "../../core/repository/core_three_repository";
|
||||
import { SceneHttpRepository } from "../scene_manager/data/scene_repository";
|
||||
import { Asset, RobossemblerAssets } from "../../core/model/robossembler_assets";
|
||||
import { StickObjectsMarkingStoreMode } from "./model/stick_objects_marking_store_mode";
|
||||
import { StickyHelper } from "./model/sticky_helper";
|
||||
import { StickyLoaderMode } from "./model/sticky_loader_mode";
|
||||
|
||||
export class StickObjectsMarkingStore extends UiErrorState<HttpError> {
|
||||
mode: StickObjectsMarkingStoreMode;
|
||||
stickObjectsMarkingThreeRepository: null | StickObjectsMarkingThreeRepository = null;
|
||||
sceneHttpRepository: SceneHttpRepository;
|
||||
objectThatSticksName: string;
|
||||
objectThatSticksNamePoints: Vector3[] = [];
|
||||
objectsToWhichItSticksName: string;
|
||||
objectsToWhichItSticksPoints: Vector3[] = [];
|
||||
sceneAssets?: RobossemblerAssets;
|
||||
points = {};
|
||||
|
||||
get stickyObjects() {
|
||||
return this.sceneAssets?.assets.filter((el) => el.actions.includes("Sticking"));
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
makeAutoObservable(this);
|
||||
this.points = {};
|
||||
this.mode = StickObjectsMarkingStoreMode.move;
|
||||
this.sceneHttpRepository = new SceneHttpRepository();
|
||||
}
|
||||
updatePoint = (key: string, value: any) => {
|
||||
// @ts-expect-error
|
||||
this.points[key] = value;
|
||||
};
|
||||
onSaveSticky(): void {}
|
||||
setMode(stickObjectsMarkingStoreMode: StickObjectsMarkingStoreMode): void {
|
||||
this.mode = stickObjectsMarkingStoreMode;
|
||||
}
|
||||
|
||||
loaderWatcher() {}
|
||||
|
||||
async init(): Promise<any> {
|
||||
this.mapOk("sceneAssets", this.sceneHttpRepository.getRobossemblerAssets());
|
||||
}
|
||||
|
||||
errorHandingStrategy = (error: HttpError) => {
|
||||
if (error.status === 404) {
|
||||
this.errors.push(new UiBaseError(`${RobossemblerFiles.robossemblerAssets} not found to project`));
|
||||
}
|
||||
};
|
||||
|
||||
async loadScene(canvasRef: HTMLCanvasElement) {
|
||||
this.loadWebGl(canvasRef);
|
||||
}
|
||||
watcherSceneEditorObject() {}
|
||||
loadWebGl(canvasRef: HTMLCanvasElement): void {
|
||||
this.stickObjectsMarkingThreeRepository = new StickObjectsMarkingThreeRepository(
|
||||
canvasRef as HTMLCanvasElement,
|
||||
this.watcherSceneEditorObject,
|
||||
this.updatePoint
|
||||
);
|
||||
this.stickObjectsMarkingThreeRepository.stickyHelperLoader([
|
||||
new StickyHelper(
|
||||
this.objectThatSticksName,
|
||||
this.objectThatSticksNamePoints,
|
||||
this.objectsToWhichItSticksName,
|
||||
this.objectsToWhichItSticksPoints
|
||||
),
|
||||
]);
|
||||
this.stickObjectsMarkingThreeRepository.render();
|
||||
window.addEventListener("click", (event) => this.clickLister(event));
|
||||
}
|
||||
|
||||
clickLister(event: MouseEvent) {
|
||||
const vector = new Vector2();
|
||||
vector.x = (event.clientX / window.innerWidth) * 2 - 1;
|
||||
vector.y = -(event.clientY / window.innerHeight) * 2 + 1;
|
||||
if (this.mode) {
|
||||
if (this.mode === StickObjectsMarkingStoreMode.move) {
|
||||
this.stickObjectsMarkingThreeRepository?.setRayCastAndGetFirstObject(vector).fold(
|
||||
(success) => this.stickObjectsMarkingThreeRepository?.setTransformControlsAttach(success),
|
||||
(_error) => this.stickObjectsMarkingThreeRepository?.disposeTransformControlsMode()
|
||||
);
|
||||
}
|
||||
this.stickObjectsMarkingThreeRepository?.setRayCast(vector).map((touch) => {
|
||||
const objectMagnetism = touch.filter((el) => el.object.userData[UserData.objectForMagnetism] === true);
|
||||
const BoundBoxVector = new Box3().setFromObject(objectMagnetism[0].object).getCenter(new Vector3());
|
||||
const centerRelativeVector = new Vector3().subVectors(BoundBoxVector, objectMagnetism[0].point);
|
||||
if (objectMagnetism.isNotEmpty()) {
|
||||
if (this.mode === StickObjectsMarkingStoreMode.objectsToWhichItSticks) {
|
||||
this.objectsToWhichItSticksName = objectMagnetism[0].object.name;
|
||||
}
|
||||
if (this.mode === StickObjectsMarkingStoreMode.objectThatSticks) {
|
||||
this.objectThatSticksName = objectMagnetism[0].object.name;
|
||||
}
|
||||
if (this.mode === StickObjectsMarkingStoreMode.addPointsObjectThatSticks) {
|
||||
this.objectThatSticksNamePoints.push(centerRelativeVector);
|
||||
}
|
||||
if (this.mode === StickObjectsMarkingStoreMode.addPointsObjectsToWhichItSticks) {
|
||||
this.objectsToWhichItSticksPoints.push(centerRelativeVector);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
loadAsset(asset: Asset, mode: StickyLoaderMode): void {
|
||||
this.stickObjectsMarkingThreeRepository?.loadInstance(asset,() =>{
|
||||
|
||||
});
|
||||
}
|
||||
dispose() {
|
||||
window.removeEventListener("click", this.clickLister);
|
||||
}
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
import { Box3, BoxGeometry, Mesh, MeshBasicMaterial, Object3D, Vector3 } from "three";
|
||||
import { CoreThreeRepository } from "../../core/repository/core_three_repository";
|
||||
import { CoreVector3 } from "../../core/model/core_vector3";
|
||||
import { StickyHelper } from "./model/sticky_helper";
|
||||
|
||||
export class StickObjectsMarkingThreeRepository extends CoreThreeRepository {
|
||||
stickyObjects: StickyHelper[];
|
||||
drawUiPoint: Function;
|
||||
constructor(htmlCanvasRef: HTMLCanvasElement, watcherSceneEditorObject: Function, updatePoint: Function) {
|
||||
super(htmlCanvasRef, watcherSceneEditorObject);
|
||||
this.drawUiPoint = updatePoint;
|
||||
this.sceneWatcher();
|
||||
}
|
||||
|
||||
getStickyObject(name: string, pointNameHelper: string, index: number) {
|
||||
const objectThatSticksNameMesh = this.scene.getObjectByName(name);
|
||||
const pointName = objectThatSticksNameMesh!.name + ":point:" + index + pointNameHelper;
|
||||
return this.scene.getObjectByName(pointName);
|
||||
}
|
||||
|
||||
mapperStickyObject(point: Vector3, index: number, name: string, pointNameHelper: string) {
|
||||
const objectThatSticksNameMesh = this.scene.getObjectByName(name);
|
||||
const pointName = objectThatSticksNameMesh!.name + ":point:" + index + pointNameHelper;
|
||||
const sceneObject = this.scene.getObjectByName(pointName);
|
||||
let pointMesh: Object3D;
|
||||
if (sceneObject) {
|
||||
pointMesh = sceneObject;
|
||||
} else {
|
||||
pointMesh = new Mesh(new BoxGeometry(1.1, 1.1, 1.1), new MeshBasicMaterial({ color: "#8BC34A" }));
|
||||
}
|
||||
pointMesh.position.copy(new Box3().setFromObject(objectThatSticksNameMesh!).getCenter(new Vector3()).add(point));
|
||||
pointMesh.name = pointName;
|
||||
if (sceneObject === undefined) this.scene.add(pointMesh);
|
||||
}
|
||||
|
||||
stickyHelperLoader(stickyObjects: StickyHelper[]) {
|
||||
this.stickyObjects = stickyObjects;
|
||||
|
||||
stickyObjects.forEach((el) => {
|
||||
el.objectThatSticksNamePoints.forEach((point, index) =>
|
||||
this.mapperStickyObject(point, index, el.objectThatSticksName, "objectThatSticksNamePoints")
|
||||
);
|
||||
el.objectsToWhichItSticksPoints.forEach((point, index) =>
|
||||
this.mapperStickyObject(point, index, el.objectsToWhichItSticksName, "objectsToWhichItSticksPoints")
|
||||
);
|
||||
});
|
||||
}
|
||||
getCenter = (obj: Object3D) => new Box3().setFromObject(obj).getCenter(new Vector3());
|
||||
|
||||
sceneWatcher() {
|
||||
this.transformControls.addEventListener("objectChange", (event) => {
|
||||
//@ts-expect-error
|
||||
const sceneActiveObject = event.target.object as Mesh;
|
||||
|
||||
this.stickyObjects.forEach((stickyHelper) => {
|
||||
if (sceneActiveObject.name === stickyHelper.objectThatSticksName) {
|
||||
const objectsToWhichItSticksPointLocalVector = stickyHelper.objectsToWhichItSticksPoints[0];
|
||||
const globalVectorObjStickyName = this.scene.getObjectByName(stickyHelper.objectThatSticksName);
|
||||
|
||||
const globalVectorObjToWhichSticks = this.scene.getObjectByName(stickyHelper.objectsToWhichItSticksName);
|
||||
|
||||
const objectsToWhichItSticksNamePosition = new CoreVector3(globalVectorObjToWhichSticks!.position).add(
|
||||
objectsToWhichItSticksPointLocalVector
|
||||
).vector;
|
||||
|
||||
this.scene
|
||||
.getObjectByName("cube2:point:0objectThatSticksNamePoints")
|
||||
?.position.copy(objectsToWhichItSticksNamePosition);
|
||||
|
||||
globalVectorObjStickyName?.position.copy(
|
||||
this.scene
|
||||
.getObjectByName("cube2:point:0objectThatSticksNamePoints")!
|
||||
.position.add(objectsToWhichItSticksPointLocalVector)
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
24
ui/src/features/all_projects/data/project_http_repository.ts
Normal file
24
ui/src/features/all_projects/data/project_http_repository.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { Result } from "../../../core/helper/result";
|
||||
import { HttpMethod, CoreHttpRepository } from "../../../core/repository/http_repository";
|
||||
import { IProjectModel } from "../model/project_model";
|
||||
export interface ICreateProjectViewModel {
|
||||
description: string;
|
||||
}
|
||||
export interface UUID {
|
||||
id: string;
|
||||
}
|
||||
export class ProjectHttpRepository extends CoreHttpRepository {
|
||||
async getAllProject() {
|
||||
return this._jsonRequest<IProjectModel[]>(HttpMethod.GET, "/projects");
|
||||
}
|
||||
async saveProject(model: ICreateProjectViewModel): Promise<Result<Error, UUID>> {
|
||||
return await this._jsonRequest<UUID>(HttpMethod.POST, "/projects", model);
|
||||
}
|
||||
async setProjectRootFile(file: File, projectId: string) {
|
||||
return await this._formDataRequest(HttpMethod.POST, `/projects/upload?id=${projectId}`, file);
|
||||
}
|
||||
|
||||
async setActivePipeline(id: string) {
|
||||
return this._jsonRequest(HttpMethod.POST, `/projects/set/active/project?id=${id}`);
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import { HttpMethod, CoreHttpRepository } from "../../../core/repository/http_repository";
|
||||
import { IProjectModel } from "../model/project_model";
|
||||
|
||||
export interface UUID {
|
||||
id: string;
|
||||
}
|
||||
export class ProjectRepository extends CoreHttpRepository {
|
||||
async getAllProject() {
|
||||
return this._jsonRequest<IProjectModel[]>(HttpMethod.GET, "/projects");
|
||||
}
|
||||
|
||||
|
||||
async setActivePipeline(id: string) {
|
||||
return this._jsonRequest(HttpMethod.POST, `/projects/set/active/project?id=${id}`);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
import { PipelineModel } from "../../create_project/create_project_repository";
|
||||
|
||||
export interface IProjectModel {
|
||||
_id?: string;
|
||||
|
@ -6,3 +5,8 @@ export interface IProjectModel {
|
|||
description: string;
|
||||
isActive?: boolean;
|
||||
}
|
||||
export interface IProjectView {
|
||||
isActive: boolean;
|
||||
description: string;
|
||||
id: string;
|
||||
}
|
|
@ -1,52 +1,103 @@
|
|||
import * as React from "react";
|
||||
import { AllProjectStore } from "./all_projects_store";
|
||||
import { ProjectRepository } from "../data/project_repository";
|
||||
import { LoadPage } from "../../../core/ui/pages/load_page";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Button } from "antd";
|
||||
import { PipelineInstanceScreenPath } from "../../pipeline_instance_main_screen/pipeline_instance_screen";
|
||||
import { CreateProjectScreenPath } from "../../create_project/create_project_screen";
|
||||
import { Modal, Upload } from "antd";
|
||||
import { PreviewPage } from "../../../core/ui/pages/preview_page";
|
||||
import { CoreText, CoreTextType } from "../../../core/ui/text/text";
|
||||
import { CoreButton } from "../../../core/ui/button/button";
|
||||
import { CoreInput } from "../../../core/ui/input/input";
|
||||
import { DetailsScreenPath } from "../../details/details_screen";
|
||||
|
||||
export const AllProjectScreenPath = "/";
|
||||
export const AllProjectScreen: React.FunctionComponent = observer(() => {
|
||||
const [store] = React.useState(() => new AllProjectStore(new ProjectRepository()));
|
||||
const [store] = React.useState(() => new AllProjectStore());
|
||||
const navigate = useNavigate();
|
||||
|
||||
React.useEffect(() => {
|
||||
store.init();
|
||||
}, [store]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<LoadPage
|
||||
largeText={"Projects"}
|
||||
needBackButton={false}
|
||||
minText="create project?"
|
||||
path={CreateProjectScreenPath}
|
||||
isError={false}
|
||||
isLoading={store.isLoading}
|
||||
children={
|
||||
<div>
|
||||
{store.projectsModels?.map((el) => {
|
||||
return (
|
||||
<div style={{ margin: 10, backgroundColor: "chartreuse" }}>
|
||||
{el.isActive ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
navigate(`${PipelineInstanceScreenPath}${el._id}`);
|
||||
}}
|
||||
>
|
||||
instance screen
|
||||
</Button>
|
||||
) : <Button style={{ backgroundColor: 'red' }} onClick={() => store.setActiveProject(el._id as string)}>active project</Button>}
|
||||
<div style={{ margin: "10px", display: "contents" }}> {el.description}</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
<PreviewPage
|
||||
largeText={"Проекты"}
|
||||
needBackButton={false}
|
||||
minText="Создать новый проект?"
|
||||
click={() => store.showModal()}
|
||||
isError={false}
|
||||
isLoading={store.isLoading}
|
||||
children={
|
||||
<>
|
||||
{store.projectsModels?.map((el) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
border: "1px solid #CAC4D0",
|
||||
margin: 10,
|
||||
height: 60,
|
||||
alignItems: "center",
|
||||
borderRadius: 7,
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
backgroundColor: el.isActive ? "rgba(104, 80, 164, 1)" : "rgba(255, 255, 255, 1)",
|
||||
}}
|
||||
>
|
||||
<CoreText
|
||||
text={el.description}
|
||||
type={CoreTextType.medium}
|
||||
style={{ color: el.isActive ? "white" : "black", margin: 10 }}
|
||||
/>
|
||||
{el.isActive ? (
|
||||
<CoreButton
|
||||
text="Перейти"
|
||||
onClick={() => {
|
||||
navigate(`${DetailsScreenPath}`);
|
||||
}}
|
||||
textStyle={{ color: "black",textAlign:'center' }}
|
||||
style={{ marginRight: 10, backgroundColor: "white", width: 126 }}
|
||||
/>
|
||||
) : (
|
||||
<CoreButton
|
||||
text="Активировать"
|
||||
onClick={() => store.setActiveProject(el._id as string)}
|
||||
style={{ marginRight: 10, width: 126 }}
|
||||
filled={true}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<Modal
|
||||
destroyOnClose={true}
|
||||
open={store.isModalOpen}
|
||||
footer={null}
|
||||
closable={false}
|
||||
closeIcon={null}
|
||||
onCancel={store.handleCancel}
|
||||
>
|
||||
<CoreText text="Новый проект" type={CoreTextType.big} />
|
||||
<CoreInput label={"название проекта"} onChange={(text) => store.setDescriptionToNewProject(text)} />
|
||||
<div style={{ height: 20 }} />
|
||||
<Upload
|
||||
onChange={(e) => {
|
||||
store.file = e.file.originFileObj;
|
||||
}}
|
||||
>
|
||||
<CoreButton text="файл проекта" />
|
||||
</Upload>
|
||||
<div style={{ height: 20 }} />
|
||||
<div style={{ display: "flex" }}>
|
||||
<CoreButton
|
||||
text="Сохранить"
|
||||
onClick={() => store.saveProject()}
|
||||
style={{ marginRight: 10 }}
|
||||
filled={true}
|
||||
/>
|
||||
<CoreButton text="Отменить" onClick={() => store.handleCancel()} style={{ marginRight: 10 }} />
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
import makeAutoObservable from "mobx-store-inheritance";
|
||||
import { ProjectRepository, UUID } from "../data/project_repository";
|
||||
import { IProjectModel } from "../model/project_model";
|
||||
import { SimpleErrorState } from "../../../core/store/base_store";
|
||||
import { ProjectHttpRepository, UUID } from "../data/project_http_repository";
|
||||
import { IProjectModel, IProjectView } from "../model/project_model";
|
||||
import { ModalStore } from "../../../core/store/base_store";
|
||||
import { message } from "antd";
|
||||
|
||||
interface IProjectView {
|
||||
isActive: boolean;
|
||||
description: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export class ProjectView {
|
||||
isActive: boolean;
|
||||
description: string;
|
||||
|
@ -18,31 +15,64 @@ export class ProjectView {
|
|||
this.id = view.id;
|
||||
}
|
||||
}
|
||||
export class AllProjectStore extends SimpleErrorState {
|
||||
|
||||
export class AllProjectStore extends ModalStore {
|
||||
projectsModels?: IProjectModel[];
|
||||
activeProjectId?: UUID;
|
||||
repository: ProjectRepository;
|
||||
constructor(repository: ProjectRepository) {
|
||||
newProjectDescription: string = "";
|
||||
file?: File;
|
||||
|
||||
projectHttpRepository: ProjectHttpRepository = new ProjectHttpRepository();
|
||||
constructor() {
|
||||
super();
|
||||
this.repository = repository;
|
||||
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
async getProjects(): Promise<void> {
|
||||
await this.mapOk<IProjectModel[]>("projectsModels", this.repository.getAllProject());
|
||||
await this.mapOk<IProjectModel[]>("projectsModels", this.projectHttpRepository.getAllProject());
|
||||
}
|
||||
async getActiveProjectId(): Promise<void> {
|
||||
await this.mapOk<UUID>("activeProjectId", this.repository.getActiveProjectId());
|
||||
await this.mapOk<UUID>("activeProjectId", this.projectHttpRepository.getActiveProjectId());
|
||||
}
|
||||
setActiveProject = async (id: string) => {
|
||||
await this.messageHttp(this.repository.setActivePipeline(id), { successMessage: "проект активирован", errorMessage: 'ошибка активации' })
|
||||
await this.mapOk<UUID>("activeProjectId", this.repository.getActiveProjectId());
|
||||
await this.mapOk<IProjectModel[]>("projectsModels", this.repository.getAllProject());
|
||||
}
|
||||
await this.messageHttp(this.projectHttpRepository.setActivePipeline(id), {
|
||||
successMessage: "проект активирован",
|
||||
errorMessage: "ошибка активации",
|
||||
});
|
||||
await this.mapOk<UUID>("activeProjectId", this.projectHttpRepository.getActiveProjectId());
|
||||
await this.mapOk<IProjectModel[]>("projectsModels", this.projectHttpRepository.getAllProject());
|
||||
};
|
||||
async init() {
|
||||
await Promise.all([this.getProjects(), this.getActiveProjectId()]);
|
||||
this.projectsModels?.map((el) => (el._id === this.activeProjectId ? ((el.isActive = true), el) : el));
|
||||
}
|
||||
setDescriptionToNewProject = (value: string) => {
|
||||
this.newProjectDescription = value;
|
||||
};
|
||||
async saveProject(): Promise<void> {
|
||||
if (this.newProjectDescription.isEmpty()) {
|
||||
message.error("Описание проекта не должно быть пустым");
|
||||
return;
|
||||
}
|
||||
if (this.file === undefined) {
|
||||
message.error("загрузите файл");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
this.isLoading = true;
|
||||
(
|
||||
await this.projectHttpRepository.saveProject({
|
||||
description: this.newProjectDescription,
|
||||
})
|
||||
).fold(
|
||||
async (uuid) => {
|
||||
this.newProjectDescription = "";
|
||||
await this.projectHttpRepository.setProjectRootFile(this.file as File, uuid.id);
|
||||
this.isLoading = false;
|
||||
this.init();
|
||||
},
|
||||
async (_) => {
|
||||
this.isError = true;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { Result } from "../../../core/helper/result";
|
||||
import { Skills } from "../../../core/model/skill_model";
|
||||
import { HttpError, HttpMethod, CoreHttpRepository } from "../../../core/repository/http_repository";
|
||||
import { UUID } from "../../all_projects/data/project_repository";
|
||||
import { BehaviorTreeModel } from "../model/behavior_tree_model";
|
||||
import { BehaviorTreeViewModel } from "../model/behavior_tree_view_model";
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ export const BehaviorTreeBuilderScreen = observer(() => {
|
|||
/>
|
||||
</div>
|
||||
))}
|
||||
<Icon type="PlusCircle" onClick={() => store.edtDrawer(DrawerState.newBehaviorTree, true)} />
|
||||
<Icon type="PlusCircle" onClick={() => store.editDrawer(DrawerState.newBehaviorTree, true)} />
|
||||
</div>
|
||||
</>
|
||||
))
|
||||
|
@ -125,7 +125,7 @@ export const BehaviorTreeBuilderScreen = observer(() => {
|
|||
<Drawer
|
||||
title={store.titleDrawer}
|
||||
destroyOnClose={true}
|
||||
onClose={() => store.edtDrawer(DrawerState.newBehaviorTree, false)}
|
||||
onClose={() => store.editDrawer(DrawerState.newBehaviorTree, false)}
|
||||
open={store.drawers.find((el) => el.name === DrawerState.newBehaviorTree)?.status}
|
||||
>
|
||||
<div style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", height: "100%" }}>
|
||||
|
@ -135,14 +135,14 @@ export const BehaviorTreeBuilderScreen = observer(() => {
|
|||
<div style={{ display: "flex" }}>
|
||||
<CoreButton text="Сохранить" filled={true} onClick={() => store.createNewBehaviorTree()} />
|
||||
<div style={{ width: 10 }} />
|
||||
<CoreButton text="Отмена" onClick={() => store.edtDrawer(DrawerState.newBehaviorTree, false)} />
|
||||
<CoreButton text="Отмена" onClick={() => store.editDrawer(DrawerState.newBehaviorTree, false)} />
|
||||
</div>
|
||||
</div>
|
||||
</Drawer>
|
||||
<Drawer
|
||||
title={store.titleDrawer}
|
||||
destroyOnClose={true}
|
||||
onClose={() => store.edtDrawer(DrawerState.editThreadBehaviorTree, false)}
|
||||
onClose={() => store.editDrawer(DrawerState.editThreadBehaviorTree, false)}
|
||||
open={store.drawers.find((el) => el.name === DrawerState.editThreadBehaviorTree)?.status}
|
||||
>
|
||||
<div style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", height: "100%" }}>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import makeAutoObservable from "mobx-store-inheritance";
|
||||
import { CoreError, UiFormState } from "../../../core/store/base_store";
|
||||
import { CoreError, UiDrawerFormState } from "../../../core/store/base_store";
|
||||
import {
|
||||
BehaviorTreeBuilderModel,
|
||||
BtNodeView as BtNodeObserver,
|
||||
|
@ -44,7 +44,7 @@ export enum StoreUIType {
|
|||
}
|
||||
|
||||
|
||||
export class BehaviorTreeBuilderStore extends UiFormState<BehaviorTreeViewModel, CoreError> {
|
||||
export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeViewModel, CoreError> {
|
||||
type: StoreUIType = StoreUIType.ViewBehaviorTree;
|
||||
viewModel: BehaviorTreeViewModel = BehaviorTreeViewModel.empty();
|
||||
behaviorTreeModel: BehaviorTreeModel = BehaviorTreeModel.empty();
|
||||
|
@ -254,7 +254,7 @@ export class BehaviorTreeBuilderStore extends UiFormState<BehaviorTreeViewModel,
|
|||
!Object.keys(SystemPrimitive).includes(label) &&
|
||||
this.skillTemplates.skillHasForm(label)
|
||||
) {
|
||||
this.edtDrawer(DrawerState.editThreadBehaviorTree, selected);
|
||||
this.editDrawer(DrawerState.editThreadBehaviorTree, selected);
|
||||
this.selected = label;
|
||||
}
|
||||
if (this.deleteIsPressed) {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
import { CameraDeviceForm } from "./camera_device_form/camera_device_form_form";
|
||||
import { RobotDeviceForm } from "./robot_device_form/robot_device_form_form";
|
||||
import { TopicsForm } from "./topics_form/topics_form";
|
||||
|
@ -14,14 +13,14 @@ export interface IForms {
|
|||
component: JSX.Element;
|
||||
}
|
||||
export enum Form {
|
||||
weights = 'weights',
|
||||
robotName = 'robot_name',
|
||||
cameraDeviceForm = 'camera',
|
||||
topic = 'topic'
|
||||
weights = "weights",
|
||||
robotName = "robot_name",
|
||||
cameraDeviceForm = "camera",
|
||||
topic = "topic",
|
||||
}
|
||||
export const forms = (props: any, onChange: (dependency: Object) => void): IForms[] => [
|
||||
{ name: Form.weights, component: <WeightsForm dependency={props} onChange={onChange} /> },
|
||||
{ name: Form.robotName, component: <RobotDeviceForm dependency={props} onChange={onChange} /> },
|
||||
{ name: Form.cameraDeviceForm, component: <CameraDeviceForm dependency={props} onChange={onChange} /> },
|
||||
{ name: Form.topic, component: <TopicsForm dependency={props} onChange={onChange} /> }
|
||||
{ name: Form.topic, component: <TopicsForm dependency={props} onChange={onChange} /> },
|
||||
];
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
import { Result } from "../../core/helper/result";
|
||||
import { DatabaseModel } from "../../core/model/database_model";
|
||||
import { ITriggerModel } from "../../core/model/trigger_model";
|
||||
import { HttpMethod, CoreHttpRepository } from "../../core/repository/http_repository";
|
||||
import { UUID } from "../all_projects/data/project_repository";
|
||||
import { ICreateProjectViewModel } from "./project_model";
|
||||
|
||||
export interface PipelineModel extends DatabaseModel {
|
||||
process: any;
|
||||
trigger: ITriggerModel;
|
||||
}
|
||||
|
||||
export class CreateProjectRepository extends CoreHttpRepository {
|
||||
async saveProject(model: ICreateProjectViewModel): Promise<Result<Error, UUID>> {
|
||||
return await this._jsonRequest<UUID>(HttpMethod.POST, "/projects", model);
|
||||
}
|
||||
async setProjectRootFile(file: File, projectId: string) {
|
||||
return await this._formDataRequest(HttpMethod.POST, `/projects/upload?id=${projectId}`, file);
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
import * as React from "react";
|
||||
import { LoadPage as MainPage } from "../../core/ui/pages/load_page";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { Col, Row, Input, Button, Upload } from "antd";
|
||||
import type { UploadProps } from "antd";
|
||||
import { CreateProjectStore } from "./create_project_store";
|
||||
import { CreateProjectRepository } from "./create_project_repository";
|
||||
|
||||
export const CreateProjectScreenPath = "/create_project";
|
||||
export const CreateProjectScreen: React.FunctionComponent = observer(() => {
|
||||
const [store] = React.useState(() => new CreateProjectStore(new CreateProjectRepository()));
|
||||
|
||||
React.useEffect(() => {
|
||||
store.init();
|
||||
}, [store]);
|
||||
return (
|
||||
<>
|
||||
<MainPage
|
||||
path={""}
|
||||
largeText={"Create project"}
|
||||
isLoading={store.isLoading}
|
||||
isError={store.isError}
|
||||
children={
|
||||
<Row>
|
||||
<Row>
|
||||
<Col>
|
||||
<Row>
|
||||
<Input
|
||||
style={{ width: "250px" }}
|
||||
onChange={(e) => store.setDescriptionToNewProject(e.target.value)}
|
||||
placeholder="project description"
|
||||
/>
|
||||
<Upload
|
||||
onChange={(e) => {
|
||||
store.file = e.file.originFileObj;
|
||||
}}
|
||||
>
|
||||
<Button>Click to Upload</Button>
|
||||
</Upload>
|
||||
<Button onClick={() => store.saveProject()}>save</Button>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Row>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
});
|
|
@ -1,51 +0,0 @@
|
|||
import makeAutoObservable from "mobx-store-inheritance";
|
||||
import { CreateProjectRepository } from "./create_project_repository";
|
||||
import { message } from "antd";
|
||||
import { SimpleErrorState } from "../../core/store/base_store";
|
||||
|
||||
export class CreateProjectStore extends SimpleErrorState {
|
||||
repository: CreateProjectRepository;
|
||||
|
||||
newProjectDescription: string = "";
|
||||
file?: File;
|
||||
|
||||
constructor(repository: CreateProjectRepository) {
|
||||
super();
|
||||
this.repository = repository;
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
async init() {}
|
||||
|
||||
setDescriptionToNewProject(value: string): void {
|
||||
this.newProjectDescription = value;
|
||||
}
|
||||
|
||||
async saveProject(): Promise<void> {
|
||||
if (this.newProjectDescription.isEmpty()) {
|
||||
message.error("project description is not empty");
|
||||
return;
|
||||
}
|
||||
if (this.file === undefined) {
|
||||
message.error("upload file");
|
||||
return;
|
||||
}
|
||||
|
||||
this.isLoading = true;
|
||||
(
|
||||
await this.repository.saveProject({
|
||||
description: this.newProjectDescription,
|
||||
})
|
||||
).fold(
|
||||
(uuid) => {
|
||||
this.newProjectDescription = "";
|
||||
this.isLoading = false;
|
||||
this.repository.setProjectRootFile(this.file as File, uuid.id);
|
||||
},
|
||||
(_) => {
|
||||
this.isError = true;
|
||||
}
|
||||
);
|
||||
|
||||
//
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
export interface ICreateProjectViewModel {
|
||||
description: string;
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
import { Result } from "../../core/helper/result";
|
||||
import { HttpError, HttpMethod, CoreHttpRepository } from "../../core/repository/http_repository";
|
||||
import { UUID } from "../all_projects/data/project_repository";
|
||||
import { Parts } from "../details/details_http_repository";
|
||||
import { DataSetModel, Dataset, IDatasetModel, ProcessStatus } from "./dataset_model";
|
||||
|
||||
export class DataSetHttpRepository extends CoreHttpRepository {
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Drawer, UiErrorState } from "../../core/store/base_store";
|
|||
import { HttpError } from "../../core/repository/http_repository";
|
||||
import { DataSetModel, IDatasetModel, ProcessStatus } from "./dataset_model";
|
||||
import { message } from "antd";
|
||||
import { UUID } from "../all_projects/data/project_repository";
|
||||
import { UUID } from "../all_projects/data/project_http_repository";
|
||||
import { SocketRepository, socketRepository } from "../../core/repository/socket_repository";
|
||||
import { Parts } from "../details/details_http_repository";
|
||||
|
||||
|
|
|
@ -10,21 +10,18 @@ export const DetailsScreen = observer(() => {
|
|||
const [store] = React.useState(() => new DetailsStore());
|
||||
React.useEffect(() => {
|
||||
store.loadScene(canvasRef.current!);
|
||||
|
||||
}, [])
|
||||
}, []);
|
||||
const canvasRef = React.useRef<HTMLCanvasElement>(null);
|
||||
|
||||
return (
|
||||
<MainPage
|
||||
page={"Детали"}
|
||||
panelStyle={{ overflowX: "auto" }}
|
||||
bodyChildren={
|
||||
<canvas ref={canvasRef} style={{ overflow: "hidden", width: '100%' }} />
|
||||
}
|
||||
bodyChildren={<canvas ref={canvasRef} style={{ overflow: "hidden", width: "100%" }} />}
|
||||
panelChildren={
|
||||
<>
|
||||
{store.detailsViewModel.map((el) => (
|
||||
<div onClick={() => store.selectedDetail(el.label)} style={{ margin: 5, cursor: "pointer" }}>
|
||||
{store.detailsViewModel.map((el, i) => (
|
||||
<div key={i} onClick={() => store.selectedDetail(el.label)} style={{ margin: 5, cursor: "pointer" }}>
|
||||
<div style={el.selected ? { width: "100%", background: "#E8DEF8", borderRadius: 100 } : {}}>
|
||||
<CoreText
|
||||
style={{ textAlign: "start", padding: 10, paddingLeft: 40 }}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
export class PipelineInstanceRepository {}
|
|
@ -1,25 +0,0 @@
|
|||
import * as React from "react";
|
||||
import { PipelineInstanceStore } from "./pipeline_instance_store";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { MainPage } from "../../core/ui/pages/main_page";
|
||||
|
||||
export const PipelineInstanceScreenPath = "/pipeline_instance/";
|
||||
|
||||
export const PipelineInstanceScreen: React.FunctionComponent = () => {
|
||||
const [store] = React.useState(() => {
|
||||
new PipelineInstanceStore();
|
||||
});
|
||||
React.useEffect(() => {
|
||||
document.body.style.overflow = "hidden";
|
||||
return () => {
|
||||
document.body.style.overflow = "scroll";
|
||||
};
|
||||
}, [store]);
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<>
|
||||
<MainPage page="Датасеты" />
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -1,9 +0,0 @@
|
|||
import makeAutoObservable from "mobx-store-inheritance";
|
||||
import { SimpleErrorState } from "../../core/store/base_store";
|
||||
|
||||
export class PipelineInstanceStore extends SimpleErrorState {
|
||||
constructor() {
|
||||
super();
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
}
|
12
ui/src/features/scene_manager/data/scene_http_repository.ts
Normal file
12
ui/src/features/scene_manager/data/scene_http_repository.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { Result } from "../../../core/helper/result";
|
||||
import { HttpMethod, CoreHttpRepository } 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";
|
||||
|
||||
export class SceneHttpRepository extends CoreHttpRepository {
|
||||
getAllScenes = () => this._jsonRequest<SceneModel[]>(HttpMethod.GET, "/scenes");
|
||||
|
||||
newScene = (sceneViewModel: SceneViewModel) =>
|
||||
this._jsonRequest(HttpMethod.POST, "/scenes", sceneViewModel) as unknown as Promise<Result<CoreError, void>>;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
import { Result } from "../../../core/helper/result";
|
||||
import { HttpMethod, CoreHttpRepository } from "../../../core/repository/http_repository";
|
||||
import { CoreError } from "../../../core/store/base_store";
|
||||
import { RobossemblerAssets } from "../../../core/model/robossembler_assets";
|
||||
|
||||
export class SceneHttpRepository extends CoreHttpRepository {
|
||||
async getRobossemblerAssets() {
|
||||
return this._jsonToClassInstanceRequest<RobossemblerAssets>(
|
||||
HttpMethod.GET,
|
||||
"/robossembler_assets",
|
||||
RobossemblerAssets
|
||||
) as unknown as Promise<Result<CoreError, RobossemblerAssets>>;
|
||||
}
|
||||
async saveScene(robossemblerAssets: RobossemblerAssets) {
|
||||
return this._jsonRequest(HttpMethod.POST, "/robossembler_assets", robossemblerAssets) as unknown as Promise<
|
||||
Result<CoreError, void>
|
||||
>;
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import {
|
|||
InstanceType,
|
||||
SceneSimpleObject,
|
||||
} from "../../../core/model/robossembler_assets";
|
||||
import { Result } from "../../../core/helper/result";
|
||||
|
||||
export enum RobossemblerFiles {
|
||||
robossemblerAssets = "robossembler_assets.json",
|
||||
|
@ -137,19 +138,11 @@ export class CameraViewModel extends BaseSceneItemModel {
|
|||
};
|
||||
}
|
||||
|
||||
validate(cameraLinksNames: string[]) {
|
||||
if (cameraLinksNames.filter((el) => this.cameraLink === el).isNotEmpty()) {
|
||||
return { cameraLink: "the name for the camera is not unique" };
|
||||
}
|
||||
validate(): Result<string, CameraViewModel> {
|
||||
if (this.cameraLink.isEmpty()) {
|
||||
return { cameraLink: "is empty" };
|
||||
}
|
||||
if (this.topicImage.isEmpty()) {
|
||||
return { topicImage: "is empty" };
|
||||
}
|
||||
if (this.topicCameraInfo.isEmpty()) {
|
||||
return { topicCameraInfo: "is empty" };
|
||||
return Result.error("cameraLink is empty");
|
||||
}
|
||||
return Result.ok(this);
|
||||
}
|
||||
|
||||
mapPerspectiveCamera(htmlSceneWidth: number, htmlSceneHeight: number) {
|
||||
|
|
4
ui/src/features/scene_manager/model/scene_model.ts
Normal file
4
ui/src/features/scene_manager/model/scene_model.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
export interface SceneModel {
|
||||
_id: string;
|
||||
name: string;
|
||||
}
|
17
ui/src/features/scene_manager/model/scene_view_model.ts
Normal file
17
ui/src/features/scene_manager/model/scene_view_model.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { Result } from "../../../core/helper/result";
|
||||
|
||||
export class SceneViewModel {
|
||||
name: string;
|
||||
constructor(name: string) {
|
||||
this.name = name;
|
||||
}
|
||||
static empty() {
|
||||
return new SceneViewModel("");
|
||||
}
|
||||
valid = (): Result<string,SceneViewModel> => {
|
||||
if (this.name.isEmpty()) {
|
||||
return Result.error("name is empty");
|
||||
}
|
||||
return Result.ok(this);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
import { NavigateFunction } from "react-router-dom";
|
||||
import { CoreError, FormState, UiDrawerFormState } from "../../../../../core/store/base_store";
|
||||
import { CoreButton } from "../../../../../core/ui/button/button";
|
||||
import { CameraViewModel } from "../../../model/scene_assets";
|
||||
import { IDefaultSceneManagerProps } from "../scene_manager_forms";
|
||||
import React from "react";
|
||||
import { CoreInput } from "../../../../../core/ui/input/input";
|
||||
import { CoreText, CoreTextType } from "../../../../../core/ui/text/text";
|
||||
import { message } from "antd";
|
||||
|
||||
class CameraFormStore extends FormState<CameraViewModel, CoreError> {
|
||||
errorHandingStrategy = (error: CoreError) => {};
|
||||
init = async (navigate?: NavigateFunction | undefined) => {};
|
||||
viewModel: CameraViewModel = CameraViewModel.empty();
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
export const CameraForm = (props: IDefaultSceneManagerProps) => {
|
||||
const [store] = React.useState(() => new CameraFormStore());
|
||||
|
||||
React.useEffect(() => {
|
||||
store.init();
|
||||
}, []);
|
||||
return (
|
||||
<div style={{ margin: 10, padding: 10 }}>
|
||||
<CoreText text="Камера" type={CoreTextType.header} />
|
||||
<CoreInput label={"Камера линк"} onChange={(text) => store.updateForm({ cameraLink: text })} />
|
||||
<div style={{ height: 10 }} />
|
||||
<CoreButton
|
||||
text="Создать"
|
||||
style={{ width: 96 }}
|
||||
onClick={() =>
|
||||
store.viewModel.validate().fold(
|
||||
(model) => {
|
||||
props.store.addNewCamera(model);
|
||||
},
|
||||
(error) => message.error(error)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// onClick={props.store.addNewCamera()}
|
|
@ -0,0 +1,6 @@
|
|||
import { IDefaultSceneManagerProps } from "../scene_manager_forms";
|
||||
|
||||
|
||||
export const RobotForm = (props: IDefaultSceneManagerProps) => {
|
||||
return <div>ROBOT</div>;
|
||||
};
|
|
@ -0,0 +1,23 @@
|
|||
import { SceneMangerStore } from "../scene_manager_store";
|
||||
import { CameraForm } from "./camera/camera_form";
|
||||
import { RobotForm } from "./robot/robot_form";
|
||||
import { SolidBodyForm } from "./solid_body/solid_body_form";
|
||||
|
||||
export enum SceneManagerForms {
|
||||
robot = "robot",
|
||||
camera = "camera",
|
||||
solidBody = "solidBody",
|
||||
}
|
||||
interface IForms {
|
||||
name: string;
|
||||
component: JSX.Element;
|
||||
}
|
||||
export interface IDefaultSceneManagerProps {
|
||||
dependency: Object;
|
||||
store: SceneMangerStore;
|
||||
}
|
||||
export const sceneManagerForms = (props: Object, store: SceneMangerStore): IForms[] => [
|
||||
{ name: SceneManagerForms.camera, component: <CameraForm dependency={props} store={store} /> },
|
||||
{ name: SceneManagerForms.robot, component: <RobotForm dependency={props} store={store} /> },
|
||||
{ name: SceneManagerForms.solidBody, component: <SolidBodyForm dependency={props} store={store} /> },
|
||||
];
|
|
@ -0,0 +1,5 @@
|
|||
import { IDefaultSceneManagerProps } from "../scene_manager_forms";
|
||||
|
||||
export const SolidBodyForm = (props:IDefaultSceneManagerProps) => {
|
||||
return <></>;
|
||||
};
|
|
@ -0,0 +1,41 @@
|
|||
import makeAutoObservable from "mobx-store-inheritance";
|
||||
import { SolidBodyViewModel } from "./solid_body_view_model";
|
||||
import { FormState, CoreError } from "../../../../../core/store/base_store";
|
||||
import { CoreHttpRepository } from "../../../../../core/repository/http_repository";
|
||||
import { Parts } from "../../../../details/details_http_repository";
|
||||
import { Vector2 } from "three";
|
||||
export enum SolidBodyStoreType {
|
||||
selectBody = "selectBody",
|
||||
selectSpawnPositionType = "selectSpawnPositionType",
|
||||
spawn2DVector = "spawn2DVector",
|
||||
}
|
||||
export enum SpawnPositionTypes {
|
||||
BoundBox = "BoundBox",
|
||||
}
|
||||
export class SolidBodyStore extends FormState<SolidBodyViewModel, CoreError> {
|
||||
viewModel: SolidBodyViewModel = SolidBodyViewModel.empty();
|
||||
parts: Parts[] = [];
|
||||
spawnPositionTypes = Object.keys(SpawnPositionTypes);
|
||||
coreHttpRepository: CoreHttpRepository = new CoreHttpRepository();
|
||||
solidBodyStoreType: SolidBodyStoreType = SolidBodyStoreType.selectBody;
|
||||
selectBody: Parts;
|
||||
spawnType: string;
|
||||
errorHandingStrategy = (error: CoreError) => {};
|
||||
constructor() {
|
||||
super();
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
vector2d?: Vector2;
|
||||
init = async () => {
|
||||
this.mapOk("parts", this.coreHttpRepository.getAssetsActiveProject());
|
||||
};
|
||||
selectSpawnType = (type: string) => {
|
||||
this.spawnType = type;
|
||||
this.solidBodyStoreType = SolidBodyStoreType.spawn2DVector;
|
||||
};
|
||||
selectVector = () => {};
|
||||
clickSelectBody = (el: Parts) => {
|
||||
this.selectBody = el;
|
||||
this.solidBodyStoreType = SolidBodyStoreType.selectSpawnPositionType;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
export class SolidBodyViewModel {
|
||||
name: string;
|
||||
|
||||
static empty() {
|
||||
return new SolidBodyViewModel();
|
||||
}
|
||||
}
|
|
@ -1,8 +1,16 @@
|
|||
import * as React from "react";
|
||||
import { SceneMangerStore } from "./scene_manager_store";
|
||||
import { DrawersSceneManager, SceneMangerStore, StoreMode } from "./scene_manager_store";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { MainPage } from "../../../core/ui/pages/main_page";
|
||||
import { CoreText, CoreTextType } from "../../../core/ui/text/text";
|
||||
import { Drawer } from "antd";
|
||||
import { CoreButton } from "../../../core/ui/button/button";
|
||||
import { CoreInput } from "../../../core/ui/input/input";
|
||||
import { DrawersDataset } from "../../dataset/dataset_store";
|
||||
import { Popover } from "antd";
|
||||
import { Icon } from "../../../core/ui/icons/icons";
|
||||
import { sceneManagerForms } from "./forms/scene_manager_forms";
|
||||
|
||||
export const SceneManagerPath = "/scene/manager/";
|
||||
|
||||
|
@ -10,6 +18,8 @@ export const SceneManger = observer(() => {
|
|||
const canvasRef = React.useRef<HTMLCanvasElement>(null);
|
||||
const [store] = React.useState(() => new SceneMangerStore());
|
||||
const id = useParams().id as string;
|
||||
const navigate = useNavigate();
|
||||
store.initParam(id);
|
||||
|
||||
React.useEffect(() => {
|
||||
store.init();
|
||||
|
@ -24,146 +34,171 @@ export const SceneManger = observer(() => {
|
|||
return (
|
||||
<MainPage
|
||||
page={"Сцена"}
|
||||
bodyChildren={
|
||||
<>
|
||||
<canvas ref={canvasRef} style={{ overflow: "hidden" }} />
|
||||
panelChildren={
|
||||
<div style={{ width: "100%", height: "100%" }}>
|
||||
<div style={{ height: 260, width: "100%", padding: 10 }}>
|
||||
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
||||
<CoreText text="Сцена" type={CoreTextType.large} />
|
||||
<Popover
|
||||
placement="bottom"
|
||||
color="rgba(104, 80, 164, 1)"
|
||||
content={
|
||||
<div>
|
||||
{store.popoverItems.map((el, i) => (
|
||||
<div onClick={() => el.fn()}>
|
||||
<CoreText key={i} text={el.name} type={CoreTextType.medium} color="white" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<span>
|
||||
<CoreButton text="Добавить" filled={true} />
|
||||
</span>
|
||||
</Popover>
|
||||
</div>
|
||||
<div style={{ height: 10 }} />
|
||||
<div
|
||||
style={{
|
||||
borderRadius: 22,
|
||||
height: 200,
|
||||
width: "-webkit-fill-available",
|
||||
backgroundColor: "white",
|
||||
overflowX: "auto",
|
||||
}}
|
||||
>
|
||||
{store.sceneItems.map((el, index) => (
|
||||
<div
|
||||
key={index}
|
||||
style={{
|
||||
paddingLeft: 20,
|
||||
display: "flex",
|
||||
backgroundColor: index.isEven() ? "rgba(217, 217, 217, 0.27)" : "",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Icon type={el.icon} />
|
||||
<div style={{ width: 10 }} />
|
||||
<CoreText text={el.name} type={CoreTextType.small} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ height: 20 }} />
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignContent: "center",
|
||||
justifyContent: "space-between",
|
||||
position: "absolute",
|
||||
width: "100vw",
|
||||
width: "-webkit-fill-available",
|
||||
height: "100%",
|
||||
borderRadius: 7,
|
||||
backgroundColor: "white",
|
||||
margin: 10,
|
||||
|
||||
}}
|
||||
/>
|
||||
{/* <div>
|
||||
{sceneIcons.map((el) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: store.sceneMode === el.name ? "aqua" : "ActiveBorder",
|
||||
}}
|
||||
onClick={() => {
|
||||
el.clickHandel();
|
||||
}}
|
||||
>
|
||||
{el.name}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<div
|
||||
style={{
|
||||
marginTop: "10px",
|
||||
backgroundColor: "GrayText",
|
||||
border: "solid",
|
||||
borderRadius: "10px",
|
||||
padding: "8px",
|
||||
borderColor: "white",
|
||||
}}
|
||||
>
|
||||
{/* <div style={{ color: "white" }}>Scene manager</div>
|
||||
{store.isVisibleSaveButton ? (
|
||||
<>
|
||||
<Button onClick={() => store.onTapSave()}>Save</Button>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
{store.isLoading ? <>Loading...</> : <></>}
|
||||
{store.sceneMode === SceneMode.ADD_CAMERA ? (
|
||||
<div>
|
||||
<Formik
|
||||
initialValues={CameraViewModel.empty()}
|
||||
onSubmit={async (model, actions) => {
|
||||
store.addNewCamera(model);
|
||||
actions.setSubmitting(false);
|
||||
actions.resetForm();
|
||||
}}
|
||||
validate={(model) => {
|
||||
return model.validate(store.getCameraLinkNames());
|
||||
}}
|
||||
render={() => (
|
||||
<Form>
|
||||
<div
|
||||
style={{
|
||||
background: "white",
|
||||
flex: 1,
|
||||
padding: 40,
|
||||
width: "400px",
|
||||
}}
|
||||
>
|
||||
<Input name="cameraLink" placeholder="Camera link" />
|
||||
<Input name="topicImage" placeholder="Topic Image" />
|
||||
<Input name="topicCameraInfo" placeholder="Topic Camera Info" />
|
||||
<Input name="topicDepth" placeholder="Topic Depth" />
|
||||
>
|
||||
{sceneManagerForms(store.activeFormDependency ?? {}, store).map((el) => {
|
||||
if (el.name.isEqual(store.activeFormType ?? "")) {
|
||||
return <>{el.component}</>;
|
||||
}
|
||||
return <></>;
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
bodyChildren={
|
||||
<>
|
||||
{store.storeMode.isEqual(StoreMode.sceneInstance) ? (
|
||||
<>
|
||||
<canvas ref={canvasRef} style={{ overflow: "hidden" }} />
|
||||
</>
|
||||
) : (
|
||||
<div
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100vh",
|
||||
background: "rgba(246, 242, 249, 1)",
|
||||
padding: 50,
|
||||
paddingLeft: 70,
|
||||
paddingRight: 70,
|
||||
}}
|
||||
>
|
||||
<div style={{ width: "100%", height: "100%", background: "white" }}>
|
||||
<div style={{ width: "100%", textAlign: "center" }}>
|
||||
<CoreText text="Сцены" type={CoreTextType.big} />
|
||||
<CoreText
|
||||
text="Создать новую сцену?"
|
||||
onClick={() => store.editDrawer(DrawersSceneManager.NewScene, true)}
|
||||
type={CoreTextType.small}
|
||||
color="rgba(68, 142, 247, 1)"
|
||||
style={{ cursor: "pointer" }}
|
||||
/>
|
||||
|
||||
<ResetButton>Reset</ResetButton>
|
||||
<SubmitButton>Submit</SubmitButton>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
{store.sceneMode === SceneMode.MOVING || SceneMode.ROTATE ? (
|
||||
<>
|
||||
{store.robossemblerAssets?.assets.map((el) => {
|
||||
return (
|
||||
<div>
|
||||
<div style={{ color: "white", marginLeft: "10px", marginRight: "10px", display: "contents" }}>
|
||||
{el.name}
|
||||
{store.isRenderedAsset(el.name) ? (
|
||||
<></>
|
||||
) : (
|
||||
<Button
|
||||
onClick={() => {
|
||||
store.loadSceneRobossemblerAsset(el.name);
|
||||
}}
|
||||
>
|
||||
add scene
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{store.sceneModels.map((el) => {
|
||||
return <StaticAssetModelView onTap={() => store.deleteSceneItem(el)} model={el} />;
|
||||
})}
|
||||
</div>
|
||||
|
||||
{store.sceneMode === SceneMode.MAGNETISM_MARKING ? (
|
||||
<>
|
||||
<div style={{ backgroundColor: "white" }}>
|
||||
<div>completion of objects</div>
|
||||
<div>
|
||||
{store.objectMagnetism ? (
|
||||
<>{store.objectMagnetism}</>
|
||||
) : (
|
||||
<Button>Selects an object for magnetism</Button>
|
||||
)}
|
||||
{store.objectForMagnetism ? (
|
||||
<>{store.objectForMagnetism}</>
|
||||
) : (
|
||||
<Button>Selects an object magnet</Button>
|
||||
)}
|
||||
{store.scenes.map((el, i) => (
|
||||
<div
|
||||
key={i}
|
||||
style={{
|
||||
border: "1px solid #CAC4D0",
|
||||
margin: 10,
|
||||
height: 60,
|
||||
alignItems: "center",
|
||||
borderRadius: 7,
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
backgroundColor: "rgba(104, 80, 164, 1)",
|
||||
color: "white",
|
||||
paddingLeft: 10,
|
||||
}}
|
||||
>
|
||||
<CoreText text={el.name} type={CoreTextType.large} color="white" />
|
||||
<CoreButton
|
||||
text="Перейти"
|
||||
onClick={() => {
|
||||
navigate(`${SceneManagerPath}${el._id}`);
|
||||
}}
|
||||
textStyle={{ color: "black", textAlign: "center" }}
|
||||
style={{ marginRight: 10, backgroundColor: "white", width: 126 }}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)} */}
|
||||
{/* </div> */}
|
||||
<div></div>
|
||||
</div>
|
||||
<canvas ref={canvasRef} style={{ overflow: "hidden" }} />
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignContent: "center",
|
||||
justifyContent: "space-between",
|
||||
position: "absolute",
|
||||
width: "100vw",
|
||||
}}
|
||||
/>
|
||||
<Drawer
|
||||
title={store.titleDrawer}
|
||||
destroyOnClose={true}
|
||||
onClose={() => store.editDrawer(DrawersSceneManager.NewScene, false)}
|
||||
open={store.drawers.find((el) => el.name === DrawersSceneManager.NewScene)?.status}
|
||||
>
|
||||
<div
|
||||
style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", height: "100%" }}
|
||||
>
|
||||
<CoreInput
|
||||
value={store.viewModel.name}
|
||||
label={"Имя сцены"}
|
||||
onChange={(text) => store.updateForm({ name: text })}
|
||||
/>
|
||||
|
||||
<div style={{ display: "flex" }}>
|
||||
<CoreButton text="Сохранить" filled={true} onClick={() => store.createNewScene()} />
|
||||
<div style={{ width: 10 }} />
|
||||
<CoreButton text="Отмена" onClick={() => store.editDrawer(DrawersDataset.NewDataset, false)} />
|
||||
</div>
|
||||
</div>
|
||||
</Drawer>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
|
|
@ -2,17 +2,48 @@ import makeAutoObservable from "mobx-store-inheritance";
|
|||
import { CoreThreeRepository } from "../../../core/repository/core_three_repository";
|
||||
import { Object3D, Vector2 } from "three";
|
||||
import { HttpError } from "../../../core/repository/http_repository";
|
||||
import { UiErrorState } from "../../../core/store/base_store";
|
||||
import { UiDrawerFormState } from "../../../core/store/base_store";
|
||||
import { UiBaseError } from "../../../core/model/ui_base_error";
|
||||
import { SceneMenu, SceneMode } from "../model/scene_view";
|
||||
import { BaseSceneItemModel, CameraViewModel, RobossemblerFiles, StaticAssetItemModel } from "../model/scene_assets";
|
||||
import { SceneHttpRepository } from "../data/scene_repository";
|
||||
import { SceneHttpRepository } from "../data/scene_http_repository";
|
||||
import { message } from "antd";
|
||||
import { RobossemblerAssets } from "../../../core/model/robossembler_assets";
|
||||
import { SceneViewModel } from "../model/scene_view_model";
|
||||
import { SceneModel } from "../model/scene_model";
|
||||
import { SceneManagerForms } from "./forms/scene_manager_forms";
|
||||
|
||||
export class SceneMangerStore extends UiErrorState<HttpError> {
|
||||
export enum DrawersSceneManager {
|
||||
NewScene = "Новая сцена",
|
||||
}
|
||||
export enum StoreMode {
|
||||
sceneInstance = "sceneInstance",
|
||||
allScenes = "allScenes",
|
||||
}
|
||||
interface IPopoverItem {
|
||||
name: string;
|
||||
fn: Function;
|
||||
}
|
||||
interface SceneItems {
|
||||
fn: Function;
|
||||
name: string;
|
||||
icon: string;
|
||||
}
|
||||
export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpError> {
|
||||
popoverItems: IPopoverItem[] = [
|
||||
{ name: "Камера", fn: () => this.createNewForm(SceneManagerForms.camera, { store: this }) },
|
||||
{ name: "Твердое тело", fn: () => this.createNewForm(SceneManagerForms.solidBody, { store: this }) },
|
||||
{ name: "Робот", fn: () => this.createNewForm(SceneManagerForms.robot, { store: this }) },
|
||||
{ name: "Точка", fn: () => {} },
|
||||
{ name: "Траектория", fn: () => {} },
|
||||
{ name: "Зона", fn: () => {} },
|
||||
];
|
||||
activeFormType?: string;
|
||||
activeFormDependency?: Object;
|
||||
viewModel: SceneViewModel = SceneViewModel.empty();
|
||||
sceneMode: SceneMode;
|
||||
sceneMenu: SceneMenu;
|
||||
sceneItems: SceneItems[];
|
||||
isVisibleSaveButton: boolean = false;
|
||||
coreThreeRepository: null | CoreThreeRepository = null;
|
||||
sceneHttpRepository: SceneHttpRepository;
|
||||
|
@ -21,21 +52,31 @@ export class SceneMangerStore extends UiErrorState<HttpError> {
|
|||
robossemblerAssets?: RobossemblerAssets;
|
||||
objectForMagnetism: string;
|
||||
objectMagnetism: string;
|
||||
|
||||
scenes: SceneModel[] = [];
|
||||
storeMode: StoreMode;
|
||||
canvasRef?: HTMLCanvasElement;
|
||||
constructor() {
|
||||
super();
|
||||
super(DrawersSceneManager);
|
||||
makeAutoObservable(this);
|
||||
this.sceneItems = [];
|
||||
this.sceneHttpRepository = new SceneHttpRepository();
|
||||
this.sceneMode = SceneMode.EMPTY;
|
||||
this.sceneMenu = SceneMenu.empty();
|
||||
}
|
||||
|
||||
onTapSave(): void {
|
||||
this.robossemblerAssets!.instances = [];
|
||||
this.sceneModels.forEach((el) => this.robossemblerAssets?.instances.push(el.toInstance()));
|
||||
this.httpHelper(this.sceneHttpRepository.saveScene(this.robossemblerAssets as RobossemblerAssets));
|
||||
this.isVisibleSaveButton = false;
|
||||
}
|
||||
createNewForm = (formType: SceneManagerForms, dependency: Object) => {
|
||||
this.activeFormDependency = dependency;
|
||||
this.activeFormType = formType;
|
||||
};
|
||||
makeSolid = () => {};
|
||||
createNewScene = () =>
|
||||
this.viewModel.valid().fold(
|
||||
async (s) => {
|
||||
await this.sceneHttpRepository.newScene(s);
|
||||
this.init();
|
||||
this.editDrawer(DrawersSceneManager.NewScene, false);
|
||||
},
|
||||
async (e) => message.error(e)
|
||||
);
|
||||
|
||||
deleteSceneItem(item: BaseSceneItemModel) {
|
||||
const itm = this.sceneModels.filter((el) => el.id === item.id);
|
||||
|
@ -44,30 +85,30 @@ export class SceneMangerStore extends UiErrorState<HttpError> {
|
|||
this.visibleSaveButton();
|
||||
}
|
||||
|
||||
visibleSaveButton() {
|
||||
visibleSaveButton = () => {
|
||||
this.isVisibleSaveButton = true;
|
||||
}
|
||||
};
|
||||
|
||||
addNewCamera(model: CameraViewModel) {
|
||||
addNewCamera = (model: CameraViewModel) => {
|
||||
model.position = this.coreThreeRepository!.camera.position;
|
||||
model.quaternion = this.coreThreeRepository!.camera.quaternion;
|
||||
this.sceneModels.push(model);
|
||||
this.sceneItems.push({ name: model.cameraLink, icon: "Camera", fn: () => {} });
|
||||
this.coreThreeRepository?.addSceneCamera(model);
|
||||
this.visibleSaveButton();
|
||||
}
|
||||
};
|
||||
|
||||
getCameraLinkNames(): string[] {
|
||||
getCameraLinkNames = (): string[] => {
|
||||
return this.sceneModels.map((el) => {
|
||||
if (el instanceof CameraViewModel) {
|
||||
return el.cameraLink;
|
||||
}
|
||||
return "";
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
loaderWatcher() {}
|
||||
loaderWatcher = () => {};
|
||||
|
||||
loadSceneRobossemblerAsset(name: string) {
|
||||
loadSceneRobossemblerAsset = (name: string) => {
|
||||
try {
|
||||
const assetPath = this.robossemblerAssets?.getAssetPath(name) as string;
|
||||
|
||||
|
@ -105,8 +146,15 @@ export class SceneMangerStore extends UiErrorState<HttpError> {
|
|||
|
||||
sceneModeWatcher() {}
|
||||
|
||||
async init(): Promise<any> {}
|
||||
|
||||
init = async () => {};
|
||||
initParam = (id: string | undefined) => {
|
||||
if (id) {
|
||||
this.storeMode = StoreMode.sceneInstance;
|
||||
} else {
|
||||
this.storeMode = StoreMode.allScenes;
|
||||
this.mapOk("scenes", this.sceneHttpRepository.getAllScenes());
|
||||
}
|
||||
};
|
||||
errorHandingStrategy = (error: HttpError) => {
|
||||
if (error.status === 404) {
|
||||
this.errors.push(new UiBaseError(`${RobossemblerFiles.robossemblerAssets} not found to project`));
|
||||
|
@ -114,11 +162,12 @@ export class SceneMangerStore extends UiErrorState<HttpError> {
|
|||
};
|
||||
|
||||
async loadScene(canvasRef: HTMLCanvasElement) {
|
||||
this.loadWebGl(canvasRef);
|
||||
await this.mapOk<RobossemblerAssets>("robossemblerAssets", this.sceneHttpRepository.getRobossemblerAssets());
|
||||
if (this.robossemblerAssets) {
|
||||
this.coreThreeRepository?.loadInstances(this.robossemblerAssets);
|
||||
}
|
||||
this.canvasRef = canvasRef;
|
||||
if (this.storeMode.isEqual(StoreMode.sceneInstance)) this.loadWebGl(canvasRef);
|
||||
// await this.mapOk<RobossemblerAssets>("robossemblerAssets", this.sceneHttpRepository.getRobossemblerAssets());
|
||||
// if (this.robossemblerAssets) {
|
||||
// this.coreThreeRepository?.loadInstances(this.robossemblerAssets);
|
||||
// }
|
||||
}
|
||||
|
||||
loadWebGl(canvasRef: HTMLCanvasElement): void {
|
||||
|
|
|
@ -63,14 +63,14 @@ export const SkillScreen = observer(() => {
|
|||
onDelete={(id) => store.deleteSkill(id)}
|
||||
/>
|
||||
))}
|
||||
<SkillCard empty={true} emptyOnClick={() => store.edtDrawer(DrawersSkill.NEW_SKILL, true)} />
|
||||
<SkillCard empty={true} emptyOnClick={() => store.editDrawer(DrawersSkill.NEW_SKILL, true)} />
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<Drawer
|
||||
title={store.titleDrawer}
|
||||
destroyOnClose={true}
|
||||
onClose={() => store.edtDrawer(DrawersSkill.EDIT_SKILL, false)}
|
||||
onClose={() => store.editDrawer(DrawersSkill.EDIT_SKILL, false)}
|
||||
open={store.drawers.find((el) => el.name === DrawersSkill.EDIT_SKILL)?.status}
|
||||
>
|
||||
<div style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", height: "100%" }}>
|
||||
|
@ -94,14 +94,14 @@ export const SkillScreen = observer(() => {
|
|||
<div style={{ display: "flex" }}>
|
||||
<CoreButton text="Сохранить" filled={true} onClick={() => store.saveEdiSkill()} />
|
||||
<div style={{ width: 10 }} />
|
||||
<CoreButton text="Отмена" onClick={() => store.edtDrawer(DrawersSkill.NEW_SKILL, false)} />
|
||||
<CoreButton text="Отмена" onClick={() => store.editDrawer(DrawersSkill.NEW_SKILL, false)} />
|
||||
</div>
|
||||
</div>
|
||||
</Drawer>
|
||||
<Drawer
|
||||
title={store.titleDrawer}
|
||||
destroyOnClose={true}
|
||||
onClose={() => store.edtDrawer(DrawersSkill.NEW_SKILL, false)}
|
||||
onClose={() => store.editDrawer(DrawersSkill.NEW_SKILL, false)}
|
||||
open={store.drawers.find((el) => el.name === DrawersSkill.NEW_SKILL)?.status}
|
||||
>
|
||||
<div style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", height: "100%" }}>
|
||||
|
@ -142,7 +142,7 @@ export const SkillScreen = observer(() => {
|
|||
<div style={{ display: "flex" }}>
|
||||
<CoreButton text="Сохранить" filled={true} onClick={() => store.saveSkill()} />
|
||||
<div style={{ width: 10 }} />
|
||||
<CoreButton text="Отмена" onClick={() => store.edtDrawer(DrawersSkill.NEW_SKILL, false)} />
|
||||
<CoreButton text="Отмена" onClick={() => store.editDrawer(DrawersSkill.NEW_SKILL, false)} />
|
||||
</div>
|
||||
</div>
|
||||
</Drawer>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import makeAutoObservable from "mobx-store-inheritance";
|
||||
import { NavigateFunction } from "react-router-dom";
|
||||
import { HttpError } from "../../core/repository/http_repository";
|
||||
import { Drawer, UiFormState } from "../../core/store/base_store";
|
||||
import { Drawer, UiDrawerFormState } from "../../core/store/base_store";
|
||||
import { ISkils, SkillsHttpRepository } from "./skills_http_repository";
|
||||
import { IDatasetModel } from "../dataset/dataset_model";
|
||||
import { message } from "antd";
|
||||
import { UUID } from "../all_projects/data/project_repository";
|
||||
import { UUID } from "../all_projects/data/project_http_repository";
|
||||
import { SkillModel } from "./skill_model";
|
||||
import { ProcessUpdate, SkillSocketRepository } from "./skill_socket_repository";
|
||||
|
||||
|
@ -14,7 +14,7 @@ export enum DrawersSkill {
|
|||
EDIT_SKILL = "Редактировать навык",
|
||||
}
|
||||
|
||||
export class SkillStore extends UiFormState<SkillModel, HttpError> {
|
||||
export class SkillStore extends UiDrawerFormState<SkillModel, HttpError> {
|
||||
skillsHttpRepository: SkillsHttpRepository;
|
||||
skillSocketRepository: SkillSocketRepository = new SkillSocketRepository();
|
||||
skils?: ISkils[];
|
||||
|
@ -92,7 +92,7 @@ export class SkillStore extends UiFormState<SkillModel, HttpError> {
|
|||
);
|
||||
}
|
||||
|
||||
edtDrawer(drawerName: DrawersSkill, status: boolean): void {
|
||||
editDrawer(drawerName: DrawersSkill, status: boolean): void {
|
||||
this.titleDrawer = drawerName;
|
||||
this.drawers = this.drawers.map((el) => {
|
||||
if (el.name === drawerName) {
|
||||
|
@ -108,13 +108,13 @@ export class SkillStore extends UiFormState<SkillModel, HttpError> {
|
|||
fromEditSkill(id: string): void {
|
||||
this.viewModel = SkillModel.fromISkill(this.getSkillById(id) as ISkils);
|
||||
|
||||
this.edtDrawer(DrawersSkill.EDIT_SKILL, true);
|
||||
this.editDrawer(DrawersSkill.EDIT_SKILL, true);
|
||||
}
|
||||
saveEdiSkill = async () => {
|
||||
const skillOrigin = this.getSkillById(this.viewModel.id as string) as ISkils;
|
||||
skillOrigin.numberOfTrainedEpochs = this.viewModel.epoch;
|
||||
skillOrigin.isFinished = this.viewModel.isFinished ?? false;
|
||||
await this.skillsHttpRepository.editSkill(skillOrigin);
|
||||
this.edtDrawer(DrawersSkill.EDIT_SKILL, false);
|
||||
this.editDrawer(DrawersSkill.EDIT_SKILL, false);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ export const SocketLister = observer((props: ISocketListerProps) => {
|
|||
socketListerStore.init();
|
||||
}, []);
|
||||
return (
|
||||
<div>
|
||||
< >
|
||||
{/* {socketListerStore.socketHasDisconnect ? (
|
||||
<ReloadIcon
|
||||
onClick={() => {
|
||||
|
@ -30,6 +30,6 @@ export const SocketLister = observer((props: ISocketListerProps) => {
|
|||
)} */}
|
||||
|
||||
{props.children}
|
||||
</div>
|
||||
</ >
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,133 +0,0 @@
|
|||
import * as React from "react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { Button } from "antd";
|
||||
import { StickObjectsMarkingStore, StickObjectsMarkingStoreMode } from "./stick_objects_marking_store";
|
||||
import { Vector3 } from "three";
|
||||
|
||||
export const StickObjectsMarking = "/stick/objects/marking";
|
||||
interface StickButtonsProps {
|
||||
isVisible: boolean;
|
||||
name: string;
|
||||
groupMode: StickObjectsMarkingStoreMode;
|
||||
storeMode: StickObjectsMarkingStoreMode;
|
||||
storeModePoints: StickObjectsMarkingStoreMode;
|
||||
setMode: Function;
|
||||
setPointMode: Function;
|
||||
points: Vector3[];
|
||||
body: string;
|
||||
}
|
||||
|
||||
export const StickButtons: React.FunctionComponent<StickButtonsProps> = observer((props) => {
|
||||
return (
|
||||
<>
|
||||
{props.isVisible ? (
|
||||
<>
|
||||
{props.name}
|
||||
<Button
|
||||
style={{
|
||||
backgroundColor: props.storeMode === props.storeModePoints ? "#ff7e1e" : "",
|
||||
}}
|
||||
onClick={() => props.setPointMode()}
|
||||
>
|
||||
add points
|
||||
</Button>
|
||||
{props.points.map((el) => {
|
||||
return (
|
||||
<>
|
||||
{el.x} {el.y} {el.z}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
) : (
|
||||
<Button
|
||||
style={{
|
||||
backgroundColor: props.groupMode === props.storeMode ? "#ff7e1e" : "",
|
||||
}}
|
||||
onClick={() => props.setMode(props.storeMode)}
|
||||
>
|
||||
{props.body}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
export const StickObjectsMarkingScreen = observer(() => {
|
||||
const canvasRef = React.useRef<HTMLCanvasElement>(null);
|
||||
const [store] = React.useState(() => new StickObjectsMarkingStore());
|
||||
const id = useParams().id as string;
|
||||
|
||||
React.useEffect(() => {
|
||||
store.init();
|
||||
store.loadScene(canvasRef.current!);
|
||||
document.body.style.overflow = "hidden";
|
||||
return () => {
|
||||
document.body.style.overflow = "scroll";
|
||||
store.dispose();
|
||||
};
|
||||
}, [id, store]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<canvas ref={canvasRef} style={{ position: "absolute", overflow: "hidden" }} />
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignContent: "center",
|
||||
justifyContent: "space-between",
|
||||
position: "absolute",
|
||||
width: "100vw",
|
||||
}}
|
||||
>
|
||||
<div style={{ backgroundColor: "white", padding: "20px" }}>
|
||||
{Object.keys(store.points).map((el) => {
|
||||
// @ts-expect-error
|
||||
const v = store.points[el];
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
{el as string}:{v}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
<div>Marking objects for sticking</div>
|
||||
<div>
|
||||
<StickButtons
|
||||
storeMode={store.mode}
|
||||
setMode={() => store.setMode(StickObjectsMarkingStoreMode.objectThatSticks)}
|
||||
groupMode={StickObjectsMarkingStoreMode.objectThatSticks}
|
||||
name={store.objectThatSticksName}
|
||||
storeModePoints={StickObjectsMarkingStoreMode.addPointsObjectThatSticks}
|
||||
isVisible={store.objectThatSticksName !== undefined}
|
||||
setPointMode={() => store.setMode(StickObjectsMarkingStoreMode.addPointsObjectThatSticks)}
|
||||
points={store.objectThatSticksNamePoints}
|
||||
body="objectThatSticksName"
|
||||
/>
|
||||
<StickButtons
|
||||
body="objectsToWhichItSticksName"
|
||||
points={store.objectsToWhichItSticksPoints}
|
||||
storeMode={store.mode}
|
||||
setMode={() => store.setMode(StickObjectsMarkingStoreMode.objectsToWhichItSticks)}
|
||||
groupMode={StickObjectsMarkingStoreMode.objectsToWhichItSticks}
|
||||
name={store.objectsToWhichItSticksName}
|
||||
storeModePoints={StickObjectsMarkingStoreMode.addPointsObjectsToWhichItSticks}
|
||||
isVisible={store.objectsToWhichItSticksName !== undefined}
|
||||
setPointMode={() => store.setMode(StickObjectsMarkingStoreMode.addPointsObjectsToWhichItSticks)}
|
||||
/>
|
||||
<Button onClick={() => store.onSaveSticky()}>save</Button>
|
||||
<Button
|
||||
onClick={() => store.setMode(StickObjectsMarkingStoreMode.move)}
|
||||
style={{ backgroundColor: store.mode === StickObjectsMarkingStoreMode.move ? "#ff7e1e" : "" }}
|
||||
>
|
||||
run
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
|
@ -1,164 +0,0 @@
|
|||
import makeAutoObservable from "mobx-store-inheritance";
|
||||
import { Box3, Vector2, Vector3 } from "three";
|
||||
import { UiErrorState } from "../../core/store/base_store";
|
||||
import { HttpError } from "../../core/repository/http_repository";
|
||||
import { UiBaseError } from "../../core/model/ui_base_error";
|
||||
import { RobossemblerFiles } from "../scene_manager/model/scene_assets";
|
||||
import { StickObjectsMarkingThreeRepository } from "./stick_objects_marking_three_repository";
|
||||
import { UserData } from "../../core/repository/core_three_repository";
|
||||
import { ObjectExtensionsIsKeyExists } from "../../core/extensions/object";
|
||||
|
||||
export enum StickObjectsMarkingStoreMode {
|
||||
objectsToWhichItSticks = "objectsToWhichItSticks",
|
||||
objectThatSticks = "objectThatSticks",
|
||||
addPointsObjectsToWhichItSticks = "addPointsObjectsToWhichItSticks",
|
||||
addPointsObjectThatSticks = "addPointsObjectThatSticks",
|
||||
move = "move",
|
||||
}
|
||||
|
||||
export class StickyHelper {
|
||||
objectThatSticksName: string;
|
||||
objectThatSticksNamePoints: Vector3[] = [];
|
||||
objectsToWhichItSticksName: string;
|
||||
objectsToWhichItSticksPoints: Vector3[] = [];
|
||||
|
||||
constructor(
|
||||
objectThatSticksName: string,
|
||||
objectThatSticksNamePoints: Vector3[],
|
||||
objectsToWhichItSticksName: string,
|
||||
objectsToWhichItSticksPoints: Vector3[]
|
||||
) {
|
||||
this.objectThatSticksName = objectThatSticksName;
|
||||
this.objectThatSticksNamePoints = objectThatSticksNamePoints;
|
||||
this.objectsToWhichItSticksName = objectsToWhichItSticksName;
|
||||
this.objectsToWhichItSticksPoints = objectsToWhichItSticksPoints;
|
||||
}
|
||||
}
|
||||
|
||||
export class StickObjectsMarkingStore extends UiErrorState<HttpError> {
|
||||
mode: StickObjectsMarkingStoreMode;
|
||||
stickObjectsMarkingThreeRepository: null | StickObjectsMarkingThreeRepository = null;
|
||||
objectThatSticksName: string;
|
||||
objectThatSticksNamePoints: Vector3[] = [];
|
||||
objectsToWhichItSticksName: string;
|
||||
objectsToWhichItSticksPoints: Vector3[] = [];
|
||||
points = {};
|
||||
constructor() {
|
||||
super();
|
||||
makeAutoObservable(this);
|
||||
this.points = {};
|
||||
this.mode = StickObjectsMarkingStoreMode.move;
|
||||
this.loadStickyJSON(
|
||||
'{"objectThatSticksName":"cube2","objectThatSticksNamePoints":[{"x":5,"y":-0.5419443937360455,"z":0.041458499858311626}],"objectsToWhichItSticksName":"cube1","objectsToWhichItSticksPoints":[{"x":-5,"y":-2.2134708060033113,"z":1.1937718220731925}]}'
|
||||
);
|
||||
}
|
||||
updatePoint = (key: string, value: any) => {
|
||||
// @ts-expect-error
|
||||
this.points[key] = value;
|
||||
};
|
||||
onSaveSticky(): void {
|
||||
window.prompt(
|
||||
"Copy to clipboard: Ctrl+C, Enter",
|
||||
JSON.stringify(
|
||||
new StickyHelper(
|
||||
this.objectThatSticksName,
|
||||
this.objectThatSticksNamePoints,
|
||||
this.objectsToWhichItSticksName,
|
||||
this.objectsToWhichItSticksPoints
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
setMode(stickObjectsMarkingStoreMode: StickObjectsMarkingStoreMode): void {
|
||||
this.mode = stickObjectsMarkingStoreMode;
|
||||
}
|
||||
|
||||
loaderWatcher() {}
|
||||
|
||||
async init(): Promise<any> {}
|
||||
|
||||
errorHandingStrategy = (error: HttpError) => {
|
||||
if (error.status === 404) {
|
||||
this.errors.push(new UiBaseError(`${RobossemblerFiles.robossemblerAssets} not found to project`));
|
||||
}
|
||||
};
|
||||
|
||||
async loadScene(canvasRef: HTMLCanvasElement) {
|
||||
this.loadWebGl(canvasRef);
|
||||
}
|
||||
watcherSceneEditorObject() {}
|
||||
loadWebGl(canvasRef: HTMLCanvasElement): void {
|
||||
this.stickObjectsMarkingThreeRepository = new StickObjectsMarkingThreeRepository(
|
||||
canvasRef as HTMLCanvasElement,
|
||||
this.watcherSceneEditorObject,
|
||||
this.updatePoint
|
||||
);
|
||||
this.stickObjectsMarkingThreeRepository.stickyHelperLoader([
|
||||
new StickyHelper(
|
||||
this.objectThatSticksName,
|
||||
this.objectThatSticksNamePoints,
|
||||
this.objectsToWhichItSticksName,
|
||||
this.objectsToWhichItSticksPoints
|
||||
),
|
||||
]);
|
||||
this.stickObjectsMarkingThreeRepository.render();
|
||||
window.addEventListener("click", (event) => this.clickLister(event));
|
||||
}
|
||||
|
||||
clickLister(event: MouseEvent) {
|
||||
const vector = new Vector2();
|
||||
vector.x = (event.clientX / window.innerWidth) * 2 - 1;
|
||||
vector.y = -(event.clientY / window.innerHeight) * 2 + 1;
|
||||
if (this.mode) {
|
||||
if (this.mode === StickObjectsMarkingStoreMode.move) {
|
||||
this.stickObjectsMarkingThreeRepository?.setRayCastAndGetFirstObject(vector).fold(
|
||||
(success) => this.stickObjectsMarkingThreeRepository?.setTransformControlsAttach(success),
|
||||
(_error) => this.stickObjectsMarkingThreeRepository?.disposeTransformControlsMode()
|
||||
);
|
||||
}
|
||||
this.stickObjectsMarkingThreeRepository?.setRayCast(vector).map((touch) => {
|
||||
const objectMagnetism = touch.filter((el) => el.object.userData[UserData.objectForMagnetism] === true);
|
||||
const BoundBoxVector = new Box3().setFromObject(objectMagnetism[0].object).getCenter(new Vector3());
|
||||
const centerRelativeVector = new Vector3().subVectors(BoundBoxVector, objectMagnetism[0].point);
|
||||
if (objectMagnetism.isNotEmpty()) {
|
||||
if (this.mode === StickObjectsMarkingStoreMode.objectsToWhichItSticks) {
|
||||
this.objectsToWhichItSticksName = objectMagnetism[0].object.name;
|
||||
}
|
||||
if (this.mode === StickObjectsMarkingStoreMode.objectThatSticks) {
|
||||
this.objectThatSticksName = objectMagnetism[0].object.name;
|
||||
}
|
||||
if (this.mode === StickObjectsMarkingStoreMode.addPointsObjectThatSticks) {
|
||||
this.objectThatSticksNamePoints.push(centerRelativeVector);
|
||||
}
|
||||
if (this.mode === StickObjectsMarkingStoreMode.addPointsObjectsToWhichItSticks) {
|
||||
this.objectsToWhichItSticksPoints.push(centerRelativeVector);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
dispose() {
|
||||
window.removeEventListener("click", this.clickLister);
|
||||
}
|
||||
loadStickyJSON(value: string): void {
|
||||
const object = JSON.parse(value) as Object;
|
||||
if (
|
||||
ObjectExtensionsIsKeyExists(object, [
|
||||
"objectThatSticksName",
|
||||
"objectThatSticksNamePoints",
|
||||
"objectsToWhichItSticksName",
|
||||
"objectsToWhichItSticksPoints",
|
||||
])
|
||||
) {
|
||||
// @ts-expect-error
|
||||
this.objectThatSticksName = object["objectThatSticksName"];
|
||||
// @ts-expect-error
|
||||
this.objectThatSticksNamePoints = object["objectThatSticksNamePoints"];
|
||||
// @ts-expect-error
|
||||
this.objectsToWhichItSticksName = object["objectsToWhichItSticksName"];
|
||||
// @ts-expect-error
|
||||
this.objectsToWhichItSticksPoints = object["objectsToWhichItSticksPoints"];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
import { Box3, BoxGeometry, Mesh, MeshBasicMaterial, Object3D, Vector3 } from "three";
|
||||
import { CoreThreeRepository } from "../../core/repository/core_three_repository";
|
||||
import { StickyHelper } from "./stick_objects_marking_store";
|
||||
import { CoreVector3 } from "../../core/model/core_vector3";
|
||||
|
||||
export class StickObjectsMarkingThreeRepository extends CoreThreeRepository {
|
||||
stickyObjects: StickyHelper[];
|
||||
drawUiPoint: Function;
|
||||
constructor(htmlCanvasRef: HTMLCanvasElement, watcherSceneEditorObject: Function, updatePoint: Function) {
|
||||
super(htmlCanvasRef, watcherSceneEditorObject);
|
||||
this.drawUiPoint = updatePoint;
|
||||
this.sceneWatcher();
|
||||
}
|
||||
|
||||
getStickyObject(name: string, pointNameHelper: string, index: number) {
|
||||
const objectThatSticksNameMesh = this.scene.getObjectByName(name);
|
||||
const pointName = objectThatSticksNameMesh!.name + ":point:" + index + pointNameHelper;
|
||||
return this.scene.getObjectByName(pointName);
|
||||
}
|
||||
|
||||
mapperStickyObject(point: Vector3, index: number, name: string, pointNameHelper: string) {
|
||||
const objectThatSticksNameMesh = this.scene.getObjectByName(name);
|
||||
const pointName = objectThatSticksNameMesh!.name + ":point:" + index + pointNameHelper;
|
||||
const sceneObject = this.scene.getObjectByName(pointName);
|
||||
let pointMesh: Object3D;
|
||||
if (sceneObject) {
|
||||
pointMesh = sceneObject;
|
||||
} else {
|
||||
pointMesh = new Mesh(new BoxGeometry(1.1, 1.1, 1.1), new MeshBasicMaterial({ color: "#8BC34A" }));
|
||||
}
|
||||
pointMesh.position.copy(new Box3().setFromObject(objectThatSticksNameMesh!).getCenter(new Vector3()).add(point));
|
||||
pointMesh.name = pointName;
|
||||
if (sceneObject === undefined) this.scene.add(pointMesh);
|
||||
}
|
||||
|
||||
stickyHelperLoader(stickyObjects: StickyHelper[]) {
|
||||
this.stickyObjects = stickyObjects;
|
||||
|
||||
stickyObjects.forEach((el) => {
|
||||
el.objectThatSticksNamePoints.forEach((point, index) =>
|
||||
this.mapperStickyObject(point, index, el.objectThatSticksName, "objectThatSticksNamePoints")
|
||||
);
|
||||
el.objectsToWhichItSticksPoints.forEach((point, index) =>
|
||||
this.mapperStickyObject(point, index, el.objectsToWhichItSticksName, "objectsToWhichItSticksPoints")
|
||||
);
|
||||
});
|
||||
}
|
||||
getCenter(obj: Object3D) {
|
||||
return new Box3().setFromObject(obj).getCenter(new Vector3());
|
||||
}
|
||||
sceneWatcher() {
|
||||
this.transformControls.addEventListener("objectChange", (event) => {
|
||||
//@ts-expect-error
|
||||
const sceneActiveObject = event.target.object as Mesh;
|
||||
|
||||
this.stickyObjects.forEach((stickyHelper) => {
|
||||
if (sceneActiveObject.name === stickyHelper.objectThatSticksName) {
|
||||
//локальные векторы точек
|
||||
const objectThatSticksNameLocalVector = stickyHelper.objectThatSticksNamePoints[0];
|
||||
const objectsToWhichItSticksPointLocalVector = stickyHelper.objectsToWhichItSticksPoints[0];
|
||||
|
||||
//глобальные векторы обьектов
|
||||
const globalVectorObjStickyName = this.scene.getObjectByName(stickyHelper.objectThatSticksName);
|
||||
|
||||
const globalVectorObjToWhichSticks = this.scene.getObjectByName(stickyHelper.objectsToWhichItSticksName);
|
||||
|
||||
const objectsToWhichItSticksNamePosition = new CoreVector3(globalVectorObjToWhichSticks!.position).add(
|
||||
objectsToWhichItSticksPointLocalVector
|
||||
).vector;
|
||||
|
||||
this.scene
|
||||
.getObjectByName("cube2:point:0objectThatSticksNamePoints")
|
||||
?.position.copy(objectsToWhichItSticksNamePosition);
|
||||
|
||||
// this.scene.getObjectByName("cube2:point:0objectThatSticksNamePoints")?.position;
|
||||
|
||||
globalVectorObjStickyName?.position.copy(
|
||||
this.scene
|
||||
.getObjectByName("cube2:point:0objectThatSticksNamePoints")!
|
||||
.position.add(objectsToWhichItSticksPointLocalVector)
|
||||
);
|
||||
|
||||
// console.log(this.scene.children.map((e) => console.log(e.name)));
|
||||
// cube2:point:0objectThatSticksNamePoints
|
||||
// cube1:point:0objectsToWhichItSticksPoints
|
||||
|
||||
// this.makePoint(objectThatSticksNamePosition, "red", 1.1);
|
||||
// this.makePoint(objectsToWhichItSticksNamePosition, "red", 1.1);
|
||||
|
||||
// const movePosition = objectThatSticksNamePosition.sub(objectsToWhichItSticksNamePosition);
|
||||
// const movePosition = new Vector3().subVectors(
|
||||
// objectThatSticksNamePosition,
|
||||
// objectsToWhichItSticksNamePosition
|
||||
// );
|
||||
|
||||
// this.scene.getObjectByName(stickyHelper.objectsToWhichItSticksName)?.position.copy(movePosition);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue