diff --git a/.vscode/settings.json b/.vscode/settings.json index fc4aa24..07a9450 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,7 @@ { "cSpell.words": [ "Ведите", + "Навыки", "typedataset" ] } diff --git a/server/src/core/controllers/routes.ts b/server/src/core/controllers/routes.ts index b63fc5b..fb869b5 100644 --- a/server/src/core/controllers/routes.ts +++ b/server/src/core/controllers/routes.ts @@ -1,3 +1,4 @@ +import { BehaviorTreesPresentation } from "../../features/behavior_trees/behavior_trees"; import { DatasetsPresentation } from "../../features/datasets/datasets_presentation"; import { ProjectsPresentation } from "../../features/projects/projects_presentation"; // import { ProjectsPresentation } from "../../features/_projects/projects_presentation"; @@ -6,4 +7,4 @@ import { Routes } from "../interfaces/router"; extensions(); -export const httpRoutes: Routes[] = [new ProjectsPresentation(), new DatasetsPresentation()].map((el) => el.call()); +export const httpRoutes: Routes[] = [new ProjectsPresentation(), new DatasetsPresentation(), new BehaviorTreesPresentation()].map((el) => el.call()); diff --git a/server/src/core/models/skill_model.ts b/server/src/core/models/skill_model.ts new file mode 100644 index 0000000..97121ec --- /dev/null +++ b/server/src/core/models/skill_model.ts @@ -0,0 +1,147 @@ +import { IsArray, IsString, ValidateNested } from "class-validator"; +import { Type } from "class-transformer"; + +export interface SkillPoseEstimation { + SkillPackage: ISkillPackage; + Module: IModule; + Launch: ILaunch; + ROS2: IRos2; + BTAction: IBTAction[]; + Interface: IInterface; + Settings: ISetting[]; + xxx: IXxx; +} + +export interface IBTAction { + name: string; + format: string; + type: string; + param: string[]; + result: string[]; +} + +export interface IInterface { + Input: IPut[]; + Output: IPut[]; +} + +export interface IPut { + name: string; + type: string; +} + +export interface ILaunch { + executable: string; +} + +export interface IModule { + name: string; + description: string; +} + +export interface IRos2 { + node_name: string; +} + +export interface ISetting { + name: string; + value: number | string; +} + +export interface ISkillPackage { + name: string; + version: string; + format: string; +} + +export interface IXxx { + cameraLink: string; + topicImage: string; + topicCameraInfo: string; +} + +export class SkillPackage implements ISkillPackage { + @IsString() + name: string; + @IsString() + version: string; + @IsString() + format: string; +} +export class Module implements IModule { + @IsString() + name: string; + @IsString() + description: string; +} +export class BTAction implements IBTAction { + @IsString() + name: string; + @IsString() + format: string; + @IsString() + type: string; + @IsArray() + param: string[]; + @IsArray() + result: string[]; +} +export class Launch implements ILaunch { + @IsString() + executable: string; +} +export class Ros2 implements IRos2 { + @IsString() + node_name: string; +} +export class Put implements IPut { + @IsString() + name: string; + @IsString() + type: string; +} +export class Interface implements IInterface { + @ValidateNested() + @Type(() => Put) + Input: IPut[]; + @ValidateNested() + @Type(() => Put) + Output: IPut[]; +} +export class Setting implements ISetting { + name: string; + value: string | number; +} +export class Xxx implements IXxx { + cameraLink: string; + topicImage: string; + topicCameraInfo: string; +} +export class SkillModelPoseEstimation implements SkillPoseEstimation { + @ValidateNested() + @Type(() => SkillPackage) + SkillPackage: ISkillPackage; + @ValidateNested() + @Type(() => Module) + Module: IModule; + @ValidateNested() + @Type(() => Launch) + Launch: ILaunch; + @ValidateNested() + @Type(() => Ros2) + ROS2: IRos2; + @ValidateNested() + @IsArray() + @Type(() => BTAction) + BTAction: IBTAction[]; + @ValidateNested() + @Type(() => Interface) + Interface: IInterface; + @ValidateNested() + @IsArray() + @Type(() => Setting) + Settings: ISetting[]; + @ValidateNested() + @Type(() => Xxx) + xxx: IXxx; +} diff --git a/server/src/features/behavior_trees/behavior_trees.ts b/server/src/features/behavior_trees/behavior_trees.ts new file mode 100644 index 0000000..0d84513 --- /dev/null +++ b/server/src/features/behavior_trees/behavior_trees.ts @@ -0,0 +1,12 @@ +import { CoreHttpController } from "../../core/controllers/http_controller"; +import { DatasetValidationModel } from "../datasets/models/dataset_validation_model"; +import { GetBehaviorTreeSkillsUseCase } from "./get_bt_usecase"; +export class BehaviorTreesPresentation extends CoreHttpController { + constructor() { + super({ + url: "behavior/trees", + validationModel: DatasetValidationModel, + }); + super.get(new GetBehaviorTreeSkillsUseCase().call); + } +} diff --git a/server/src/features/behavior_trees/get_bt_usecase.ts b/server/src/features/behavior_trees/get_bt_usecase.ts new file mode 100644 index 0000000..17d6926 --- /dev/null +++ b/server/src/features/behavior_trees/get_bt_usecase.ts @@ -0,0 +1,154 @@ +import { Result } from "../../core/helpers/result"; + +export class GetBehaviorTreeSkillsUseCase { + call = () => { + return Result.ok({ + skills: [ + { + SkillPackage: { + name: "Robossembler", + version: "1.0", + format: "1", + }, + Module: { + name: "PoseEstimation", + description: "Pose Estimation skill with DOPE", + }, + Launch: { + executable: "pe_dope_lc.py", + }, + ROS2: { + node_name: "lc_dope", + }, + BTAction: [ + { + name: "peConfigure", + format: "yaml", + type: "run", + param: ["object_name", "weights_file"], + result: ["Pose"], + }, + { + name: "peStop", + format: "yaml", + type: "stop", + param: [], + result: [], + }, + ], + Interface: { + Input: [ + { + name: "cameraLink", + type: "CAMERA", + }, + { + name: "object_name", + type: "MODEL", + }, + ], + Output: [ + { + name: "pose_estimation_topic", + type: "POSE", + }, + ], + }, + Settings: [ + { + name: "cameraLink", + value: "inner_rgbd_camera", + }, + { + name: "pose", + value: "", + }, + { + name: "publishDelay", + value: 0.5, + }, + { + name: "tf2_send_pose", + value: 1, + }, + { + name: "mesh_scale", + value: 0.001, + }, + ], + xxx: { + cameraLink: "inner_rgbd_camera", + topicImage: "/inner_rgbd_camera/image", + topicCameraInfo: "/inner_rgbd_camera/camera_info", + }, + }, + { + SkillPackage: { + name: "Robossembler", + version: "1.0", + format: "1", + }, + Module: { + name: "ObjectDetection", + description: "Object detection skill with YOLOv8", + }, + Launch: { + executable: "detection_lifecycle.py", + }, + ROS2: { + node_name: "lc_detection", + }, + BTAction: [ + { + name: "odConfigure", + format: "yaml", + args: ["SettingPath", "server_name", "server_timeout"], + result: ["boundBox"], + }, + { + name: "odStop", + format: "yaml", + args: ["server_name", "server_timeout"], + result: [], + }, + ], + Interface: { + Input: [ + { + name: "cameraLink", + type: "string", + group: "STD_USER", + }, + { + name: "topicImage", + type: "Image", + group: "sensor_msgs.msg", + }, + ], + Output: [ + { + name: "boundBox", + type: "BoundBox", + group: ".msg", + }, + ], + }, + Settings: [ + { + name: "publishDelay", + value: 0.5, + }, + { + name: "server_timeout", + value: 1000, + }, + { + name: "server_name", + value: "/object_detection/change_state", + }, + ], + }, + ], + }); + }; +} diff --git a/ui/src/core/model/skill_model.ts b/ui/src/core/model/skill_model.ts new file mode 100644 index 0000000..63f61b0 --- /dev/null +++ b/ui/src/core/model/skill_model.ts @@ -0,0 +1,183 @@ +import { IsArray, IsString, ValidateNested } from "class-validator"; +import { Type } from "class-transformer"; +import { ISkillView } from "../../features/behavior_tree_builder/presentation/ui/skill_tree/skill_tree"; +import { v4 } from "uuid"; + +export interface ISkillPoseEstimation { + SkillPackage: ISkillPackage; + Module: IModule; + Launch: ILaunch; + ROS2: IRos2; + BTAction: IBTAction[]; + Interface: IInterface; + Settings: ISetting[]; + xxx: IXxx; +} + +export interface IBTAction { + name: string; + format: string; + type: string; + param: string[]; + result: string[]; +} + +export interface IInterface { + Input: IPut[]; + Output: IPut[]; +} + +export interface IPut { + name: string; + type: string; +} + +export interface ILaunch { + executable: string; +} + +export interface IModule { + name: string; + description: string; +} + +export interface IRos2 { + node_name: string; +} + +export interface ISetting { + name: string; + value: number | string; +} + +export interface ISkillPackage { + name: string; + version: string; + format: string; +} + +export interface IXxx { + cameraLink: string; + topicImage: string; + topicCameraInfo: string; +} + +export class SkillPackage implements ISkillPackage { + @IsString() + name: string; + @IsString() + version: string; + @IsString() + format: string; +} +export class Module implements IModule { + @IsString() + name: string; + @IsString() + description: string; +} +export class BTAction implements IBTAction { + @IsString() + name: string; + @IsString() + format: string; + @IsString() + type: string; + @IsArray() + param: string[]; + @IsArray() + result: string[]; +} +export class Launch implements ILaunch { + @IsString() + executable: string; +} +export class Ros2 implements IRos2 { + @IsString() + node_name: string; +} +export class Put implements IPut { + @IsString() + name: string; + @IsString() + type: string; +} +export class Interface implements IInterface { + @ValidateNested() + @Type(() => Put) + Input: IPut[]; + @ValidateNested() + @Type(() => Put) + Output: IPut[]; +} +export class Setting implements ISetting { + name: string; + value: string | number; +} +export class Xxx implements IXxx { + cameraLink: string; + topicImage: string; + topicCameraInfo: string; +} +export class SkillModelPoseEstimation implements ISkillPoseEstimation { + @ValidateNested() + @Type(() => SkillPackage) + SkillPackage: ISkillPackage; + @ValidateNested() + @Type(() => Module) + Module: IModule; + @ValidateNested() + @Type(() => Launch) + Launch: ILaunch; + @ValidateNested() + @Type(() => Ros2) + ROS2: IRos2; + @ValidateNested() + @IsArray() + @Type(() => BTAction) + BTAction: IBTAction[]; + @ValidateNested() + @Type(() => Interface) + Interface: IInterface; + @ValidateNested() + @IsArray() + @Type(() => Setting) + Settings: ISetting[]; + @ValidateNested() + @Type(() => Xxx) + xxx: IXxx; +} + +export class Skills { + @IsArray() + @Type(() => SkillModelPoseEstimation) + skills: SkillModelPoseEstimation[]; + toSkillView(): ISkillView[] { + return this.skills.map((el) => { + return { + name: el.Module.name, + children: el.BTAction.map((act) => { + // return { name: `${el.Module.name} - ${act.name}` }; + return { name: act.name, uuid: v4() }; + }), + }; + }); + } + getSkillDo(name: string) { + return this.skills.reduce((acc, el) => { + if (el.BTAction.find((el) => el.name.isEqual(name))) { + acc = el.Module.name; + } + return acc; + }, "error"); + } + getSkillsNames() { + return this.skills + .map((el) => { + return el.BTAction.map((act) => { + return { name: act.name }; + }); + }) + .flat(1); + } +} diff --git a/ui/src/core/routers/routers.tsx b/ui/src/core/routers/routers.tsx index ccc7d24..0851af5 100644 --- a/ui/src/core/routers/routers.tsx +++ b/ui/src/core/routers/routers.tsx @@ -21,6 +21,7 @@ import DetailsScreen, { DetailsScreenPath } from "../../features/details/details import { AssemblesScreen, AssemblesScreenPath } from "../../features/assembles/assembles_screen"; import SimulationScreen, { SimulationScreenPath } from "../../features/simulations/simulations_screen"; import { EstimateScreen, EstimateScreenPath } from "../../features/estimate/estimate_screen"; +import { SkillPath, SkillScreen } from "../../features/skils/skills_screen"; const idURL = ":id"; @@ -67,9 +68,12 @@ export const router = createBrowserRouter([ path: SimulationScreenPath, element: , }, - { path: EstimateScreenPath, element: , }, + { + path: SkillPath, + element: , + }, ]); diff --git a/ui/src/core/ui/button/button.tsx b/ui/src/core/ui/button/button.tsx index e38256a..bf52d57 100644 --- a/ui/src/core/ui/button/button.tsx +++ b/ui/src/core/ui/button/button.tsx @@ -31,3 +31,6 @@ export function CoreButton(props: IButtonProps) { ); } + + + \ No newline at end of file diff --git a/ui/src/core/ui/pages/main_page.tsx b/ui/src/core/ui/pages/main_page.tsx index 07efdef..daf2ba4 100644 --- a/ui/src/core/ui/pages/main_page.tsx +++ b/ui/src/core/ui/pages/main_page.tsx @@ -10,6 +10,7 @@ import { DetailsScreenPath } from "../../../features/details/details_screen"; import { SimulationScreenPath } from "../../../features/simulations/simulations_screen"; import { EstimateScreenPath } from "../../../features/estimate/estimate_screen"; import { BehaviorTreeBuilderPath } from "../../../features/behavior_tree_builder/presentation/behavior_tree_builder_screen"; +import { SkillPath as SkillScreenPath } from "../../../features/skils/skills_screen"; export interface IBlockProps { name: string; isActive: boolean; @@ -45,6 +46,7 @@ const Block = (props: IBlockProps) => { export interface IMainPageProps { page: string; bodyChildren?: JSX.Element; + panelChildren?: JSX.Element; isLoading?: boolean; } export const MainPage = (props: IMainPageProps) => { @@ -53,7 +55,8 @@ export const MainPage = (props: IMainPageProps) => { { name: "Сборки", path: AssemblesScreenPath, icon: "Assembly" }, { name: "Датасеты", path: DatasetsScreenPath, icon: "Datasets" }, { name: "Сцена", path: SceneManagerPath, icon: "Layers" }, - { name: "Навыки", path: BehaviorTreeBuilderPath, icon: "Rocket" }, + { name: "Навыки", path: SkillScreenPath, icon: "Layers" }, + { name: "Поведение", path: BehaviorTreeBuilderPath, icon: "Rocket" }, { name: "Симуляция", path: SimulationScreenPath, icon: "Simulation" }, { name: "Оценка", path: EstimateScreenPath, icon: "Grade" }, ]; @@ -118,7 +121,9 @@ export const MainPage = (props: IMainPageProps) => { ) : ( <> -
+
+ {props.panelChildren}{" "} +
{props.bodyChildren} )} diff --git a/ui/src/features/behavior_tree_builder/data/behavior_tree_builder_repository.ts b/ui/src/features/behavior_tree_builder/data/behavior_tree_builder_repository.ts new file mode 100644 index 0000000..5115701 --- /dev/null +++ b/ui/src/features/behavior_tree_builder/data/behavior_tree_builder_repository.ts @@ -0,0 +1,9 @@ +import { Result } from "../../../core/helper/result"; +import { Skills } from "../../../core/model/skill_model"; +import { HttpError, HttpMethod, HttpRepository } from "../../../core/repository/http_repository"; + +export class BehaviorTreeBuilderRepository extends HttpRepository { + getBtSkills = async ():Promise> => { + return await this._jsonToClassInstanceRequest(HttpMethod.GET, "/behavior/trees", Skills) as unknown as Promise>; + }; +} diff --git a/ui/src/features/behavior_tree_builder/model/editor_view.ts b/ui/src/features/behavior_tree_builder/model/editor_view.ts index 800d994..360722b 100644 --- a/ui/src/features/behavior_tree_builder/model/editor_view.ts +++ b/ui/src/features/behavior_tree_builder/model/editor_view.ts @@ -3,6 +3,7 @@ import { NodeEditor } from "rete"; import { AreaExtra, Schemes } from "../presentation/ui/editor/editor"; import { Result } from "../../../core/helper/result"; import { AreaPlugin } from "rete-area-plugin"; +import { Skills } from "../../../core/model/skill_model"; export interface BtDrawDragAndDropView { x: number; @@ -15,21 +16,31 @@ export class BtNodeView extends TypedEvent {} export class ReteObserver extends TypedEvent {} export class BtBuilderModel { public static result = ""; - static fromReteScene(editor: NodeEditor, area: AreaPlugin): Result { + static fromReteScene( + editor: NodeEditor, + area: AreaPlugin, + skills?: Skills + ): Result { try { + this.result = ""; this.getFirstSequence(editor).map((sortedSequence) => { const firstNodeId = sortedSequence.getKeyFromValueIsExists(1) as string; this.findSequence(firstNodeId, editor, sortedSequence, 2); - this.result += `<${this.getNodeLabelAtId(editor, firstNodeId)} id="${firstNodeId}">`; - this.toXML(sortedSequence as Map, editor, area, firstNodeId); - this.result += ``; + this.result += `<${this.getNodeLabelAtId(editor, firstNodeId, skills)}>`; + this.toXML(sortedSequence as Map, editor, area, firstNodeId, skills); + this.result += ``; }); return Result.ok(this.result); } catch (error) { return Result.error("BtBuilderModel fromReteScene error"); } } - public static getNodeLabelAtId(editor: NodeEditor, id: string) { + public static getNodeLabelAtId(editor: NodeEditor, id: string, skills?: Skills) { + if (skills?.getSkillsNames().find((el) => el.name.isEqual(editor.getNode(id).label))) { + return `Action ID="RbsBtAction" do="${skills.getSkillDo(editor.getNode(id).label)}" command="${ + editor.getNode(id).label + }" server_name="rbs_interface" server_timeout="1000"`; + } return editor.getNode(id).label; } @@ -37,18 +48,20 @@ export class BtBuilderModel { sortedSequence: Map, editor: NodeEditor, area: AreaPlugin, - activeElementId = "" + activeElementId = "", + skills?: Skills ) { editor.getConnections().forEach((el) => { if (el.source === activeElementId) { - this.result += `<${this.getNodeLabelAtId(editor, el.target)} id="${el.target}">`; - this.toXML(sortedSequence, editor, area, el.target); + this.result += `<${this.getNodeLabelAtId(editor, el.target, skills)}>`; + this.toXML(sortedSequence, editor, area, el.target, skills); this.result += ``; } }); } public static getBtPriorities(ids: string[]) {} + public static findSequence( nodeId: string, editor: NodeEditor, diff --git a/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_screen.tsx b/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_screen.tsx index 249d3a9..4cee1da 100644 --- a/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_screen.tsx +++ b/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_screen.tsx @@ -1,51 +1,37 @@ import * as React from "react"; -import { CoreText, CoreTextType } from "../../../core/ui/text/text"; -import { Button, Input } from "antd"; import { useRete } from "rete-react-plugin"; import { createEditor } from "./ui/editor/editor"; import { SkillTree } from "./ui/skill_tree/skill_tree"; import { BehaviorTreeBuilderStore } from "./behavior_tree_builder_store"; import { MainPage } from "../../../core/ui/pages/main_page"; +import { CoreButton } from "../../../core/ui/button/button"; +import { observer } from "mobx-react-lite"; export const behaviorTreeBuilderScreenPath = "behavior/tree/screen/path"; -const skills = { - name: "", - children: [ - { - name: "Actions", - children: [{ name: "MoveToPose", interface: "Vector3", out: "vo" }], - }, - { - name: "Control", - children: [ - { name: "Fallback", interface: "Vector3", out: "vo" }, - { name: "Sequence", interface: "Vector3", out: "vo" }, - ], - }, - ], -}; export const behaviorTreeBuilderStore = new BehaviorTreeBuilderStore(); + export const BehaviorTreeBuilderPath = "/behavior/tree/"; -export function BehaviorTreeBuilderScreen() { + +export const BehaviorTreeBuilderScreen = observer(() => { const store = behaviorTreeBuilderStore; - const [ref] = useRete(createEditor); + // @ts-expect-error + const [ref] = useRete(createEditor); React.useEffect(() => { store.init(); - - store.dragZoneSetOffset( - // @ts-expect-error - ref.current.offsetTop, - // @ts-expect-error - ref.current.offsetLeft, - // @ts-expect-error - ref.current.clientWidth, - // @ts-expect-error - ref.current.clientHeight - ); - + if (ref.current) + store.dragZoneSetOffset( + // @ts-expect-error + ref.current.offsetTop, + // @ts-expect-error + ref.current.offsetLeft, + // @ts-expect-error + ref.current.clientWidth, + // @ts-expect-error + ref.current.clientHeight + ); return () => { store.dispose(); }; @@ -54,11 +40,17 @@ export function BehaviorTreeBuilderScreen() { return ( + {store.skills ? : null} +
+ store.saveBt()} text="SAVE BT" /> +
+ + } bodyChildren={ <>
- {/* */} -
); -} +}); diff --git a/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_store.tsx b/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_store.tsx index a67032a..6927ebb 100644 --- a/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_store.tsx +++ b/ui/src/features/behavior_tree_builder/presentation/behavior_tree_builder_store.tsx @@ -7,6 +7,9 @@ import { NodeEditor } from "rete"; import { AreaExtra, Schemes } from "./ui/editor/editor"; import { AreaPlugin } from "rete-area-plugin"; import { NodeBehaviorTree } from "../model/node_behavior_tree"; +import { BehaviorTreeBuilderRepository } from "../data/behavior_tree_builder_repository"; +import { Skills } from "../../../core/model/skill_model"; +import { ISkillView } from "./ui/skill_tree/skill_tree"; interface I2DArea { x: number; @@ -20,9 +23,11 @@ export class BehaviorTreeBuilderStore extends UiErrorState { this.reteNode?.emit("200"); } validateBt() {} + skills?: Skills; area?: I2DArea; btNodeView: BtNodeView = new BtNodeView(); reteNode?: ReteObserver; + behaviorTreeBuilderRepository = new BehaviorTreeBuilderRepository(); canRun = true; nodes: NodeBehaviorTree[] = [ { @@ -32,64 +37,24 @@ export class BehaviorTreeBuilderStore extends UiErrorState { inputs: ["a"], position: { x: -488.1303402823156, y: -227.90861570911895 }, }, - { - label: "Sequence", - id: "2", - outputs: ["a"], - inputs: ["a"], - connectTo: "1", - position: { x: 119.95735514023244, y: -182.24902817216878 }, - }, - { - label: "Sequence", - id: "6", - outputs: ["a"], - inputs: ["a"], - connectTo: "2", - position: { x: 402.06111561958505, y: -100.97814086372247 }, - }, - { - label: "MoveToPose", - id: "7", - outputs: ["a"], - inputs: ["a"], - connectTo: "6", - position: { x: 932.0688448287292, y: 90.10780461923443 }, - }, - { - label: "MoveToPose", - id: "8", - outputs: ["a"], - inputs: ["a"], - connectTo: "6", - position: { x: 898.1684213039546, y: -119.80545806921208 }, - }, - { - label: "MoveToPose", - id: "3", - outputs: [], - inputs: ["a"], - connectTo: "1", - position: { x: 208.65749743442188, y: 16.256489050033785 }, - }, - { - label: "MoveToPose", - id: "4", - outputs: [], - inputs: ["a"], - connectTo: "1", - position: { x: -50.46426323140673, y: 99.22642447650014 }, - }, - { - label: "Sequence", - id: "5", - outputs: ["a"], - inputs: ["a"], - connectTo: "1", - position: { x: -234.54554662642457, y: 245.4012710608967 }, - }, + ]; - + skillTree: ISkillView = { + name: "", + children: [ + { + name: "Actions", + children: [], + }, + { + name: "Control", + children: [ + { name: "Fallback", interface: "Vector3", out: "vo" }, + { name: "Sequence", interface: "Vector3", out: "vo" }, + ], + }, + ], + }; constructor() { super(); makeAutoObservable(this); @@ -99,10 +64,9 @@ export class BehaviorTreeBuilderStore extends UiErrorState { JSON.parse(value) as BtNodeView[]; } bt = async (editor: NodeEditor, area: AreaPlugin) => { - (await BtBuilderModel.fromReteScene(editor, area)).fold( + (await BtBuilderModel.fromReteScene(editor, area, this.skills)).fold( (s) => { - console.log( - xmlFormat(` + console.log(xmlFormat(` ${s} @@ -117,15 +81,12 @@ export class BehaviorTreeBuilderStore extends UiErrorState { - `) - ); + `)); }, (_) => _ ); }; - copyBt = () => { - this.reteNode?.emit("200"); - }; + errorHandingStrategy: (error: HttpError) => void; dragEnd = (e: EventTarget) => { @@ -155,7 +116,20 @@ export class BehaviorTreeBuilderStore extends UiErrorState { } } - async init(): Promise {} + async init(): Promise { + (await this.behaviorTreeBuilderRepository.getBtSkills()).fold( + (model) => { + this.skills = model; + this.skillTree.children = this.skillTree.children?.map((el) => { + if (el.name === "Actions") { + el.children = model.toSkillView(); + } + return el; + }); + }, + (e) => console.log(e) + ); + } dragZoneSetOffset(offsetTop: number, offsetWidth: number, width: number, height: number) { this.area = { x: offsetTop, diff --git a/ui/src/features/behavior_tree_builder/presentation/ui/editor/custom_node.tsx b/ui/src/features/behavior_tree_builder/presentation/ui/editor/custom_node.tsx index b651623..354bca3 100644 --- a/ui/src/features/behavior_tree_builder/presentation/ui/editor/custom_node.tsx +++ b/ui/src/features/behavior_tree_builder/presentation/ui/editor/custom_node.tsx @@ -93,7 +93,7 @@ export function CustomNode(props: Props) { const controls = Object.entries(props.data.controls); const selected = props.data.selected || false; const { id, label, width, height } = props.data; - + console.log(label) sortByIndex(inputs); sortByIndex(outputs); sortByIndex(controls); diff --git a/ui/src/features/behavior_tree_builder/presentation/ui/editor/editor.tsx b/ui/src/features/behavior_tree_builder/presentation/ui/editor/editor.tsx index 3b5d810..0d704cf 100644 --- a/ui/src/features/behavior_tree_builder/presentation/ui/editor/editor.tsx +++ b/ui/src/features/behavior_tree_builder/presentation/ui/editor/editor.tsx @@ -21,6 +21,7 @@ export async function createEditor(container: HTMLElement) { behaviorTreeBuilderStore.btNodeView.on(async (event) => { setTimeout(async () => { + console.log(event) const node = new ClassicPreset.Node(event.name); const { x, y } = areaContainer.area.pointer; @@ -33,6 +34,7 @@ export async function createEditor(container: HTMLElement) { }); observer.on(() => { + console.log(200) behaviorTreeBuilderStore.bt(editor, areaContainer); }); diff --git a/ui/src/features/behavior_tree_builder/presentation/ui/editor/nodes/controls_node.tsx b/ui/src/features/behavior_tree_builder/presentation/ui/editor/nodes/controls_node.tsx index a098d48..1a1d794 100644 --- a/ui/src/features/behavior_tree_builder/presentation/ui/editor/nodes/controls_node.tsx +++ b/ui/src/features/behavior_tree_builder/presentation/ui/editor/nodes/controls_node.tsx @@ -8,7 +8,7 @@ const { RefSocket, RefControl } = Presets.classic; type NodeExtraData = { width?: number; height?: number }; export const NodeStyles = styled.div any }>` - background: blue; + background: red; border: 2px solid grey; cursor: pointer; @@ -97,7 +97,6 @@ export function SequenceNode(props: Props) const selected = props.data.selected || false; const { id, label, width, height } = props.data; - sortByIndex(inputs); sortByIndex(outputs); sortByIndex(controls); diff --git a/ui/src/features/behavior_tree_builder/presentation/ui/skill_tree/skill_tree.tsx b/ui/src/features/behavior_tree_builder/presentation/ui/skill_tree/skill_tree.tsx index b314948..b4f16be 100644 --- a/ui/src/features/behavior_tree_builder/presentation/ui/skill_tree/skill_tree.tsx +++ b/ui/src/features/behavior_tree_builder/presentation/ui/skill_tree/skill_tree.tsx @@ -2,8 +2,16 @@ import * as React from "react"; import TreeView, { EventCallback, IBranchProps, INode, LeafProps, flattenTree } from "react-accessible-treeview"; import { IFlatMetadata } from "react-accessible-treeview/dist/TreeView/utils"; import { CallBackEventTarget } from "../../../../../core/extensions/extensions"; + +export interface ISkillView { + name: string; + children?: ISkillView[]; + id?: string; + interface?: string; + out?: string; +} export interface ISkillTreeProps { - skills: any; + skills: ISkillView; dragEnd: CallBackEventTarget; } @@ -16,12 +24,12 @@ interface IRefListerProps { } export const RefListener = (props: IRefListerProps) => { - const ref = React.useRef(null); + const ref = React.useRef(null); React.useEffect(() => { if (ref.current) { ref.current.addEventListener("dragend", (e) => { // @ts-expect-error - if (e.target.innerHTML) { + if (e && e.target && e.target.innerHTML) { // @ts-expect-error props.dragEnd(e); } @@ -36,13 +44,13 @@ export const RefListener = (props: IRefListerProps) => { props.handleSelect(e); }} /> - + {props.element.name}
); }; -export function SkillTree(props: ISkillTreeProps) { +export const SkillTree = (props: ISkillTreeProps) => { return (
); -} +}; diff --git a/ui/src/features/skils/skills_screen.tsx b/ui/src/features/skils/skills_screen.tsx new file mode 100644 index 0000000..ba22d5e --- /dev/null +++ b/ui/src/features/skils/skills_screen.tsx @@ -0,0 +1,20 @@ +import { MainPage } from "../../core/ui/pages/main_page"; + +export const SkillPath = "/skills"; +export const SkillScreen = () => { + return ( + <> + +
+ +
+ + } + /> + + ); +}; diff --git a/ui/src/features/skils/skills_store.tsx b/ui/src/features/skils/skills_store.tsx new file mode 100644 index 0000000..cfe354a --- /dev/null +++ b/ui/src/features/skils/skills_store.tsx @@ -0,0 +1,3 @@ +export class SkillStore{ + +} \ No newline at end of file diff --git a/ui/src/features/socket_lister/socket_lister.tsx b/ui/src/features/socket_lister/socket_lister.tsx index 3e00adf..04ea360 100644 --- a/ui/src/features/socket_lister/socket_lister.tsx +++ b/ui/src/features/socket_lister/socket_lister.tsx @@ -10,7 +10,7 @@ export interface ISocketListerProps { export const SocketLister = observer((props: ISocketListerProps) => { return (
- {socketListerStore.socketHasDisconnect ? ( + {/* {socketListerStore.socketHasDisconnect ? ( { socketListerStore.reconnect(); @@ -25,7 +25,7 @@ export const SocketLister = observer((props: ISocketListerProps) => { /> ) : ( <> - )} + )} */} {props.children}