progress scene builder

This commit is contained in:
IDONTSUDO 2024-06-25 12:43:41 +03:00
parent 0a4eea19c5
commit 50d0c4c12b
64 changed files with 858 additions and 1315 deletions

View file

@ -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());

View file

@ -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);
})
);
})
);
});
}

View file

@ -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`);
});
})
);
}

View 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);

View 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,
});
}
}

View 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;
}

View file

@ -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>

View file

@ -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> {

View file

@ -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();
};
}
};

View file

@ -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;

View file

@ -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",

View file

@ -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 />,

View file

@ -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

View file

@ -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>

View file

@ -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>
);
};

View file

@ -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">

View file

@ -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}

View file

@ -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" },

View 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>
);
};

View file

@ -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}

View file

@ -1,7 +0,0 @@
export enum StickObjectsMarkingStoreMode {
objectsToWhichItSticks = "objectsToWhichItSticks",
objectThatSticks = "objectThatSticks",
addPointsObjectsToWhichItSticks = "addPointsObjectsToWhichItSticks",
addPointsObjectThatSticks = "addPointsObjectThatSticks",
move = "move",
}

View file

@ -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;
}
}

View file

@ -1,4 +0,0 @@
export enum StickyLoaderMode {
IN = "IN",
OUT = "OUT",
}

View file

@ -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>
);
});

View file

@ -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);
}
}

View file

@ -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)
);
}
});
});
}
}

View 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}`);
}
}

View file

@ -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}`);
}
}

View file

@ -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;
}

View file

@ -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>
</>
}
/>
);
});

View file

@ -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;
}
);
}
}

View file

@ -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";

View file

@ -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%" }}>

View file

@ -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) {

View file

@ -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} /> },
];

View file

@ -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);
}
}

View 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>
}
/>
</>
);
});

View file

@ -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;
}
);
//
}
}

View file

@ -1,3 +0,0 @@
export interface ICreateProjectViewModel {
description: string;
}

View file

@ -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 {

View file

@ -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";

View file

@ -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 }}

View file

@ -1 +0,0 @@
export class PipelineInstanceRepository {}

View file

@ -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="Датасеты" />
</>
);
};

View file

@ -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);
}
}

View 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>>;
}

View file

@ -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>
>;
}
}

View file

@ -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) {

View file

@ -0,0 +1,4 @@
export interface SceneModel {
_id: string;
name: string;
}

View 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);
};
}

View file

@ -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()}

View file

@ -0,0 +1,6 @@
import { IDefaultSceneManagerProps } from "../scene_manager_forms";
export const RobotForm = (props: IDefaultSceneManagerProps) => {
return <div>ROBOT</div>;
};

View file

@ -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} /> },
];

View file

@ -0,0 +1,5 @@
import { IDefaultSceneManagerProps } from "../scene_manager_forms";
export const SolidBodyForm = (props:IDefaultSceneManagerProps) => {
return <></>;
};

View file

@ -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;
};
}

View file

@ -0,0 +1,7 @@
export class SolidBodyViewModel {
name: string;
static empty() {
return new SolidBodyViewModel();
}
}

View file

@ -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>
)}
</>
}
/>

View file

@ -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 {

View file

@ -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>

View file

@ -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);
};
}

View file

@ -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>
</ >
);
});

View file

@ -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>
);
});

View file

@ -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"];
}
}
}

View file

@ -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);
}
});
});
}
}