This commit is contained in:
IDONTSUDO 2024-11-27 19:29:49 +03:00
parent 3f951d1c09
commit 28c36ae710
31 changed files with 495 additions and 65 deletions

View file

@ -19,6 +19,7 @@
"Contolls",
"GLTF",
"grau",
"idontsudo",
"raycaster",
"skils",
"typedataset",

1
p.json
View file

@ -1 +0,0 @@
{"name": "default","collision_shape": "BOX","loc_xyz": [0, 0, 0],"rot_euler": [0,0, 0],"material_randomization": {   "specular": [0, 1],    "roughness": [0, 1],    "metallic": [0, 1],    "base_color": [        [            0,            0,            0,            1        ],        [            1,            1,            1,            1        ]    ]}}

26
server/command.json Normal file
View file

@ -0,0 +1,26 @@
{
"tensorBoard": {
"execCommand": "nix run github:nixos/nixpkgs#python312Packages.tensorboard -- --logdir ${dir_path}",
"date": null,
"status": "Fail,Ok",
"delay": 200,
"checkCommand": null,
"filter": null
},
"simulationProcess": {
"execCommand": "nix run github:nixos/nixpkgs#python312Packages.tensorboard -- --logdir ${dir_path}",
"date": null,
"status": null,
"delay": 0,
"checkCommand": null,
"filter": null
},
"btBuilderProcess": {
"execCommand": "nix run github:nixos/nixpkgs#python312Packages.tensorboard -- --logdir ${dir_path}",
"date": null,
"status": null,
"delay": 0,
"checkCommand": null,
"filter": null
}
}

View file

