everything but light

This commit is contained in:
IDONTSUDO 2024-10-13 21:52:55 +03:00
parent 139f012803
commit 1cc489fc72
17 changed files with 206 additions and 132 deletions

View file

@ -4,6 +4,7 @@ export enum StaticFilesProject {
parts = "/assets/parts.json", parts = "/assets/parts.json",
scenes = "/scenes/", scenes = "/scenes/",
behaviorTrees = "behavior_trees", behaviorTrees = "behavior_trees",
robots = 'robots'
} }
export enum StaticFilesServer { export enum StaticFilesServer {

View file

@ -1,25 +1,45 @@
import { CallbackStrategyWithValidationModel, ResponseBase } from "../../../core/controllers/http_controller"; import { CallbackStrategyWithValidationModel, ResponseBase } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result"; import { Result } from "../../../core/helpers/result";
import { RobotModel } from "../model/robot_model"; import { RobotModel } from "../model/robot_model";
import { StaticFilesProject } from "../../../core/models/static_files";
import { GetServerAddressUseCase } from "../../../core/usecases/get_server_address_usecase"; import { GetServerAddressUseCase } from "../../../core/usecases/get_server_address_usecase";
import { SearchManyDataBaseModelUseCase } from "../../../core/usecases/search_many_database_model_usecase"; import { SearchManyDataBaseModelUseCase } from "../../../core/usecases/search_many_database_model_usecase";
import { IProjectModel, ProjectDBModel } from "../../projects/models/project_model_database_model"; import { IProjectModel, ProjectDBModel } from "../../projects/models/project_model_database_model";
import { ExecProcessUseCase } from "../../../core/usecases/exec_process_usecase"; import { ExecProcessUseCase } from "../../../core/usecases/exec_process_usecase";
import { StaticFilesProject } from "../../../core/models/static_files";
export class CreateRobotScenario extends CallbackStrategyWithValidationModel<RobotModel> { export class CreateRobotScenario extends CallbackStrategyWithValidationModel<RobotModel> {
validationModel: RobotModel = new RobotModel(); validationModel: RobotModel = new RobotModel();
call = async (model: RobotModel): ResponseBase => ( call = async (model: RobotModel): ResponseBase =>
await new SearchManyDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call( (
{ isActive: true }, await new SearchManyDataBaseModelUseCase<IProjectModel>(ProjectDBModel).call(
"is dont active projects" { isActive: true },
) "is dont active projects"
).map(async (projectModel) => { )
const { rootDir } = projectModel[0]; ).map((projectModel) => {
rootDir + '/robots/' const { rootDir } = projectModel[0];
console.log(
return Result.ok([]) `python3 $PYTHON_ROBOT_BUILDER --path ${
}); projectModel[0].rootDir + "/" + StaticFilesProject.robots + "/"
} --name ${model.name} --nDOF ${model.nDof} --toolType ${model.toolType}`
);
return new GetServerAddressUseCase().call().map(async (serverAddress) =>
(
await new ExecProcessUseCase().call(
rootDir,
`python3 $PYTHON_ROBOT_BUILDER --path ${
projectModel[0].rootDir + "/" + StaticFilesProject.robots + "/"
} --name ${model.name} --nDOF ${model.nDof} --toolType ${model.toolType}`,
""
)
).map((log) =>
Result.ok({
robotUrl: `${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]
}/${StaticFilesProject.robots}/${model.name}/robot.xml`,
})
)
);
});
} }
// PYTHON_ROBOT_BUILDER

View file

@ -18,3 +18,14 @@ export const useStore = <S extends LifeCycleStore>(storeConstructor: ClassConstr
}, []); }, []);
return store; return store;
}; };
export const useStoreClass = <S extends LifeCycleStore>(storeClass: S) => {
const [store] = React.useState(storeClass);
const navigate = useNavigate();
React.useEffect(() => {
store?.init?.(navigate);
return () => {
store?.dispose?.();
};
}, []);
return store;
};

View file

@ -141,3 +141,5 @@ export class CoreHttpRepository extends HttpRepository {
} }
getAllScenes = () => this._jsonRequest<SceneModel[]>(HttpMethod.GET, "/scenes"); getAllScenes = () => this._jsonRequest<SceneModel[]>(HttpMethod.GET, "/scenes");
} }
["", "", ""].map((el) => el.toLowerCase()).map((el) => el != "");
["", "", ""].map((el) => el.toLowerCase()).filter((el) => el != "");

View file

@ -127,3 +127,16 @@ export abstract class FormState<V, E> extends UiErrorState<E> {
this.viewModel = plainToInstance(instance, viewModel); this.viewModel = plainToInstance(instance, viewModel);
}; };
} }
abstract class Foo {
abstract init?(): void;
}
interface Foo1 {
init?(param1: number | undefined): void;
}
class Bar implements Foo1 {}
export interface LifeCycleStore {
init?(navigate?: NavigateFunction | undefined): void;
dispose?(): void;
}
class VVV implements LifeCycleStore {}

View file

@ -28,6 +28,13 @@ export const CoreInput = (props: IInputProps) => {
setAppendInnerText(false); setAppendInnerText(false);
} }
}, [ref, value, isAppendInnerText, setAppendInnerText, props]); }, [ref, value, isAppendInnerText, setAppendInnerText, props]);
React.useEffect(() => {
if (ref.current && props.value) {
ref.current.innerText = value;
setValue(props.value);
console.log(props.value);
}
}, [props.value]);
const isSmall = props.type !== undefined && props.type.isEqual(CoreInputType.small); const isSmall = props.type !== undefined && props.type.isEqual(CoreInputType.small);
return ( return (
<div <div

View file

@ -25,15 +25,12 @@ export const CoreInputNumber = (props: IInputProps) => {
setAppendInnerText(false); setAppendInnerText(false);
} }
}, [ref, value, isAppendInnerText, setAppendInnerText, props]); }, [ref, value, isAppendInnerText, setAppendInnerText, props]);
React.useEffect(() => {
if (props.value) setValue(props.value);
}, [props.value]);
return ( return (
<> <>
{/* <div style={{ position: "absolute" }}>
<div style={{ width: width, display: "flex", justifyContent: "flex-end" }}>
<Icon type="Plus" />
<Icon type="Minus" />
</div>
</div> */}
<div <div
style={Object.assign( style={Object.assign(
{ {

View file

@ -10,18 +10,18 @@ interface IToggleProps {
export const Toggle = (props: IToggleProps) => { export const Toggle = (props: IToggleProps) => {
const [isOpen, setOpen] = useState(props.isOpen); const [isOpen, setOpen] = useState(props.isOpen);
return ( return (
<div style={{ border: "1px black solid" }}> <div style={{ border: "1px black solid", height: "max-content",width:"100%" }}>
<div <div
style={{ style={{
display: "flex", display: "flex",
justifyContent: "space-between", justifyContent: "space-between",
margin: 0, margin: 0,
padding:5, padding: 5,
alignItems: "center", alignItems: "center",
}} }}
onClick={() => setOpen(!isOpen)} onClick={() => setOpen(!isOpen)}
> >
<CoreText style={{ height: 33 }} text={props.name} type={CoreTextType.large} /> <CoreText text={props.name} type={CoreTextType.large} />
<Icon type="PlusCircle" style={{ width: 33 }} /> <Icon type="PlusCircle" style={{ width: 33 }} />
</div> </div>
{isOpen ? props.child : <></>} {isOpen ? props.child : <></>}

View file

@ -10,7 +10,7 @@ export class RobotDeviceFormStore extends FormState<SidViewModel, CoreError> {
makeAutoObservable(this); makeAutoObservable(this);
} }
viewModel: SidViewModel = SidViewModel.empty(); viewModel: SidViewModel = SidViewModel.empty();
cameraDeviceHttpRepository: RobotDeviceFormHttpRepository = new RobotDeviceFormHttpRepository(); robotDeviceFormHttpRepository: RobotDeviceFormHttpRepository = new RobotDeviceFormHttpRepository();
errorHandingStrategy = (error: CoreError) => { } errorHandingStrategy = (error: CoreError) => { }
init = async (navigate?: NavigateFunction | undefined) => { init = async (navigate?: NavigateFunction | undefined) => {

View file

@ -10,7 +10,7 @@ export const CoordsForm = ({ store, update }: { store: FormState<any, any>; upda
<Toggle <Toggle
name={"Координаты"} name={"Координаты"}
child={ child={
<div style={{margin:10}}> <div >
<CoreText text="Позиция" type={CoreTextType.header} /> <CoreText text="Позиция" type={CoreTextType.header} />
<CoreInput <CoreInput

View file

@ -7,69 +7,83 @@ import { CoreSelect } from "../../../../../core/ui/select/select";
import { CameraFormStore } from "./camera_store"; import { CameraFormStore } from "./camera_store";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { CameraTypes } from "../../../../../core/model/camera_model"; import { CameraTypes } from "../../../../../core/model/camera_model";
import { useStoreClass } from "../../../../../core/helper/use_store";
import { CoordsForm } from "../../components/coords_form";
import { Toggle } from "../../../../../core/ui/toggle/toggle";
export const CameraForm = observer((props: IDefaultSceneManagerFormProps) => { export const CameraForm = observer((props: IDefaultSceneManagerFormProps) => {
const [store] = React.useState(() => new CameraFormStore(props.store)); const store = useStoreClass(new CameraFormStore(props.store));
return (
React.useEffect(() => { <div style={{ overflowY: "auto", height: "100%" }}>
store.init();
}, []); <Toggle
return ( name={"Настройки камеры"}
<div style={{ margin: 10, padding: 10, overflowY: "auto", height: "100%" }}> isOpen={false}
<CoreText text="Камера" type={CoreTextType.header} /> child={
<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
<CoreInput value={store.viewModel.topic}
value={String(store.viewModel.updateRate)} label={"Топик"}
validation={(text) => Number().isValid(text)} onChange={(text) => store.updateForm({ topic: text })}
label={"Update Rate"} />
onChange={(text) => store.updateForm({ updateRate: Number(text) })} <CoreInput
/> value={store.viewModel.name}
<CoreInput label={"Имя"}
value={String(store.viewModel.height)} onChange={(text) => store.updateForm({ name: text })}
validation={(text) => Number().isValid(text)} />
label={"Height"} <CoreInput
onChange={(text) => store.updateForm({ height: Number(text) })} value={String(store.viewModel.updateRate)}
/> validation={(text) => Number().isValid(text)}
<CoreInput label={"Update Rate"}
value={String(store.viewModel.width)} onChange={(text) => store.updateForm({ updateRate: Number(text) })}
validation={(text) => Number().isValid(text)} />
label={"Width"} <CoreInput
onChange={(text) => store.updateForm({ width: Number(text) })} value={String(store.viewModel.height)}
/> validation={(text) => Number().isValid(text)}
<CoreInput label={"Height"}
value={String(store.viewModel.fov)} onChange={(text) => store.updateForm({ height: Number(text) })}
label={"Fov"} />
validation={(text) => Number().isValid(text)} <CoreInput
onChange={(text) => (store.updateForm({ fov: Number(text) }), store.updateCameraScene())} value={String(store.viewModel.width)}
/> validation={(text) => Number().isValid(text)}
<CoreInput label={"Width"}
value={String(store.viewModel.far)} onChange={(text) => store.updateForm({ width: Number(text) })}
label={"Far"} />
validation={(text) => Number().isValid(text)} <CoreInput
onChange={(text) => (store.updateForm({ far: Number(text) }), store.updateCameraScene())} value={String(store.viewModel.fov)}
/> label={"Fov"}
<CoreInput validation={(text) => Number().isValid(text)}
value={String(store.viewModel.near)} onChange={(text) => (store.updateForm({ fov: Number(text) }), store.updateCameraScene())}
label={"Near"} />
validation={(text) => Number().isValid(text)} <CoreInput
onChange={(text) => (store.updateForm({ near: Number(text) }), store.updateCameraScene())} value={String(store.viewModel.far)}
/> label={"Far"}
validation={(text) => Number().isValid(text)}
<CoreSelect onChange={(text) => (store.updateForm({ far: Number(text) }), store.updateCameraScene())}
items={Object.entries(CameraTypes).map(([_, v]) => v)} />
value={store.viewModel.cameraType} <CoreInput
label={"Тип камеры"} value={String(store.viewModel.near)}
onChange={(text) => store.updateForm({ cameraType: text as CameraTypes })} label={"Near"}
validation={(text) => Number().isValid(text)}
onChange={(text) => (store.updateForm({ near: Number(text) }), store.updateCameraScene())}
/>
<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 }} /> <div style={{ height: 10 }} />
<CoordsForm store={store} update={() => store.updateCameraScene()} />
<div style={{ height: 10 }} />
{store.type !== "preview" ? ( {store.type !== "preview" ? (
<CoreButton text="Создать" style={{ width: 96 }} onClick={() => store.clickNewCamera()} /> <CoreButton text="Создать" style={{ width: 96 }} onClick={() => store.clickNewCamera()} />
) : null} ) : null}
<div style={{ height: 50 }} /> <div style={{ height: 50 }} />
</div> </div>
); );
}); });

View file

@ -36,6 +36,7 @@ export class CameraFormStore extends FormState<CameraModel, CoreError> {
.rFind<CameraModel>((el) => el.name.isEqual(this.sceneBuilderStore.selectedItemName ?? "")) .rFind<CameraModel>((el) => el.name.isEqual(this.sceneBuilderStore.selectedItemName ?? ""))
.fold( .fold(
(cameraModel) => { (cameraModel) => {
console.log(200)
this.loadDependency(cameraModel); this.loadDependency(cameraModel);
this.type = "preview"; this.type = "preview";
}, },

View file

@ -7,21 +7,18 @@ import { CoreInputNumber } from "../../../../../core/ui/inputNumber/input_number
import { CoreInput, CoreInputType } from "../../../../../core/ui/input/input"; import { CoreInput, CoreInputType } from "../../../../../core/ui/input/input";
import { match } from "ts-pattern"; import { match } from "ts-pattern";
import { CoreSelect } from "../../../../../core/ui/select/select"; import { CoreSelect } from "../../../../../core/ui/select/select";
import { ToolTypes } from "../../../../../core/model/robot_model"; import { RobotModel, ToolTypes } from "../../../../../core/model/robot_model";
import { CoreButton } from "../../../../../core/ui/button/button"; import { CoreButton } from "../../../../../core/ui/button/button";
import { SpawnPositionTypesForm } from "../../components/spawn_position_types"; import { SpawnPositionTypesForm } from "../../components/spawn_position_types";
import { CoordsForm } from "../../components/coords_form"; import { CoordsForm } from "../../components/coords_form";
import { useStoreClass } from "../../../../../core/helper/use_store";
import { Toggle } from "../../../../../core/ui/toggle/toggle";
export const RobotForm = observer((props: IDefaultSceneManagerFormProps) => { export const RobotForm = observer((props: IDefaultSceneManagerFormProps) => {
const [store] = React.useState(() => new RobotFormStore(props.store)); const store = useStoreClass(new RobotFormStore(props.store));
React.useEffect(() => {
store.init();
return () => {
store.dispose();
};
}, []);
return ( return (
<div style={{ overflowY: "scroll", height: "100%" }}> <div style={{ overflowY: "auto", height: "100%" }}>
{match(store.storeType) {match(store.storeType)
.with(RobotStoreType.awaitMouseClick, () => ( .with(RobotStoreType.awaitMouseClick, () => (
<> <>
@ -59,37 +56,44 @@ export const RobotForm = observer((props: IDefaultSceneManagerFormProps) => {
)) ))
.with(RobotStoreType.previewRobot, () => ( .with(RobotStoreType.previewRobot, () => (
<> <>
<CoreText text="Управление соединениями" type={CoreTextType.small} /> <Toggle
{store.viewModel.jointPosition.map((el, i) => ( name={"Управление соединениями"}
<div> child={
<CoreInputNumber <>
key={i} {store.viewModel.jointPosition.map((el, i) => (
step={0.1} <div>
max={Number(el.limit.upper)} <CoreInputNumber
min={Number(el.limit.lower)} key={i}
value={0} step={0.1}
onChange={(value) => ( max={Number(el.limit.upper)}
store.updateForm({ min={Number(el.limit.lower)}
jointPosition: store.viewModel.jointPosition.map((element, index) => value={el.angle}
index.isEqualR(i).fold( onChange={(value) => (
() => { store.updateForm({
element.angle = value; jointPosition: store.viewModel.jointPosition.map((element, index) =>
return element; index.isEqualR(i).fold(
}, () => {
() => element element.angle = value;
) return element;
), },
}), () => element
store.updateScene() )
)} ),
label={el.name} }),
/> store.updateScene()
</div> )}
))} label={el.name}
<div style={{ height: 40 }} /> />
</div>
))}
</>
}
isOpen={false}
/>
<div style={{ height: 10 }} />
<CoordsForm store={store} update={() => store.updateScene()} /> <CoordsForm store={store} update={() => store.updateScene()} />
<div style={{ height: 40 }} /> <div style={{ height: 40 }} />
</> </>
)) ))
.otherwise(() => ( .otherwise(() => (

View file

@ -75,8 +75,8 @@ export class RobotFormStore extends FormState<RobotModel, CoreError> {
this.sceneBuilderStore.scene this.sceneBuilderStore.scene
.rFind<RobotModel>((el) => el.name.isEqual(this.sceneBuilderStore.selectedItemName ?? "")) .rFind<RobotModel>((el) => el.name.isEqual(this.sceneBuilderStore.selectedItemName ?? ""))
.fold( .fold(
(solidBodyModel) => { (robotModel) => {
this.loadDependency(solidBodyModel); this.loadDependency(robotModel);
this.storeType = RobotStoreType.previewRobot; this.storeType = RobotStoreType.previewRobot;
}, },
() => () =>

View file

@ -8,22 +8,29 @@ import { match } from "ts-pattern";
import { SpawnPositionTypesForm } from "../../components/spawn_position_types"; import { SpawnPositionTypesForm } from "../../components/spawn_position_types";
import { CoreInput } from "../../../../../core/ui/input/input"; import { CoreInput } from "../../../../../core/ui/input/input";
import { CoordsForm } from "../../components/coords_form"; import { CoordsForm } from "../../components/coords_form";
import { useStoreClass } from "../../../../../core/helper/use_store";
import { Toggle } from "../../../../../core/ui/toggle/toggle";
export const SolidBodyForm = observer((props: IDefaultSceneManagerFormProps) => { export const SolidBodyForm = observer((props: IDefaultSceneManagerFormProps) => {
const [store] = React.useState(() => new SolidBodyStore(props.store)); const store = useStoreClass(new SolidBodyStore(props.store));
React.useEffect(() => {
store.init();
}, []);
return ( return (
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", overflow: "auto", height: "100%" }}> <div style={{ display: "flex", flexDirection: "column", alignItems: "center", overflow: "auto", height: "100%",width:'100%' }}>
<> <>
{match(store.solidBodyStoreType) {match(store.solidBodyStoreType)
.with(SolidBodyStoreType.previewSolid, () => ( .with(SolidBodyStoreType.previewSolid, () => (
<> <>
<CoreText text={"Твердое тело"} type={CoreTextType.header} /> <Toggle
name={"Настройки твердого тела"}
child={
<>
<CoreText text={"Тип твердого тела: " + store.viewModel.solidType} type={CoreTextType.header} />
</>
}
isOpen={false}
/>
<div style={{height:10}}/>
<CoordsForm store={store} update={store.updateBodySimulation} /> <CoordsForm store={store} update={store.updateBodySimulation} />
<CoreText text={"Тип твердого тела: " + store.viewModel.solidType} type={CoreTextType.header} />
</> </>
)) ))
.with(SolidBodyStoreType.selectBody, () => ( .with(SolidBodyStoreType.selectBody, () => (

View file

@ -1,4 +1,3 @@
import { message } from "antd";
import makeAutoObservable from "mobx-store-inheritance"; import makeAutoObservable from "mobx-store-inheritance";
import { Vector2, Vector3, Object3D } from "three"; import { Vector2, Vector3, Object3D } from "three";
import { CameraModel } from "../../../core/model/camera_model"; import { CameraModel } from "../../../core/model/camera_model";

View file

@ -1,16 +1,14 @@
import * as React from "react"; import * as React from "react";
import { DrawersSceneManager, SceneMangerStore } from "./scene_manager_store"; import { DrawersSceneManager, SceneMangerStore } from "./scene_manager_store";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { Drawer, Popover } from "antd"; import { Drawer } from "antd";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { MainPage } from "../../../core/ui/pages/main_page"; import { MainPage } from "../../../core/ui/pages/main_page";
import { CoreText, CoreTextType } from "../../../core/ui/text/text"; import { CoreText, CoreTextType } from "../../../core/ui/text/text";
import { CoreButton } from "../../../core/ui/button/button"; import { CoreButton } from "../../../core/ui/button/button";
import { CoreInput } from "../../../core/ui/input/input"; import { CoreInput } from "../../../core/ui/input/input";
import { DrawersDataset } from "../../dataset/dataset_store"; import { DrawersDataset } from "../../dataset/dataset_store";
import { Icon } from "../../../core/ui/icons/icons"; import { Icon } from "../../../core/ui/icons/icons";
import { sceneManagerForms } from "../../scene_builder/presentation/forms/scene_manager_forms";
import { SceneMode } from "../model/scene_view";
import { useStore } from "../../../core/helper/use_store"; import { useStore } from "../../../core/helper/use_store";
import { SceneBuilderScreenPath } from "../../scene_builder/presentation/scene_builder_screen"; import { SceneBuilderScreenPath } from "../../scene_builder/presentation/scene_builder_screen";