├── README.md
└── behaviortree-editor
├── panel
├── icon
│ ├── root.svg
│ ├── sequence.svg
│ ├── succeeder.svg
│ ├── mensequence.svg
│ ├── repeatuntilfailure.svg
│ ├── wait.svg
│ ├── priority.svg
│ ├── limit.svg
│ ├── repeatuntilsuccess.svg
│ ├── menpriority.svg
│ ├── customaction.svg
│ ├── inverter.svg
│ ├── repeat.svg
│ ├── customdecorator.svg
│ ├── error.svg
│ ├── maxtime.svg
│ ├── customcondition.svg
│ ├── failer.svg
│ ├── base.svg
│ ├── customcomposite.svg
│ └── running.svg
├── node_modules
│ └── gojs
│ │ ├── bower.json
│ │ ├── README.md
│ │ └── package.json
├── index.html
├── jsoneditor.css
└── img
│ └── jsoneditor-icons.svg
├── bt-inspector.js
├── package.json
├── main.js
└── b3core.0.1.0module.js
/README.md:
--------------------------------------------------------------------------------
1 | # cocos-creator-behavior-tree-editor
2 | youtube: [cocos creator visual behavior tree editor package introduction ](https://www.youtube.com/watch?v=tNkTQk18YlU)
3 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/root.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/sequence.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/succeeder.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/mensequence.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/bt-inspector.js:
--------------------------------------------------------------------------------
1 | Vue.component('foobar-inspector', {
2 | template: `
3 | 编辑
4 | `,
5 |
6 | props: {
7 | target: {
8 | twoWay: true,
9 | type: Object,
10 | },
11 | },
12 |
13 | methods: {
14 | openBTEditor:function(){
15 | Editor.Ipc.sendToMain('behaviortree-editor:re-open-by-comp',{uuid:this.target.__scriptAsset.value.uuid,name:this.target.name.value});
16 | }
17 | }
18 | });
--------------------------------------------------------------------------------
/behaviortree-editor/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "behaviortree-editor",
3 | "version": "0.0.1",
4 | "description": "行为树可视化编辑器",
5 | "author": "Cocos Creator",
6 | "main": "main.js",
7 | "main-menu": {
8 | "bt-editor/open": {
9 | "message": "behaviortree-editor:open"
10 | }
11 | },
12 | "panel": {
13 | "main": "panel/index.html",
14 | "type": "simple",
15 | "title": "behaviortree-editor",
16 | "width": "100%",
17 | "height": "100%"
18 | }
19 | }
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/repeatuntilfailure.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/wait.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/priority.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/limit.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/repeatuntilsuccess.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/menpriority.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/customaction.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/inverter.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/repeat.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/customdecorator.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/error.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/maxtime.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/customcondition.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/failer.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/base.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/customcomposite.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/node_modules/gojs/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gojs",
3 | "description": "Interactive diagrams, charts, and graphs, such as trees, flowcharts, orgcharts, UML, BPMN, or business diagrams",
4 | "main": "release/go.js",
5 | "moduleType": [ "globals", "amd", "node" ],
6 | "license": "https://gojs.net/latest/doc/license.html",
7 | "ignore": [ "**/.*" ],
8 | "keywords": [ "diagram", "chart", "tree", "flowchart", "orgchart", "uml", "bpmn", "graphics", "editor", "inspector", "drawing", "canvas", "shape", "svg", "hierarchy", "node", "link", "group", "vertex", "edge", "connection", "port", "label", "arrowhead", "family-tree", "decision-tree", "mindmap", "tournament", "treeview", "pipe-tree", "genogram", "ivr-tree", "parse-tree", "concept-map", "euler", "visualization", "entity-relationship", "er-diagram", "friend-wheel", "radial", "graph-distances", "graph-paths", "sankey", "pert", "gantt", "timeline", "monitor", "layer", "swimlane", "spreadsheet", "virtualization", "flow", "process", "state", "sequential-function", "grafcet", "sequence", "circuit", "record", "field", "table", "dataflow", "data-flow", "planogram", "seating", "pipes", "overview", "palette", "comment", "layout", "grid-layout", "tree-layout", "force-directed", "layered", "hierarchical", "circular", "fishbone", "ishikawa", "parallel", "serpentine", "treemap", "tree-map", "freehand", "polygon", "polyline", "bezier", "panel", "view", "model", "databinding", "data-binding", "binding", "transaction", "coordinates", "subgraph", "selection", "highlight", "tooltip", "context-menu", "tool", "command", "validation", "button", "template", "legend", "grid", "printing" ],
9 | "authors": [ "Northwoods Software" ],
10 | "homepage": "https://gojs.net"
11 | }
--------------------------------------------------------------------------------
/behaviortree-editor/panel/node_modules/gojs/README.md:
--------------------------------------------------------------------------------
1 | GoJS, a JavaScript Library for HTML Diagrams
2 | ============================================
3 |
4 |
5 |
6 | [GoJS](https://gojs.net) is a JavaScript and HTML5 library for creating interactive diagrams, charts, and graphs.
7 |
8 | [See GoJS Samples](https://gojs.net/latest/samples).
9 |
10 | [Get Started with GoJS](https://gojs.net/latest/learn)
11 |
12 | Read more about GoJS at [gojs.net](https://gojs.net)
13 |
14 | This repository contains both the library and the sources for all samples, extensions, and documentation.
15 | You can use the GitHub repository to quickly [search through all of the sources](https://github.com/NorthwoodsSoftware/GoJS-Samples/search?q=setDataProperty&type=Code).
16 |
17 |
18 |
Support
19 |
20 | Northwoods Software offers a month of free developer-to-developer support for GoJS to help you get started on your project.
21 |
22 | Read and search the official GoJS forum for any topics related to your questions.
23 |
24 | Posting in the forum is the fastest and most effective way of obtaining support for any GoJS related inquiries.
25 | Please register for support at Northwoods Software's registration form before posting in the forum.
26 |
27 | For any nontechnical questions about GoJS, such as about sales or licensing,
28 | please visit Northwoods Software's contact form .
29 |
30 |
31 | License
32 |
33 | The GoJS software license .
34 |
35 | Copyright (c) Northwoods Software Corporation
--------------------------------------------------------------------------------
/behaviortree-editor/panel/icon/running.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/node_modules/gojs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "_args": [
3 | [
4 | {
5 | "raw": "gojs",
6 | "scope": null,
7 | "escapedName": "gojs",
8 | "name": "gojs",
9 | "rawSpec": "",
10 | "spec": "latest",
11 | "type": "tag"
12 | },
13 | "C:\\Users\\Administrator\\Desktop\\test_behaviour_tree"
14 | ]
15 | ],
16 | "_cnpm_publish_time": 1487779127170,
17 | "_from": "gojs@latest",
18 | "_id": "gojs@1.7.0",
19 | "_inCache": true,
20 | "_location": "/gojs",
21 | "_nodeVersion": "5.10.1",
22 | "_npmOperationalInternal": {
23 | "host": "packages-12-west.internal.npmjs.com",
24 | "tmp": "tmp/gojs-1.7.0.tgz_1487779123549_0.9793568486347795"
25 | },
26 | "_npmUser": {
27 | "name": "gojs",
28 | "email": "gojs@nwoods.com"
29 | },
30 | "_npmVersion": "3.8.3",
31 | "_phantomChildren": {},
32 | "_requested": {
33 | "raw": "gojs",
34 | "scope": null,
35 | "escapedName": "gojs",
36 | "name": "gojs",
37 | "rawSpec": "",
38 | "spec": "latest",
39 | "type": "tag"
40 | },
41 | "_requiredBy": [
42 | "#USER"
43 | ],
44 | "_resolved": "https://registry.npm.taobao.org/gojs/download/gojs-1.7.0.tgz",
45 | "_shasum": "78a1b2de2978fe69afe16a369e1262692ead3393",
46 | "_shrinkwrap": null,
47 | "_spec": "gojs",
48 | "_where": "C:\\Users\\Administrator\\Desktop\\test_behaviour_tree",
49 | "author": {
50 | "name": "Northwoods Software"
51 | },
52 | "bugs": {
53 | "url": "https://forum.nwoods.com/c/gojs",
54 | "email": "gojs@nwoods.com"
55 | },
56 | "dependencies": {},
57 | "description": "Interactive diagrams, charts, and graphs, such as trees, flowcharts, orgcharts, UML, BPMN, or business diagrams",
58 | "devDependencies": {},
59 | "directories": {},
60 | "dist": {
61 | "shasum": "78a1b2de2978fe69afe16a369e1262692ead3393",
62 | "size": 6631621,
63 | "noattachment": false,
64 | "tarball": "http://registry.npm.taobao.org/gojs/download/gojs-1.7.0.tgz"
65 | },
66 | "files": [
67 | "package.json",
68 | "bower.json",
69 | "index.html",
70 | "README.md",
71 | "api",
72 | "assets",
73 | "doc/changelog.html",
74 | "doc/download.html",
75 | "doc/license.html",
76 | "extensions",
77 | "intro",
78 | "learn",
79 | "projects",
80 | "release/go.js",
81 | "release/go-debug.js",
82 | "release/go.d.ts",
83 | "samples"
84 | ],
85 | "homepage": "https://gojs.net",
86 | "keywords": [
87 | "diagram",
88 | "chart",
89 | "tree",
90 | "flowchart",
91 | "orgchart",
92 | "uml",
93 | "bpmn",
94 | "graphics",
95 | "editor",
96 | "inspector",
97 | "drawing",
98 | "canvas",
99 | "shape",
100 | "svg",
101 | "hierarchy",
102 | "node",
103 | "link",
104 | "group",
105 | "vertex",
106 | "edge",
107 | "connection",
108 | "port",
109 | "label",
110 | "arrowhead",
111 | "family-tree",
112 | "decision-tree",
113 | "mindmap",
114 | "tournament",
115 | "treeview",
116 | "pipe-tree",
117 | "genogram",
118 | "ivr-tree",
119 | "parse-tree",
120 | "concept-map",
121 | "euler",
122 | "visualization",
123 | "entity-relationship",
124 | "er-diagram",
125 | "friend-wheel",
126 | "radial",
127 | "graph-distances",
128 | "graph-paths",
129 | "sankey",
130 | "pert",
131 | "gantt",
132 | "timeline",
133 | "monitor",
134 | "layer",
135 | "swimlane",
136 | "spreadsheet",
137 | "virtualization",
138 | "flow",
139 | "process",
140 | "state",
141 | "sequential-function",
142 | "grafcet",
143 | "sequence",
144 | "circuit",
145 | "record",
146 | "field",
147 | "table",
148 | "dataflow",
149 | "data-flow",
150 | "planogram",
151 | "seating",
152 | "pipes",
153 | "overview",
154 | "palette",
155 | "comment",
156 | "layout",
157 | "grid-layout",
158 | "tree-layout",
159 | "force-directed",
160 | "layered",
161 | "hierarchical",
162 | "circular",
163 | "fishbone",
164 | "ishikawa",
165 | "parallel",
166 | "serpentine",
167 | "treemap",
168 | "tree-map",
169 | "freehand",
170 | "polygon",
171 | "polyline",
172 | "bezier",
173 | "panel",
174 | "view",
175 | "model",
176 | "databinding",
177 | "data-binding",
178 | "binding",
179 | "transaction",
180 | "coordinates",
181 | "subgraph",
182 | "selection",
183 | "highlight",
184 | "tooltip",
185 | "context-menu",
186 | "tool",
187 | "command",
188 | "validation",
189 | "button",
190 | "template",
191 | "legend",
192 | "grid",
193 | "printing"
194 | ],
195 | "license": "SEE LICENSE AT https://gojs.net/latest/doc/license.html",
196 | "main": "release/go.js",
197 | "maintainers": [
198 | {
199 | "name": "gojs",
200 | "email": "gojs@nwoods.com"
201 | },
202 | {
203 | "name": "simonsarris",
204 | "email": "simon@nwoods.com"
205 | }
206 | ],
207 | "name": "gojs",
208 | "optionalDependencies": {},
209 | "publish_time": 1487779127170,
210 | "readme": "ERROR: No README data found!",
211 | "repository": {
212 | "type": "git",
213 | "url": "git+https://github.com/NorthwoodsSoftware/GoJS.git"
214 | },
215 | "scripts": {},
216 | "typings": "release/go.d.ts",
217 | "version": "1.7.0"
218 | }
219 |
--------------------------------------------------------------------------------
/behaviortree-editor/panel/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
269 |
270 |
--------------------------------------------------------------------------------
/behaviortree-editor/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | let reEditing = false;
3 | let reSaving = false;
4 | let reEditingModelString = null;
5 | let reEditingUuid = null;
6 | let reEditingName = null;
7 |
8 | module.exports = {
9 | load () {
10 | // 当 package 被正确加载的时候执行
11 | //console.log("behaviortree-editor loaded");
12 | },
13 |
14 | unload () {
15 | // 当 package 被正确卸载的时候执行
16 | //console.log("behaviortree-editor unloaded");
17 | },
18 |
19 | messages: {
20 | 'test' (e,arg){
21 | Editor.log(arg);
22 | Editor.log(Editor.metas);
23 | },
24 |
25 | 're-open-by-comp' (e,arg) {
26 | if(reEditing){
27 | Editor.Dialog.messageBox ({
28 | type:"none",
29 | buttons: ["shut up"],
30 | title:"tips",
31 | message: "you are locked in re-editing mode.",
32 | detail:"leave the re-editing mode and try again. maybe you should save first."
33 | },function(){});
34 |
35 | return};
36 | reEditing = true;
37 | Editor.Panel.open("behaviortree-editor");
38 | //Editor.Ipc.sendToPanel('behaviortree-editor','load-data',);
39 | //Editor.log(arg.uuid);
40 | Editor.Ipc.sendToMain("asset-db:query-path-by-uuid",arg.uuid,function(e,result){
41 | //Editor.log(e);
42 | //Editor.log(result);
43 | let fs_handler = require('fs');
44 | fs_handler.readFile(result, "utf-8", function(err, data) {
45 | //Editor.log(data);
46 | let modelString= data.match(/\/\/#########################################.*#############################################/)[0].replace(/#*/g,"").replace(/^\/\//,"");
47 | reEditingModelString = modelString;
48 | reEditingUuid = arg.uuid;
49 | reEditingName = arg.name;
50 | //Editor.log(reEditingName);
51 | //Editor.log(modelData);
52 | //Editor.Ipc.sendToPanel("behaviortree-editor","re-modify-by-comp",{modelString:modelString,uuid:arg.uuid});
53 | //require('electron').ipcMain.send('behaviortree-editor:re-modify-by-comp',{modelString:modelString,uuid:arg.uuid});
54 | //Editor.log(Editor.Ipc);
55 | });
56 | });
57 | },
58 | 'load-data-of-comp' (e,arg){
59 | if(!reEditing){Editor.Dialog.messageBox ({
60 | type:"none",
61 | buttons: ["shut up"],
62 | title:"tips",
63 | message: "you are not in re-editing mode",
64 | detail:"you can enter the re-editing mode from behaviortree-Component."
65 | },function(){});
66 | e.reply(null,{error: true});
67 | }else{
68 | if(reSaving){Editor.log(Editor.Dialog.messageBox ({
69 | type:"none",
70 | buttons: ["shut up"],
71 | title:"tips",
72 | message: "please wait the temp saving",
73 | detail:"after saving, you can load from lasteat saved data if in re-editing mode."
74 | },function(){}));e.reply(null,{error:true})}
75 | else{
76 | e.reply(null,{error: false, reEditingModelString:reEditingModelString, reEditingName: reEditingName});
77 | }
78 | }
79 |
80 | },
81 | 'leave-re-editing-mode' (e){
82 | reEditing = false;
83 | Editor.log(Editor.Dialog.messageBox ({
84 | type:"none",
85 | buttons: ["shut up"],
86 | title:"tips",
87 | message: "you leave re-editing mode",
88 | detail:"in new mode the file would saved as default way.and just close the edit-panel would not leave re-editing mode."
89 | },function(){}));e.reply(null,{error:true})
90 | e.reply(null,{});
91 | },
92 |
93 | 'open' () {
94 | Editor.Panel.open("behaviortree-editor");
95 | },
96 | 'receive-json' (e,arg) {
97 | let modelAsObj = arg;
98 | //console.log(modelAsObj);
99 | let nodeDataArray = modelAsObj.nodeDataArray;
100 |
101 | let getNodeByType = function(type){
102 | for(let node of nodeDataArray){
103 | if(node.type == type){
104 | return node;
105 | }
106 | }
107 | };
108 |
109 | let getNodesByParentKey = function(key){
110 | let nodes = [];
111 | for(let node of nodeDataArray){
112 | if(node.parent!== undefined && node.parent == key){
113 | nodes.push(node);
114 | }
115 | }
116 | return nodes;
117 | };
118 |
119 | let orderFromTopToDown = function(a,b){
120 | let ay = a.loc.split(" ")[1];
121 | let by = b.loc.split(" ")[1];
122 | //Editor.log(ay,by,(ay - by) | 0);
123 | return (ay - by) | 0;
124 | }
125 |
126 | let rootNode = getNodeByType("Root");
127 |
128 | let generateTreeLayerString = function(parentNode,childNodes){
129 | let children = [];
130 | for(let childNode of childNodes){
131 | if(childNode.name == childNode.type){
132 | children.push("new b3." + childNode.type + "(" + "##key" + childNode.key +"##" +")");
133 | }else{
134 | children.push("new " + childNode.name + "(" +"##key" + childNode.key +"##"+ ")");
135 | }
136 | // if(childNode.parameter){
137 | // console.log(childNode.parameter.replace(/\"/g,"'"));
138 | // }
139 | }
140 | let tempParameter = JSON.parse(parentNode.parameter);
141 | let resultObj = {};
142 | resultObj.parameter = parentNode.parameter.replace(/"/g,"'");
143 | switch(parentNode.type){
144 | case 'Limiter':
145 | case 'RepeaterUntilFailure':
146 | case 'RepeaterUntilSuccess':
147 | case 'Repeater':{resultObj.maxLoop = tempParameter.maxLoop; break;}
148 | }
149 | switch(parentNode.type){
150 | case 'MaxTime': {resultObj.maxTime = rtempParameter.maxTime; break;}
151 | }
152 | switch(parentNode.type){
153 | case 'Wait': {resultObj.milliseconds = tempParameter.milliseconds; break;}
154 | }
155 | switch(parentNode.catagory){
156 | case 'Composite': {resultObj.children = children; break;}
157 | }
158 | switch(parentNode.catagory){
159 | case 'Decorator': {resultObj.child = children[0]; break;}
160 | }
161 |
162 | return JSON.stringify(resultObj);
163 | }
164 |
165 |
166 |
167 | let nodeQuene = [];
168 | nodeQuene.push(rootNode);
169 | let finalString = "new b3.Sequence(##key" + rootNode.key +"##)";
170 | while(nodeQuene.length != 0){
171 | let node = nodeQuene.shift();
172 | let childNodes = getNodesByParentKey(node.key);
173 | let orderedChildNodes = childNodes.sort(orderFromTopToDown);
174 | nodeQuene = nodeQuene.concat(orderedChildNodes);
175 | let gString = generateTreeLayerString(node,orderedChildNodes);
176 | finalString = finalString.replace("##key"+node.key+"##",gString);
177 | }
178 | //console.log(finalString);
179 |
180 | let customNodeString = "let self = this;\n";
181 | let hasGeneratedNodes = [];
182 | for(let node of nodeDataArray){
183 | if(hasGeneratedNodes[node.name] != undefined){continue;}
184 | if(node.name != node.type || node.type == 'Action' || node.type == 'Condition' || node.type == 'Composite' || node.type == 'Decorator'){
185 | hasGeneratedNodes[node.name] = true;
186 | customNodeString += "let "+node.name+" = b3.Class(b3."+node.type+");\n" +
187 | node.name+".prototype.name = '"+node.name+"';\n" +
188 | node.name+".prototype.__"+node.catagory+"_initialize = "+node.name+".prototype.initialize;\n" +
189 | node.name+".prototype.initialize = function(settings){\n" +
190 | " settings = settings || {};\n" +
191 | " this.__"+node.catagory+"_initialize();\n" +
192 | " this.parameter = settings.parameter;\n";
193 | switch(node.type){
194 | case 'Limiter':
195 | case 'RepeaterUntilFailure':
196 | case 'RepeaterUntilSuccess':
197 | case 'Repeater':{customNodeString += "this.maxLoop = settings.maxLoop;\n";break;}
198 | }
199 | switch(node.type){
200 | case 'MaxTime': {customNodeString += "this.maxTime = settings.maxTime;\n";break;}
201 | }
202 | switch(node.type){
203 | case 'Wait': {customNodeString += "this.milliseconds = settings.milliseconds;\n";break;}
204 | }
205 | switch(node.catagory){
206 | case 'Composite': {customNodeString += "this.children = settings.children;\n";break;}
207 | }
208 | switch(node.catagory){
209 | case 'Decorator': {customNodeString += "this.child = settings.child;\n";break;}
210 | }
211 | customNodeString += "}\n" +
212 | node.name+".prototype.enter = function(tick){\n" +
213 | " return self.getComponent('"+node.name+"').enter(tick,b3,this);\n" +
214 | "}\n" +
215 | node.name+".prototype.open = function(tick) {\n" +
216 | " return self.getComponent('"+node.name+"').open(tick,b3,this);\n" +
217 | "}\n" +
218 | node.name+".prototype.tick = function(tick) {\n" +
219 | " return self.getComponent('"+node.name+"').tick(tick,b3,this);\n" +
220 | "}\n" +
221 | node.name+".prototype.close = function(tick) {\n" +
222 | " return self.getComponent('"+node.name+"').close(tick,b3,this);\n" +
223 | "}\n" +
224 | node.name+".prototype.exit = function(tick) {\n" +
225 | " return self.getComponent('"+node.name+"').exit(tick,b3,this);\n" +
226 | "}\n";
227 | }
228 | }
229 | let tipsString = "//Don't modify this if you want to re-modify the behaviortree in the future\n";
230 | let modelString = "//#########################################" + JSON.stringify(modelAsObj) + "#############################################\n";
231 |
232 | let mainString = tipsString +
233 | modelString +
234 | "\n" +
235 | "\n" +
236 | "cc.Class({\n" +
237 | "extends: cc.Component,\n" +
238 | "editor: {\n" +
239 | "inspector: 'packages://behaviortree-editor/bt-inspector.js'\n"+
240 | "},\n" +
241 | "properties: {\n" +
242 | "},\n" +
243 | "onLoad: function () {\n" +
244 | "let b3 = require('b3core.0.1.0module');\n"+
245 | customNodeString +
246 | "let tree = new b3.BehaviorTree();\n"+
247 | "tree.root = " + finalString.replace(/"/g,"") + ";\n"+
248 | "this.tree = tree;\n"+
249 | "this.blackboard = new b3.Blackboard();\n" +
250 | "this.b3 = b3;\n" +
251 | "},\n" +
252 | "tick: function(target){\n"+
253 | "let t = {};\n" +
254 | "if(target != undefined){t = target;}\n" +
255 | "this.tree.tick(t,this.blackboard)\n" +
256 | "}" +
257 | "});\n";
258 |
259 | //console.log(mainString);
260 | let fs_handler = require("fs");
261 | if(reEditing){
262 | Editor.Ipc.sendToMain("asset-db:query-url-by-uuid",reEditingUuid,function(e,result){
263 | fs_handler.writeFileSync(Editor.url(result),mainString);
264 | Editor.Ipc.sendToMain("asset-db:refresh",result,function(err,results){
265 | reSaving = true;
266 | fs_handler.readFile(Editor.url(result), "utf-8", function(err, data) {
267 |
268 | let modelString= data.match(/\/\/#########################################.*#############################################/)[0].replace(/#*/g,"").replace(/^\/\//,"");
269 | reEditingModelString = modelString;
270 | reSaving = false;
271 | Editor.log(Editor.Dialog.messageBox ({
272 | type:"none",
273 | buttons: ["shut up"],
274 | title:"tips",
275 | message: "file of re-edit saved",
276 | detail:"you could see something blink blink in assetdb. take care of the component name."
277 | },function(){}));
278 | });
279 | });
280 | });
281 | }
282 | else{
283 | //生成行为树组件脚本
284 | fs_handler.writeFileSync(Editor.url("db://assets/BehaviorTree.js"),mainString);
285 | Editor.Ipc.sendToMain("asset-db:refresh","db://assets/BehaviorTree.js",function(err,results){
286 | Editor.log(Editor.Dialog.messageBox ({
287 | type:"none",
288 | buttons: ["shut up"],
289 | title:"tips",
290 | message: "file of new saved",
291 | detail:"you could see something new(maybe) in assetdb. take care of the component name."
292 | },function(){}));
293 | });
294 | }
295 |
296 | },
297 |
298 | 'add-lib' () {
299 | let fs_handler = require("fs");
300 | fs_handler.writeFileSync(Editor.url("db://assets/b3core.0.1.0module.js"), fs_handler.readFileSync(Editor.url("packages://behaviortree-editor/b3core.0.1.0module.js")));
301 | Editor.Ipc.sendToMain("asset-db:refresh","db://assets/b3core.0.1.0module.js",function(err,results){
302 | Editor.log(Editor.Dialog.messageBox ({
303 | type:"none",
304 | buttons: ["shut up"],
305 | title:"tips",
306 | message: "behaviortree lib added",
307 | detail:"even though the lib name is ugly, but don't modify it please."
308 | },function(){}));
309 | });
310 | },
311 |
312 | 'generate-tree-node-template' (){
313 | let mainString = "cc.Class({\n" +
314 | "extends: cc.Component,\n" +
315 | "\n" +
316 | "properties: {\n" +
317 | "\n" +
318 | "},\n" +
319 | "\n" +
320 | "\n" +
321 | "onLoad: function () {\n" +
322 | "\n" +
323 | "},\n" +
324 | "enter: function(tick,b3,treeNode){\n" +
325 | "\n" +
326 | "},\n"+
327 | "open: function(tick,b3,treeNode){\n" +
328 | "\n"+
329 | "},\n" +
330 | "tick: function(tick,b3,treeNode){\n" +
331 | "\n"+
332 | "},\n" +
333 | "close: function(tick,b3,treeNode){\n" +
334 | "\n" +
335 | "},\n" +
336 | "exit: function(tick,b3,treeNode){\n" +
337 | "\n" +
338 | "},\n" +
339 | "\n" +
340 | "});\n";
341 |
342 | let fs_handler = require("fs");
343 | fs_handler.writeFileSync(Editor.url("db://assets/TreeNodeTemplate.js"), mainString);
344 | Editor.Ipc.sendToMain("asset-db:refresh","db://assets/TreeNodeTemplate.js",function(err,results){
345 | Editor.log(Editor.Dialog.messageBox ({
346 | type:"none",
347 | buttons: ["shut up"],
348 | title:"tips",
349 | message: "treenode code template generated",
350 | detail:"look more about the code and the src in behaviortree lib to get more tips"
351 | },function(){}));
352 | });
353 | },
354 |
355 | },
356 |
357 | };
--------------------------------------------------------------------------------
/behaviortree-editor/panel/jsoneditor.css:
--------------------------------------------------------------------------------
1 | /* reset styling (prevent conflicts with bootstrap, materialize.css, etc.) */
2 |
3 | div.jsoneditor .jsoneditor-search input {
4 | height: auto;
5 | border: inherit;
6 | }
7 |
8 | div.jsoneditor .jsoneditor-search input:focus {
9 | border: none !important;
10 | box-shadow: none !important;
11 | }
12 |
13 | div.jsoneditor table {
14 | border-collapse: collapse;
15 | width: auto;
16 | }
17 |
18 | div.jsoneditor td,
19 | div.jsoneditor th {
20 | padding: 0;
21 | display: table-cell;
22 | text-align: left;
23 | vertical-align: inherit;
24 | border-radius: inherit;
25 | }
26 |
27 |
28 | div.jsoneditor-field,
29 | div.jsoneditor-value,
30 | div.jsoneditor-readonly {
31 | border: 1px solid transparent;
32 | min-height: 16px;
33 | min-width: 32px;
34 | padding: 2px;
35 | margin: 1px;
36 | word-wrap: break-word;
37 | float: left;
38 | }
39 |
40 | /* adjust margin of p elements inside editable divs, needed for Opera, IE */
41 |
42 | div.jsoneditor-field p,
43 | div.jsoneditor-value p {
44 | margin: 0;
45 | }
46 |
47 | div.jsoneditor-value {
48 | word-break: break-word;
49 | }
50 |
51 | div.jsoneditor-readonly {
52 | min-width: 16px;
53 | color: gray;
54 | }
55 |
56 | div.jsoneditor-empty {
57 | border-color: lightgray;
58 | border-style: dashed;
59 | border-radius: 2px;
60 | }
61 |
62 | div.jsoneditor-field.jsoneditor-empty::after,
63 | div.jsoneditor-value.jsoneditor-empty::after {
64 | pointer-events: none;
65 | color: lightgray;
66 | font-size: 8pt;
67 | }
68 |
69 | div.jsoneditor-field.jsoneditor-empty::after {
70 | content: "field";
71 | }
72 |
73 | div.jsoneditor-value.jsoneditor-empty::after {
74 | content: "value";
75 | }
76 |
77 | div.jsoneditor-value.jsoneditor-url,
78 | a.jsoneditor-value.jsoneditor-url {
79 | color: green;
80 | text-decoration: underline;
81 | }
82 |
83 | a.jsoneditor-value.jsoneditor-url {
84 | display: inline-block;
85 | padding: 2px;
86 | margin: 2px;
87 | }
88 |
89 | a.jsoneditor-value.jsoneditor-url:hover,
90 | a.jsoneditor-value.jsoneditor-url:focus {
91 | color: #ee422e;
92 | }
93 |
94 | div.jsoneditor td.jsoneditor-separator {
95 | padding: 3px 0;
96 | vertical-align: top;
97 | color: gray;
98 | }
99 |
100 | div.jsoneditor-field[contenteditable=true]:focus,
101 | div.jsoneditor-field[contenteditable=true]:hover,
102 | div.jsoneditor-value[contenteditable=true]:focus,
103 | div.jsoneditor-value[contenteditable=true]:hover,
104 | div.jsoneditor-field.jsoneditor-highlight,
105 | div.jsoneditor-value.jsoneditor-highlight {
106 | background-color: #FFFFAB;
107 | border: 1px solid yellow;
108 | border-radius: 2px;
109 | }
110 |
111 | div.jsoneditor-field.jsoneditor-highlight-active,
112 | div.jsoneditor-field.jsoneditor-highlight-active:focus,
113 | div.jsoneditor-field.jsoneditor-highlight-active:hover,
114 | div.jsoneditor-value.jsoneditor-highlight-active,
115 | div.jsoneditor-value.jsoneditor-highlight-active:focus,
116 | div.jsoneditor-value.jsoneditor-highlight-active:hover {
117 | background-color: #ffee00;
118 | border: 1px solid #ffc700;
119 | border-radius: 2px;
120 | }
121 |
122 | div.jsoneditor-value.jsoneditor-string {
123 | color: #008000;
124 | }
125 |
126 | div.jsoneditor-value.jsoneditor-object,
127 | div.jsoneditor-value.jsoneditor-array {
128 | min-width: 16px;
129 | color: #808080;
130 | }
131 |
132 | div.jsoneditor-value.jsoneditor-number {
133 | color: #ee422e;
134 | }
135 |
136 | div.jsoneditor-value.jsoneditor-boolean {
137 | color: #ff8c00;
138 | }
139 |
140 | div.jsoneditor-value.jsoneditor-null {
141 | color: #004ED0;
142 | }
143 |
144 | div.jsoneditor-value.jsoneditor-invalid {
145 | color: #000000;
146 | }
147 |
148 | div.jsoneditor-tree button {
149 | width: 24px;
150 | height: 24px;
151 | padding: 0;
152 | margin: 0;
153 | border: none;
154 | cursor: pointer;
155 | background: transparent url("img/jsoneditor-icons.svg");
156 | }
157 |
158 | div.jsoneditor-mode-view tr.jsoneditor-expandable td.jsoneditor-tree,
159 | div.jsoneditor-mode-form tr.jsoneditor-expandable td.jsoneditor-tree {
160 | cursor: pointer;
161 | }
162 |
163 | div.jsoneditor-tree button.jsoneditor-collapsed {
164 | background-position: 0 -48px;
165 | }
166 |
167 | div.jsoneditor-tree button.jsoneditor-expanded {
168 | background-position: 0 -72px;
169 | }
170 |
171 | div.jsoneditor-tree button.jsoneditor-contextmenu {
172 | background-position: -48px -72px;
173 | }
174 |
175 | div.jsoneditor-tree button.jsoneditor-contextmenu:hover,
176 | div.jsoneditor-tree button.jsoneditor-contextmenu:focus,
177 | div.jsoneditor-tree button.jsoneditor-contextmenu.jsoneditor-selected,
178 | tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu {
179 | background-position: -48px -48px;
180 | }
181 |
182 | div.jsoneditor-tree *:focus {
183 | outline: none;
184 | }
185 |
186 | div.jsoneditor-tree button:focus {
187 | /* TODO: nice outline for buttons with focus
188 | outline: #97B0F8 solid 2px;
189 | box-shadow: 0 0 8px #97B0F8;
190 | */
191 | background-color: #f5f5f5;
192 | outline: #e5e5e5 solid 1px;
193 | }
194 |
195 | div.jsoneditor-tree button.jsoneditor-invisible {
196 | visibility: hidden;
197 | background: none;
198 | }
199 |
200 | div.jsoneditor {
201 | color: #1A1A1A;
202 | border: 1px solid #3883fa;
203 | -moz-box-sizing: border-box;
204 | -webkit-box-sizing: border-box;
205 | box-sizing: border-box;
206 | width: 100%;
207 | height: 100%;
208 | overflow: hidden;
209 | position: relative;
210 | padding: 0;
211 | line-height: 100%;
212 | }
213 |
214 | div.jsoneditor-tree table.jsoneditor-tree {
215 | border-collapse: collapse;
216 | border-spacing: 0;
217 | width: 100%;
218 | margin: 0;
219 | }
220 |
221 | div.jsoneditor-outer {
222 | position: static;
223 | width: 100%;
224 | height: 100%;
225 | margin: -35px 0 0 0;
226 | padding: 35px 0 0 0;
227 | -moz-box-sizing: border-box;
228 | -webkit-box-sizing: border-box;
229 | box-sizing: border-box;
230 | }
231 |
232 | textarea.jsoneditor-text,
233 | .ace-jsoneditor {
234 | min-height: 150px;
235 | }
236 |
237 | div.jsoneditor-tree {
238 | width: 100%;
239 | height: 100%;
240 | position: relative;
241 | overflow: auto;
242 | }
243 |
244 | textarea.jsoneditor-text {
245 | width: 100%;
246 | height: 100%;
247 | margin: 0;
248 | -moz-box-sizing: border-box;
249 | -webkit-box-sizing: border-box;
250 | box-sizing: border-box;
251 | outline-width: 0;
252 | border: none;
253 | background-color: white;
254 | resize: none;
255 | }
256 |
257 | tr.jsoneditor-highlight,
258 | tr.jsoneditor-selected {
259 | background-color: #e6e6e6;
260 | }
261 |
262 | tr.jsoneditor-selected button.jsoneditor-dragarea,
263 | tr.jsoneditor-selected button.jsoneditor-contextmenu {
264 | visibility: hidden;
265 | }
266 |
267 | tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea,
268 | tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu {
269 | visibility: visible;
270 | }
271 |
272 | div.jsoneditor-tree button.jsoneditor-dragarea {
273 | background: url("img/jsoneditor-icons.svg") -72px -72px;
274 | cursor: move;
275 | }
276 |
277 | div.jsoneditor-tree button.jsoneditor-dragarea:hover,
278 | div.jsoneditor-tree button.jsoneditor-dragarea:focus,
279 | tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea {
280 | background-position: -72px -48px;
281 | }
282 |
283 | div.jsoneditor tr,
284 | div.jsoneditor th,
285 | div.jsoneditor td {
286 | padding: 0;
287 | margin: 0;
288 | }
289 |
290 | div.jsoneditor td {
291 | vertical-align: top;
292 | }
293 |
294 | div.jsoneditor td.jsoneditor-tree {
295 | vertical-align: top;
296 | }
297 |
298 | div.jsoneditor-field,
299 | div.jsoneditor-value,
300 | div.jsoneditor td,
301 | div.jsoneditor th,
302 | div.jsoneditor textarea,
303 | .jsoneditor-schema-error {
304 | font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif;
305 | font-size: 10pt;
306 | color: #1A1A1A;
307 | }
308 |
309 | /* popover */
310 |
311 | .jsoneditor-schema-error {
312 | cursor: default;
313 | display: inline-block;
314 | /*font-family: arial, sans-serif;*/
315 | height: 24px;
316 | line-height: 24px;
317 | position: relative;
318 | text-align: center;
319 | width: 24px;
320 | }
321 |
322 | div.jsoneditor-tree .jsoneditor-schema-error {
323 | width: 24px;
324 | height: 24px;
325 | padding: 0;
326 | margin: 0 4px 0 0;
327 | background: url("img/jsoneditor-icons.svg") -168px -48px;
328 | }
329 |
330 | .jsoneditor-schema-error .jsoneditor-popover {
331 | background-color: #4c4c4c;
332 | border-radius: 3px;
333 | box-shadow: 0 0 5px rgba(0,0,0,0.4);
334 | color: #fff;
335 | display: none;
336 | padding: 7px 10px;
337 | position: absolute;
338 | width: 200px;
339 | z-index: 4;
340 | }
341 |
342 | .jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above {
343 | bottom: 32px;
344 | left: -98px;
345 | }
346 |
347 | .jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below {
348 | top: 32px;
349 | left: -98px;
350 | }
351 |
352 | .jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left {
353 | top: -7px;
354 | right: 32px;
355 | }
356 |
357 | .jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right {
358 | top: -7px;
359 | left: 32px;
360 | }
361 |
362 | .jsoneditor-schema-error .jsoneditor-popover:before {
363 | border-right: 7px solid transparent;
364 | border-left: 7px solid transparent;
365 | content: '';
366 | display: block;
367 | left: 50%;
368 | margin-left: -7px;
369 | position: absolute;
370 | }
371 |
372 | .jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above:before {
373 | border-top: 7px solid #4c4c4c;
374 | bottom: -7px;
375 | }
376 |
377 | .jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below:before {
378 | border-bottom: 7px solid #4c4c4c;
379 | top: -7px;
380 | }
381 |
382 | .jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left:before {
383 | border-left: 7px solid #4c4c4c;
384 | border-top: 7px solid transparent;
385 | border-bottom: 7px solid transparent;
386 | content: '';
387 | top: 19px;
388 | right: -14px;
389 | left: inherit;
390 | margin-left: inherit;
391 | margin-top: -7px;
392 | position: absolute;
393 | }
394 |
395 | .jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right:before {
396 | border-right: 7px solid #4c4c4c;
397 | border-top: 7px solid transparent;
398 | border-bottom: 7px solid transparent;
399 | content: '';
400 | top: 19px;
401 | left: -14px;
402 | margin-left: inherit;
403 | margin-top: -7px;
404 | position: absolute;
405 | }
406 |
407 | .jsoneditor-schema-error:hover .jsoneditor-popover,
408 | .jsoneditor-schema-error:focus .jsoneditor-popover {
409 | display: block;
410 | -webkit-animation: fade-in .3s linear 1, move-up .3s linear 1;
411 | -moz-animation: fade-in .3s linear 1, move-up .3s linear 1;
412 | -ms-animation: fade-in .3s linear 1, move-up .3s linear 1;
413 | }
414 |
415 | @-webkit-keyframes fade-in {
416 | from {
417 | opacity: 0;
418 | }
419 |
420 | to {
421 | opacity: 1;
422 | }
423 | }
424 |
425 | @-moz-keyframes fade-in {
426 | from {
427 | opacity: 0;
428 | }
429 |
430 | to {
431 | opacity: 1;
432 | }
433 | }
434 |
435 | @-ms-keyframes fade-in {
436 | from {
437 | opacity: 0;
438 | }
439 |
440 | to {
441 | opacity: 1;
442 | }
443 | }
444 |
445 | /*@-webkit-keyframes move-up {*/
446 |
447 | /*from { bottom: 24px; }*/
448 |
449 | /*to { bottom: 32px; }*/
450 |
451 | /*}*/
452 |
453 | /*@-moz-keyframes move-up {*/
454 |
455 | /*from { bottom: 24px; }*/
456 |
457 | /*to { bottom: 32px; }*/
458 |
459 | /*}*/
460 |
461 | /*@-ms-keyframes move-up {*/
462 |
463 | /*from { bottom: 24px; }*/
464 |
465 | /*to { bottom: 32px; }*/
466 |
467 | /*}*/
468 |
469 | /* JSON schema errors displayed at the bottom of the editor in mode text and code */
470 |
471 | .jsoneditor .jsoneditor-text-errors {
472 | width: 100%;
473 | border-collapse: collapse;
474 | background-color: #ffef8b;
475 | border-top: 1px solid #ffd700;
476 | }
477 |
478 | .jsoneditor .jsoneditor-text-errors td {
479 | padding: 3px 6px;
480 | vertical-align: middle;
481 | }
482 |
483 | .jsoneditor-text-errors .jsoneditor-schema-error {
484 | border: none;
485 | width: 24px;
486 | height: 24px;
487 | padding: 0;
488 | margin: 0 4px 0 0;
489 | background: url("img/jsoneditor-icons.svg") -168px -48px;
490 | }
491 | /* ContextMenu - main menu */
492 |
493 | div.jsoneditor-contextmenu-root {
494 | position: relative;
495 | width: 0;
496 | height: 0;
497 | }
498 |
499 | div.jsoneditor-contextmenu {
500 | position: absolute;
501 | box-sizing: content-box;
502 | z-index: 99999;
503 | }
504 |
505 | div.jsoneditor-contextmenu ul,
506 | div.jsoneditor-contextmenu li {
507 | box-sizing: content-box;
508 | }
509 |
510 | div.jsoneditor-contextmenu ul {
511 | position: relative;
512 | left: 0;
513 | top: 0;
514 | width: 124px;
515 | background: white;
516 | border: 1px solid #d3d3d3;
517 | box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3);
518 | list-style: none;
519 | margin: 0;
520 | padding: 0;
521 | }
522 |
523 | div.jsoneditor-contextmenu ul li button {
524 | padding: 0;
525 | margin: 0;
526 | width: 124px;
527 | height: 24px;
528 | border: none;
529 | cursor: pointer;
530 | color: #4d4d4d;
531 | background: transparent;
532 | font-size: 10pt;
533 | font-family: arial, sans-serif;
534 | box-sizing: border-box;
535 | line-height: 26px;
536 | text-align: left;
537 | }
538 |
539 | /* Fix button padding in firefox */
540 |
541 | div.jsoneditor-contextmenu ul li button::-moz-focus-inner {
542 | padding: 0;
543 | border: 0;
544 | }
545 |
546 | div.jsoneditor-contextmenu ul li button:hover,
547 | div.jsoneditor-contextmenu ul li button:focus {
548 | color: #1a1a1a;
549 | background-color: #f5f5f5;
550 | outline: none;
551 | }
552 |
553 | div.jsoneditor-contextmenu ul li button.jsoneditor-default {
554 | width: 92px;
555 | }
556 |
557 | div.jsoneditor-contextmenu ul li button.jsoneditor-expand {
558 | float: right;
559 | width: 32px;
560 | height: 24px;
561 | border-left: 1px solid #e5e5e5;
562 | }
563 |
564 | div.jsoneditor-contextmenu div.jsoneditor-icon {
565 | float: left;
566 | width: 24px;
567 | height: 24px;
568 | border: none;
569 | padding: 0;
570 | margin: 0;
571 | background-image: url("img/jsoneditor-icons.svg");
572 | }
573 |
574 | div.jsoneditor-contextmenu ul li button div.jsoneditor-expand {
575 | float: right;
576 | width: 24px;
577 | height: 24px;
578 | padding: 0;
579 | margin: 0 4px 0 0;
580 | background: url("img/jsoneditor-icons.svg") 0 -72px;
581 | opacity: 0.4;
582 | }
583 |
584 | div.jsoneditor-contextmenu ul li button:hover div.jsoneditor-expand,
585 | div.jsoneditor-contextmenu ul li button:focus div.jsoneditor-expand,
586 | div.jsoneditor-contextmenu ul li.jsoneditor-selected div.jsoneditor-expand,
587 | div.jsoneditor-contextmenu ul li button.jsoneditor-expand:hover div.jsoneditor-expand,
588 | div.jsoneditor-contextmenu ul li button.jsoneditor-expand:focus div.jsoneditor-expand {
589 | opacity: 1;
590 | }
591 |
592 | div.jsoneditor-contextmenu div.jsoneditor-separator {
593 | height: 0;
594 | border-top: 1px solid #e5e5e5;
595 | padding-top: 5px;
596 | margin-top: 5px;
597 | }
598 |
599 | div.jsoneditor-contextmenu button.jsoneditor-remove > div.jsoneditor-icon {
600 | background-position: -24px -24px;
601 | }
602 |
603 | div.jsoneditor-contextmenu button.jsoneditor-remove:hover > div.jsoneditor-icon,
604 | div.jsoneditor-contextmenu button.jsoneditor-remove:focus > div.jsoneditor-icon {
605 | background-position: -24px 0;
606 | }
607 |
608 | div.jsoneditor-contextmenu button.jsoneditor-append > div.jsoneditor-icon {
609 | background-position: 0 -24px;
610 | }
611 |
612 | div.jsoneditor-contextmenu button.jsoneditor-append:hover > div.jsoneditor-icon,
613 | div.jsoneditor-contextmenu button.jsoneditor-append:focus > div.jsoneditor-icon {
614 | background-position: 0 0;
615 | }
616 |
617 | div.jsoneditor-contextmenu button.jsoneditor-insert > div.jsoneditor-icon {
618 | background-position: 0 -24px;
619 | }
620 |
621 | div.jsoneditor-contextmenu button.jsoneditor-insert:hover > div.jsoneditor-icon,
622 | div.jsoneditor-contextmenu button.jsoneditor-insert:focus > div.jsoneditor-icon {
623 | background-position: 0 0;
624 | }
625 |
626 | div.jsoneditor-contextmenu button.jsoneditor-duplicate > div.jsoneditor-icon {
627 | background-position: -48px -24px;
628 | }
629 |
630 | div.jsoneditor-contextmenu button.jsoneditor-duplicate:hover > div.jsoneditor-icon,
631 | div.jsoneditor-contextmenu button.jsoneditor-duplicate:focus > div.jsoneditor-icon {
632 | background-position: -48px 0;
633 | }
634 |
635 | div.jsoneditor-contextmenu button.jsoneditor-sort-asc > div.jsoneditor-icon {
636 | background-position: -168px -24px;
637 | }
638 |
639 | div.jsoneditor-contextmenu button.jsoneditor-sort-asc:hover > div.jsoneditor-icon,
640 | div.jsoneditor-contextmenu button.jsoneditor-sort-asc:focus > div.jsoneditor-icon {
641 | background-position: -168px 0;
642 | }
643 |
644 | div.jsoneditor-contextmenu button.jsoneditor-sort-desc > div.jsoneditor-icon {
645 | background-position: -192px -24px;
646 | }
647 |
648 | div.jsoneditor-contextmenu button.jsoneditor-sort-desc:hover > div.jsoneditor-icon,
649 | div.jsoneditor-contextmenu button.jsoneditor-sort-desc:focus > div.jsoneditor-icon {
650 | background-position: -192px 0;
651 | }
652 |
653 | /* ContextMenu - sub menu */
654 |
655 | div.jsoneditor-contextmenu ul li button.jsoneditor-selected,
656 | div.jsoneditor-contextmenu ul li button.jsoneditor-selected:hover,
657 | div.jsoneditor-contextmenu ul li button.jsoneditor-selected:focus {
658 | color: white;
659 | background-color: #ee422e;
660 | }
661 |
662 | div.jsoneditor-contextmenu ul li {
663 | overflow: hidden;
664 | }
665 |
666 | div.jsoneditor-contextmenu ul li ul {
667 | display: none;
668 | position: relative;
669 | left: -10px;
670 | top: 0;
671 | border: none;
672 | box-shadow: inset 0 0 10px rgba(128, 128, 128, 0.5);
673 | padding: 0 10px;
674 | /* TODO: transition is not supported on IE8-9 */
675 | -webkit-transition: all 0.3s ease-out;
676 | -moz-transition: all 0.3s ease-out;
677 | -o-transition: all 0.3s ease-out;
678 | transition: all 0.3s ease-out;
679 | }
680 |
681 |
682 |
683 | div.jsoneditor-contextmenu ul li ul li button {
684 | padding-left: 24px;
685 | animation: all ease-in-out 1s;
686 | }
687 |
688 | div.jsoneditor-contextmenu ul li ul li button:hover,
689 | div.jsoneditor-contextmenu ul li ul li button:focus {
690 | background-color: #f5f5f5;
691 | }
692 |
693 | div.jsoneditor-contextmenu button.jsoneditor-type-string > div.jsoneditor-icon {
694 | background-position: -144px -24px;
695 | }
696 |
697 | div.jsoneditor-contextmenu button.jsoneditor-type-string:hover > div.jsoneditor-icon,
698 | div.jsoneditor-contextmenu button.jsoneditor-type-string:focus > div.jsoneditor-icon,
699 | div.jsoneditor-contextmenu button.jsoneditor-type-string.jsoneditor-selected > div.jsoneditor-icon {
700 | background-position: -144px 0;
701 | }
702 |
703 | div.jsoneditor-contextmenu button.jsoneditor-type-auto > div.jsoneditor-icon {
704 | background-position: -120px -24px;
705 | }
706 |
707 | div.jsoneditor-contextmenu button.jsoneditor-type-auto:hover > div.jsoneditor-icon,
708 | div.jsoneditor-contextmenu button.jsoneditor-type-auto:focus > div.jsoneditor-icon,
709 | div.jsoneditor-contextmenu button.jsoneditor-type-auto.jsoneditor-selected > div.jsoneditor-icon {
710 | background-position: -120px 0;
711 | }
712 |
713 | div.jsoneditor-contextmenu button.jsoneditor-type-object > div.jsoneditor-icon {
714 | background-position: -72px -24px;
715 | }
716 |
717 | div.jsoneditor-contextmenu button.jsoneditor-type-object:hover > div.jsoneditor-icon,
718 | div.jsoneditor-contextmenu button.jsoneditor-type-object:focus > div.jsoneditor-icon,
719 | div.jsoneditor-contextmenu button.jsoneditor-type-object.jsoneditor-selected > div.jsoneditor-icon {
720 | background-position: -72px 0;
721 | }
722 |
723 | div.jsoneditor-contextmenu button.jsoneditor-type-array > div.jsoneditor-icon {
724 | background-position: -96px -24px;
725 | }
726 |
727 | div.jsoneditor-contextmenu button.jsoneditor-type-array:hover > div.jsoneditor-icon,
728 | div.jsoneditor-contextmenu button.jsoneditor-type-array:focus > div.jsoneditor-icon,
729 | div.jsoneditor-contextmenu button.jsoneditor-type-array.jsoneditor-selected > div.jsoneditor-icon {
730 | background-position: -96px 0;
731 | }
732 |
733 | div.jsoneditor-contextmenu button.jsoneditor-type-modes > div.jsoneditor-icon {
734 | background-image: none;
735 | width: 6px;
736 | }
737 | div.jsoneditor-menu {
738 | width: 100%;
739 | height: 35px;
740 | padding: 2px;
741 | margin: 0;
742 | -moz-box-sizing: border-box;
743 | -webkit-box-sizing: border-box;
744 | box-sizing: border-box;
745 | color: white;
746 | background-color: #CCCCCC;
747 | border-bottom: 1px solid #CCCCCC;
748 | }
749 |
750 | div.jsoneditor-menu > button,
751 | div.jsoneditor-menu > div.jsoneditor-modes > button {
752 | width: 26px;
753 | height: 26px;
754 | margin: 2px;
755 | padding: 0;
756 | border-radius: 2px;
757 | border: 1px solid transparent;
758 | background: transparent url("img/jsoneditor-icons.svg");
759 | color: white;
760 | opacity: 0.8;
761 | font-family: arial, sans-serif;
762 | font-size: 10pt;
763 | float: left;
764 | }
765 |
766 | div.jsoneditor-menu > button:hover,
767 | div.jsoneditor-menu > div.jsoneditor-modes > button:hover {
768 | background-color: rgba(255,255,255,0.2);
769 | border: 1px solid rgba(255,255,255,0.4);
770 | }
771 |
772 | div.jsoneditor-menu > button:focus,
773 | div.jsoneditor-menu > button:active,
774 | div.jsoneditor-menu > div.jsoneditor-modes > button:focus,
775 | div.jsoneditor-menu > div.jsoneditor-modes > button:active {
776 | background-color: rgba(255,255,255,0.3);
777 | }
778 |
779 | div.jsoneditor-menu > button:disabled,
780 | div.jsoneditor-menu > div.jsoneditor-modes > button:disabled {
781 | opacity: 0.5;
782 | }
783 |
784 | div.jsoneditor-menu > button.jsoneditor-collapse-all {
785 | background-position: 0 -96px;
786 | }
787 |
788 | div.jsoneditor-menu > button.jsoneditor-expand-all {
789 | background-position: 0 -120px;
790 | }
791 |
792 | div.jsoneditor-menu > button.jsoneditor-undo {
793 | background-position: -24px -96px;
794 | }
795 |
796 | div.jsoneditor-menu > button.jsoneditor-undo:disabled {
797 | background-position: -24px -120px;
798 | }
799 |
800 | div.jsoneditor-menu > button.jsoneditor-redo {
801 | background-position: -48px -96px;
802 | }
803 |
804 | div.jsoneditor-menu > button.jsoneditor-redo:disabled {
805 | background-position: -48px -120px;
806 | }
807 |
808 | div.jsoneditor-menu > button.jsoneditor-compact {
809 | background-position: -72px -96px;
810 | }
811 |
812 | div.jsoneditor-menu > button.jsoneditor-format {
813 | background-position: -72px -120px;
814 | }
815 |
816 | div.jsoneditor-menu > div.jsoneditor-modes {
817 | display: inline-block;
818 | float: left;
819 | }
820 |
821 | div.jsoneditor-menu > div.jsoneditor-modes > button {
822 | background-image: none;
823 | width: auto;
824 | padding-left: 6px;
825 | padding-right: 6px;
826 | }
827 |
828 | div.jsoneditor-menu > button.jsoneditor-separator,
829 | div.jsoneditor-menu > div.jsoneditor-modes > button.jsoneditor-separator {
830 | margin-left: 10px;
831 | }
832 |
833 | div.jsoneditor-menu a {
834 | font-family: arial, sans-serif;
835 | font-size: 10pt;
836 | color: white;
837 | opacity: 0.8;
838 | vertical-align: middle;
839 | }
840 |
841 | div.jsoneditor-menu a:hover {
842 | opacity: 1;
843 | }
844 |
845 | div.jsoneditor-menu a.jsoneditor-poweredBy {
846 | font-size: 8pt;
847 | position: absolute;
848 | right: 0;
849 | top: 0;
850 | padding: 10px;
851 | }
852 | table.jsoneditor-search input,
853 | table.jsoneditor-search div.jsoneditor-results {
854 | font-family: arial, sans-serif;
855 | font-size: 10pt;
856 | color: #1A1A1A;
857 | background: transparent;
858 | /* For Firefox */
859 | }
860 |
861 | table.jsoneditor-search div.jsoneditor-results {
862 | color: white;
863 | padding-right: 5px;
864 | line-height: 24px;
865 | }
866 |
867 | table.jsoneditor-search {
868 | position: absolute;
869 | right: 4px;
870 | top: 4px;
871 | border-collapse: collapse;
872 | border-spacing: 0;
873 | }
874 |
875 | table.jsoneditor-search div.jsoneditor-frame {
876 | border: 1px solid transparent;
877 | background-color: white;
878 | padding: 0 2px;
879 | margin: 0;
880 | }
881 |
882 | table.jsoneditor-search div.jsoneditor-frame table {
883 | border-collapse: collapse;
884 | }
885 |
886 | table.jsoneditor-search input {
887 | width: 120px;
888 | border: none;
889 | outline: none;
890 | margin: 1px;
891 | line-height: 20px;
892 | }
893 |
894 | table.jsoneditor-search button {
895 | width: 16px;
896 | height: 24px;
897 | padding: 0;
898 | margin: 0;
899 | border: none;
900 | background: url("img/jsoneditor-icons.svg");
901 | vertical-align: top;
902 | }
903 |
904 | table.jsoneditor-search button:hover {
905 | background-color: transparent;
906 | }
907 |
908 | table.jsoneditor-search button.jsoneditor-refresh {
909 | width: 18px;
910 | background-position: -99px -73px;
911 | }
912 |
913 | table.jsoneditor-search button.jsoneditor-next {
914 | cursor: pointer;
915 | background-position: -124px -73px;
916 | }
917 |
918 | table.jsoneditor-search button.jsoneditor-next:hover {
919 | background-position: -124px -49px;
920 | }
921 |
922 | table.jsoneditor-search button.jsoneditor-previous {
923 | cursor: pointer;
924 | background-position: -148px -73px;
925 | margin-right: 2px;
926 | }
927 |
928 | table.jsoneditor-search button.jsoneditor-previous:hover {
929 | background-position: -148px -49px;
930 | }
--------------------------------------------------------------------------------
/behaviortree-editor/panel/img/jsoneditor-icons.svg:
--------------------------------------------------------------------------------
1 |
2 |
16 | JSON Editor Icons
18 |
20 |
21 |
23 | image/svg+xml
24 |
26 | JSON Editor Icons
27 |
28 |
29 |
30 |
32 |
56 |
60 |
61 |
62 |
64 |
71 |
78 |
85 |
92 |
99 |
102 |
109 |
116 |
117 |
121 |
128 |
135 |
136 |
143 |
150 |
157 |
159 |
166 |
173 |
180 |
181 |
184 |
191 |
198 |
205 |
206 |
213 |
219 |
225 |
232 |
237 |
242 |
249 |
255 |
260 |
267 |
273 |
279 |
280 |
287 |
294 |
301 |
308 |
315 |
319 |
326 |
333 |
334 |
338 |
345 |
352 |
353 |
360 |
367 |
374 |
377 |
384 |
391 |
398 |
399 |
402 |
409 |
416 |
423 |
424 |
431 |
437 |
443 |
450 |
455 |
460 |
467 |
473 |
478 |
485 |
491 |
497 |
504 |
511 |
518 |
525 |
532 |
539 |
546 |
552 |
560 |
566 |
572 |
579 |
587 |
595 |
602 |
609 |
616 |
623 |
630 |
637 |
644 |
651 |
657 |
665 |
671 |
677 |
684 |
692 |
700 |
707 |
714 |
721 |
728 |
735 |
742 |
749 |
756 |
761 |
766 |
771 |
777 |
783 |
788 |
793 |
798 |
803 |
808 |
824 |
841 |
858 |
875 |
881 |
887 |
893 |
894 |
--------------------------------------------------------------------------------
/behaviortree-editor/b3core.0.1.0module.js:
--------------------------------------------------------------------------------
1 | /**
2 | * b3
3 | *
4 | * Copyright (c) 2014 Renato de Pontes Pereira.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to
8 | * deal in the Software without restriction, including without limitation the
9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | * sell copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 | * IN THE SOFTWARE.
23 | **/
24 |
25 | //this.b3 = this.b3 || {};
26 | let b3 = {};
27 |
28 | /**
29 | * Behavior3JS
30 | * ===========
31 | *
32 | * * * *
33 | *
34 | * **Behavior3JS** is a Behavior Tree library written in JavaScript. It
35 | * provides structures and algorithms that assist you in the task of creating
36 | * intelligent agents for your game or application. Check it out some features
37 | * of Behavior3JS:
38 | *
39 | * - Based on the work of (Marzinotto et al., 2014), in which they propose a
40 | * **formal**, **consistent** and **general** definition of Behavior Trees;
41 | * - **Optimized to control multiple agents**: you can use a single behavior
42 | * tree instance to handle hundreds of agents;
43 | * - It was **designed to load and save trees in a JSON format**, in order to
44 | * use, edit and test it in multiple environments, tools and languages;
45 | * - A **cool visual editor** which you can access online;
46 | * - Several **composite, decorator and action nodes** available within the
47 | * library. You still can define your own nodes, including composites and
48 | * decorators;
49 | * - **Completely free**, the core module and the visual editor are all published
50 | * under the MIT License, which means that you can use them for your open source
51 | * and commercial projects;
52 | * - **Lightweight**, only 11.5KB!
53 | *
54 | * Visit http://behavior3js.guineashots.com to know more!
55 | *
56 | *
57 | * Core Classes and Functions
58 | * --------------------------
59 | *
60 | * This library include the following core structures...
61 | *
62 | * **Public:**
63 | *
64 | * - **BehaviorTree**: the structure that represents a Behavior Tree;
65 | * - **Blackboard**: represents a "memory" in an agent and is required to to
66 | * run a `BehaviorTree`;
67 | * - **Composite**: base class for all composite nodes;
68 | * - **Decorator**: base class for all decorator nodes;
69 | * - **Action**: base class for all action nodes;
70 | * - **Condition**: base class for all condition nodes;
71 | *
72 | * **Internal:**
73 | *
74 | *
75 | * - **Tick**: used as container and tracking object through the tree during
76 | * the tick signal;
77 | * - **BaseNode**: the base class that provide all common node features;
78 | *
79 | * *Some classes are used internally on Behavior3JS, but you may need to access
80 | * its functionalities eventually, specially the `Tick` object.*
81 | *
82 | *
83 | * Nodes Included
84 | * --------------
85 | *
86 | * **Composite Nodes**:
87 | *
88 | * - Sequence;
89 | * - Priority;
90 | * - MemSequence;
91 | * - MemPriority;
92 | *
93 | *
94 | * **Decorators**:
95 | *
96 | * - Inverter;
97 | * - Limiter
98 | * - MaxTime;
99 | * - Repeater;
100 | * - RepeaterUntilFailure;
101 | * - RepeaterUntilSuccess;
102 | *
103 | *
104 | * **Actions**:
105 | *
106 | * - Succeeder;
107 | * - Failer;
108 | * - Error;
109 | * - Runner;
110 | * - Wait.
111 | *
112 | * @module Behavior3JS
113 | * @main Behavior3JS
114 | **/
115 |
116 | (function() {
117 | "use strict";
118 |
119 | /**
120 | * List of all constants in Behavior3JS.
121 | *
122 | * @class Constants
123 | **/
124 |
125 | /**
126 | * Version of the library.
127 | *
128 | * @property VERSION
129 | * @type {String}
130 | */
131 | b3.VERSION = '0.1.0';
132 |
133 | /**
134 | * Returned when a criterion has been met by a condition node or an action node
135 | * has been completed successfully.
136 | *
137 | * @property SUCCESS
138 | * @type {Integer}
139 | */
140 | b3.SUCCESS = 1;
141 |
142 | /**
143 | * Returned when a criterion has not been met by a condition node or an action
144 | * node could not finish its execution for any reason.
145 | *
146 | * @property FAILURE
147 | * @type {Integer}
148 | */
149 | b3.FAILURE = 2;
150 |
151 | /**
152 | * Returned when an action node has been initialized but is still waiting the
153 | * its resolution.
154 | *
155 | * @property FAILURE
156 | * @type {Integer}
157 | */
158 | b3.RUNNING = 3;
159 |
160 | /**
161 | * Returned when some unexpected error happened in the tree, probably by a
162 | * programming error (trying to verify an undefined variable). Its use depends
163 | * on the final implementation of the leaf nodes.
164 | *
165 | * @property ERROR
166 | * @type {Integer}
167 | */
168 | b3.ERROR = 4;
169 |
170 |
171 | /**
172 | * Describes the node category as Composite.
173 | *
174 | * @property COMPOSITE
175 | * @type {String}
176 | */
177 | b3.COMPOSITE = 'composite';
178 |
179 | /**
180 | * Describes the node category as Decorator.
181 | *
182 | * @property DECORATOR
183 | * @type {String}
184 | */
185 | b3.DECORATOR = 'decorator';
186 |
187 | /**
188 | * Describes the node category as Action.
189 | *
190 | * @property ACTION
191 | * @type {String}
192 | */
193 | b3.ACTION = 'action';
194 |
195 | /**
196 | * Describes the node category as Condition.
197 | *
198 | * @property CONDITION
199 | * @type {String}
200 | */
201 | b3.CONDITION = 'condition';
202 |
203 |
204 | /**
205 | * List of internal and helper functions in Behavior3JS.
206 | *
207 | * @class Utils
208 | **/
209 |
210 |
211 | /**
212 | * This function is used to create unique IDs for trees and nodes.
213 | *
214 | * (consult http://www.ietf.org/rfc/rfc4122.txt).
215 | *
216 | * @method createUUID
217 | * @return {String} A unique ID.
218 | **/
219 | b3.createUUID = function() {
220 | var s = [];
221 | var hexDigits = "0123456789abcdef";
222 | for (var i = 0; i < 36; i++) {
223 | s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
224 | }
225 | // bits 12-15 of the time_hi_and_version field to 0010
226 | s[14] = "4";
227 |
228 | // bits 6-7 of the clock_seq_hi_and_reserved to 01
229 | s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
230 |
231 | s[8] = s[13] = s[18] = s[23] = "-";
232 |
233 | var uuid = s.join("");
234 | return uuid;
235 | }
236 |
237 | /**
238 | * Class is a meta-factory function to create classes in JavaScript. It is a
239 | * shortcut for the CreateJS syntax style. By default, the class created by
240 | * this function have an initialize function (the constructor). Optionally, you
241 | * can specify the inheritance by passing another class as parameter.
242 | *
243 | * By default, all classes created using this function, may receives only a
244 | * settings parameter as argument. This pattern is commonly used by jQuery and
245 | * its plugins.
246 | *
247 | * Usage
248 | * -----
249 | *
250 | * // Creating a simple class
251 | * var BaseClass = b3.Class();
252 | *
253 | * // Using inheritance
254 | * var ChildClass = b3.Class(BaseClass);
255 | *
256 | * // Defining the constructor
257 | * ChildClass.prototype.initialize = function(settings) { ... }
258 | *
259 | * @method Class
260 | * @param {Object} [baseClass] The super class.
261 | * @return {Object} A new class.
262 | **/
263 | b3.Class = function(baseClass) {
264 | // create a new class
265 | var cls = function(params) {
266 | this.initialize(params);
267 | }
268 |
269 | // if base class is provided, inherit
270 | if (baseClass) {
271 | cls.prototype = new baseClass();
272 | cls.prototype.constructor = cls;
273 | }
274 |
275 | // create initialize if does not exist on baseClass
276 | cls.prototype.initialize = cls.prototype.initialize || function() {};
277 |
278 | return cls;
279 | }
280 |
281 | })();/**
282 | * Blackboard
283 | *
284 | * Copyright (c) 2014 Renato de Pontes Pereira.
285 | *
286 | * Permission is hereby granted, free of charge, to any person obtaining a copy
287 | * of this software and associated documentation files (the "Software"), to
288 | * deal in the Software without restriction, including without limitation the
289 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
290 | * sell copies of the Software, and to permit persons to whom the Software is
291 | * furnished to do so, subject to the following conditions:
292 | *
293 | * The above copyright notice and this permission notice shall be included in
294 | * all copies or substantial portions of the Software.
295 | *
296 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
297 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
298 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
299 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
300 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
301 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
302 | * IN THE SOFTWARE.
303 | **/
304 |
305 | /**
306 | * @module Behavior3JS
307 | **/
308 |
309 | // namespace:
310 | //this.b3 = this.b3 || {};
311 |
312 | (function() {
313 | "use strict";
314 |
315 | /**
316 | * The Blackboard is the memory structure required by `BehaviorTree` and its
317 | * nodes. It only have 2 public methods: `set` and `get`. These methods works
318 | * in 3 different contexts: global, per tree, and per node per tree.
319 | *
320 | * Suppose you have two different trees controlling a single object with a
321 | * single blackboard, then:
322 | *
323 | * - In the global context, all nodes will access the stored information.
324 | * - In per tree context, only nodes sharing the same tree share the stored
325 | * information.
326 | * - In per node per tree context, the information stored in the blackboard can
327 | * only be accessed by the same node that wrote the data.
328 | *
329 | * The context is selected indirectly by the parameters provided to these
330 | * methods, for example:
331 | *
332 | * // getting/setting variable in global context
333 | * blackboard.set('testKey', 'value');
334 | * var value = blackboard.get('testKey');
335 | *
336 | * // getting/setting variable in per tree context
337 | * blackboard.set('testKey', 'value', tree.id);
338 | * var value = blackboard.get('testKey', tree.id);
339 | *
340 | * // getting/setting variable in per node per tree context
341 | * blackboard.set('testKey', 'value', tree.id, node.id);
342 | * var value = blackboard.get('testKey', tree.id, node.id);
343 | *
344 | * Note: Internally, the blackboard store these memories in different objects,
345 | * being the global on `_baseMemory`, the per tree on `_treeMemory` and the
346 | * per node per tree dynamically create inside the per tree memory (it is
347 | * accessed via `_treeMemory[id].nodeMemory`). Avoid to use these variables
348 | * manually, use `get` and `set` instead.
349 | *
350 | * @class Blackboard
351 | **/
352 | var Blackboard = b3.Class();
353 |
354 | var p = Blackboard.prototype;
355 |
356 | /**
357 | * Initialization method.
358 | *
359 | * @method initialize
360 | * @constructor
361 | **/
362 | p.initialize = function() {
363 | this._baseMemory = {};
364 | this._treeMemory = {};
365 | }
366 |
367 | /**
368 | * Internal method to retrieve the tree context memory. If the memory does
369 | * not exist, this method creates it.
370 | *
371 | * @method _getTreeMemory
372 | * @param {string} treeScope The id of the tree in scope.
373 | * @returns {Object} The tree memory.
374 | * @protected
375 | **/
376 | p._getTreeMemory = function(treeScope) {
377 | if (!this._treeMemory[treeScope]) {
378 | this._treeMemory[treeScope] = {
379 | 'nodeMemory' : {},
380 | 'openNodes' : [],
381 | 'traversalDepth' : 0,
382 | 'traversalCycle' : 0,
383 | };
384 | }
385 | return this._treeMemory[treeScope];
386 | };
387 |
388 | /**
389 | * Internal method to retrieve the node context memory, given the tree
390 | * memory. If the memory does not exist, this method creates is.
391 | *
392 | * @method _getNodeMemory
393 | * @param {String} treeMemory the tree memory.
394 | * @param {String} nodeScope The id of the node in scope.
395 | * @returns {Object} The node memory.
396 | * @protected
397 | **/
398 | p._getNodeMemory = function(treeMemory, nodeScope) {
399 | var memory = treeMemory['nodeMemory'];
400 | if (!memory[nodeScope]) {
401 | memory[nodeScope] = {};
402 | }
403 |
404 | return memory[nodeScope];
405 | };
406 |
407 | /**
408 | * Internal method to retrieve the context memory. If treeScope and
409 | * nodeScope are provided, this method returns the per node per tree
410 | * memory. If only the treeScope is provided, it returns the per tree
411 | * memory. If no parameter is provided, it returns the global memory.
412 | * Notice that, if only nodeScope is provided, this method will still
413 | * return the global memory.
414 | *
415 | * @method _getMemory
416 | * @param {String} treeScope The id of the tree scope.
417 | * @param {String} nodeScope The id of the node scope.
418 | * @returns {Object} A memory object.
419 | * @protected
420 | **/
421 | p._getMemory = function(treeScope, nodeScope) {
422 | var memory = this._baseMemory;
423 |
424 | if (treeScope) {
425 | memory = this._getTreeMemory(treeScope);
426 |
427 | if (nodeScope) {
428 | memory = this._getNodeMemory(memory, nodeScope);
429 | }
430 | }
431 |
432 | return memory;
433 | };
434 |
435 | /**
436 | * Stores a value in the blackboard. If treeScope and nodeScope are
437 | * provided, this method will save the value into the per node per tree
438 | * memory. If only the treeScope is provided, it will save the value into
439 | * the per tree memory. If no parameter is provided, this method will save
440 | * the value into the global memory. Notice that, if only nodeScope is
441 | * provided (but treeScope not), this method will still save the value into
442 | * the global memory.
443 | *
444 | * @method set
445 | * @param {String} key The key to be stored.
446 | * @param {String} value The value to be stored.
447 | * @param {String} treeScope The tree id if accessing the tree or node
448 | * memory.
449 | * @param {String} nodeScope The node id if accessing the node memory.
450 | **/
451 | p.set = function(key, value, treeScope, nodeScope) {
452 | var memory = this._getMemory(treeScope, nodeScope);
453 | memory[key] = value;
454 | };
455 |
456 | /**
457 | * Retrieves a value in the blackboard. If treeScope and nodeScope are
458 | * provided, this method will retrieve the value from the per node per tree
459 | * memory. If only the treeScope is provided, it will retrieve the value
460 | * from the per tree memory. If no parameter is provided, this method will
461 | * retrieve from the global memory. If only nodeScope is provided (but
462 | * treeScope not), this method will still try to retrieve from the global
463 | * memory.
464 | *
465 | * @method get
466 | * @param {String} key The key to be retrieved.
467 | * @param {String} treeScope The tree id if accessing the tree or node
468 | * memory.
469 | * @param {String} nodeScope The node id if accessing the node memory.
470 | * @returns {Object} The value stored or undefined.
471 | **/
472 | p.get = function(key, treeScope, nodeScope) {
473 | var memory = this._getMemory(treeScope, nodeScope);
474 | return memory[key];
475 | };
476 |
477 | b3.Blackboard = Blackboard;
478 |
479 | })();/**
480 | * Tick
481 | *
482 | * Copyright (c) 2014 Renato de Pontes Pereira.
483 | *
484 | * Permission is hereby granted, free of charge, to any person obtaining a copy
485 | * of this software and associated documentation files (the "Software"), to
486 | * deal in the Software without restriction, including without limitation the
487 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
488 | * sell copies of the Software, and to permit persons to whom the Software is
489 | * furnished to do so, subject to the following conditions:
490 | *
491 | * The above copyright notice and this permission notice shall be included in
492 | * all copies or substantial portions of the Software.
493 | *
494 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
495 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
496 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
497 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
498 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
499 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
500 | * IN THE SOFTWARE.
501 | **/
502 |
503 | /**
504 | * @module Behavior3JS
505 | **/
506 |
507 | // namespace:
508 | //this.b3 = this.b3 || {};
509 |
510 | (function() {
511 | "use strict";
512 |
513 | /**
514 | * A new Tick object is instantiated every tick by BehaviorTree. It is passed
515 | * as parameter to the nodes through the tree during the traversal.
516 | *
517 | * The role of the Tick class is to store the instances of tree, debug, target
518 | * and blackboard. So, all nodes can access these informations.
519 | *
520 | * For internal uses, the Tick also is useful to store the open node after the
521 | * tick signal, in order to let `BehaviorTree` to keep track and close them
522 | * when necessary.
523 | *
524 | * This class also makes a bridge between nodes and the debug, passing the node
525 | * state to the debug if the last is provided.
526 | *
527 | * @class Tick
528 | **/
529 | var Tick = b3.Class();
530 |
531 | var p = Tick.prototype;
532 |
533 | /**
534 | * The tree reference.
535 | *
536 | * @property tree
537 | * @type {b3.BehaviorTree}
538 | * @readOnly
539 | */
540 |
541 | /**
542 | * The debug reference.
543 | *
544 | * @property debug
545 | * @type {Object}
546 | * @readOnly
547 | */
548 |
549 | /**
550 | * The target object reference.
551 | *
552 | * @property target
553 | * @type {Object}
554 | * @readOnly
555 | */
556 |
557 | /**
558 | * The blackboard reference.
559 | *
560 | * @property blackboard
561 | * @type {Blackboard}
562 | * @readOnly
563 | */
564 |
565 | /**
566 | * The list of open nodes. Update during the tree traversal.
567 | *
568 | * @property _openNodes
569 | * @type {Array}
570 | * @protected
571 | * @readOnly
572 | */
573 |
574 | /**
575 | * The number of nodes entered during the tick. Update during the tree
576 | * traversal.
577 | *
578 | * @property _nodeCount
579 | * @type {Integer}
580 | * @protected
581 | * @readOnly
582 | */
583 |
584 | /**
585 | * Initialization method.
586 | *
587 | * @method initialize
588 | * @constructor
589 | **/
590 | p.initialize = function() {
591 | // set by BehaviorTree
592 | this.tree = null;
593 | this.debug = null;
594 | this.target = null;
595 | this.blackboard = null;
596 |
597 | // updated during the tick signal
598 | this._openNodes = [];
599 | this._nodeCount = 0;
600 | }
601 |
602 | /**
603 | * Called when entering a node (called by BaseNode).
604 | *
605 | * @method _enterNode
606 | * @param {Object} node The node that called this method.
607 | * @protected
608 | **/
609 | p._enterNode = function(node) {
610 | this._nodeCount++;
611 | this._openNodes.push(node);
612 |
613 | // TODO: call debug here
614 | }
615 |
616 | /**
617 | * Callback when opening a node (called by BaseNode).
618 | *
619 | * @method _openNode
620 | * @param {Object} node The node that called this method.
621 | * @protected
622 | **/
623 | p._openNode = function(node) {
624 | // TODO: call debug here
625 | }
626 |
627 | /**
628 | * Callback when ticking a node (called by BaseNode).
629 | *
630 | * @method _tickNode
631 | * @param {Object} node The node that called this method.
632 | * @protected
633 | **/
634 | p._tickNode = function(node) {
635 | // TODO: call debug here
636 | }
637 |
638 | /**
639 | * Callback when closing a node (called by BaseNode).
640 | *
641 | * @method _closeNode
642 | * @param {Object} node The node that called this method.
643 | * @protected
644 | **/
645 | p._closeNode = function(node) {
646 | // TODO: call debug here
647 | this._openNodes.pop();
648 | }
649 |
650 | /**
651 | * Callback when exiting a node (called by BaseNode).
652 | *
653 | * @method _exitNode
654 | * @param {Object} node The node that called this method.
655 | * @protected
656 | **/
657 | p._exitNode = function(node) {
658 | // TODO: call debug here
659 | }
660 |
661 | b3.Tick = Tick;
662 |
663 | })();/**
664 | * BehaviorTree
665 | *
666 | * Copyright (c) 2014 Renato de Pontes Pereira.
667 | *
668 | * Permission is hereby granted, free of charge, to any person obtaining a copy
669 | * of this software and associated documentation files (the "Software"), to
670 | * deal in the Software without restriction, including without limitation the
671 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
672 | * sell copies of the Software, and to permit persons to whom the Software is
673 | * furnished to do so, subject to the following conditions:
674 | *
675 | * The above copyright notice and this permission notice shall be included in
676 | * all copies or substantial portions of the Software.
677 | *
678 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
679 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
680 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
681 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
682 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
683 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
684 | * IN THE SOFTWARE.
685 | **/
686 |
687 | /**
688 | * @module Behavior3JS
689 | **/
690 |
691 | // namespace:
692 | //this.b3 = this.b3 || {};
693 |
694 | (function() {
695 | "use strict";
696 |
697 | /**
698 | * The BehaviorTree class, as the name implies, represents the Behavior Tree
699 | * structure.
700 | *
701 | * There are two ways to construct a Behavior Tree: by manually setting the
702 | * root node, or by loading it from a data structure (which can be loaded from
703 | * a JSON). Both methods are shown in the examples below and better explained
704 | * in the user guide.
705 | *
706 | * The tick method must be called periodically, in order to send the tick
707 | * signal to all nodes in the tree, starting from the root. The method
708 | * `BehaviorTree.tick` receives a target object and a blackboard as parameters.
709 | * The target object can be anything: a game agent, a system, a DOM object,
710 | * etc. This target is not used by any piece of Behavior3JS, i.e., the target
711 | * object will only be used by custom nodes.
712 | *
713 | * The blackboard is obligatory and must be an instance of `Blackboard`. This
714 | * requirement is necessary due to the fact that neither `BehaviorTree` or any
715 | * node will store the execution variables in its own object (e.g., the BT does
716 | * not store the target, information about opened nodes or number of times the
717 | * tree was called). But because of this, you only need a single tree instance
718 | * to control multiple (maybe hundreds) objects.
719 | *
720 | * Manual construction of a Behavior Tree
721 | * --------------------------------------
722 | *
723 | * var tree = new b3.BehaviorTree();
724 | *
725 | * tree.root = new b3.Sequence({children:[
726 | * new b3.Priority({children:[
727 | * new MyCustomNode(),
728 | * new MyCustomNode()
729 | * ]}),
730 | * ...
731 | * ]});
732 | *
733 | *
734 | * Loading a Behavior Tree from data structure
735 | * -------------------------------------------
736 | *
737 | * var tree = new b3.BehaviorTree();
738 | *
739 | * tree.load({
740 | * 'title' : 'Behavior Tree title'
741 | * 'description' : 'My description'
742 | * 'root' : 'node-id-1'
743 | * 'nodes' : {
744 | * 'node-id-1' : {
745 | * 'name' : 'Priority', // this is the node type
746 | * 'title' : 'Root Node',
747 | * 'description' : 'Description',
748 | * 'children' : ['node-id-2', 'node-id-3'],
749 | * },
750 | * ...
751 | * }
752 | * })
753 | *
754 | *
755 | * @class BehaviorTree
756 | **/
757 | var BehaviorTree = b3.Class();
758 |
759 | var p = BehaviorTree.prototype;
760 |
761 | /**
762 | * The tree id, must be unique. By default, created with `b3.createUUID`.
763 | *
764 | * @property id
765 | * @type {String}
766 | * @readOnly
767 | */
768 |
769 | /**
770 | * The tree title.
771 | *
772 | * @property title
773 | * @type {String}
774 | */
775 |
776 | /**
777 | * Description of the tree.
778 | *
779 | * @property description
780 | * @type {String}
781 | */
782 |
783 | /**
784 | * A dictionary with (key-value) properties. Useful to define custom
785 | * variables in the visual editor.
786 | *
787 | * @property properties
788 | * @type {Object}
789 | */
790 |
791 | /**
792 | * The reference to the root node. Must be an instance of `b3.BaseNode`.
793 | *
794 | * @property root
795 | * @type {BaseNode}
796 | */
797 |
798 | /**
799 | * The reference to the debug instance.
800 | *
801 | * @property debug
802 | * @type {Object}
803 | */
804 |
805 | /**
806 | * Initialization method.
807 | *
808 | * @method initialize
809 | * @constructor
810 | **/
811 | p.initialize = function() {
812 | this.id = b3.createUUID();
813 | this.title = 'The behavior tree';
814 | this.description = 'Default description';
815 | this.properties = {};
816 | this.root = null;
817 | this.debug = null;
818 | }
819 |
820 | /**
821 | * This method loads a Behavior Tree from a data structure, populating this
822 | * object with the provided data. Notice that, the data structure must
823 | * follow the format specified by Behavior3JS. Consult the guide to know
824 | * more about this format.
825 | *
826 | * You probably want to use custom nodes in your BTs, thus, you need to
827 | * provide the `names` object, in which this method can find the nodes by
828 | * `names[NODE_NAME]`. This variable can be a namespace or a dictionary,
829 | * as long as this method can find the node by its name, for example:
830 | *
831 | * //json
832 | * ...
833 | * 'node1': {
834 | * 'name': MyCustomNode,
835 | * 'title': ...
836 | * }
837 | * ...
838 | *
839 | * //code
840 | * var bt = new b3.BehaviorTree();
841 | * bt.load(data, {'MyCustomNode':MyCustomNode})
842 | *
843 | *
844 | * @method load
845 | * @param {Object} data The data structure representing a Behavior Tree.
846 | * @param {Object} [names] A namespace or dict containing custom nodes.
847 | **/
848 | p.load = function(data, names) {
849 | names = names || {};
850 |
851 | this.title = data.title || this.title;
852 | this.description = data.description || this.description;
853 | this.properties = data.properties || this.properties;
854 |
855 | var nodes = {};
856 | // Create the node list (without connection between them)
857 | for (var id in data.nodes) {
858 | var spec = data.nodes[id];
859 |
860 | if (spec.name in names) {
861 | // Look for the name in custom nodes
862 | var cls = names[spec.name];
863 | } else if (spec.name in b3) {
864 | // Look for the name in default nodes
865 | var cls = b3[spec.name];
866 | } else {
867 | // Invalid node name
868 | throw EvalError('BehaviorTree.load: Invalid node name + "'+
869 | spec.name+'".');
870 | }
871 |
872 | var node = new cls(spec.parameters);
873 | node.id = spec.id || node.id;
874 | node.title = spec.title || node.title;
875 | node.description = spec.description || node.description;
876 | node.properties = spec.properties || node.properties;
877 | node.parameters = spec.parameters || node.parameters;
878 |
879 | nodes[id] = node;
880 | }
881 |
882 | // Connect the nodes
883 | for (var id in data.nodes) {
884 | var spec = data.nodes[id];
885 | var node = nodes[id];
886 |
887 | if (node.category === b3.COMPOSITE && spec.children) {
888 | for (var i=0; i 0) {
922 | var node = stack.pop();
923 |
924 | var spec = {};
925 | spec.id = node.id;
926 | spec.name = node.name;
927 | spec.title = node.title;
928 | spec.description = node.description;
929 | spec.properties = node.properties;
930 | spec.parameters = node.parameters;
931 |
932 | if (node.category === b3.COMPOSITE && node.children) {
933 | var children = []
934 | for (var i=node.children.length-1; i>=0; i--) {
935 | children.push(node.children[i].id);
936 | stack.push(node.children[i]);
937 | }
938 | spec.children = children;
939 | } else if (node.category === b3.DECORATOR && node.child) {
940 | stack.push(node.child);
941 | spec.child = node.child.id;
942 | }
943 |
944 | data.nodes[node.id] = spec;
945 | }
946 |
947 | return data;
948 | };
949 |
950 | /**
951 | * Propagates the tick signal through the tree, starting from the root.
952 | *
953 | * This method receives a target object of any type (Object, Array,
954 | * DOMElement, whatever) and a `Blackboard` instance. The target object has
955 | * no use at all for all Behavior3JS components, but surely is important
956 | * for custom nodes. The blackboard instance is used by the tree and nodes
957 | * to store execution variables (e.g., last node running) and is obligatory
958 | * to be a `Blackboard` instance (or an object with the same interface).
959 | *
960 | * Internally, this method creates a Tick object, which will store the
961 | * target and the blackboard objects.
962 | *
963 | * Note: BehaviorTree stores a list of open nodes from last tick, if these
964 | * nodes weren't called after the current tick, this method will close them
965 | * automatically.
966 | *
967 | * @method tick
968 | * @param {Object} target A target object.
969 | * @param {Blackboard} blackboard An instance of blackboard object.
970 | * @returns {Constant} The tick signal state.
971 | **/
972 | p.tick = function(target, blackboard) {
973 | if (!blackboard) {
974 | throw 'The blackboard parameter is obligatory and must be an ' +
975 | 'instance of b3.Blackboard';
976 | }
977 |
978 | /* CREATE A TICK OBJECT */
979 | var tick = new b3.Tick();
980 | tick.debug = this.debug;
981 | tick.target = target;
982 | tick.blackboard = blackboard;
983 | tick.tree = this;
984 |
985 | /* TICK NODE */
986 | var state = this.root._execute(tick);
987 |
988 | /* CLOSE NODES FROM LAST TICK, IF NEEDED */
989 | var lastOpenNodes = blackboard.get('openNodes', this.id);
990 | var currOpenNodes = tick._openNodes.slice(0);
991 |
992 | // does not close if it is still open in this tick
993 | var start = 0;
994 | for (var i=0; i=start; i--) {
1003 | lastOpenNodes[i]._close(tick);
1004 | }
1005 |
1006 | /* POPULATE BLACKBOARD */
1007 | blackboard.set('openNodes', currOpenNodes, this.id);
1008 | blackboard.set('nodeCount', tick._nodeCount, this.id);
1009 |
1010 | return state;
1011 | };
1012 |
1013 |
1014 | b3.BehaviorTree = BehaviorTree;
1015 |
1016 | })();/**
1017 | * BaseNode
1018 | *
1019 | * Copyright (c) 2014 Renato de Pontes Pereira.
1020 | *
1021 | * Permission is hereby granted, free of charge, to any person obtaining a copy
1022 | * of this software and associated documentation files (the "Software"), to
1023 | * deal in the Software without restriction, including without limitation the
1024 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1025 | * sell copies of the Software, and to permit persons to whom the Software is
1026 | * furnished to do so, subject to the following conditions:
1027 | *
1028 | * The above copyright notice and this permission notice shall be included in
1029 | * all copies or substantial portions of the Software.
1030 | *
1031 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1032 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1033 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1034 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1035 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1036 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
1037 | * IN THE SOFTWARE.
1038 | **/
1039 |
1040 | /**
1041 | * @module Behavior3JS
1042 | **/
1043 |
1044 | // namespace:
1045 | //this.b3 = this.b3 || {};
1046 |
1047 | (function() {
1048 | "use strict";
1049 |
1050 | /**
1051 | * The BaseNode class is used as super class to all nodes in BehaviorJS. It
1052 | * comprises all common variables and methods that a node must have to execute.
1053 | *
1054 | * **IMPORTANT:** Do not inherit from this class, use `b3.Composite`,
1055 | * `b3.Decorator`, `b3.Action` or `b3.Condition`, instead.
1056 | *
1057 | * The attributes are specially designed to serialization of the node in a JSON
1058 | * format. In special, the `parameters` attribute can be set into the visual
1059 | * editor (thus, in the JSON file), and it will be used as parameter on the
1060 | * node initialization at `BehaviorTree.load`.
1061 | *
1062 | * BaseNode also provide 5 callback methods, which the node implementations can
1063 | * override. They are `enter`, `open`, `tick`, `close` and `exit`. See their
1064 | * documentation to know more. These callbacks are called inside the `_execute`
1065 | * method, which is called in the tree traversal.
1066 | *
1067 | * @class BaseNode
1068 | **/
1069 | var BaseNode = b3.Class();
1070 |
1071 | var p = BaseNode.prototype;
1072 |
1073 | /**
1074 | * Node ID.
1075 | *
1076 | * @property id
1077 | * @type {String}
1078 | * @readonly
1079 | **/
1080 |
1081 | /**
1082 | * Node name. Must be a unique identifier, preferable the same name of the
1083 | * class. You have to set the node name in the prototype.
1084 | *
1085 | * @property name
1086 | * @type {String}
1087 | * @readonly
1088 | **/
1089 | p.name = null;
1090 |
1091 | /**
1092 | * Node category. Must be `b3.COMPOSITE`, `b3.DECORATOR`, `b3.ACTION` or
1093 | * `b3.CONDITION`. This is defined automatically be inheriting the
1094 | * correspondent class.
1095 | *
1096 | * @property category
1097 | * @type constant
1098 | * @readonly
1099 | **/
1100 | p.category = null;
1101 |
1102 | /**
1103 | * Node title.
1104 | *
1105 | * @property title
1106 | * @type {String}
1107 | * @optional
1108 | * @readonly
1109 | **/
1110 | p.title = null;
1111 |
1112 | /**
1113 | * Node description.
1114 | *
1115 | * @property description
1116 | * @type {String}
1117 | * @optional
1118 | * @readonly
1119 | **/
1120 | p.description = null;
1121 |
1122 | /**
1123 | * A dictionary (key, value) describing the node parameters. Useful for
1124 | * defining parameter values in the visual editor. Note: this is only
1125 | * useful for nodes when loading trees from JSON files.
1126 | *
1127 | * @property parameters
1128 | * @type {Object}
1129 | * @readonly
1130 | **/
1131 | p.parameters = null;
1132 |
1133 | /**
1134 | * A dictionary (key, value) describing the node properties. Useful for
1135 | * defining custom variables inside the visual editor.
1136 | *
1137 | * @property properties
1138 | * @type {Object}
1139 | * @readonly
1140 | **/
1141 | p.properties = null;
1142 |
1143 | /**
1144 | * Initialization method.
1145 | *
1146 | * @method initialize
1147 | * @constructor
1148 | **/
1149 | p.initialize = function() {
1150 | this.id = b3.createUUID();
1151 | this.title = this.title || this.name;
1152 | this.description = '';
1153 | this.parameters = {};
1154 | this.properties = {};
1155 | }
1156 |
1157 | /**
1158 | * This is the main method to propagate the tick signal to this node. This
1159 | * method calls all callbacks: `enter`, `open`, `tick`, `close`, and
1160 | * `exit`. It only opens a node if it is not already open. In the same
1161 | * way, this method only close a node if the node returned a status
1162 | * different of `b3.RUNNING`.
1163 | *
1164 | * @method _execute
1165 | * @param {Tick} tick A tick instance.
1166 | * @returns {Constant} The tick state.
1167 | * @protected
1168 | **/
1169 | p._execute = function(tick) {
1170 | /* ENTER */
1171 | this._enter(tick);
1172 |
1173 | /* OPEN */
1174 | if (!tick.blackboard.get('isOpen', tick.tree.id, this.id)) {
1175 | this._open(tick);
1176 | }
1177 |
1178 | /* TICK */
1179 | var status = this._tick(tick);
1180 |
1181 | /* CLOSE */
1182 | if (status !== b3.RUNNING) {
1183 | this._close(tick);
1184 | }
1185 |
1186 | /* EXIT */
1187 | this._exit(tick);
1188 |
1189 | return status;
1190 | }
1191 |
1192 | /**
1193 | * Wrapper for enter method.
1194 | *
1195 | * @method _enter
1196 | * @param {Tick} tick A tick instance.
1197 | * @protected
1198 | **/
1199 | p._enter = function(tick) {
1200 | tick._enterNode(this);
1201 | this.enter(tick);
1202 | }
1203 |
1204 | /**
1205 | * Wrapper for open method.
1206 | *
1207 | * @method _open
1208 | * @param {Tick} tick A tick instance.
1209 | * @protected
1210 | **/
1211 | p._open = function(tick) {
1212 | tick._openNode(this);
1213 | tick.blackboard.set('isOpen', true, tick.tree.id, this.id);
1214 | this.open(tick);
1215 | }
1216 |
1217 | /**
1218 | * Wrapper for tick method.
1219 | *
1220 | * @method _tick
1221 | * @param {Tick} tick A tick instance.
1222 | * @returns {Constant} A state constant.
1223 | * @protected
1224 | **/
1225 | p._tick = function(tick) {
1226 | tick._tickNode(this);
1227 | return this.tick(tick);
1228 | }
1229 |
1230 | /**
1231 | * Wrapper for close method.
1232 | *
1233 | * @method _close
1234 | * @param {Tick} tick A tick instance.
1235 | * @protected
1236 | **/
1237 | p._close = function(tick) {
1238 | tick._closeNode(this);
1239 | tick.blackboard.set('isOpen', false, tick.tree.id, this.id);
1240 | this.close(tick);
1241 | }
1242 |
1243 | /**
1244 | * Wrapper for exit method.
1245 | *
1246 | * @method _exit
1247 | * @param {Tick} tick A tick instance.
1248 | * @protected
1249 | **/
1250 | p._exit = function(tick) {
1251 | tick._exitNode(this);
1252 | this.exit(tick);
1253 | }
1254 |
1255 | /**
1256 | * Enter method, override this to use. It is called every time a node is
1257 | * asked to execute, before the tick itself.
1258 | *
1259 | * @method enter
1260 | * @param {Tick} tick A tick instance.
1261 | **/
1262 | p.enter = function(tick) {}
1263 |
1264 | /**
1265 | * Open method, override this to use. It is called only before the tick
1266 | * callback and only if the not isn't closed.
1267 | *
1268 | * Note: a node will be closed if it returned `b3.RUNNING` in the tick.
1269 | *
1270 | * @method open
1271 | * @param {Tick} tick A tick instance.
1272 | **/
1273 | p.open = function(tick) {}
1274 |
1275 | /**
1276 | * Tick method, override this to use. This method must contain the real
1277 | * execution of node (perform a task, call children, etc.). It is called
1278 | * every time a node is asked to execute.
1279 | *
1280 | * @method tick
1281 | * @param {Tick} tick A tick instance.
1282 | **/
1283 | p.tick = function(tick) {}
1284 |
1285 | /**
1286 | * Close method, override this to use. This method is called after the tick
1287 | * callback, and only if the tick return a state different from
1288 | * `b3.RUNNING`.
1289 | *
1290 | * @method close
1291 | * @param {Tick} tick A tick instance.
1292 | **/
1293 | p.close = function(tick) {}
1294 |
1295 | /**
1296 | * Exit method, override this to use. Called every time in the end of the
1297 | * execution.
1298 | *
1299 | * @method exit
1300 | * @param {Tick} tick A tick instance.
1301 | **/
1302 | p.exit = function(tick) {}
1303 |
1304 | b3.BaseNode = BaseNode;
1305 |
1306 | })();/**
1307 | * Action
1308 | *
1309 | * Copyright (c) 2014 Renato de Pontes Pereira.
1310 | *
1311 | * Permission is hereby granted, free of charge, to any person obtaining a copy
1312 | * of this software and associated documentation files (the "Software"), to
1313 | * deal in the Software without restriction, including without limitation the
1314 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1315 | * sell copies of the Software, and to permit persons to whom the Software is
1316 | * furnished to do so, subject to the following conditions:
1317 | *
1318 | * The above copyright notice and this permission notice shall be included in
1319 | * all copies or substantial portions of the Software.
1320 | *
1321 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1322 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1323 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1324 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1325 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1326 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
1327 | * IN THE SOFTWARE.
1328 | **/
1329 |
1330 | /**
1331 | * @module Behavior3JS
1332 | **/
1333 |
1334 | // namespace:
1335 | //this.b3 = this.b3 || {};
1336 |
1337 | (function() {
1338 | "use strict";
1339 |
1340 | /**
1341 | * Action is the base class for all action nodes. Thus, if you want to
1342 | * create new custom action nodes, you need to inherit from this class.
1343 | *
1344 | * For example, take a look at the Runner action:
1345 | *
1346 | * var Runner = b3.Class(b3.Action);
1347 | * var p = Runner.prototype;
1348 | *
1349 | * p.name = 'Runner';
1350 | *
1351 | * p.tick = function(tick) {
1352 | * return b3.RUNNING;
1353 | * }
1354 | *
1355 | * @class Action
1356 | * @extends BaseNode
1357 | **/
1358 | var Action = b3.Class(b3.BaseNode);
1359 |
1360 | var p = Action.prototype;
1361 |
1362 | /**
1363 | * Node category. Default to `b3.ACTION`.
1364 | *
1365 | * @property category
1366 | * @type {String}
1367 | * @readonly
1368 | **/
1369 | p.category = b3.ACTION;
1370 |
1371 | p.__BaseNode_initialize = p.initialize;
1372 | /**
1373 | * Initialization method.
1374 | *
1375 | * @method initialize
1376 | * @constructor
1377 | **/
1378 | p.initialize = function() {
1379 | this.__BaseNode_initialize();
1380 | }
1381 |
1382 | b3.Action = Action;
1383 |
1384 | })();/**
1385 | * Composite
1386 | *
1387 | * Copyright (c) 2014 Renato de Pontes Pereira.
1388 | *
1389 | * Permission is hereby granted, free of charge, to any person obtaining a copy
1390 | * of this software and associated documentation files (the "Software"), to
1391 | * deal in the Software without restriction, including without limitation the
1392 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1393 | * sell copies of the Software, and to permit persons to whom the Software is
1394 | * furnished to do so, subject to the following conditions:
1395 | *
1396 | * The above copyright notice and this permission notice shall be included in
1397 | * all copies or substantial portions of the Software.
1398 | *
1399 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1400 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1401 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1402 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1403 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1404 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
1405 | * IN THE SOFTWARE.
1406 | **/
1407 |
1408 | /**
1409 | * @module Behavior3JS
1410 | **/
1411 |
1412 | // namespace:
1413 | //this.b3 = this.b3 || {};
1414 |
1415 | (function() {
1416 | "use strict";
1417 |
1418 | /**
1419 | * Composite is the base class for all composite nodes. Thus, if you want to
1420 | * create new custom composite nodes, you need to inherit from this class.
1421 | *
1422 | * When creating composite nodes, you will need to propagate the tick signal to
1423 | * the children nodes manually. To do that, override the `tick` method and call
1424 | * the `_execute` method on all nodes. For instance, take a look at how the
1425 | * Sequence node inherit this class and how it call its children:
1426 | *
1427 | *
1428 | * // Inherit from Composite, using the util function Class.
1429 | * var Sequence = b3.Class(b3.Composite);
1430 | * var p = Sequence.prototype;
1431 | *
1432 | * // Remember to set the name of the node.
1433 | * p.name = 'Sequence';
1434 | *
1435 | * // Override the tick function
1436 | * p.tick = function(tick) {
1437 | *
1438 | * // Iterates over the children
1439 | * for (var i=0; i this.maxTime) {
2323 | return b3.FAILURE;
2324 | }
2325 |
2326 | return status;
2327 | };
2328 |
2329 | b3.MaxTime = MaxTime;
2330 |
2331 | })();/**
2332 | * Repeater
2333 | *
2334 | * Copyright (c) 2014 Renato de Pontes Pereira.
2335 | *
2336 | * Permission is hereby granted, free of charge, to any person obtaining a copy
2337 | * of this software and associated documentation files (the "Software"), to
2338 | * deal in the Software without restriction, including without limitation the
2339 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
2340 | * sell copies of the Software, and to permit persons to whom the Software is
2341 | * furnished to do so, subject to the following conditions:
2342 | *
2343 | * The above copyright notice and this permission notice shall be included in
2344 | * all copies or substantial portions of the Software.
2345 | *
2346 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2347 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2348 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2349 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2350 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2351 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2352 | * IN THE SOFTWARE.
2353 | **/
2354 |
2355 | /**
2356 | * @module Behavior3JS
2357 | **/
2358 |
2359 | // namespace:
2360 | //this.b3 = this.b3 || {};
2361 |
2362 | (function() {
2363 | "use strict";
2364 |
2365 | /**
2366 | * Repeater is a decorator that repeats the tick signal until the child node
2367 | * return `RUNNING` or `ERROR`. Optionally, a maximum number of repetitions
2368 | * can be defined.
2369 | *
2370 | * @class Repeater
2371 | * @extends Decorator
2372 | **/
2373 | var Repeater = b3.Class(b3.Decorator);
2374 |
2375 | var p = Repeater.prototype;
2376 |
2377 | /**
2378 | * Node name. Default to `Repeater`.
2379 | *
2380 | * @property name
2381 | * @type {String}
2382 | * @readonly
2383 | **/
2384 | p.name = 'Repeater';
2385 |
2386 | /**
2387 | * Node parameters.
2388 | *
2389 | * @property parameters
2390 | * @type {String}
2391 | * @readonly
2392 | **/
2393 | p.parameters = {'maxLoop': -1};
2394 |
2395 | p.__Decorator_initialize = p.initialize;
2396 | /**
2397 | * Initialization method.
2398 | *
2399 | * Settings parameters:
2400 | *
2401 | * - **maxLoop** (*Integer*) Maximum number of repetitions. Default to -1
2402 | * (infinite).
2403 | * - **child** (*BaseNode*) The child node.
2404 | *
2405 | * @method initialize
2406 | * @param {Object} settings Object with parameters.
2407 | * @constructor
2408 | **/
2409 | p.initialize = function(settings) {
2410 | settings = settings || {};
2411 |
2412 | this.__Decorator_initialize(settings);
2413 |
2414 | this.maxLoop = settings.maxLoop || -1;
2415 | };
2416 |
2417 | /**
2418 | * Open method.
2419 | *
2420 | * @method open
2421 | * @param {Tick} tick A tick instance.
2422 | **/
2423 | p.open = function(tick) {
2424 | tick.blackboard.set('i', 0, tick.tree.id, this.id);
2425 | };
2426 |
2427 | /**
2428 | * Tick method.
2429 | *
2430 | * @method tick
2431 | * @param {Tick} tick A tick instance.
2432 | **/
2433 | p.tick = function(tick) {
2434 | if (!this.child) {
2435 | return b3.ERROR;
2436 | }
2437 |
2438 | var i = tick.blackboard.get('i', tick.tree.id, this.id);
2439 | var status = b3.SUCCESS;
2440 |
2441 | while (this.maxLoop < 0 || i < this.maxLoop) {
2442 | status = this.child._execute(tick);
2443 |
2444 | if (status == b3.SUCCESS || status == b3.FAILURE)
2445 | i++;
2446 | else
2447 | break;
2448 | }
2449 |
2450 | i = tick.blackboard.set('i', i, tick.tree.id, this.id);
2451 | return status;
2452 | };
2453 |
2454 | b3.Repeater = Repeater;
2455 |
2456 | })();/**
2457 | * RepeatUntilFailure
2458 | *
2459 | * Copyright (c) 2014 Renato de Pontes Pereira.
2460 | *
2461 | * Permission is hereby granted, free of charge, to any person obtaining a copy
2462 | * of this software and associated documentation files (the "Software"), to
2463 | * deal in the Software without restriction, including without limitation the
2464 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
2465 | * sell copies of the Software, and to permit persons to whom the Software is
2466 | * furnished to do so, subject to the following conditions:
2467 | *
2468 | * The above copyright notice and this permission notice shall be included in
2469 | * all copies or substantial portions of the Software.
2470 | *
2471 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2472 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2473 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2474 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2475 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2476 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2477 | * IN THE SOFTWARE.
2478 | **/
2479 |
2480 | /**
2481 | * @module Behavior3JS
2482 | **/
2483 |
2484 | // namespace:
2485 | //this.b3 = this.b3 || {};
2486 |
2487 | (function() {
2488 | "use strict";
2489 |
2490 | /**
2491 | * RepeatUntilFailure is a decorator that repeats the tick signal until the
2492 | * node child returns `FAILURE`, `RUNNING` or `ERROR`. Optionally, a maximum
2493 | * number of repetitions can be defined.
2494 | *
2495 | * @class RepeatUntilFailure
2496 | * @extends Decorator
2497 | **/
2498 | var RepeatUntilFailure = b3.Class(b3.Decorator);
2499 |
2500 | var p = RepeatUntilFailure.prototype;
2501 |
2502 | /**
2503 | * Node name. Default to `RepeatUntilFailure`.
2504 | *
2505 | * @property name
2506 | * @type {String}
2507 | * @readonly
2508 | **/
2509 | p.name = 'RepeatUntilFailure';
2510 |
2511 | /**
2512 | * Node title. Default to `Repeat Until Failure`.
2513 | *
2514 | * @property title
2515 | * @type {String}
2516 | * @readonly
2517 | **/
2518 | p.title = 'Repeat Until Failure';
2519 |
2520 | /**
2521 | * Node parameters.
2522 | *
2523 | * @property parameters
2524 | * @type {String}
2525 | * @readonly
2526 | **/
2527 | p.parameters = {'maxLoop': -1};
2528 |
2529 | p.__Decorator_initialize = p.initialize;
2530 | /**
2531 | * Initialization method.
2532 | *
2533 | * Settings parameters:
2534 | *
2535 | * - **maxLoop** (*Integer*) Maximum number of repetitions. Default to -1
2536 | * (infinite).
2537 | * - **child** (*BaseNode*) The child node.
2538 | *
2539 | * @method initialize
2540 | * @param {Object} settings Object with parameters.
2541 | * @constructor
2542 | **/
2543 | p.initialize = function(settings) {
2544 | settings = settings || {};
2545 |
2546 | this.__Decorator_initialize(settings);
2547 |
2548 | this.maxLoop = settings.maxLoop || -1;
2549 | }
2550 |
2551 | /**
2552 | * Open method.
2553 | *
2554 | * @method open
2555 | * @param {Tick} tick A tick instance.
2556 | **/
2557 | p.open = function(tick) {
2558 | tick.blackboard.set('i', 0, tick.tree.id, this.id);
2559 | }
2560 |
2561 | /**
2562 | * Tick method.
2563 | *
2564 | * @method tick
2565 | * @param {Tick} tick A tick instance.
2566 | * @returns {Constant} A state constant.
2567 | **/
2568 | p.tick = function(tick) {
2569 | if (!this.child) {
2570 | return b3.ERROR;
2571 | }
2572 |
2573 | var i = tick.blackboard.get('i', tick.tree.id, this.id);
2574 |
2575 | while (this.maxLoop < 0 || i < this.maxLoop) {
2576 | var status = this.child._execute(tick);
2577 |
2578 | if (status == b3.SUCCESS)
2579 | i++;
2580 | else
2581 | break;
2582 | }
2583 |
2584 | var i = tick.blackboard.set('i', i, tick.tree.id, this.id);
2585 | return status;
2586 | }
2587 |
2588 | b3.RepeatUntilFailure = RepeatUntilFailure;
2589 |
2590 | })();/**
2591 | * RepeatUntilSuccess
2592 | *
2593 | * Copyright (c) 2014 Renato de Pontes Pereira.
2594 | *
2595 | * Permission is hereby granted, free of charge, to any person obtaining a copy
2596 | * of this software and associated documentation files (the "Software"), to
2597 | * deal in the Software without restriction, including without limitation the
2598 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
2599 | * sell copies of the Software, and to permit persons to whom the Software is
2600 | * furnished to do so, subject to the following conditions:
2601 | *
2602 | * The above copyright notice and this permission notice shall be included in
2603 | * all copies or substantial portions of the Software.
2604 | *
2605 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2606 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2607 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2608 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2609 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2610 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2611 | * IN THE SOFTWARE.
2612 | **/
2613 |
2614 | /**
2615 | * @module Behavior3JS
2616 | **/
2617 |
2618 | // namespace:
2619 | //this.b3 = this.b3 || {};
2620 |
2621 | (function() {
2622 | "use strict";
2623 |
2624 | /**
2625 | * RepeatUntilSuccess is a decorator that repeats the tick signal until the
2626 | * node child returns `SUCCESS`, `RUNNING` or `ERROR`. Optionally, a maximum
2627 | * number of repetitions can be defined.
2628 | *
2629 | * @class RepeatUntilSuccess
2630 | * @extends Decorator
2631 | **/
2632 | var RepeatUntilSuccess = b3.Class(b3.Decorator);
2633 |
2634 | var p = RepeatUntilSuccess.prototype;
2635 |
2636 | /**
2637 | * Node name. Default to `RepeatUntilSuccess`.
2638 | *
2639 | * @property name
2640 | * @type {String}
2641 | * @readonly
2642 | **/
2643 | p.name = 'RepeatUntilSuccess';
2644 |
2645 | /**
2646 | * Node title. Default to `Repeat Until Success`.
2647 | *
2648 | * @property title
2649 | * @type {String}
2650 | * @readonly
2651 | **/
2652 | p.title = 'Repeat Until Success';
2653 |
2654 | /**
2655 | * Node parameters.
2656 | *
2657 | * @property parameters
2658 | * @type {String}
2659 | * @readonly
2660 | **/
2661 | p.parameters = {'maxLoop': -1};
2662 |
2663 | p.__Decorator_initialize = p.initialize;
2664 | /**
2665 | * Initialization method.
2666 | *
2667 | * Settings parameters:
2668 | *
2669 | * - **maxLoop** (*Integer*) Maximum number of repetitions. Default to -1
2670 | * (infinite).
2671 | * - **child** (*BaseNode*) The child node.
2672 | *
2673 | * @method initialize
2674 | * @param {Object} settings Object with parameters.
2675 | * @constructor
2676 | **/
2677 | p.initialize = function(settings) {
2678 | settings = settings || {};
2679 |
2680 | this.__Decorator_initialize(settings);
2681 |
2682 | this.maxLoop = settings.maxLoop || -1;
2683 | }
2684 |
2685 | /**
2686 | * Open method.
2687 | *
2688 | * @method open
2689 | * @param {Tick} tick A tick instance.
2690 | **/
2691 | p.open = function(tick) {
2692 | tick.blackboard.set('i', 0, tick.tree.id, this.id);
2693 | }
2694 |
2695 | /**
2696 | * Tick method.
2697 | *
2698 | * @method tick
2699 | * @param {Tick} tick A tick instance.
2700 | * @returns {Constant} A state constant.
2701 | **/
2702 | p.tick = function(tick) {
2703 | if (!this.child) {
2704 | return b3.ERROR;
2705 | }
2706 |
2707 | var i = tick.blackboard.get('i', tick.tree.id, this.id);
2708 |
2709 | while (this.maxLoop < 0 || i < this.maxLoop) {
2710 | var status = this.child._execute(tick);
2711 |
2712 | if (status == b3.FAILURE)
2713 | i++;
2714 | else
2715 | break;
2716 | }
2717 |
2718 | var i = tick.blackboard.set('i', i, tick.tree.id, this.id);
2719 | return status;
2720 | }
2721 |
2722 | b3.RepeatUntilSuccess = RepeatUntilSuccess;
2723 |
2724 | })();/**
2725 | * Error
2726 | *
2727 | * Copyright (c) 2014 Renato de Pontes Pereira.
2728 | *
2729 | * Permission is hereby granted, free of charge, to any person obtaining a copy
2730 | * of this software and associated documentation files (the "Software"), to
2731 | * deal in the Software without restriction, including without limitation the
2732 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
2733 | * sell copies of the Software, and to permit persons to whom the Software is
2734 | * furnished to do so, subject to the following conditions:
2735 | *
2736 | * The above copyright notice and this permission notice shall be included in
2737 | * all copies or substantial portions of the Software.
2738 | *
2739 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2740 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2741 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2742 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2743 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2744 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2745 | * IN THE SOFTWARE.
2746 | **/
2747 |
2748 | /**
2749 | * @module Behavior3JS
2750 | **/
2751 |
2752 | // namespace:
2753 | //this.b3 = this.b3 || {};
2754 |
2755 | (function() {
2756 | "use strict";
2757 |
2758 | /**
2759 | * This action node returns `ERROR` always.
2760 | *
2761 | * @class Error
2762 | * @extends Action
2763 | **/
2764 | var Error = b3.Class(b3.Action);
2765 |
2766 | var p = Error.prototype;
2767 |
2768 | /**
2769 | * Node name. Default to `Error`.
2770 | *
2771 | * @property name
2772 | * @type {String}
2773 | * @readonly
2774 | **/
2775 | p.name = 'Error';
2776 |
2777 | /**
2778 | * Tick method.
2779 | *
2780 | * @method tick
2781 | * @param {b3.Tick} tick A tick instance.
2782 | * @returns {Constant} Always return `b3.ERROR`.
2783 | **/
2784 | p.tick = function(tick) {
2785 | return b3.ERROR;
2786 | }
2787 |
2788 | b3.Error = Error;
2789 |
2790 | })();/**
2791 | * Failer
2792 | *
2793 | * Copyright (c) 2014 Renato de Pontes Pereira.
2794 | *
2795 | * Permission is hereby granted, free of charge, to any person obtaining a copy
2796 | * of this software and associated documentation files (the "Software"), to
2797 | * deal in the Software without restriction, including without limitation the
2798 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
2799 | * sell copies of the Software, and to permit persons to whom the Software is
2800 | * furnished to do so, subject to the following conditions:
2801 | *
2802 | * The above copyright notice and this permission notice shall be included in
2803 | * all copies or substantial portions of the Software.
2804 | *
2805 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2806 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2807 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2808 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2809 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2810 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2811 | * IN THE SOFTWARE.
2812 | **/
2813 |
2814 | /**
2815 | * @module Behavior3JS
2816 | **/
2817 |
2818 | // namespace:
2819 | //this.b3 = this.b3 || {};
2820 |
2821 | (function() {
2822 | "use strict";
2823 |
2824 | /**
2825 | * This action node returns `FAILURE` always.
2826 | *
2827 | * @class Failer
2828 | * @extends Action
2829 | **/
2830 | var Failer = b3.Class(b3.Action);
2831 |
2832 | var p = Failer.prototype;
2833 |
2834 | /**
2835 | * Node name. Default to `Failer`.
2836 | *
2837 | * @property name
2838 | * @type {String}
2839 | * @readonly
2840 | **/
2841 | p.name = 'Failer';
2842 |
2843 | /**
2844 | * Tick method.
2845 | *
2846 | * @method tick
2847 | * @param {b3.Tick} tick A tick instance.
2848 | * @returns {Constant} Always return `b3.FAILURE`.
2849 | **/
2850 | p.tick = function(tick) {
2851 | return b3.FAILURE;
2852 | }
2853 |
2854 | b3.Failer = Failer;
2855 |
2856 | })();/**
2857 | * Runner
2858 | *
2859 | * Copyright (c) 2014 Renato de Pontes Pereira.
2860 | *
2861 | * Permission is hereby granted, free of charge, to any person obtaining a copy
2862 | * of this software and associated documentation files (the "Software"), to
2863 | * deal in the Software without restriction, including without limitation the
2864 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
2865 | * sell copies of the Software, and to permit persons to whom the Software is
2866 | * furnished to do so, subject to the following conditions:
2867 | *
2868 | * The above copyright notice and this permission notice shall be included in
2869 | * all copies or substantial portions of the Software.
2870 | *
2871 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2872 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2873 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2874 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2875 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2876 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2877 | * IN THE SOFTWARE.
2878 | **/
2879 |
2880 | /**
2881 | * @module Behavior3JS
2882 | **/
2883 |
2884 | // namespace:
2885 | //this.b3 = this.b3 || {};
2886 |
2887 | (function() {
2888 | "use strict";
2889 |
2890 | /**
2891 | * This action node returns RUNNING always.
2892 | *
2893 | * @class Runner
2894 | * @extends Action
2895 | **/
2896 | var Runner = b3.Class(b3.Action);
2897 |
2898 | var p = Runner.prototype;
2899 |
2900 | /**
2901 | * Node name. Default to `Runner`.
2902 | *
2903 | * @property name
2904 | * @type {String}
2905 | * @readonly
2906 | **/
2907 | p.name = 'Runner';
2908 |
2909 | /**
2910 | * Tick method.
2911 | *
2912 | * @method tick
2913 | * @param {b3.Tick} tick A tick instance.
2914 | * @returns {Constant} Always return `b3.RUNNING`.
2915 | **/
2916 | p.tick = function(tick) {
2917 | return b3.RUNNING;
2918 | }
2919 |
2920 | b3.Runner = Runner;
2921 |
2922 | })();/**
2923 | * Succeeder
2924 | *
2925 | * Copyright (c) 2014 Renato de Pontes Pereira.
2926 | *
2927 | * Permission is hereby granted, free of charge, to any person obtaining a copy
2928 | * of this software and associated documentation files (the "Software"), to
2929 | * deal in the Software without restriction, including without limitation the
2930 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
2931 | * sell copies of the Software, and to permit persons to whom the Software is
2932 | * furnished to do so, subject to the following conditions:
2933 | *
2934 | * The above copyright notice and this permission notice shall be included in
2935 | * all copies or substantial portions of the Software.
2936 | *
2937 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2938 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2939 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2940 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2941 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2942 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2943 | * IN THE SOFTWARE.
2944 | **/
2945 |
2946 | /**
2947 | * @module Behavior3JS
2948 | **/
2949 |
2950 | // namespace:
2951 | //this.b3 = this.b3 || {};
2952 |
2953 | (function() {
2954 | "use strict";
2955 |
2956 | /**
2957 | * This action node returns `SUCCESS` always.
2958 | *
2959 | * @class Succeeder
2960 | * @extends Action
2961 | **/
2962 | var Succeeder = b3.Class(b3.Action);
2963 |
2964 | var p = Succeeder.prototype;
2965 |
2966 | /**
2967 | * Node name. Default to `Succeeder`.
2968 | *
2969 | * @property name
2970 | * @type String
2971 | * @readonly
2972 | **/
2973 | p.name = 'Succeeder';
2974 |
2975 | /**
2976 | * Tick method.
2977 | *
2978 | * @method tick
2979 | * @param {b3.Tick} tick A tick instance.
2980 | * @returns {Constant} Always return `b3.SUCCESS`.
2981 | **/
2982 | p.tick = function(tick) {
2983 | return b3.SUCCESS;
2984 | }
2985 |
2986 | b3.Succeeder = Succeeder;
2987 |
2988 | })();/**
2989 | * Wait
2990 | *
2991 | * Copyright (c) 2014 Renato de Pontes Pereira.
2992 | *
2993 | * Permission is hereby granted, free of charge, to any person obtaining a copy
2994 | * of this software and associated documentation files (the "Software"), to
2995 | * deal in the Software without restriction, including without limitation the
2996 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
2997 | * sell copies of the Software, and to permit persons to whom the Software is
2998 | * furnished to do so, subject to the following conditions:
2999 | *
3000 | * The above copyright notice and this permission notice shall be included in
3001 | * all copies or substantial portions of the Software.
3002 | *
3003 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3004 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3005 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
3006 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3007 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
3008 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
3009 | * IN THE SOFTWARE.
3010 | **/
3011 |
3012 | /**
3013 | * @module Behavior3JS
3014 | **/
3015 |
3016 | // namespace:
3017 | //this.b3 = this.b3 || {};
3018 |
3019 | (function() {
3020 | "use strict";
3021 |
3022 | /**
3023 | * Wait a few seconds.
3024 | *
3025 | * @class Wait
3026 | * @extends Action
3027 | **/
3028 | var Wait = b3.Class(b3.Action);
3029 |
3030 | var p = Wait.prototype;
3031 |
3032 | /**
3033 | * Node name. Default to `Wait`.
3034 | *
3035 | * @property name
3036 | * @type {String}
3037 | * @readonly
3038 | **/
3039 | p.name = 'Wait';
3040 |
3041 | /**
3042 | * Node parameters.
3043 | *
3044 | * @property parameters
3045 | * @type {String}
3046 | * @readonly
3047 | **/
3048 | p.parameters = {'milliseconds': 0};
3049 |
3050 | p.__Action_initialize = p.initialize;
3051 | /**
3052 | * Initialization method.
3053 | *
3054 | * Settings parameters:
3055 | *
3056 | * - **milliseconds** (*Integer*) Maximum time, in milliseconds, a child
3057 | * can execute.
3058 | *
3059 | * @method initialize
3060 | * @param {Object} settings Object with parameters.
3061 | * @constructor
3062 | **/
3063 | p.initialize = function(settings) {
3064 | settings = settings || {};
3065 |
3066 | this.__Action_initialize();
3067 |
3068 | this.endTime = settings.milliseconds || 0;
3069 | }
3070 |
3071 | /**
3072 | * Open method.
3073 | *
3074 | * @method open
3075 | * @param {Tick} tick A tick instance.
3076 | **/
3077 | p.open = function(tick) {
3078 | var startTime = (new Date()).getTime();
3079 | tick.blackboard.set('startTime', startTime, tick.tree.id, this.id);
3080 | }
3081 |
3082 | /**
3083 | * Tick method.
3084 | *
3085 | * @method tick
3086 | * @param {Tick} tick A tick instance.
3087 | * @returns {Constant} A state constant.
3088 | **/
3089 | p.tick = function(tick) {
3090 | var currTime = (new Date()).getTime();
3091 | var startTime = tick.blackboard.get('startTime', tick.tree.id, this.id);
3092 |
3093 | if (currTime - startTime > this.endTime) {
3094 | return b3.SUCCESS;
3095 | }
3096 |
3097 | return b3.RUNNING;
3098 | }
3099 |
3100 | b3.Wait = Wait;
3101 |
3102 | })();
3103 |
3104 | module.exports = b3;
--------------------------------------------------------------------------------