@ -34,6 +34,33 @@ export abstract class CallbackStrategyWithFilesUploads {
abstract call(files: File[]): ResponseBase;
}
export class SubRouter<A> implements ISubSetFeatureRouter<A> {
method: HttpMethodType;
subUrl: string;
fn:
| CallbackStrategyWithValidationModel<A>
| CallbackStrategyWithEmpty
| CallbackStrategyWithIdQuery
| CallBackStrategyWithQueryPage
| CallbackStrategyWithFileUpload
| CallbackStrategyWithFilesUploads;
constructor(
method: HttpMethodType,
subUrl: string,
fn:
| CallbackStrategyWithValidationModel<A>
| CallbackStrategyWithEmpty
| CallbackStrategyWithIdQuery
| CallBackStrategyWithQueryPage
| CallbackStrategyWithFileUpload
| CallbackStrategyWithFilesUploads
) {
this.fn = fn;
this.subUrl = subUrl;
this.method = method;
}
}
interface ISubSetFeatureRouter<A> {
method: HttpMethodType;
subUrl: string;
@ -118,7 +145,7 @@ export class CoreHttpController<V> implements ICoreHttpController {
await this.responseHelper(res, el.fn.call());
return;
}
if (el.fn instanceof CallbackStrategyWithFileUpload) {
if (req["files"] === undefined) {
res.status(400).json("need files to form-data request");

View file

@ -10,6 +10,7 @@ import { DigitalTwinsInstancePresentation } from "../../features/digital_twins_i
import { DigitalTwinsTemplatePresentation } from "../../features/digital_twins_template/digital_twins_template_presentation";
import { TopicsPresentation } from "../../features/topics/topics_presentation";
import { SkillsPresentation } from "../../features/skills/skill_presentation";
import { RunTimePresentation } from "../../features/runtime/runtime_presentation";
extensions();
@ -24,4 +25,5 @@ export const httpRoutes: Routes[] = [
new DigitalTwinsInstancePresentation(),
new TopicsPresentation(),
new SkillsPresentation(),
new RunTimePresentation(),
].map((el) => el.call());

View file

@ -41,7 +41,7 @@ export class ExecutorProgramService
await delay(300);
this.worker = worker;
const workerDataExec: WorkerDataExec = {
command: command,
execPath: this.execPath,
@ -50,6 +50,7 @@ export class ExecutorProgramService
};
worker.send(workerDataExec);
worker.on("message", (e) => {
console.log(JSON.stringify(e));
const spawnError = SpawnError.isError(e);
if (spawnError instanceof SpawnError) {
@ -60,7 +61,7 @@ export class ExecutorProgramService
const execError = ExecError.isExecError(e);
if (execError instanceof ExecError) {
execError.id = id
execError.id = id;
this.emit(Result.error(execError));
this.worker = undefined;
return;
@ -68,7 +69,7 @@ export class ExecutorProgramService
const executorResult = ExecutorResult.isExecutorResult(e);
if (executorResult instanceof ExecutorResult) {
executorResult.id = id
executorResult.id = id;
this.emit(Result.ok(executorResult));
this.worker = undefined;
return;
@ -103,7 +104,8 @@ export class ExecutorProgramService
return;
}
this.workerExecuted(command, WorkerType.SPAWN, args, id);
const commands = command.split(" ");
this.workerExecuted(commands.at(0), WorkerType.SPAWN, commands.slice(1, commands.length), id);
return;
}

View file

@ -1,7 +1,8 @@
import * as cp from "child_process";
import { CallbackStrategyWithEmpty } from "../controllers/http_controller";
import { Result } from "../helpers/result";
import { TypedEvent } from "../helpers/typed_event";
import { EXEC_TYPE, ExecError, SpawnError } from "../models/exec_error_model";
import { EXEC_EVENT, EXEC_TYPE, ExecError, SpawnError } from "../models/exec_error_model";
import { ExecutorResult } from "../models/executor_result";
import { ExecutorProgramService } from "../services/executor_program_service";
@ -26,7 +27,7 @@ export class ExecProcessUseCase {
call = async (
path: string,
command: string,
id:string,
id: string,
watcher?: TypedEvent<Result<ExecError | SpawnError, ExecutorResult>>
): Promise<Result<Error, string>> => {
try {
@ -34,7 +35,7 @@ export class ExecProcessUseCase {
executorProgramService.on((event) => {
if (watcher) watcher.emit(event);
});
executorProgramService.call(EXEC_TYPE.EXEC, command, undefined ,id);
executorProgramService.call(EXEC_TYPE.EXEC, command, undefined, id);
return Result.ok("ok");
} catch (error) {
@ -42,3 +43,38 @@ export class ExecProcessUseCase {
}
};
}
export class SpawnProcessUseCase {
call = async (
path: string,
command: string,
id: string,
watcher?: TypedEvent<Result<ExecError | SpawnError, ExecutorResult>>
): Promise<Result<Error, string>> => {
try {
const commands = command.split(" ");
const subprocess = cp.spawn(commands.at(0), commands.slice(1, commands.length), {
cwd: path,
});
const sendWatcher = (event: Buffer) => {
if (watcher) {
watcher.emit(Result.ok(new ExecutorResult(EXEC_TYPE.SPAWN, EXEC_EVENT.PROGRESS, event.toString())));
}
};
subprocess.stdout.on("data", (data) => sendWatcher(data));
subprocess.stderr.on("data", (data) => sendWatcher(data));
subprocess.on("error", (error) => {
console.error(`Ошибка: ${error.message}`);
});
subprocess.on("close", (code) => {
console.log(`Процесс завершился с кодом: ${code}`);
});
} catch (error) {
return Result.error(error);
}
};
}

View file

@ -15,8 +15,7 @@ export class ExecCalculationInstanceProcessScenario extends CallbackStrategyWith
return (await new IsHaveActiveProcessUseCase().call()).map(async () => {
const execCommand = `${model.script} --form '${JSON.stringify(
model.formBuilder
)}' --path ${model.instancePath.normalize()}`;
console.log(execCommand);
)}' --path ${model.instancePath.pathNormalize()}`;
await CalculationInstanceDBModel.findById(id).updateOne({
processStatus: "RUN",
lastProcessExecCommand: execCommand,

View file

@ -21,10 +21,13 @@ export class ExecInstanceScenario extends CallbackStrategyWithIdQuery {
await new ReadByIdDataBaseModelUseCase<IDigitalTwinsInstanceModel>(DigitalTwinsInstanceDatabaseModel).call(id)
).map(
(document) => (
console.log(JSON.stringify(document)),
console.log('DOCUMeNT PATH'),
console.log(document.instancePath.pathNormalize()),
new ExecProcessUseCase().call(
document.instancePath,
`python3 $GET_INTERFACES --path ${document.instancePath.pathNormalize()} --package '${JSON.stringify(document)}'`,
`python3 $GET_INTERFACES --path ${document.instancePath.pathNormalize()} --package '${JSON.stringify(
document
)}'`,
"",
new ExecInstanceTwinsProcessService(document.instancePath, document)
)

View file

@ -27,10 +27,11 @@ export class RobossemblerAssetsLocaleMapperScenario extends CallbackStrategyWith
)
).map(async (projectModel) => {
const { rootDir } = projectModel[0];
return (await new ReadFileAndParseJsonUseCase().call<Parts[]>(rootDir + StaticFilesProject.parts)).map(
(model) => {
return (await new ReadFileAndParseJsonUseCase().call<Parts[]>(rootDir + StaticFilesProject.parts)).map((model) =>
Result.ok(
model.map((el) => {
const assetLibsAddress = rootDir + "/libs/objects/" + el.name;
const assetLibsAddress = rootDir + "/assets/libs/objects/" + el.name;
console.log(assetLibsAddress);
el.fbx = `${assetLibsAddress}.fbx`;
el.stlUrl = `${assetLibsAddress}${el.part_path}`;
el.glUrl = `${assetLibsAddress}.glb`;
@ -38,11 +39,11 @@ export class RobossemblerAssetsLocaleMapperScenario extends CallbackStrategyWith
el.objUrl = `${assetLibsAddress}.obj`;
el.image = `${assetLibsAddress}.png`;
el.solidType = "active";
return el;
});
return Result.ok(model);
}
})
)
);
// );
});
}

View file

@ -34,8 +34,8 @@ export class RobossemblerAssetsNetworkMapperScenario extends CallbackStrategyWit
rootDir.match(new RegExp(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gm))[0] +
"/assets/";
model.map((el) => {
const assetLibsAddress = assetAddress + "libs/objects/" + el.name;
const assetLibsAddress = assetAddress + "/libs/objects/" + el.name;
console.log(assetLibsAddress);
el.stlUrl = `${assetAddress}${el.part_path}`;
el.glUrl = `${assetLibsAddress}.glb`;
el.daeUrl = `${assetLibsAddress}.dae`;

View file

@ -0,0 +1,7 @@
import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller";
export class ExecBtBuilderUseCase extends CallbackStrategyWithEmpty {
call(): ResponseBase {
throw new Error("Method not implemented.");
}
}

View file

@ -0,0 +1,21 @@
import { App } from "../../../core/controllers/app";
import { CallbackStrategyWithValidationModel, ResponseBase } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result";
import { SpawnProcessUseCase } from "../../../core/usecases/exec_process_usecase";
import { ExecProcesssss } from "../model/exec_process";
import { ProcessWatcher } from "../service/process_watcher";
import { GetCommandScenario } from "./get_command_scenario";
export class ExecSimulationUseCase extends CallbackStrategyWithValidationModel<ExecProcesssss> {
validationModel = new ExecProcesssss();
call = async (): ResponseBase =>
(await new GetCommandScenario().call("btBuilderProcess")).map((el) => {
new SpawnProcessUseCase().call(
App.staticFilesStoreDir(),
el.execCommand.replace("${dir_path}", "/Users/idontsudo/train"),
"btBuilder",
new ProcessWatcher(2000, "localhost")
);
return Result.ok("200");
});
}

View file

@ -0,0 +1,7 @@
import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller";
export class GetBtBuilderStateUseCase extends CallbackStrategyWithEmpty {
call(): ResponseBase {
throw new Error("Method not implemented.");
}
}

View file

@ -0,0 +1,14 @@
import { ReadFileAndParseJsonUseCase } from "../../../core/usecases/read_file_and_parse_json";
import { Result } from "../../../core/helpers/result";
import { Command, ExecProcess } from "../model/command";
export class GetCommandScenario {
call = async (command: string): Promise<Result<unknown, ExecProcess>> =>
(
await new ReadFileAndParseJsonUseCase().call<Command>(
__filename.slice(0, __filename.lastIndexOf("/")).replace("/build/src/features/runtime/domain", "") +
"/" +
"command.json"
)
).map((el) => Result.ok(el[command]));
}

View file

@ -0,0 +1,10 @@
import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller";
import { Result } from "../../../core/helpers/result";
import { SpawnProcessUseCase } from "../../../core/usecases/exec_process_usecase";
import { GetCommandScenario } from "./get_command_scenario";
import { ProcessWatcher } from "../service/process_watcher";
import { App } from "../../../core/controllers/app";
export class GetSimulationStateScenario extends CallbackStrategyWithEmpty {
call = async (): ResponseBase => Result.ok("");
}

View file

@ -0,0 +1,14 @@
export interface Command {
tensorBoard: ExecProcess;
simulationProcess: ExecProcess;
btBuilderProcess: ExecProcess;
}
export interface ExecProcess {
execCommand: string;
date: null;
status: null | string;
delay: number;
checkCommand: null;
filter: null;
}

View file

@ -0,0 +1,3 @@
export class ExecProcesssss{
}

View file

@ -0,0 +1,23 @@
import { Schema, model } from "mongoose";
import { ExecRunTimeCommandValidationModel as ExecRunTimeCommandValidationModel } from "./run_time_validation_model";
export interface IDigitalTwinsInstanceModel {
instancePath: string;
status?: string;
}
export const ExecRunTimeDataBaseSchema = new Schema({
execCommand: String,
date: String,
status: String,
delay: Number,
checkCommand: String,
filter: Array,
}).plugin(require("mongoose-autopopulate"));
export const ExecRuntimeSchema = "digital_twins_instance";
export const ExecRuntimeDatabaseModel = model<ExecRunTimeCommandValidationModel>(
ExecRuntimeSchema,
ExecRunTimeDataBaseSchema
);

View file

@ -0,0 +1,21 @@
import { IsArray, IsEnum, IsNumber, IsString } from "class-validator";
export enum Status {
OK = "Ok",
ERROR = "Error",
}
export class ExecRunTimeCommandValidationModel {
@IsString()
execCommand: string;
@IsString()
date: string = Date();
@IsEnum(Status)
status: Status;
@IsNumber()
delay: number;
@IsString()
checkCommand: string;
@IsArray()
filter: string[] = [];
}

View file

@ -0,0 +1,25 @@
import { CrudController } from "../../core/controllers/crud_controller";
import { ExecRunTimeCommandValidationModel } from "./model/run_time_validation_model";
import { ExecRuntimeDatabaseModel } from "./model/run_time_database_model";
import { CoreHttpController, SubRouter, HttpMethodType } from "../../core/controllers/http_controller";
import { ExecBtBuilderUseCase } from "./domain/exec_bt_builder_usecase";
import { ExecSimulationUseCase } from "./domain/exec_simulation_usecase";
import { GetBtBuilderStateUseCase } from "./domain/get_bt_builder_status_usecase";
import { GetSimulationStateScenario } from "./domain/get_simulation_state_usecase";
export class RunTimePresentation extends CoreHttpController<ExecRunTimeCommandValidationModel> {
constructor() {
super({
url: "run_time",
});
this.subRoutes.push(new SubRouter("POST", "/exec/bt/builder", new ExecBtBuilderUseCase()));
this.subRoutes.push(new SubRouter("POST", "/get/bt/builder/state", new GetBtBuilderStateUseCase()));
this.subRoutes.push(new SubRouter("POST", "/get/simulator/state", new GetSimulationStateScenario()));
this.subRoutes.push({
method: "POST",
subUrl: "/exec/simulation/",
fn: new ExecSimulationUseCase(),
});
}
}

View file

@ -0,0 +1,22 @@
import { Result } from "../../../core/helpers/result";
import { TypedEvent } from "../../../core/helpers/typed_event";
import { ExecError, SpawnError } from "../../../core/models/exec_error_model";
import { ExecutorResult } from "../../../core/models/executor_result";
export class ProcessWatcher extends TypedEvent<Result<ExecError | SpawnError, ExecutorResult>> {
logs = "";
delay: number;
constructor(delay: number, pattern: string) {
super();
this.on(this.lister);
setTimeout(() => {
console.log(this.logs);
}, delay);
}
lister = (event: Result<ExecError | SpawnError, ExecutorResult>) => {
event.map(async (success) => {
this.logs += success.data;
});
};
}

10
server/src/p.json Normal file
View file

@ -0,0 +1,10 @@
{
"execCommand": "string",
"date": "date",
"status": "Fail,Ok",
"delay": 1000,
"checkCommand": "string",
"filter": [
"/assembly_config"
]
}

View file

@ -21,6 +21,7 @@
"react-dom": "^18.2.0",
"react-i18next": "^13.3.1",
"react-infinite-scroll-component": "^6.1.0",
"react-resizable-panels": "^2.1.7",
"react-router-dom": "^6.18.0",
"react-scripts": "5.0.1",
"reflect-metadata": "^0.1.13",
@ -39,7 +40,6 @@
"ws": "^8.17.0",
"xml-formatter": "^3.6.2"
},
"overrides": {
"typescript": "^5.0.2"
},
@ -76,4 +76,4 @@
"@types/three": "^0.158.3",
"@types/uuid": "^9.0.2"
}
}
}

View file

@ -23,7 +23,7 @@
<title>Robossembler</title>
</head>
<body>
<body style="overflow: auto;">
<noscript>You need to enable JavaScript to run this app.</noscript>
<div style="width: 100%; height: 100%" id="root"></div>
</body>

View file

@ -54,12 +54,72 @@ export class FormBuilderValidationModel
new FormBuilderValidationModel("", simpleFormBuilder, [], "");
static vision = () =>
new FormBuilderValidationModel(
`ENUM PRETRAIN = "true","false";`,
`{
"numberOfEpochs": \${numberOfEpochs:number:10},
"selectDataset": \${<SelectDataset/>:OBJECT:{"dataset": {}},
"pretrain": \${pretrain:Enum<PRETRAIN>:true}
}`,
`
ENUM T = "ObjectDetection","PoseEstimation";
ENUM L = "POINT","SUN";
ENUM F = "JPEG","PNG";
ENUM COLLISION_SHAPE = "BOX","COLLISION";
type OBJECTS_SCENE = {
"name": \${NAME:string:default},
"collision_shape": \${collision_shape:Enum<COLLISION_SHAPE>:BOX},
"loc_xyz": [\${LOC_XYZ_1:number:0}, \${LOC_XYZ_2:number:0}, \${LOC_XYZ_3:number:0}],
"rot_euler": [\${ROT_EULER_1:number:0},\${ROT_EULER_2:number:0}, \${ROT_EULER_3:number:0}],
"material_randomization": {
"specular": [\${SPECULAR_1:number:0}, \${SPECULAR_2:number:1}],
"roughness": [\${ROUGHNESS_1:number:0}, \${ROUGHNESS_2:number:1}],
"metallic": [\${METALLIC_1:number:0}, \${METALLIC_2:number:1}],
"base_color": [
[
\${BASE_COLOR_1:number:0},
\${BASE_COLOR_2:number:0},
\${BASE_COLOR_3:number:0},
\${BASE_COLOR_4:number:1}
],
[
\${BASE_COLOR_5:number:1},
\${BASE_COLOR_6:number:1},
\${BASE_COLOR_7:number:1},
\${BASE_COLOR_8:number:1}
]
]
}
};
type LIGHTS = {
"id": \${ID:number:1},
"type": \${type:Enum<L>:POINT},
"loc_xyz": [\${LOC_XYZ_1:number:5}, \${LOC_XYZ_2:number:5}, \${LOC_XYZ_3:number:5}],
"rot_euler": [\${ROT_EULER_1:number:-0.06}, \${ROT_EULER_2:number:0.61}, \${ROT_EULER_3:number:-0.19}],
"color_range_low": [\${COLOR_RANGE_LOW_1:number:0.5}, \${COLOR_RANGE_LOW_2:number:0.5}, \${COLOR_RANGE_LOW_3:number:0.5}],
"color_range_high":[\${COLOR_RANGE_HIGH_1:number:1}, \${COLOR_RANGE_HIGH_2:number:1}, $\{COLOR_RANGE_HIGH_3:number:1}],
"energy_range":[\${ENERGY_RANGE_1:number:400},\${ENERGY_RANGE_2:number:900}]
};`,
`
{
"datasetObjects":\${<SelectDetail/>:OBJECT:{"details": []},
"typedataset": \${typedataset:Enum<T>:ObjectDetection},
"models_randomization":{
"loc_range_low": [\${LOC_RANGE_LOW_1:number:-1}, \${LOC_RANGE_LOW_2:number:-1},\${LOC_RANGE_LOW_3:number:0}],
"loc_range_high": [\${LOC_RANGE_HIGH_1:number:1}, \${LOC_RANGE_HIGH_2:number:1},\${LOC_RANGE_HIGH_3:number:2}]
},
"scene":{
"objects": \${OBJECTS_SCENE:Array<OBJECTS_SCENE>:[]},
"lights": \${LIGHTS:Array<LIGHTS>:[]}
},
"camera_position":{
"center_shell": [\${CENTER_SHELL_1:number:0}, \${CENTER_SHELL_2:number:0}, \${CENTER_SHELL_3:number:0}],
"radius_range": [\${RADIUS_RANGE_1:number:1}, \${RADIUS_RANGE_2:number:1.4}],
"elevation_range": [\${ELEVATION_RANGE_1:number:10}, \${ELEVATION_RANGE_2:number:90}]
},
"generation":{
"n_cam_pose": \${N_CAM_POSE:number:5},
"n_sample_on_pose": \${N_SAMPLE_ON_POSE:number:3},
"n_series": \${N_SERIES:number:100},
"image_format": \${image_format:Enum<F>:JPEG},
"image_size_wh": [\${IMAGE_SIZE_WH_1:number:640}, \${IMAGE_SIZE_WH_2:number:480}]
}
}
`,
[],
""
);

View file

@ -8,6 +8,7 @@ interface InputV2Props {
trim?: boolean;
height?: number;
onChange?: (text: string) => void;
}
export const InputV2: React.FC<InputV2Props> = ({ label, height, value, onChange, trim }) => {
return (

View file

@ -0,0 +1,21 @@
import { IsArray, IsEnum, IsNumber, IsString } from "class-validator";
import { ValidationModel } from "../../../core/model/validation_model";
export enum Status {
OK = "Ok",
ERROR = "Error",
}
export class ExecRunTimeCommand extends ValidationModel {
@IsString()
execCommand: string;
@IsString()
date: string = Date();
@IsEnum(Status)
status: Status;
@IsNumber()
delay: number;
@IsString()
checkCommand: string;
@IsArray()
filter: string[] = [];
}

View file

@ -17,8 +17,10 @@ import { InputV2 } from "../../../core/ui/input/input_v2";
import { SelectV2 } from "../../../core/ui/select/select_v2";
import { MainPageV2 } from "../../../core/ui/pages/main_page_v2";
import { DrawerV2 } from "../../../core/ui/drawer/drawer";
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
export const behaviorTreeBuilderScreenPath = "behavior/tree/screen/path";
export interface DOMReact {
x: number;
y: number;
@ -31,14 +33,17 @@ export interface DOMReact {
}
export const behaviorTreeBuilderStore = new BehaviorTreeBuilderStore();
export const BehaviorTreeBuilderPath = (id?: string) => {
if (id) {
return `/behavior/tree/${id}`;
}
return `/behavior/tree/`;
};
export const isBtScreen = () =>
Boolean(window.location.href.match(new RegExp(BehaviorTreeBuilderPath()))?.at(0)) ?? false;
export const BehaviorTreeBuilderScreen = observer(() => {
const navigate = useNavigate();
const { id } = useParams();
@ -54,9 +59,7 @@ export const BehaviorTreeBuilderScreen = observer(() => {
}, [ref.current]);
React.useEffect(() => {
store.init(navigate).then(() => {
store.initParam(id);
});
store.init(navigate).then(() => store.initParam(id));
return () => {
store.dispose();
};
@ -71,10 +74,11 @@ export const BehaviorTreeBuilderScreen = observer(() => {
display: "flex",
flexDirection: "row",
justifyContent: "end",
paddingRight: 30,
alignItems: "center",
}}
>
<ButtonV2 style={{ height: 40 }} onClick={() => {}} text="Запуск" textColor={themeStore.theme.black} />
{/* <ButtonV2 style={{ height: 40 }} onClick={() => {}} text="Запуск" textColor={themeStore.theme.black} />
<div style={{ width: 10 }} />
<ButtonV2
style={{ height: 40 }}
@ -83,21 +87,25 @@ export const BehaviorTreeBuilderScreen = observer(() => {
type={ButtonV2Type.empty}
textColor={themeStore.theme.greenWhite}
/>
<div style={{ width: 10 }} />
<div
style={{
backgroundColor: store.isNeedSaveBtn ? themeStore.theme.greenWhite : undefined,
height: 40,
textAlign: "center",
alignContent: "center",
width: 40,
borderRadius: 100,
}}
>
{store.isNeedSaveBtn ? (
<Icon style={{ height: 21 }} onClick={() => store.onClickSaveBehaviorTree()} type="Floppy" />
) : undefined}
</div>
<div style={{ width: 10 }} /> */}
{store.isNeedSaveBtn ? (
<div
style={{
backgroundColor: store.isNeedSaveBtn ? themeStore.theme.greenWhite : undefined,
height: 40,
textAlign: "center",
alignContent: "center",
width: 40,
borderRadius: 100,
}}
>
{store.isNeedSaveBtn ? (
<Icon style={{ height: 21 }} onClick={() => store.onClickSaveBehaviorTree()} type="Floppy" />
) : undefined}
</div>
) : (
<></>
)}
</div>
</>
}
@ -131,15 +139,33 @@ export const BehaviorTreeBuilderScreen = observer(() => {
{store.skillTemplates ? <SkillTree skills={store.skillTree} dragEnd={store.dragEnd} /> : null}
</div>
</div>
<div
ref={ref}
className="dotted"
style={{
width: "100%",
position: "absolute",
left: 300,
height: "100%",
backgroundSize: "20px 20px",
width: "calc(100% - 300px)",
}}
/>
>
<PanelGroup direction="horizontal" style={{ width: "100%" }}>
<Panel>
<div
ref={ref}
className="dotted"
style={{
width: "100%",
height: "100%",
backgroundSize: "20px 20px",
}}
/>
</Panel>
<PanelResizeHandle>
<div style={{ width: 10, height: "100%", backgroundColor: "beige" }}></div>
</PanelResizeHandle>
<Panel defaultSize={0}> </Panel>
</PanelGroup>
</div>
</>
<DrawerV2

View file

@ -51,7 +51,7 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeView
activeProject: string = "";
behaviorTreeBuilderHttpRepository = new BehaviorTreeBuilderHttpRepository();
canRun = true;
isNeedSaveBtn = true;
isNeedSaveBtn = false;
selected: string = "";
selectedSid: string = "";
nodeBehaviorTree: NodeBehaviorTree[] = [];
@ -207,7 +207,7 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeView
)
).fold(
(xml) => {
console.log(xml)
console.log(xml);
this.behaviorTreeModel.skills = this.filledOutTemplates;
this.behaviorTreeModel.scene = NodeBehaviorTree.fromReteScene(
this.editor as NodeEditor<Schemes>,
@ -230,7 +230,7 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeView
);
validateBt() {}
setSelected = (label: string, selected: boolean, sid: string) => {
this.selectedSid = sid;
this.selected = label;

View file

@ -9,6 +9,16 @@ import { configure } from "mobx";
import { ThemeStore } from "./core/store/theme_store";
import { FormBuilderValidationModel } from "./core/model/form_builder_validation_model";
import { FormBuilder } from "./core/ui/form_builder/form_builder";
import { observer } from "mobx-react-lite";
import { useStore } from "./core/helper/use_store";
import { LifeCycleStore, ModalStore } from "./core/store/base_store";
import { CoreInput } from "./core/ui/input/input";
import { InputV2 } from "./core/ui/input/input_v2";
import { useState } from "react";
import { Button, Modal } from "antd";
import makeAutoObservable from "mobx-store-inheritance";
import { CoreButton } from "./core/ui/button/button";
import { SelectDetail } from "./core/ui/form_builder/forms/select_detail/presentation/select_detail_screen";
configure({
enforceActions: "never",
@ -19,16 +29,55 @@ extensions();
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
export const themeStore = new ThemeStore();
class FormBuilderTextStore extends ModalStore {
viewModel = FormBuilderValidationModel.empty();
constructor() {
super();
makeAutoObservable(this);
}
init = undefined;
}
export const FormBuildTest = observer(() => {
const [store] = useState(new FormBuilderTextStore());
return (
<div>
<InputV2 label={"result"} onChange={(text) => (store.viewModel.result = text)} />
<InputV2 label={"context"} onChange={(text) => (store.viewModel.context = text)} />
<CoreButton text="click" onClick={() => (store.isModalOpen = true)} />
<Modal
destroyOnClose={true}
open={store.isModalOpen}
footer={null}
closable={false}
closeIcon={null}
onCancel={() => {
store.isModalOpen = false;
}}
>
<FormBuilder
formBuilder={store.viewModel}
onChange={(e) => {
console.log(e.output);
// console.log(JSON.stringify(e.output))
}}
/>
</Modal>
</div>
);
});
root.render(
<>
<SocketListener>
{/* <FormBuildTest /> */}
{/* <SocketListener>
<RouterProvider router={router} />
</SocketListener>
{/* <FormBuilder
formBuilder={FormBuilderValidationModel.test()}
onChange={function (change: FormBuilderValidationModel): void {
console.log(JSON.stringify(change.output));
</SocketListener> */}
<SelectDetail
// @ts-expect-error
dependency={{}}
onChange={function (obj: any): void {
throw new Error("Function not implemented.");
}}
/> */}
/>
</>
);