progress
This commit is contained in:
parent
559262db34
commit
50822a031d
65 changed files with 7738 additions and 1412 deletions
|
@ -3,10 +3,10 @@
|
|||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg width="64px" height="12" "strokeWidth="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"/>strokeWidth
|
||||
<g id="SVGRepo_bgCarrier" strokeWidth="0"/>strokeWidth
|
||||
|
||||
<g id="SVGRepo_tracerCarrier" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
|
||||
<g id="SVGRepo_iconCarrier"> <g id="Interface / Check"> <path id="Vector" d="M6 12L10.2426 16.2426L18.727 7.75732" stroke="#f8f9fa" stroke-width="2" strokeLinecap="round" strokeLinejoin="round"/> </g> </g>
|
||||
<g id="SVGRepo_iconCarrier"> <g id="Interface / Check"> <path id="Vector" d="M6 12L10.2426 16.2426L18.727 7.75732" stroke="#f8f9fa" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/> </g> </g>
|
||||
|
||||
</svg>
|
Before Width: | Height: | Size: 638 B After Width: | Height: | Size: 636 B |
|
@ -3,7 +3,7 @@
|
|||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg width="64px" height="6strokeWidth="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||
<g id="SVGRepo_bgCarrier" strokeWidth="0"/>
|
||||
|
||||
<g id="SVGRepo_tracerCarrier" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 661 B After Width: | Height: | Size: 660 B |
|
@ -34,6 +34,7 @@ declare global {
|
|||
isNegative(): boolean;
|
||||
isEven(): boolean;
|
||||
isOdd(): boolean;
|
||||
isEqualR(num: number): Result<void, void>;
|
||||
}
|
||||
|
||||
interface String {
|
||||
|
@ -45,6 +46,7 @@ declare global {
|
|||
hasPattern(pattern: string): boolean;
|
||||
hasNoPattern(pattern: string): boolean;
|
||||
divideByIndex(index: number): string[];
|
||||
isEqualR(str: string): Result<void, string>;
|
||||
}
|
||||
|
||||
interface Map<K, V> {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { Result } from "../helper/result";
|
||||
|
||||
export const NumberExtensions = () => {
|
||||
if (Number().fromArray === undefined) {
|
||||
Number.prototype.fromArray = function () {
|
||||
|
@ -15,6 +17,14 @@ export const NumberExtensions = () => {
|
|||
return `${date.getUTCFullYear()}.${date.getMonth()}.${date.getDay()} ${date.getHours()}:${date.getMinutes()}`;
|
||||
};
|
||||
}
|
||||
if (Number().isEqualR === undefined) {
|
||||
Number.prototype.isEqualR = function (num) {
|
||||
if(this === num) {
|
||||
return Result.ok(undefined)
|
||||
}
|
||||
return Result.error(undefined)
|
||||
};
|
||||
}
|
||||
if (Number().isValid === undefined) {
|
||||
Number.prototype.isValid = function (str: string) {
|
||||
return !isNaN(Number(str));
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { Result } from "../helper/result";
|
||||
|
||||
/* eslint-disable no-extend-native */
|
||||
export const StringExtensions = () => {
|
||||
if ("".isEmpty === undefined) {
|
||||
|
@ -10,6 +12,14 @@ export const StringExtensions = () => {
|
|||
return this.length !== 0;
|
||||
};
|
||||
}
|
||||
if ("".isEqualR === undefined) {
|
||||
String.prototype.isEqualR = function (str) {
|
||||
if (this === str) {
|
||||
return Result.ok(String(this));
|
||||
}
|
||||
return Result.error(undefined);
|
||||
};
|
||||
}
|
||||
if ("".replaceMany === undefined) {
|
||||
String.prototype.replaceMany = function (searchValues: string[], replaceValue: string) {
|
||||
let result = this as string;
|
||||
|
@ -44,13 +54,13 @@ export const StringExtensions = () => {
|
|||
return !this.hasPattern(pattern);
|
||||
};
|
||||
}
|
||||
if (''.divideByIndex === undefined) {
|
||||
if ("".divideByIndex === undefined) {
|
||||
String.prototype.divideByIndex = function (index) {
|
||||
if (this.at(index) === undefined) {
|
||||
return []
|
||||
return [];
|
||||
}
|
||||
|
||||
return [this.slice(0, index), this.slice(index+1, this.length)]
|
||||
}
|
||||
return [this.slice(0, index), this.slice(index + 1, this.length)];
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
3
ui/src/core/model/spawn_position_types.ts
Normal file
3
ui/src/core/model/spawn_position_types.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export enum SpawnPositionTypes {
|
||||
BoundBox = "BoundBox",
|
||||
}
|
|
@ -1,36 +1,36 @@
|
|||
import { Scene, Engine, MeshBuilder, FreeCamera, HemisphericLight, Vector3, SceneLoader } from 'babylonjs';
|
||||
import { GLTFFileLoader } from 'babylonjs-loaders';
|
||||
// import { Scene, Engine, MeshBuilder, FreeCamera, HemisphericLight, Vector3, SceneLoader } from 'babylonjs';
|
||||
// import { GLTFFileLoader } from 'babylonjs-loaders';
|
||||
|
||||
|
||||
export class BabylonRepository {
|
||||
engine: Engine;
|
||||
canvas: HTMLCanvasElement;
|
||||
scene: Scene;
|
||||
sceneLoader: SceneLoader
|
||||
constructor(canvas: HTMLCanvasElement) {
|
||||
this.sceneLoader = new SceneLoader();
|
||||
this.engine = new Engine(canvas, true);
|
||||
this.scene = new Scene(this.engine);
|
||||
this.engine.runRenderLoop(() => {
|
||||
this.scene.render();
|
||||
});
|
||||
this.scene.createDefaultCameraOrLight(true, true, true);
|
||||
new HemisphericLight("hemiLight", new Vector3(0, 1, 0));
|
||||
SceneLoader.RegisterPlugin(new GLTFFileLoader())
|
||||
SceneLoader.ImportMeshAsync("",
|
||||
"http://localhost:4001/1dfc4e1a-9c1a-4fa2-96b2-19c86acb6ea4/assets/libs/objects/",
|
||||
"sol_gear.glb", this.scene)
|
||||
// export class BabylonRepository {
|
||||
// engine: Engine;
|
||||
// canvas: HTMLCanvasElement;
|
||||
// scene: Scene;
|
||||
// sceneLoader: SceneLoader
|
||||
// constructor(canvas: HTMLCanvasElement) {
|
||||
// this.sceneLoader = new SceneLoader();
|
||||
// this.engine = new Engine(canvas, true);
|
||||
// this.scene = new Scene(this.engine);
|
||||
// this.engine.runRenderLoop(() => {
|
||||
// this.scene.render();
|
||||
// });
|
||||
// this.scene.createDefaultCameraOrLight(true, true, true);
|
||||
// new HemisphericLight("hemiLight", new Vector3(0, 1, 0));
|
||||
// SceneLoader.RegisterPlugin(new GLTFFileLoader())
|
||||
// SceneLoader.ImportMeshAsync("",
|
||||
// "http://localhost:4001/1dfc4e1a-9c1a-4fa2-96b2-19c86acb6ea4/assets/libs/objects/",
|
||||
// "sol_gear.glb", this.scene)
|
||||
|
||||
}
|
||||
deleteAllObjectsScene = () => this.scene.meshes.forEach((el) => this.scene.removeMesh(el, true))
|
||||
// }
|
||||
// deleteAllObjectsScene = () => this.scene.meshes.forEach((el) => this.scene.removeMesh(el, true))
|
||||
|
||||
loadHttp = (url: string) => {
|
||||
const divide = url.divideByIndex(url.lastIndexOf('/'))
|
||||
// loadHttp = (url: string) => {
|
||||
// const divide = url.divideByIndex(url.lastIndexOf('/'))
|
||||
|
||||
SceneLoader.ImportMeshAsync("",
|
||||
`${divide.at(0)}/`,
|
||||
`${divide.at(1)}`, this.scene).then((frame) => {
|
||||
});
|
||||
// SceneLoader.ImportMeshAsync("",
|
||||
// `${divide.at(0)}/`,
|
||||
// `${divide.at(1)}`, this.scene).then((frame) => {
|
||||
// });
|
||||
|
||||
}
|
||||
}
|
||||
// }
|
||||
// }
|
|
@ -21,23 +21,26 @@ import {
|
|||
Quaternion,
|
||||
MeshBasicMaterial,
|
||||
BoxGeometry,
|
||||
MeshStandardMaterial
|
||||
MeshStandardMaterial,
|
||||
} from "three";
|
||||
import { TypedEvent } from "../helper/typed_event";
|
||||
import { Result } from "../helper/result";
|
||||
import { GLTFLoader, OrbitControls, TransformControls, OBJLoader, STLLoader, ColladaLoader } from "three-stdlib";
|
||||
import { ColladaLoader } from "three/examples/jsm/loaders/ColladaLoader";
|
||||
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
|
||||
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
|
||||
import { STLLoader } from "three/examples/jsm/loaders/STLLoader";
|
||||
import { OrbitControls, TransformControls } from "three/examples/jsm/Addons";
|
||||
import {
|
||||
BaseSceneItemModel,
|
||||
CameraViewModel,
|
||||
StaticAssetItemModel,
|
||||
} from "../../features/scene_manager/model/scene_assets";
|
||||
import { SceneMode } from "../../features/scene_manager/model/scene_view";
|
||||
import { throttle } from "../helper/throttle";
|
||||
import { Asset, InstanceRgbCamera, RobossemblerAssets, SceneSimpleObject } from "../model/robossembler_assets";
|
||||
import { LoadingManager } from 'three';
|
||||
import { UrdfTransforms, coordsToQuaternion } from "../../features/simulations/tranforms_model";
|
||||
import URDFLoader, { URDFLink } from 'urdf-loader';
|
||||
import { LoadingManager } from "three";
|
||||
|
||||
import { SceneMode } from "../../features/scene_manager/model/scene_view";
|
||||
import { UrdfTransforms, coordsToQuaternion } from "../../features/simulations/tranforms_model";
|
||||
import URDFLoader, { URDFLink } from "urdf-loader";
|
||||
import { ISolidSpawnHelper } from "../../features/scene_manager/presentation/scene_manager_store";
|
||||
|
||||
Object3D.DEFAULT_UP = new Vector3(0, 0, 1);
|
||||
|
||||
|
@ -45,7 +48,7 @@ export enum UserData {
|
|||
selectedObject = "selected_object",
|
||||
cameraInitialization = "camera_initialization",
|
||||
objectForMagnetism = "object_for_magnetism",
|
||||
loadObject = 'load_object'
|
||||
loadObject = "load_object",
|
||||
}
|
||||
|
||||
interface IEventDraggingChange {
|
||||
|
@ -58,10 +61,7 @@ interface IEmissiveCache {
|
|||
status: boolean;
|
||||
object3d: Object3D<Object3DEventMap>;
|
||||
}
|
||||
type SceneFrames = { [K in string]: URDFLink; }
|
||||
|
||||
|
||||
|
||||
type SceneFrames = { [K in string]: URDFLink };
|
||||
|
||||
export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
|
||||
scene = new Scene();
|
||||
|
@ -110,19 +110,22 @@ export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
|
|||
}
|
||||
|
||||
deleteAllObjectsScene = () => {
|
||||
|
||||
|
||||
this.getAllSceneNameModels().forEach((el) => this.scene.remove(this.scene.getObjectByName(el) as Object3D<Object3DEventMap>))
|
||||
}
|
||||
|
||||
this.getAllSceneNameModels().forEach((el) =>
|
||||
this.scene.remove(this.scene.getObjectByName(el) as Object3D<Object3DEventMap>)
|
||||
);
|
||||
};
|
||||
raiseAnObjectAboveZeroVector = (name: string) => {
|
||||
const mesh = this.scene.getObjectByName(name) as Object3D;
|
||||
mesh.position.sub(new Box3().setFromObject(mesh).min);
|
||||
};
|
||||
drawPoint(point: Vector3): Mesh<BoxGeometry, MeshBasicMaterial, Object3DEventMap> {
|
||||
var cube = new Mesh(new BoxGeometry(0.5, 0.5, 0.5), new MeshBasicMaterial({ color: 0x0095dd }));
|
||||
cube.position.add(point);
|
||||
this.scene.add(cube);
|
||||
return cube;
|
||||
}
|
||||
getCenterPoint = (object: Object3D<Object3DEventMap>) => object.getWorldPosition(new Box3().setFromObject(object).getCenter(object.position));
|
||||
|
||||
getCenterPoint = (object: Object3D<Object3DEventMap>) =>
|
||||
object.getWorldPosition(new Box3().setFromObject(object).getCenter(object.position));
|
||||
|
||||
makeCube(inc: number, vector?: Vector3, color?: string, size?: number) {
|
||||
const cube = new Mesh(
|
||||
|
@ -151,55 +154,34 @@ export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
|
|||
cube.position.copy(vector);
|
||||
}
|
||||
this.scene.add(cube);
|
||||
}
|
||||
deleteSceneItem = (item: string) =>
|
||||
this.scene.children.forEach((el) => el.name.isEqualR(item).map(() => this.scene.remove(el)));
|
||||
|
||||
}
|
||||
deleteSceneItem(item: BaseSceneItemModel) {
|
||||
const updateScene = this.scene;
|
||||
updateScene.children = item.deleteToScene(updateScene);
|
||||
}
|
||||
loadUrdf = (urlPath: string) => {
|
||||
this.urdfLoader.load(
|
||||
urlPath,
|
||||
robot => {
|
||||
|
||||
this.scene.add(robot)
|
||||
// @ts-expect-error
|
||||
this.sceneFrame = robot.frames
|
||||
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
loadInstances(robossemblerAssets: RobossemblerAssets) {
|
||||
robossemblerAssets.instances.forEach(async (el) => {
|
||||
if (el instanceof InstanceRgbCamera) {
|
||||
const cameraModel = CameraViewModel.fromInstanceRgbCamera(el);
|
||||
cameraModel.mapPerspectiveCamera(this.htmlSceneWidth, this.htmlSceneHeight).forEach((el) => this.scene.add(el));
|
||||
this.emit(cameraModel);
|
||||
}
|
||||
if (el instanceof SceneSimpleObject) {
|
||||
const asset = robossemblerAssets.getAssetAtInstance(el.instanceAt as string);
|
||||
this.loader(
|
||||
asset.meshPath,
|
||||
() => { },
|
||||
asset.name,
|
||||
new Vector3(el.position.x, el.position.y, el.position.z),
|
||||
new Quaternion(el.quaternion[0], el.quaternion[1], el.quaternion[2], el.quaternion[3])
|
||||
);
|
||||
}
|
||||
this.urdfLoader.load(urlPath, (robot) => {
|
||||
this.scene.add(robot);
|
||||
// @ts-expect-error
|
||||
this.sceneFrame = robot.frames;
|
||||
});
|
||||
}
|
||||
loadInstance(asset: Asset, loadCallback?: Function) {
|
||||
};
|
||||
|
||||
solidSpawn(
|
||||
solidSpawn: ISolidSpawnHelper,
|
||||
loadCallback?: (obj: Object3D<Object3DEventMap> | undefined) => void,
|
||||
vector3?: Vector3
|
||||
) {
|
||||
this.loader(
|
||||
asset.meshPath,
|
||||
loadCallback ? loadCallback : () => { },
|
||||
asset.name,
|
||||
new Vector3(Number(asset.posX), Number(asset.posY), Number(asset.posZ)),
|
||||
new Quaternion(0, 0, 0, 0)
|
||||
solidSpawn.url,
|
||||
() => {
|
||||
this.raiseAnObjectAboveZeroVector(solidSpawn.name);
|
||||
if (loadCallback) loadCallback(this.scene.getObjectByName(solidSpawn.name));
|
||||
},
|
||||
solidSpawn.name,
|
||||
vector3
|
||||
);
|
||||
}
|
||||
loadHttpAndPreview(path: string, name: string, loadCallback?: Function) {
|
||||
|
||||
this.loader(
|
||||
path,
|
||||
() => {
|
||||
|
@ -209,7 +191,6 @@ export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
|
|||
name,
|
||||
new Vector3(0, 0, 0)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
setTransformMode(mode?: SceneMode) {
|
||||
|
@ -218,10 +199,10 @@ export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
|
|||
this.transformControls.detach();
|
||||
this.transformControls.dispose();
|
||||
break;
|
||||
case SceneMode.MOVING:
|
||||
case SceneMode.Move:
|
||||
this.transformControls.setMode("translate");
|
||||
break;
|
||||
case SceneMode.ROTATE:
|
||||
case SceneMode.Rotate:
|
||||
this.transformControls.setMode("rotate");
|
||||
break;
|
||||
}
|
||||
|
@ -275,7 +256,7 @@ export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
|
|||
}
|
||||
}
|
||||
|
||||
setRayCast(vector: Vector2): Result<void, Intersection<Object3D<Object3DEventMap>>[]> {
|
||||
setRayCast = (vector: Vector2): Result<void, Intersection<Object3D<Object3DEventMap>>[]> => {
|
||||
const raycaster = new Raycaster();
|
||||
raycaster.setFromCamera(vector, this.camera);
|
||||
const intersects = raycaster.intersectObjects(this.scene.children);
|
||||
|
@ -284,16 +265,17 @@ export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
|
|||
}
|
||||
|
||||
return Result.error(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
setRayCastAndGetFirstObjectAndPointToObject(vector: Vector2): Result<void, Vector3> {
|
||||
this.setRayCast(vector).map((intersects) => {
|
||||
if (intersects.length > 0) {
|
||||
return Result.ok(intersects[0].point);
|
||||
}
|
||||
});
|
||||
return Result.error(undefined);
|
||||
}
|
||||
setRayCastAndGetFirstObjectAndPointToObject = (vector: Vector2): Result<void, Vector3> =>
|
||||
this.setRayCast(vector).fold(
|
||||
(intersects) => {
|
||||
if (intersects.isNotEmpty()) {
|
||||
return Result.ok(intersects[0].point);
|
||||
}
|
||||
},
|
||||
() => Result.error(undefined)
|
||||
) as Result<void, Vector3>;
|
||||
|
||||
light() {
|
||||
const ambientLight = new AmbientLight(0xffffff, 0.7);
|
||||
|
@ -321,12 +303,7 @@ export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
|
|||
this.orbitControls.enabled = !e.value;
|
||||
});
|
||||
this.transformControls.addEventListener("objectChange", (event) => {
|
||||
//@ts-expect-error
|
||||
const sceneObject = event.target.object;
|
||||
//TODO:(IDONTSUDO) Trotting doesn't work, need to figure out why
|
||||
const fn = () => this.watcherSceneEditorObject(sceneObject);
|
||||
const [throttleFn] = throttle(fn, 1000);
|
||||
throttleFn();
|
||||
this.watcherSceneEditorObject(event.target.object);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -334,10 +311,10 @@ export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
|
|||
this.light();
|
||||
this.addListeners();
|
||||
const floor = new GridHelper(1000, 100, 0x888888, 0x444444);
|
||||
floor.geometry.rotateX(Math.PI * 0.5)
|
||||
floor.geometry.rotateX(Math.PI * 0.5);
|
||||
floor.userData = {};
|
||||
floor.userData[UserData.cameraInitialization] = true;
|
||||
floor.up.copy(new Vector3(0, 0, 1))
|
||||
floor.up.copy(new Vector3(0, 0, 1));
|
||||
|
||||
this.scene.add(floor);
|
||||
}
|
||||
|
@ -372,10 +349,10 @@ export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
|
|||
this.glbLoader.load(
|
||||
url,
|
||||
(result) => {
|
||||
this.scene.add(result.scene)
|
||||
callBack()
|
||||
this.scene.add(result.scene);
|
||||
callBack();
|
||||
},
|
||||
(err) => { }
|
||||
(err) => {}
|
||||
);
|
||||
break;
|
||||
case "obj":
|
||||
|
@ -392,51 +369,47 @@ export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
|
|||
|
||||
this.emit(new StaticAssetItemModel(el.name, el.position, el.quaternion));
|
||||
this.scene.add(el);
|
||||
callBack()
|
||||
callBack();
|
||||
});
|
||||
},
|
||||
(err) => { }
|
||||
(err) => {}
|
||||
);
|
||||
break;
|
||||
case "dae":
|
||||
this.daeLoader.load(
|
||||
url,
|
||||
(result) => {
|
||||
this.scene.add(result.scene.children[0])
|
||||
this.scene.add(result.scene);
|
||||
},
|
||||
(err) => { }
|
||||
(err) => console.log(err)
|
||||
);
|
||||
break;
|
||||
case "stl":
|
||||
this.stlLoader.load(
|
||||
url,
|
||||
(result) => {
|
||||
|
||||
const material = new MeshStandardMaterial({
|
||||
color: 'red',
|
||||
metalness: 0.35,
|
||||
roughness: 1,
|
||||
opacity: 1.0,
|
||||
transparent: false,
|
||||
});
|
||||
|
||||
|
||||
const mesh = new Mesh(result, material);
|
||||
const mesh = new Mesh(
|
||||
result,
|
||||
new MeshStandardMaterial({
|
||||
color: "red",
|
||||
metalness: 0.35,
|
||||
roughness: 1,
|
||||
opacity: 1.0,
|
||||
transparent: false,
|
||||
})
|
||||
);
|
||||
mesh.name = name;
|
||||
|
||||
|
||||
|
||||
|
||||
// var geometry = mesh.geometry;
|
||||
// geometry.computeBoundingBox(); // Вычисляем ограничивающий параллелепипед для геометрии
|
||||
|
||||
if (position) mesh.position.copy(position)
|
||||
if (position) mesh.position.copy(position);
|
||||
|
||||
this.scene.add(mesh);
|
||||
callBack()
|
||||
callBack();
|
||||
},
|
||||
|
||||
(err) => { }
|
||||
(err) => {}
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
@ -526,11 +499,10 @@ export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
|
|||
urdfTransforms = (urdfTransforms: UrdfTransforms) => {
|
||||
urdfTransforms.transforms.forEach((transform) => {
|
||||
if (this.sceneFrame) {
|
||||
const currentLink = this.sceneFrame[transform?.child_frame_id ?? ""]
|
||||
const currentLink = this.sceneFrame[transform?.child_frame_id ?? ""];
|
||||
|
||||
currentLink.quaternion.copy(coordsToQuaternion(transform.transform.rotation))
|
||||
currentLink.quaternion.copy(coordsToQuaternion(transform.transform.rotation));
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,11 +5,12 @@ import { IStyle } from "../../model/style";
|
|||
export interface IIconsProps extends IStyle {
|
||||
type: string;
|
||||
onClick?: Function;
|
||||
height?: number;
|
||||
width?: number;
|
||||
}
|
||||
|
||||
export function Icon(props: IIconsProps) {
|
||||
const icon = getIconSvg(props.type);
|
||||
return icon.fold(
|
||||
return getIconSvg(props.type, props.height, props.width).fold(
|
||||
(node) => {
|
||||
return (
|
||||
<div
|
||||
|
@ -41,7 +42,11 @@ export function Icon(props: IIconsProps) {
|
|||
)
|
||||
);
|
||||
}
|
||||
const getIconSvg = (type: string): Result<undefined, React.JSX.Element> => {
|
||||
const getIconSvg = (
|
||||
type: string,
|
||||
height: number | undefined,
|
||||
width: number | undefined
|
||||
): Result<undefined, React.JSX.Element> => {
|
||||
switch (type) {
|
||||
case "":
|
||||
return Result.ok();
|
||||
|
@ -51,9 +56,9 @@ const getIconSvg = (type: string): Result<undefined, React.JSX.Element> => {
|
|||
<path
|
||||
d="M5 12H19M19 12L13 6M19 12L13 18"
|
||||
stroke="white"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
@ -64,65 +69,65 @@ const getIconSvg = (type: string): Result<undefined, React.JSX.Element> => {
|
|||
<path
|
||||
d="M17 18C17 18.5523 17.4477 19 18 19C18.5523 19 19 18.5523 19 18C19 17.4477 18.5523 17 18 17C17.4477 17 17 17.4477 17 18Z"
|
||||
stroke="white"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M11 18C11 18.5523 11.4477 19 12 19C12.5523 19 13 18.5523 13 18C13 17.4477 12.5523 17 12 17C11.4477 17 11 17.4477 11 18Z"
|
||||
stroke="white"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M5 18C5 18.5523 5.44772 19 6 19C6.55228 19 7 18.5523 7 18C7 17.4477 6.55228 17 6 17C5.44772 17 5 17.4477 5 18Z"
|
||||
stroke="white"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M17 12C17 12.5523 17.4477 13 18 13C18.5523 13 19 12.5523 19 12C19 11.4477 18.5523 11 18 11C17.4477 11 17 11.4477 17 12Z"
|
||||
stroke="white"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M11 12C11 12.5523 11.4477 13 12 13C12.5523 13 13 12.5523 13 12C13 11.4477 12.5523 11 12 11C11.4477 11 11 11.4477 11 12Z"
|
||||
stroke="white"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M5 12C5 12.5523 5.44772 13 6 13C6.55228 13 7 12.5523 7 12C7 11.4477 6.55228 11 6 11C5.44772 11 5 11.4477 5 12Z"
|
||||
stroke="white"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M17 6C17 6.55228 17.4477 7 18 7C18.5523 7 19 6.55228 19 6C19 5.44772 18.5523 5 18 5C17.4477 5 17 5.44772 17 6Z"
|
||||
stroke="white"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M11 6C11 6.55228 11.4477 7 12 7C12.5523 7 13 6.55228 13 6C13 5.44772 12.5523 5 12 5C11.4477 5 11 5.44772 11 6Z"
|
||||
stroke="white"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M5 6C5 6.55228 5.44772 7 6 7C6.55228 7 7 6.55228 7 6C7 5.44772 6.55228 5 6 5C5.44772 5 5 5.44772 5 6Z"
|
||||
stroke="white"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
@ -132,9 +137,9 @@ const getIconSvg = (type: string): Result<undefined, React.JSX.Element> => {
|
|||
<path
|
||||
d="M21 21L12 12M12 12L3 3M12 12L21.0001 3M12 12L3 21.0001"
|
||||
stroke="white"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
@ -367,7 +372,13 @@ const getIconSvg = (type: string): Result<undefined, React.JSX.Element> => {
|
|||
);
|
||||
case "DeleteCircle":
|
||||
return Result.ok(
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
width={width ? width : "20"}
|
||||
height={height ? height : "20"}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
|
@ -451,6 +462,24 @@ const getIconSvg = (type: string): Result<undefined, React.JSX.Element> => {
|
|||
</g>
|
||||
</svg>
|
||||
);
|
||||
case "Solid":
|
||||
return Result.ok(
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={width ? width : "20"}
|
||||
height={height ? height : "20"}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M12 10.2308L3.08495 7.02346M12 10.2308L20.9178 7.03406M12 10.2308V20.8791M5.13498 18.5771L10.935 20.6242C11.3297 20.7635 11.527 20.8331 11.7294 20.8608C11.909 20.8853 12.091 20.8853 12.2706 20.8608C12.473 20.8331 12.6703 20.7635 13.065 20.6242L18.865 18.5771C19.6337 18.3058 20.018 18.1702 20.3018 17.9269C20.5523 17.7121 20.7459 17.4386 20.8651 17.1308C21 16.7823 21 16.3747 21 15.5595V8.44058C21 7.62542 21 7.21785 20.8651 6.86935C20.7459 6.56155 20.5523 6.28804 20.3018 6.0732C20.018 5.82996 19.6337 5.69431 18.865 5.42301L13.065 3.37595C12.6703 3.23665 12.473 3.167 12.2706 3.13936C12.091 3.11484 11.909 3.11484 11.7294 3.13936C11.527 3.167 11.3297 3.23665 10.935 3.37595L5.13498 5.42301C4.36629 5.69431 3.98195 5.82996 3.69824 6.0732C3.44766 6.28804 3.25414 6.56155 3.13495 6.86935C3 7.21785 3 7.62542 3 8.44058V15.5595C3 16.3747 3 16.7823 3.13495 17.1308C3.25414 17.4386 3.44766 17.7121 3.69824 17.9269C3.98195 18.1702 4.36629 18.3058 5.13498 18.5771Z"
|
||||
stroke="#000000"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</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">
|
||||
|
@ -460,6 +489,42 @@ const getIconSvg = (type: string): Result<undefined, React.JSX.Element> => {
|
|||
/>
|
||||
</svg>
|
||||
);
|
||||
case "Move":
|
||||
return Result.ok(
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" xmlSpace="preserve">
|
||||
<g fill="#ffffff">
|
||||
<path
|
||||
fill="#ffffff"
|
||||
d="M178.492 368a.5.5 0 0 0-.346.146l-2 2a.5.5 0 1 0 .708.708l1.146-1.147v7.586l-3 3V378.5a.5.5 0 0 0-.508-.508.5.5 0 0 0-.492.508v3a.5.5 0 0 0 .5.5h3a.5.5 0 1 0 0-1h-1.793l3-3h7.586l-1.147 1.146a.5.5 0 1 0 .708.708l2-2a.5.5 0 0 0 0-.708l-2-2a.5.5 0 0 0-.36-.152.5.5 0 0 0-.348.86l1.147 1.146H179v-7.293l1.146 1.147a.5.5 0 1 0 .708-.708l-2-2a.5.5 0 0 0-.362-.146z"
|
||||
transform="translate(-171 -365)"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
case "Save":
|
||||
return Result.ok(
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M18.1716 1C18.702 1 19.2107 1.21071 19.5858 1.58579L22.4142 4.41421C22.7893 4.78929 23 5.29799 23 5.82843V20C23 21.6569 21.6569 23 20 23H4C2.34315 23 1 21.6569 1 20V4C1 2.34315 2.34315 1 4 1H18.1716ZM4 3C3.44772 3 3 3.44772 3 4V20C3 20.5523 3.44772 21 4 21L5 21L5 15C5 13.3431 6.34315 12 8 12L16 12C17.6569 12 19 13.3431 19 15V21H20C20.5523 21 21 20.5523 21 20V6.82843C21 6.29799 20.7893 5.78929 20.4142 5.41421L18.5858 3.58579C18.2107 3.21071 17.702 3 17.1716 3H17V5C17 6.65685 15.6569 8 14 8H10C8.34315 8 7 6.65685 7 5V3H4ZM17 21V15C17 14.4477 16.5523 14 16 14L8 14C7.44772 14 7 14.4477 7 15L7 21L17 21ZM9 3H15V5C15 5.55228 14.5523 6 14 6H10C9.44772 6 9 5.55228 9 5V3Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
case "Select":
|
||||
return Result.ok(
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="white" viewBox="0 0 24 24">
|
||||
<path d="M6 3v18l5-7h9zm4.485 10L7 17.88V5.058L17.108 13z" fillRule="evenodd" />
|
||||
<path fill="none" d="M0 0h24v24H0z" />
|
||||
</svg>
|
||||
);
|
||||
case "Rotate":
|
||||
return Result.ok(
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="white" viewBox="0 0 24 24">
|
||||
<path d="M11.2797426,15.9868494 L10.1464466,14.8535534 C9.95118446,14.6582912 9.95118446,14.3417088 10.1464466,14.1464466 C10.3417088,13.9511845 10.6582912,13.9511845 10.8535534,14.1464466 L12.8535534,16.1464466 C13.0488155,16.3417088 13.0488155,16.6582912 12.8535534,16.8535534 L10.8535534,18.8535534 C10.6582912,19.0488155 10.3417088,19.0488155 10.1464466,18.8535534 C9.95118446,18.6582912 9.95118446,18.3417088 10.1464466,18.1464466 L11.3044061,16.9884871 C10.3667147,16.9573314 9.46306739,16.8635462 8.61196501,16.7145167 C9.33747501,19.2936084 10.6229353,21 12,21 C14.0051086,21 15.8160018,17.3821896 15.9868494,12.7202574 L14.8535534,13.8535534 C14.6582912,14.0488155 14.3417088,14.0488155 14.1464466,13.8535534 C13.9511845,13.6582912 13.9511845,13.3417088 14.1464466,13.1464466 L16.1464466,11.1464466 C16.3417088,10.9511845 16.6582912,10.9511845 16.8535534,11.1464466 L18.8535534,13.1464466 C19.0488155,13.3417088 19.0488155,13.6582912 18.8535534,13.8535534 C18.6582912,14.0488155 18.3417088,14.0488155 18.1464466,13.8535534 L16.9884871,12.6955939 C16.8167229,17.8651676 14.7413901,22 12,22 C9.97580598,22 8.3147521,19.7456544 7.515026,16.484974 C4.2543456,15.6852479 2,14.024194 2,12 C2,9.97580598 4.2543456,8.3147521 7.515026,7.515026 C8.3147521,4.2543456 9.97580598,2 12,2 C13.5021775,2 14.8263891,3.23888365 15.7433738,5.30744582 C15.8552836,5.55989543 15.7413536,5.8552671 15.4889039,5.96717692 C15.2364543,6.07908673 14.9410827,5.96515672 14.8291729,5.71270711 C14.0550111,3.96632921 13.0221261,3 12,3 C10.6229353,3 9.33747501,4.70639159 8.61196501,7.28548333 C9.67174589,7.09991387 10.812997,7 12,7 C17.4892085,7 22,9.13669069 22,12 C22,13.5021775 20.7611164,14.8263891 18.6925542,15.7433738 C18.4401046,15.8552836 18.1447329,15.7413536 18.0328231,15.4889039 C17.9209133,15.2364543 18.0348433,14.9410827 18.2872929,14.8291729 C20.0336708,14.0550111 21,13.0221261 21,12 C21,9.89274656 17.0042017,8 12,8 C10.6991081,8 9.46636321,8.12791023 8.35424759,8.35424759 C8.12791023,9.46636321 8,10.6991081 8,12 C8,13.3008919 8.12791023,14.5336368 8.35424759,15.6457524 C9.25899447,15.8298862 10.2435788,15.9488767 11.2797426,15.9868494 Z M7.28548333,8.61196501 C4.70639159,9.33747501 3,10.6229353 3,12 C3,13.3770647 4.70639159,14.662525 7.28548333,15.388035 C7.09991387,14.3282541 7,13.187003 7,12 C7,10.812997 7.09991387,9.67174589 7.28548333,8.61196501 L7.28548333,8.61196501 Z" />
|
||||
</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">
|
||||
|
|
|
@ -55,7 +55,7 @@ export class AllProjectStore extends ModalStore {
|
|||
}
|
||||
if (this.file === undefined) {
|
||||
message.error("загрузите файл");
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
this.isLoading = true;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { extensions } from "../../../core/extensions/extensions";
|
||||
import { Form } from "../presentation/ui/forms/forms";
|
||||
import { ISkillView } from "../presentation/ui/skill_tree/skill_tree";
|
||||
|
||||
extensions();
|
||||
|
|
|
@ -6,6 +6,10 @@ export interface Parts {
|
|||
material_path: string;
|
||||
stlUrl: string;
|
||||
image: string;
|
||||
glUrl: string;
|
||||
solidType: string;
|
||||
daeUrl: string;
|
||||
objUrl: string;
|
||||
}
|
||||
|
||||
export class DetailsHttpRepository extends CoreHttpRepository {
|
||||
|
|
|
@ -29,6 +29,9 @@ export class DetailsStore extends UiDrawerFormState<EnvelopmentViewModel, CoreEr
|
|||
errorHandingStrategy = (error: CoreError) => {};
|
||||
init = async (navigate?: NavigateFunction | undefined): Promise<void> => {
|
||||
await this.mapOk("parts", this.detailsHttpRepository.getAssetsActiveProject());
|
||||
|
||||
|
||||
|
||||
this.detailsViewModel = this.parts.map((el) => {
|
||||
return {
|
||||
label: el.name,
|
||||
|
|
|
@ -2,20 +2,14 @@ import { Box3, GridHelper, Mesh, Object3D, Vector3 } from "three";
|
|||
import { CoreThreeRepository } from "../../core/repository/core_three_repository";
|
||||
|
||||
export class DetailsThreeRepository extends CoreThreeRepository {
|
||||
raiseAnObjectAboveZeroVector = (name: string) => {
|
||||
const mesh = this.scene.getObjectByName(name) as Object3D;
|
||||
mesh.position.sub(new Box3().setFromObject(mesh).min)
|
||||
}
|
||||
matchTwoPlacesInTheCenter = () => {
|
||||
|
||||
}
|
||||
|
||||
loadHttpAndPreview = (path: string, name: string, loadCallback?: Function) => {
|
||||
|
||||
this.loader(
|
||||
path,
|
||||
() => {
|
||||
this.raiseAnObjectAboveZeroVector(name)
|
||||
console.log(this.getCenterPoint(this.scene.children.filter((el) => el instanceof GridHelper).at(0) as Object3D))
|
||||
this.getCenterPoint(this.scene.children.filter((el) => el instanceof GridHelper).at(0) as Object3D)
|
||||
},
|
||||
name,
|
||||
new Vector3(0, 0, 0)
|
||||
|
|
30
ui/src/features/scene_manager/model/camera_view_model.ts
Normal file
30
ui/src/features/scene_manager/model/camera_view_model.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
import { Quaternion, Vector3 } from "three";
|
||||
import { SceneModelsTypes } from "./solid_body_model";
|
||||
import { Result } from "../../../core/helper/result";
|
||||
export enum CameraTypes {
|
||||
RGB = "RGB",
|
||||
}
|
||||
export class CameraModel {
|
||||
type = SceneModelsTypes.CAMERA;
|
||||
|
||||
constructor(
|
||||
public quaternion: Quaternion,
|
||||
public vector3: Vector3,
|
||||
public name: string,
|
||||
public cameraType: CameraTypes,
|
||||
public width: number,
|
||||
public updateRate: number,
|
||||
public fov: number,
|
||||
public near: number,
|
||||
public far: number,
|
||||
public height: number,
|
||||
public topic: string,
|
||||
public parent?: string,
|
||||
public fixed?: string
|
||||
) {}
|
||||
validate = (): Result<string, CameraModel> => {
|
||||
return Result.ok(this);
|
||||
};
|
||||
static empty = () =>
|
||||
new CameraModel(new Quaternion(0, 0, 0, 0), new Vector3(0, 0, 0), "", CameraTypes.RGB, 0, 0, 0, 0, 0, 0, "");
|
||||
}
|
|
@ -20,9 +20,8 @@ export interface SceneManagerView {
|
|||
}
|
||||
|
||||
export enum SceneMode {
|
||||
ROTATE = "Rotate",
|
||||
MOVING = "Moving",
|
||||
EMPTY = "Empty",
|
||||
ADD_CAMERA = "Add camera",
|
||||
MAGNETISM_MARKING = "magnetism_marking",
|
||||
Rotate = "Rotate",
|
||||
Move = "Move",
|
||||
Select = "Select",
|
||||
Save = 'Save',
|
||||
}
|
||||
|
|
30
ui/src/features/scene_manager/model/solid_body_model.ts
Normal file
30
ui/src/features/scene_manager/model/solid_body_model.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
import { Quaternion, Vector3 } from "three";
|
||||
|
||||
export enum SceneModelsTypes {
|
||||
SOLID = "SOLID",
|
||||
ROBOT = "ROBOT",
|
||||
LIGHT = "LIGHT",
|
||||
CAMERA = 'CAMERA'
|
||||
}
|
||||
export enum SolidBodyTypes {
|
||||
ACTIVE = "ACTIVE",
|
||||
STATIC = "STATIC",
|
||||
}
|
||||
interface ISpawnTypes {
|
||||
type: "POINT";
|
||||
name: "123";
|
||||
}
|
||||
export class SolidBodyModel {
|
||||
type = SceneModelsTypes.SOLID;
|
||||
spawn?: ISpawnTypes;
|
||||
constructor(
|
||||
public quaternion: Quaternion,
|
||||
public vector3: Vector3,
|
||||
public name: string,
|
||||
public solidType: SolidBodyTypes | string,
|
||||
public mesh: string,
|
||||
public collisionMesh: string,
|
||||
public inertia?: number,
|
||||
public mass?: number
|
||||
) {}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
import { SpawnPositionTypes } from "../../../../core/model/spawn_position_types";
|
||||
import { CoreButton } from "../../../../core/ui/button/button";
|
||||
import { CoreText, CoreTextType } from "../../../../core/ui/text/text";
|
||||
|
||||
export const SpawnPositionTypesForm = ({ onClick: onClick }: { onClick: Function }) => {
|
||||
return (
|
||||
<>
|
||||
<CoreText text={"Тип размещения"} type={CoreTextType.header} />
|
||||
{Object.entries(SpawnPositionTypes).map(([_, value], i) => (
|
||||
<CoreButton key={i} text={value} onClick={() => onClick(value)} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -1,31 +1,60 @@
|
|||
import { NavigateFunction } from "react-router-dom";
|
||||
import { CoreError, FormState, UiDrawerFormState } from "../../../../../core/store/base_store";
|
||||
import { CoreError, FormState } 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 { IDefaultSceneManagerFormProps } 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";
|
||||
import { CameraModel, CameraTypes } from "../../../model/camera_view_model";
|
||||
import { CoreSelect } from "../../../../../core/ui/select/select";
|
||||
|
||||
class CameraFormStore extends FormState<CameraViewModel, CoreError> {
|
||||
class CameraFormStore extends FormState<CameraModel, CoreError> {
|
||||
errorHandingStrategy = (error: CoreError) => {};
|
||||
init = async (navigate?: NavigateFunction | undefined) => {};
|
||||
viewModel: CameraViewModel = CameraViewModel.empty();
|
||||
viewModel: CameraModel = CameraModel.empty();
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
export const CameraForm = (props: IDefaultSceneManagerProps) => {
|
||||
export const CameraForm = (props: IDefaultSceneManagerFormProps) => {
|
||||
const [store] = React.useState(() => new CameraFormStore());
|
||||
|
||||
React.useEffect(() => {
|
||||
store.init();
|
||||
}, []);
|
||||
return (
|
||||
<div style={{ margin: 10, padding: 10 }}>
|
||||
<div style={{ margin: 10, padding: 10, overflowY: "auto", height: "100%" }}>
|
||||
<CoreText text="Камера" type={CoreTextType.header} />
|
||||
<CoreInput label={"Камера линк"} onChange={(text) => store.updateForm({ cameraLink: text })} />
|
||||
|
||||
<CoreInput value={store.viewModel.topic} label={"Топик"} onChange={(text) => store.updateForm({ topic: text })} />
|
||||
<CoreInput value={store.viewModel.name} label={"Имя"} onChange={(text) => store.updateForm({ name: text })} />
|
||||
<CoreInput
|
||||
value={String(store.viewModel.updateRate)}
|
||||
validation={(text) => Number().isValid(text)}
|
||||
label={"Update Rate"}
|
||||
onChange={(text) => store.updateForm({ updateRate: Number(text) })}
|
||||
/>
|
||||
<CoreInput
|
||||
value={String(store.viewModel.height)}
|
||||
validation={(text) => Number().isValid(text)}
|
||||
label={"Height"}
|
||||
onChange={(text) => store.updateForm({ height: Number(text) })}
|
||||
/>
|
||||
<CoreInput
|
||||
value={String(store.viewModel.width)}
|
||||
|
||||
validation={(text) => Number().isValid(text)}
|
||||
label={"Width"}
|
||||
onChange={(text) => store.updateForm({ width: Number(text) })}
|
||||
/>
|
||||
<CoreSelect
|
||||
items={Object.entries(CameraTypes).map(([_, v]) => v)}
|
||||
value={store.viewModel.cameraType}
|
||||
label={"Типы камер"}
|
||||
onChange={(text) => store.updateForm({ cameraType: text as CameraTypes })}
|
||||
/>
|
||||
<div style={{ height: 10 }} />
|
||||
<CoreButton
|
||||
text="Создать"
|
||||
|
@ -33,7 +62,7 @@ export const CameraForm = (props: IDefaultSceneManagerProps) => {
|
|||
onClick={() =>
|
||||
store.viewModel.validate().fold(
|
||||
(model) => {
|
||||
props.store.addNewCamera(model);
|
||||
// props.store.addNewCamera(model);
|
||||
},
|
||||
(error) => message.error(error)
|
||||
)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
import { observer } from "mobx-react-lite";
|
||||
import { IDefaultSceneManagerFormProps } from "../scene_manager_forms";
|
||||
|
||||
export const LightForm = observer((props: IDefaultSceneManagerFormProps) => {
|
||||
return <></>;
|
||||
});
|
|
@ -0,0 +1,14 @@
|
|||
import { NavigateFunction } from "react-router-dom";
|
||||
import { FormState, CoreError } from "../../../../../core/store/base_store";
|
||||
import { LightViewModel } from "./light_view_model";
|
||||
|
||||
export class LightStore extends FormState<LightViewModel, CoreError> {
|
||||
viewModel: LightViewModel = LightViewModel.empty();
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
errorHandingStrategy = (error: CoreError) => {};
|
||||
init(navigate?: NavigateFunction | undefined): Promise<any> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import { Result } from "../../../../../core/helper/result";
|
||||
|
||||
export class LightViewModel {
|
||||
constructor() {}
|
||||
isValid = (): Result<void, LightViewModel> => {
|
||||
return Result.ok(this);
|
||||
};
|
||||
static empty = () => new LightViewModel();
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
import React from "react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { PointStore, PointStoreType } from "./point_store";
|
||||
import { IDefaultSceneManagerFormProps } from "../scene_manager_forms";
|
||||
import { CoreText, CoreTextType } from "../../../../../core/ui/text/text";
|
||||
import { CoreInput } from "../../../../../core/ui/input/input";
|
||||
import { CoreButton } from "../../../../../core/ui/button/button";
|
||||
import { match } from "ts-pattern";
|
||||
import { SpawnPositionTypesForm } from "../../components/spawn_position_types";
|
||||
|
||||
export const PointForm = observer((props: IDefaultSceneManagerFormProps) => {
|
||||
const [store] = React.useState(() => new PointStore());
|
||||
React.useEffect(() => {
|
||||
store.init();
|
||||
}, [store]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{match(store.storeType)
|
||||
.with(PointStoreType.initNewPoint, () => (
|
||||
<>
|
||||
<CoreText text="Точка" type={CoreTextType.header} />
|
||||
<CoreInput label="Имя" onChange={(text) => store.updateForm({ name: text })} />
|
||||
<CoreButton
|
||||
text="Следующий этап"
|
||||
onClick={() => store.onClickNext(PointStoreType.makeSceneSolidAndEditPosition)}
|
||||
/>
|
||||
</>
|
||||
))
|
||||
.with(PointStoreType.makeSceneSolidAndEditPosition, () => (
|
||||
<>
|
||||
<SpawnPositionTypesForm onClick={store.selectSpawnType} />
|
||||
</>
|
||||
))
|
||||
.otherwise(() => (
|
||||
<></>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
});
|
|
@ -0,0 +1,6 @@
|
|||
import { HttpRepository } from "../../../../../core/repository/http_repository";
|
||||
|
||||
|
||||
export class PointHttpRepository extends HttpRepository {
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
import makeAutoObservable from "mobx-store-inheritance";
|
||||
import { NavigateFunction } from "react-router-dom";
|
||||
import { PointViewModel } from "./point_view_model";
|
||||
import { PointHttpRepository } from "./point_http_repository";
|
||||
import { FormState, CoreError } from "../../../../../core/store/base_store";
|
||||
import { SpawnPositionTypes } from "../../../../../core/model/spawn_position_types";
|
||||
export enum PointStoreType {
|
||||
makeSceneSolidAndEditPosition = "makeSceneSolidAndEditPosition",
|
||||
initNewPoint = "initNewPoint",
|
||||
}
|
||||
export class PointStore extends FormState<PointViewModel, CoreError> {
|
||||
onClickNext = (pointStoreType: PointStoreType) => (this.storeType = pointStoreType);
|
||||
viewModel: PointViewModel = PointViewModel.empty();
|
||||
cameraDeviceHttpRepository: PointHttpRepository = new PointHttpRepository();
|
||||
storeType: PointStoreType = PointStoreType.initNewPoint;
|
||||
spawnPositionTypes: SpawnPositionTypes;
|
||||
constructor() {
|
||||
super();
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
selectSpawnType = (type: SpawnPositionTypes) => {
|
||||
this.spawnPositionTypes = type;
|
||||
};
|
||||
errorHandingStrategy = (error: CoreError) => {};
|
||||
init = async (navigate?: NavigateFunction | undefined) => {};
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import { Quaternion, Vector3 } from "three";
|
||||
import { Result } from "../../../../../core/helper/result";
|
||||
|
||||
export class PointViewModel {
|
||||
type = "POINT";
|
||||
name: string;
|
||||
vector3: Vector3;
|
||||
quaternion: Quaternion;
|
||||
constructor() {}
|
||||
isValid(): Result<string, PointViewModel> {
|
||||
return Result.ok();
|
||||
}
|
||||
static empty() {
|
||||
return new PointViewModel();
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import { IDefaultSceneManagerProps } from "../scene_manager_forms";
|
||||
import { IDefaultSceneManagerFormProps } from "../scene_manager_forms";
|
||||
|
||||
|
||||
export const RobotForm = (props: IDefaultSceneManagerProps) => {
|
||||
export const RobotForm = (props: IDefaultSceneManagerFormProps) => {
|
||||
return <div>ROBOT</div>;
|
||||
};
|
||||
|
|
|
@ -1,23 +1,37 @@
|
|||
import { SceneMangerStore } from "../scene_manager_store";
|
||||
import { CameraForm } from "./camera/camera_form";
|
||||
import { LightForm } from "./light/light_form";
|
||||
import { PointForm } from "./point/point_form";
|
||||
import { RobotForm } from "./robot/robot_form";
|
||||
import { SolidBodyForm } from "./solid_body/solid_body_form";
|
||||
|
||||
import { Trajectory } from "./trajectory/trajectory_form";
|
||||
import { ZoneForm } from "./zone/zone_form";
|
||||
|
||||
export enum SceneManagerForms {
|
||||
robot = "robot",
|
||||
camera = "camera",
|
||||
solidBody = "solidBody",
|
||||
solidBody = "SolidBody",
|
||||
previewSolidBody = "previewSolidBody",
|
||||
light = "Light",
|
||||
point = "point",
|
||||
trajectory = "trajectory",
|
||||
zone = "zone",
|
||||
}
|
||||
interface IForms {
|
||||
name: string;
|
||||
component: JSX.Element;
|
||||
}
|
||||
export interface IDefaultSceneManagerProps {
|
||||
export interface IDefaultSceneManagerFormProps {
|
||||
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} /> },
|
||||
{ name: SceneManagerForms.point, component: <PointForm dependency={props} store={store} /> },
|
||||
{ name: SceneManagerForms.light, component: <LightForm dependency={props} store={store} /> },
|
||||
{ name: SceneManagerForms.zone, component: <ZoneForm dependency={props} store={store} /> },
|
||||
{ name: SceneManagerForms.trajectory, component: <Trajectory dependency={props} store={store} /> },
|
||||
];
|
||||
|
|
|
@ -1,5 +1,62 @@
|
|||
import { IDefaultSceneManagerProps } from "../scene_manager_forms";
|
||||
import React from "react";
|
||||
import { CoreText, CoreTextType } from "../../../../../core/ui/text/text";
|
||||
import { IDefaultSceneManagerFormProps } from "../scene_manager_forms";
|
||||
import { SolidBodyStore, SolidBodyStoreType } from "./solid_body_store";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { CoreButton } from "../../../../../core/ui/button/button";
|
||||
import { match } from "ts-pattern";
|
||||
import { SpawnPositionTypesForm } from "../../components/spawn_position_types";
|
||||
|
||||
export const SolidBodyForm = (props:IDefaultSceneManagerProps) => {
|
||||
return <></>;
|
||||
};
|
||||
export const SolidBodyForm = observer((props: IDefaultSceneManagerFormProps) => {
|
||||
const [store] = React.useState(() => new SolidBodyStore(props.store));
|
||||
React.useEffect(() => {
|
||||
store.init();
|
||||
}, []);
|
||||
return (
|
||||
<div style={{ display: "flex", flexDirection: "column", alignItems: "center" }}>
|
||||
{Object.hasOwn(props.dependency, "type") && Object.hasOwn(props.dependency, "name") ? (
|
||||
<>
|
||||
x:{props.store.scene.find((el) => el.name.isEqual(props.store.selectedItemName ?? ""))?.vector3.x}
|
||||
y:{props.store.scene.find((el) => el.name.isEqual(props.store.selectedItemName ?? ""))?.vector3.y}
|
||||
y:{props.store.scene.find((el) => el.name.isEqual(props.store.selectedItemName ?? ""))?.vector3.z}
|
||||
solidType:{props.store.scene.find((el) => el.name.isEqual(props.store.selectedItemName ?? ""))?.solidType}
|
||||
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{match(store.solidBodyStoreType)
|
||||
.with(SolidBodyStoreType.selectBody, () => (
|
||||
<>
|
||||
<CoreText text={"Твердое тело"} type={CoreTextType.header} />
|
||||
|
||||
{store.parts.map((el, i) => (
|
||||
<div key={i} style={{ padding: 10, margin: 10 }}>
|
||||
<CoreText text={el.name} type={CoreTextType.medium} />
|
||||
<img src={el.image} />
|
||||
<CoreButton text="Выбрать" onClick={() => store.clickSelectBody(el)} />
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
))
|
||||
.with(SolidBodyStoreType.selectSpawnPositionType, () => (
|
||||
<>
|
||||
<SpawnPositionTypesForm onClick={store.selectSpawnType} />
|
||||
</>
|
||||
))
|
||||
.with(SolidBodyStoreType.spawn2DVector, () => (
|
||||
<>
|
||||
{props.store.mousePosition ? (
|
||||
""
|
||||
) : (
|
||||
<CoreText text={"Выберите точку размещения"} type={CoreTextType.header} />
|
||||
)}
|
||||
</>
|
||||
))
|
||||
.otherwise(() => (
|
||||
<></>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -4,14 +4,14 @@ 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";
|
||||
import { SceneMangerStore } from "../../scene_manager_store";
|
||||
import { SpawnPositionTypes } from "../../../../../core/model/spawn_position_types";
|
||||
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[] = [];
|
||||
|
@ -20,20 +20,33 @@ export class SolidBodyStore extends FormState<SolidBodyViewModel, CoreError> {
|
|||
solidBodyStoreType: SolidBodyStoreType = SolidBodyStoreType.selectBody;
|
||||
selectBody: Parts;
|
||||
spawnType: string;
|
||||
errorHandingStrategy = (error: CoreError) => {};
|
||||
constructor() {
|
||||
sceneManagerStore: SceneMangerStore;
|
||||
vector2d?: Vector2;
|
||||
|
||||
constructor(sceneManagerStore: SceneMangerStore) {
|
||||
super();
|
||||
this.sceneManagerStore = sceneManagerStore;
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
vector2d?: Vector2;
|
||||
init = async () => {
|
||||
this.mapOk("parts", this.coreHttpRepository.getAssetsActiveProject());
|
||||
};
|
||||
errorHandingStrategy = (error: CoreError) => {};
|
||||
|
||||
dispose = () => {};
|
||||
selectSpawnType = (type: string) => {
|
||||
this.spawnType = type;
|
||||
this.solidBodyStoreType = SolidBodyStoreType.spawn2DVector;
|
||||
this.sceneManagerStore.mousePositionAwait = true;
|
||||
this.sceneManagerStore.solidSpawnHelper = {
|
||||
url: this.selectBody.objUrl,
|
||||
name: this.selectBody.name,
|
||||
isFinished: false,
|
||||
solidType: this.selectBody.solidType,
|
||||
type: this.spawnType,
|
||||
};
|
||||
this.sceneManagerStore.activeFormType = undefined;
|
||||
};
|
||||
selectVector = () => {};
|
||||
clickSelectBody = (el: Parts) => {
|
||||
this.selectBody = el;
|
||||
this.solidBodyStoreType = SolidBodyStoreType.selectSpawnPositionType;
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
import React from "react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { TrajectoryStore } from "./trajectory_store";
|
||||
import { IDefaultSceneManagerFormProps } from "../scene_manager_forms";
|
||||
|
||||
export const Trajectory = observer((props: IDefaultSceneManagerFormProps) => {
|
||||
const [store] = React.useState(() => new TrajectoryStore());
|
||||
React.useEffect(() => {
|
||||
store.init();
|
||||
}, [store]);
|
||||
|
||||
return <>Trajectory</>;
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
import { HttpRepository } from "../../../../../core/repository/http_repository";
|
||||
|
||||
export class TrajectoryHttpRepository extends HttpRepository {}
|
|
@ -0,0 +1,20 @@
|
|||
import makeAutoObservable from "mobx-store-inheritance";
|
||||
import { NavigateFunction } from "react-router-dom";
|
||||
import { TrajectoryViewModel } from "./trajectory_view_model";
|
||||
import { TrajectoryHttpRepository } from "./trajectory_http_repository";
|
||||
import { FormState, CoreError } from "../../../../../core/store/base_store";
|
||||
|
||||
export class TrajectoryStore extends FormState<TrajectoryViewModel, CoreError> {
|
||||
constructor() {
|
||||
super();
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
viewModel: TrajectoryViewModel = TrajectoryViewModel.empty();
|
||||
cameraDeviceHttpRepository: TrajectoryHttpRepository = new TrajectoryHttpRepository();
|
||||
errorHandingStrategy = (error: CoreError) => { }
|
||||
init = async (navigate?: NavigateFunction | undefined) => {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import { Result } from "../../../../../core/helper/result";
|
||||
|
||||
|
||||
export class TrajectoryViewModel {
|
||||
constructor() {}
|
||||
isValid(): Result<string, TrajectoryViewModel> {
|
||||
return Result.ok();
|
||||
}
|
||||
static empty() {
|
||||
return new TrajectoryViewModel();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import React from "react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { ZoneStore } from "./zone_store";
|
||||
import { IDefaultSceneManagerFormProps } from "../scene_manager_forms";
|
||||
|
||||
|
||||
|
||||
export const ZoneForm = observer((props: IDefaultSceneManagerFormProps) => {
|
||||
const [store] = React.useState(() => new ZoneStore());
|
||||
React.useEffect(() => {
|
||||
store.init();
|
||||
}, [store]);
|
||||
|
||||
return <>zone</>;
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
import { HttpRepository } from "../../../../../core/repository/http_repository";
|
||||
|
||||
export class ZoneHttpRepository extends HttpRepository {}
|
|
@ -0,0 +1,19 @@
|
|||
import makeAutoObservable from "mobx-store-inheritance";
|
||||
import { NavigateFunction } from "react-router-dom";
|
||||
import { ZoneViewModel } from "./zone_view_model";
|
||||
import { ZoneHttpRepository } from "./zone_http_repository";
|
||||
import { FormState, CoreError } from "../../../../../core/store/base_store";
|
||||
|
||||
export class ZoneStore extends FormState<ZoneViewModel, CoreError> {
|
||||
constructor() {
|
||||
super();
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
viewModel: ZoneViewModel = ZoneViewModel.empty();
|
||||
cameraDeviceHttpRepository: ZoneHttpRepository = new ZoneHttpRepository();
|
||||
errorHandingStrategy = (error: CoreError) => { }
|
||||
init = async (navigate?: NavigateFunction | undefined) => {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
import { Result } from "../../../../../core/helper/result";
|
||||
|
||||
export class ZoneViewModel {
|
||||
name: string;
|
||||
constructor(name: string) {
|
||||
this.name = name;
|
||||
}
|
||||
isValid(): Result<string, ZoneViewModel> {
|
||||
return Result.ok();
|
||||
}
|
||||
static empty() {
|
||||
return new ZoneViewModel("");
|
||||
}
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
import * as React from "react";
|
||||
import { DrawersSceneManager, SceneMangerStore, StoreMode } from "./scene_manager_store";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { Drawer, Popover } from "antd";
|
||||
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";
|
||||
|
||||
|
@ -34,6 +33,7 @@ export const SceneManger = observer(() => {
|
|||
return (
|
||||
<MainPage
|
||||
page={"Сцена"}
|
||||
panelStyle={{ display: store.storeMode.isEqual(StoreMode.sceneInstance) ? "" : "none" }}
|
||||
panelChildren={
|
||||
<div style={{ width: "100%", height: "100%" }}>
|
||||
<div style={{ height: 260, width: "100%", padding: 10 }}>
|
||||
|
@ -45,8 +45,8 @@ export const SceneManger = observer(() => {
|
|||
content={
|
||||
<div>
|
||||
{store.popoverItems.map((el, i) => (
|
||||
<div onClick={() => el.fn()}>
|
||||
<CoreText key={i} text={el.name} type={CoreTextType.medium} color="white" />
|
||||
<div key={i} onClick={() => el.fn()}>
|
||||
<CoreText text={el.name} type={CoreTextType.medium} color="white" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
@ -56,11 +56,33 @@ export const SceneManger = observer(() => {
|
|||
<CoreButton text="Добавить" filled={true} />
|
||||
</span>
|
||||
</Popover>
|
||||
<div style={{ position: "relative" }}>
|
||||
<div style={{ position: "absolute" }}>
|
||||
<div style={{ position: "relative", left: 20 }}>
|
||||
{store.sceneHelperInstruments.map((el, i) => (
|
||||
<div
|
||||
key={i}
|
||||
onClick={() => el.onClick()}
|
||||
style={{
|
||||
marginTop: 4,
|
||||
width: 50,
|
||||
height: 50,
|
||||
backgroundColor: el.isSelected ? "rgba(160, 132, 255, 1)" : "rgba(99, 81, 159, 1)",
|
||||
border: "1px solid",
|
||||
borderRadius: 5,
|
||||
}}
|
||||
>
|
||||
<Icon type={el.icon} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ height: 10 }} />
|
||||
<div
|
||||
style={{
|
||||
borderRadius: 22,
|
||||
borderRadius: 7,
|
||||
height: 200,
|
||||
width: "-webkit-fill-available",
|
||||
backgroundColor: "white",
|
||||
|
@ -71,15 +93,29 @@ export const SceneManger = observer(() => {
|
|||
<div
|
||||
key={index}
|
||||
style={{
|
||||
paddingLeft: 20,
|
||||
display: "flex",
|
||||
backgroundColor: index.isEven() ? "rgba(217, 217, 217, 0.27)" : "",
|
||||
backgroundColor: el.isSelected
|
||||
? "rgba(104, 80, 164, 0.47)"
|
||||
: index.isEven()
|
||||
? "rgba(217, 217, 217, 0.27)"
|
||||
: "",
|
||||
alignItems: "center",
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
width: "100%",
|
||||
}}
|
||||
onClick={() => store.selectSceneItems(el.name, index, !el.isSelected)}
|
||||
>
|
||||
<Icon type={el.icon} />
|
||||
<Icon width={13} height={13} type={el.icon} style={{ marginLeft: 10 }} />
|
||||
<div style={{ width: 10 }} />
|
||||
<CoreText text={el.name} type={CoreTextType.small} />
|
||||
<Icon
|
||||
type="DeleteCircle"
|
||||
width={13}
|
||||
height={13}
|
||||
onClick={() => store.deleteSceneItem(el)}
|
||||
style={{ marginRight: 10 }}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
@ -92,12 +128,12 @@ export const SceneManger = observer(() => {
|
|||
borderRadius: 7,
|
||||
backgroundColor: "white",
|
||||
margin: 10,
|
||||
|
||||
overflow: "auto",
|
||||
}}
|
||||
>
|
||||
{sceneManagerForms(store.activeFormDependency ?? {}, store).map((el) => {
|
||||
{sceneManagerForms(store.activeFormDependency ?? {}, store).map((el, i) => {
|
||||
if (el.name.isEqual(store.activeFormType ?? "")) {
|
||||
return <>{el.component}</>;
|
||||
return <span key={i}>{el.component}</span>;
|
||||
}
|
||||
return <></>;
|
||||
})}
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
import makeAutoObservable from "mobx-store-inheritance";
|
||||
import { Object3D, Object3DEventMap, Vector2 } from "three";
|
||||
import { message } from "antd";
|
||||
import { CoreThreeRepository } from "../../../core/repository/core_three_repository";
|
||||
import { Object3D, Vector2 } from "three";
|
||||
import { HttpError } from "../../../core/repository/http_repository";
|
||||
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_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";
|
||||
import { SolidBodyViewModel } from "./forms/solid_body/solid_body_view_model";
|
||||
import { SolidBodyModel } from "../model/solid_body_model";
|
||||
|
||||
export enum DrawersSceneManager {
|
||||
NewScene = "Новая сцена",
|
||||
|
@ -20,6 +22,13 @@ export enum StoreMode {
|
|||
sceneInstance = "sceneInstance",
|
||||
allScenes = "allScenes",
|
||||
}
|
||||
export interface ISolidSpawnHelper {
|
||||
url: string;
|
||||
solidType: string;
|
||||
name: string;
|
||||
isFinished: boolean;
|
||||
type: string;
|
||||
}
|
||||
interface IPopoverItem {
|
||||
name: string;
|
||||
fn: Function;
|
||||
|
@ -27,18 +36,12 @@ interface IPopoverItem {
|
|||
interface SceneItems {
|
||||
fn: Function;
|
||||
name: string;
|
||||
isSelected: boolean;
|
||||
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;
|
||||
selectedItemName?: string;
|
||||
activeFormDependency?: Object;
|
||||
viewModel: SceneViewModel = SceneViewModel.empty();
|
||||
sceneMode: SceneMode;
|
||||
|
@ -55,19 +58,79 @@ export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpErro
|
|||
scenes: SceneModel[] = [];
|
||||
storeMode: StoreMode;
|
||||
canvasRef?: HTMLCanvasElement;
|
||||
mousePositionAwait: boolean = false;
|
||||
mousePosition?: Vector2;
|
||||
solidSpawnHelper?: ISolidSpawnHelper;
|
||||
selectSceneObject?: Object;
|
||||
isLoadingForm: boolean = false;
|
||||
scene: SolidBodyModel[] = [];
|
||||
|
||||
sceneHelperInstruments: { icon: string; onClick: Function; isSelected: boolean }[] = [
|
||||
{ icon: SceneMode.Select, onClick: () => this.setMode(SceneMode.Select), isSelected: false },
|
||||
{ icon: SceneMode.Move, onClick: () => this.setMode(SceneMode.Move), isSelected: false },
|
||||
{ icon: SceneMode.Rotate, onClick: () => this.setMode(SceneMode.Rotate), isSelected: false },
|
||||
{
|
||||
icon: SceneMode.Save,
|
||||
onClick: () => {
|
||||
this.setMode(SceneMode.Rotate);
|
||||
this.sceneSave();
|
||||
},
|
||||
isSelected: false,
|
||||
},
|
||||
];
|
||||
popoverItems: IPopoverItem[] = [
|
||||
{ name: "Камера", fn: () => this.createNewForm(SceneManagerForms.camera) },
|
||||
{ name: "Твердое тело", fn: () => this.createNewForm(SceneManagerForms.solidBody) },
|
||||
{ name: "Источник света", fn: () => this.createNewForm(SceneManagerForms.light) },
|
||||
{ name: "Робот", fn: () => this.createNewForm(SceneManagerForms.robot) },
|
||||
{ name: "Точка", fn: () => this.createNewForm(SceneManagerForms.point) },
|
||||
{ name: "Траектория", fn: () => this.createNewForm(SceneManagerForms.trajectory) },
|
||||
{ name: "Зона", fn: () => this.createNewForm(SceneManagerForms.zone) },
|
||||
];
|
||||
constructor() {
|
||||
super(DrawersSceneManager);
|
||||
makeAutoObservable(this);
|
||||
this.sceneItems = [];
|
||||
this.sceneHttpRepository = new SceneHttpRepository();
|
||||
this.sceneMode = SceneMode.EMPTY;
|
||||
this.sceneMode = SceneMode.Select;
|
||||
this.sceneMenu = SceneMenu.empty();
|
||||
}
|
||||
createNewForm = (formType: SceneManagerForms, dependency: Object) => {
|
||||
this.activeFormDependency = dependency;
|
||||
sceneSave = () => {};
|
||||
selectSceneItems = (name: string, index: number, selected: boolean) => {
|
||||
this.sceneItems.map((el, i) => i.isEqualR(index).map(() => (el.isSelected = selected)));
|
||||
if (selected) {
|
||||
this.createNewForm(SceneManagerForms.solidBody);
|
||||
this.selectedItemName = name;
|
||||
}
|
||||
|
||||
if (!selected) {
|
||||
this.createNewForm(undefined);
|
||||
this.selectedItemName = undefined;
|
||||
}
|
||||
|
||||
this.activeFormDependency = {
|
||||
type: "Preview",
|
||||
name: name,
|
||||
};
|
||||
};
|
||||
|
||||
setMode = (mode: SceneMode) => {
|
||||
this.sceneHelperInstruments.map((el) => {
|
||||
el.isSelected = false;
|
||||
if (el.icon.isEqual(mode)) {
|
||||
el.isSelected = true;
|
||||
}
|
||||
});
|
||||
this.sceneMode = mode;
|
||||
this.coreThreeRepository?.setTransformMode(this.sceneMode);
|
||||
this.sceneModeWatcher();
|
||||
};
|
||||
createNewForm = (formType: SceneManagerForms | undefined) => {
|
||||
this.activeFormDependency = {
|
||||
store: this,
|
||||
};
|
||||
this.activeFormType = formType;
|
||||
};
|
||||
makeSolid = () => {};
|
||||
createNewScene = () =>
|
||||
this.viewModel.valid().fold(
|
||||
async (s) => {
|
||||
|
@ -78,12 +141,11 @@ export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpErro
|
|||
async (e) => message.error(e)
|
||||
);
|
||||
|
||||
deleteSceneItem(item: BaseSceneItemModel) {
|
||||
const itm = this.sceneModels.filter((el) => el.id === item.id);
|
||||
this.coreThreeRepository!.deleteSceneItem(itm[0]);
|
||||
this.sceneModels = this.sceneModels.filter((el) => el.name !== item.name);
|
||||
deleteSceneItem = (item: SceneItems) => {
|
||||
this.sceneItems = this.sceneItems.filter((el) => !el.name.isEqual(item.name));
|
||||
this.coreThreeRepository?.deleteSceneItem(item.name);
|
||||
this.visibleSaveButton();
|
||||
}
|
||||
};
|
||||
|
||||
visibleSaveButton = () => {
|
||||
this.isVisibleSaveButton = true;
|
||||
|
@ -92,7 +154,8 @@ export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpErro
|
|||
addNewCamera = (model: CameraViewModel) => {
|
||||
model.position = this.coreThreeRepository!.camera.position;
|
||||
model.quaternion = this.coreThreeRepository!.camera.quaternion;
|
||||
this.sceneItems.push({ name: model.cameraLink, icon: "Camera", fn: () => {} });
|
||||
this.sceneItems.push({ name: model.cameraLink, icon: "Camera", fn: () => {}, isSelected: false });
|
||||
|
||||
this.coreThreeRepository?.addSceneCamera(model);
|
||||
this.visibleSaveButton();
|
||||
};
|
||||
|
@ -117,7 +180,7 @@ export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpErro
|
|||
} catch (error) {
|
||||
message.error(String(error));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
isRenderedAsset(name: string): boolean {
|
||||
return this.sceneModels
|
||||
|
@ -130,19 +193,7 @@ export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpErro
|
|||
.isNotEmpty();
|
||||
}
|
||||
|
||||
hiddenMenu() {
|
||||
this.isSceneMenuShow = false;
|
||||
}
|
||||
|
||||
setSceneMode = (mode: SceneMode) => {
|
||||
if (this.sceneMode === undefined || this.sceneMode !== mode) {
|
||||
this.sceneMode = mode;
|
||||
} else if (this.sceneMode === mode) {
|
||||
this.sceneMode = SceneMode.EMPTY;
|
||||
}
|
||||
this.coreThreeRepository?.setTransformMode(this.sceneMode);
|
||||
this.sceneModeWatcher();
|
||||
};
|
||||
hiddenMenu = () => (this.isSceneMenuShow = false);
|
||||
|
||||
sceneModeWatcher() {}
|
||||
|
||||
|
@ -155,20 +206,19 @@ export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpErro
|
|||
this.mapOk("scenes", this.sceneHttpRepository.getAllScenes());
|
||||
}
|
||||
};
|
||||
errorHandingStrategy = (error: HttpError) => {
|
||||
if (error.status === 404) {
|
||||
this.errors.push(new UiBaseError(`${RobossemblerFiles.robossemblerAssets} not found to project`));
|
||||
}
|
||||
};
|
||||
errorHandingStrategy = (error: HttpError) =>
|
||||
error.status
|
||||
.isEqualR(404)
|
||||
.map(() => this.errors.push(new UiBaseError(`${RobossemblerFiles.robossemblerAssets} not found to project`)));
|
||||
|
||||
async loadScene(canvasRef: HTMLCanvasElement) {
|
||||
loadScene = (canvasRef: HTMLCanvasElement) => {
|
||||
this.canvasRef = canvasRef;
|
||||
if (this.storeMode.isEqual(StoreMode.sceneInstance)) this.loadWebGl(canvasRef);
|
||||
this.storeMode.isEqualR(StoreMode.sceneInstance).map(() => this.loadWebGl(canvasRef));
|
||||
// await this.mapOk<RobossemblerAssets>("robossemblerAssets", this.sceneHttpRepository.getRobossemblerAssets());
|
||||
// if (this.robossemblerAssets) {
|
||||
// this.coreThreeRepository?.loadInstances(this.robossemblerAssets);
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
loadWebGl(canvasRef: HTMLCanvasElement): void {
|
||||
this.coreThreeRepository = new CoreThreeRepository(canvasRef as HTMLCanvasElement, this.watcherSceneEditorObject);
|
||||
|
@ -176,56 +226,80 @@ export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpErro
|
|||
this.coreThreeRepository.render();
|
||||
this.sceneModels = this.coreThreeRepository.getAllSceneModels();
|
||||
|
||||
window.addEventListener("click", (event) => this.clickLister(event));
|
||||
window.addEventListener("mousedown", (e) => this.sceneContextMenu(e));
|
||||
canvasRef.addEventListener("click", (event) => this.clickLister(event, canvasRef.getBoundingClientRect().x));
|
||||
|
||||
canvasRef.addEventListener("mousedown", (e) => this.sceneContextMenu(e));
|
||||
}
|
||||
|
||||
clickLister(event: MouseEvent) {
|
||||
clickLister = (event: MouseEvent, offset: number = 0) => {
|
||||
const vector = new Vector2();
|
||||
vector.x = (event.clientX / window.innerWidth) * 2 - 1;
|
||||
vector.y = -(event.clientY / window.innerHeight) * 2 + 1;
|
||||
if (this.sceneMode === SceneMode.EMPTY) {
|
||||
const boundingRect = this.canvasRef!.getBoundingClientRect();
|
||||
|
||||
vector.x = ((event.clientX - offset) / boundingRect.width) * 2 - 1;
|
||||
vector.y = -(event.clientY / boundingRect.height) * 2 + 1;
|
||||
if (this.mousePositionAwait && this.solidSpawnHelper) {
|
||||
this.mousePositionAwait = false;
|
||||
this.mousePosition = vector;
|
||||
this.coreThreeRepository?.setRayCastAndGetFirstObjectAndPointToObject(vector).map((v3) => {
|
||||
this.coreThreeRepository?.solidSpawn(
|
||||
this.solidSpawnHelper as ISolidSpawnHelper,
|
||||
(obj: Object3D<Object3DEventMap> | undefined) => {
|
||||
const { solidType, name, url } = this.solidSpawnHelper as ISolidSpawnHelper;
|
||||
this.scene.push(new SolidBodyModel(obj!.quaternion, obj!.position, name, solidType, url, url));
|
||||
this.sceneItems.push({
|
||||
name: String(this.solidSpawnHelper?.name),
|
||||
icon: "Solid",
|
||||
isSelected: false,
|
||||
fn: () => this.createNewForm(SceneManagerForms.solidBody),
|
||||
});
|
||||
},
|
||||
v3
|
||||
);
|
||||
});
|
||||
}
|
||||
if (this.sceneMode.isEqual(SceneMode.Select)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.sceneMode === SceneMode.MOVING || this.sceneMode === SceneMode.ROTATE) {
|
||||
if (this.sceneMode === SceneMode.Move || this.sceneMode === SceneMode.Rotate) {
|
||||
this.transformContollsCall(vector);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
sceneContextMenu(e: MouseEvent): void {
|
||||
if (e.button === 2) {
|
||||
sceneContextMenu = (e: MouseEvent) =>
|
||||
e.button.isEqualR(2).map(() => {
|
||||
this.isSceneMenuShow = true;
|
||||
this.sceneMenu.x = e.clientX;
|
||||
this.sceneMenu.y = e.clientY;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
watcherThereObjects = (sceneItemModel: BaseSceneItemModel): void => {
|
||||
this.sceneModels.push(sceneItemModel);
|
||||
watcherThereObjects = (sceneItemModel: BaseSceneItemModel) => {
|
||||
// this.sceneModels.push(sceneItemModel);
|
||||
console.log(sceneItemModel);
|
||||
};
|
||||
|
||||
watcherSceneEditorObject = (mesh: Object3D) => {
|
||||
this.sceneModels = this.sceneModels.map((el) => {
|
||||
if (el.name === mesh.name) {
|
||||
el.position = mesh.position;
|
||||
el.quaternion = mesh.quaternion;
|
||||
return el;
|
||||
}
|
||||
return el;
|
||||
});
|
||||
this.scene = this.scene.map((el) =>
|
||||
el.name.isEqualR(mesh.name).fold(
|
||||
() => {
|
||||
el.vector3 = mesh.position;
|
||||
el.quaternion = mesh.quaternion;
|
||||
return el;
|
||||
},
|
||||
() => el
|
||||
)
|
||||
);
|
||||
this.visibleSaveButton();
|
||||
};
|
||||
|
||||
transformContollsCall = (vector: Vector2) => {
|
||||
transformContollsCall = (vector: Vector2) =>
|
||||
this.coreThreeRepository?.setRayCastAndGetFirstObject(vector).fold(
|
||||
(success) => this.coreThreeRepository?.setTransformControlsAttach(success),
|
||||
(_error) => this.coreThreeRepository?.disposeTransformControlsMode()
|
||||
(object) => this.coreThreeRepository?.setTransformControlsAttach(object),
|
||||
(_) => this.coreThreeRepository?.disposeTransformControlsMode()
|
||||
);
|
||||
};
|
||||
|
||||
dispose() {
|
||||
dispose = () => {
|
||||
window.removeEventListener("click", this.clickLister);
|
||||
window.removeEventListener("mousedown", (e) => this.sceneContextMenu(e));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue