Add BTPlayer and BehaviorTree classes, and fix leaking refs
This commit is contained in:
parent
6105c17f09
commit
a236aee22b
|
@ -0,0 +1,45 @@
|
|||
/* behavior_tree.cpp */
|
||||
|
||||
#include "behavior_tree.h"
|
||||
#include "core/class_db.h"
|
||||
#include "core/list.h"
|
||||
#include "core/object.h"
|
||||
#include "core/variant.h"
|
||||
#include <cstddef>
|
||||
|
||||
void BehaviorTree::init() {
|
||||
List<BTTask *> stack;
|
||||
BTTask *task = root_task.ptr();
|
||||
while (task != nullptr) {
|
||||
for (int i = 0; i < task->get_child_count(); i++) {
|
||||
task->get_child(i)->_parent = task;
|
||||
stack.push_back(task->get_child(i).ptr());
|
||||
}
|
||||
task = nullptr;
|
||||
if (!stack.empty()) {
|
||||
task = stack.front()->get();
|
||||
stack.pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ref<BehaviorTree> BehaviorTree::clone() const {
|
||||
Ref<BehaviorTree> copy = duplicate(false);
|
||||
copy->set_path("");
|
||||
if (root_task.is_valid()) {
|
||||
copy->root_task = root_task->clone();
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
void BehaviorTree::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_description", "p_value"), &BehaviorTree::set_description);
|
||||
ClassDB::bind_method(D_METHOD("get_description"), &BehaviorTree::get_description);
|
||||
ClassDB::bind_method(D_METHOD("set_root_task", "p_value"), &BehaviorTree::set_root_task);
|
||||
ClassDB::bind_method(D_METHOD("get_root_task"), &BehaviorTree::get_root_task);
|
||||
ClassDB::bind_method(D_METHOD("init"), &BehaviorTree::init);
|
||||
ClassDB::bind_method(D_METHOD("clone"), &BehaviorTree::clone);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "description", PROPERTY_HINT_MULTILINE_TEXT), "set_description", "get_description");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root_task", PROPERTY_HINT_RESOURCE_TYPE, "BTTask"), "set_root_task", "get_root_task");
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/* behavior_tree.h */
|
||||
|
||||
#ifndef BEHAVIOR_TREE_H
|
||||
#define BEHAVIOR_TREE_H
|
||||
|
||||
#include "core/object.h"
|
||||
#include "core/resource.h"
|
||||
|
||||
#include "bt_task.h"
|
||||
|
||||
class BehaviorTree : public Resource {
|
||||
GDCLASS(BehaviorTree, Resource);
|
||||
|
||||
private:
|
||||
String description;
|
||||
Ref<BTTask> root_task;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_description(String p_value) {
|
||||
description = p_value;
|
||||
emit_changed();
|
||||
}
|
||||
String get_description() const { return description; }
|
||||
|
||||
void set_root_task(const Ref<BTTask> &p_value) {
|
||||
root_task = p_value;
|
||||
emit_changed();
|
||||
}
|
||||
Ref<BTTask> get_root_task() const { return root_task; }
|
||||
|
||||
void init();
|
||||
Ref<BehaviorTree> clone() const;
|
||||
};
|
||||
|
||||
#endif // BEHAVIOR_TREE_H
|
|
@ -0,0 +1,111 @@
|
|||
/* bt_player.cpp */
|
||||
|
||||
#include "bt_player.h"
|
||||
|
||||
#include "../limbo_string_names.h"
|
||||
#include "bt_task.h"
|
||||
#include "core/class_db.h"
|
||||
#include "core/engine.h"
|
||||
#include "core/io/resource_loader.h"
|
||||
#include "core/object.h"
|
||||
#include <cstddef>
|
||||
|
||||
VARIANT_ENUM_CAST(BTPlayer::UpdateMode);
|
||||
|
||||
void BTPlayer::_load_tree() {
|
||||
_loaded_tree.unref();
|
||||
_root_task.unref();
|
||||
ERR_FAIL_COND_MSG(!behavior_tree.is_valid(), "BTPlayer needs a valid behavior tree.");
|
||||
ERR_FAIL_COND_MSG(!behavior_tree->get_root_task().is_valid(), "Behavior tree has no valid root task.");
|
||||
_loaded_tree = behavior_tree;
|
||||
_root_task = _loaded_tree->get_root_task()->clone();
|
||||
_root_task->initialize(get_owner(), blackboard);
|
||||
}
|
||||
|
||||
void BTPlayer::set_behavior_tree(const Ref<BehaviorTree> &p_tree) {
|
||||
behavior_tree = p_tree;
|
||||
if (Engine::get_singleton()->is_editor_hint() == false) {
|
||||
_load_tree();
|
||||
set_update_mode(update_mode);
|
||||
}
|
||||
}
|
||||
|
||||
void BTPlayer::set_update_mode(UpdateMode p_mode) {
|
||||
update_mode = p_mode;
|
||||
set_active(active);
|
||||
}
|
||||
|
||||
void BTPlayer::set_active(bool p_active) {
|
||||
active = p_active;
|
||||
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||
set_process(update_mode == UpdateMode::IDLE);
|
||||
set_physics_process(update_mode == UpdateMode::PHYSICS);
|
||||
}
|
||||
}
|
||||
|
||||
void BTPlayer::update(float p_delta) {
|
||||
if (!_root_task.is_valid()) {
|
||||
ERR_PRINT_ONCE(vformat("BTPlayer has no root task to update (owner: %s)", get_owner()));
|
||||
return;
|
||||
}
|
||||
if (active) {
|
||||
int status = _root_task->execute(p_delta);
|
||||
if (status == BTTask::SUCCESS || status == BTTask::FAILURE) {
|
||||
set_active(auto_restart);
|
||||
emit_signal(LimboStringNames::get_singleton()->behavior_tree_finished, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BTPlayer::restart() {
|
||||
_root_task->cancel();
|
||||
set_active(true);
|
||||
}
|
||||
|
||||
void BTPlayer::_notification(int p_notification) {
|
||||
switch (p_notification) {
|
||||
case NOTIFICATION_PROCESS: {
|
||||
if (active) {
|
||||
Variant time = get_process_delta_time();
|
||||
update(time);
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_PHYSICS_PROCESS: {
|
||||
if (active) {
|
||||
Variant time = get_process_delta_time();
|
||||
update(time);
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_READY: {
|
||||
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||
if (behavior_tree.is_valid()) {
|
||||
_load_tree();
|
||||
}
|
||||
set_active(active);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void BTPlayer::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_behavior_tree", "p_path"), &BTPlayer::set_behavior_tree);
|
||||
ClassDB::bind_method(D_METHOD("get_behavior_tree"), &BTPlayer::get_behavior_tree);
|
||||
ClassDB::bind_method(D_METHOD("set_update_mode", "p_mode"), &BTPlayer::set_update_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_update_mode"), &BTPlayer::get_update_mode);
|
||||
ClassDB::bind_method(D_METHOD("set_active", "p_active"), &BTPlayer::set_active);
|
||||
ClassDB::bind_method(D_METHOD("get_active"), &BTPlayer::get_active);
|
||||
ClassDB::bind_method(D_METHOD("set_auto_restart", "p_value"), &BTPlayer::set_auto_restart);
|
||||
ClassDB::bind_method(D_METHOD("get_auto_restart"), &BTPlayer::get_auto_restart);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("update", "p_delta"), &BTPlayer::update);
|
||||
ClassDB::bind_method(D_METHOD("restart"), &BTPlayer::restart);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "behavior_tree", PROPERTY_HINT_RESOURCE_TYPE, "BehaviorTree"), "set_behavior_tree", "get_behavior_tree");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Idle,Physics,Manual"), "set_update_mode", "get_update_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "get_active");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_restart"), "set_auto_restart", "get_auto_restart");
|
||||
|
||||
BIND_ENUM_CONSTANT(IDLE);
|
||||
BIND_ENUM_CONSTANT(PHYSICS);
|
||||
BIND_ENUM_CONSTANT(MANUAL);
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/* bt_player.h */
|
||||
|
||||
#ifndef BT_PLAYER_H
|
||||
#define BT_PLAYER_H
|
||||
|
||||
#include "core/object.h"
|
||||
#include "scene/main/node.h"
|
||||
|
||||
#include "behavior_tree.h"
|
||||
#include "bt_task.h"
|
||||
#include <pulse/proplist.h>
|
||||
|
||||
class BTPlayer : public Node {
|
||||
GDCLASS(BTPlayer, Node);
|
||||
|
||||
public:
|
||||
enum UpdateMode : unsigned int {
|
||||
IDLE, // automatically call update() during NOTIFICATION_PROCESS
|
||||
PHYSICS, //# automatically call update() during NOTIFICATION_PHYSICS
|
||||
MANUAL, // manually update state machine, user must call update(delta)
|
||||
};
|
||||
|
||||
private:
|
||||
Ref<BehaviorTree> behavior_tree;
|
||||
UpdateMode update_mode = UpdateMode::IDLE;
|
||||
bool active = false;
|
||||
bool auto_restart = false;
|
||||
Dictionary blackboard;
|
||||
|
||||
Ref<BehaviorTree> _loaded_tree;
|
||||
Ref<BTTask> _root_task;
|
||||
|
||||
void _load_tree();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
void _notification(int p_notification);
|
||||
|
||||
public:
|
||||
void set_behavior_tree(const Ref<BehaviorTree> &p_tree);
|
||||
Ref<BehaviorTree> get_behavior_tree() const { return behavior_tree; };
|
||||
|
||||
void set_update_mode(UpdateMode p_mode);
|
||||
UpdateMode get_update_mode() const { return update_mode; }
|
||||
|
||||
void set_active(bool p_active);
|
||||
bool get_active() const { return active; }
|
||||
|
||||
void set_auto_restart(bool p_value) { auto_restart = p_value; }
|
||||
bool get_auto_restart() const { return auto_restart; }
|
||||
|
||||
void update(float p_delta);
|
||||
void restart();
|
||||
};
|
||||
|
||||
#endif // BT_PLAYER_H
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
#include "bt_task.h"
|
||||
|
||||
#include "../limbo_string_names.h"
|
||||
#include "../limbo_utility.h"
|
||||
#include "core/class_db.h"
|
||||
#include "core/object.h"
|
||||
#include "core/script_language.h"
|
||||
#include "core/variant.h"
|
||||
#include "editor/editor_node.h"
|
||||
|
||||
#include "../limbo_string_names.h"
|
||||
#include "../limbo_utility.h"
|
||||
#include <cstddef>
|
||||
|
||||
String BTTask::_generate_name() const {
|
||||
if (get_script_instance()) {
|
||||
|
@ -58,7 +58,7 @@ String BTTask::get_task_name() const {
|
|||
Ref<BTTask> BTTask::get_root() const {
|
||||
const BTTask *task = this;
|
||||
while (!task->is_root()) {
|
||||
task = task->get_parent().ptr();
|
||||
task = task->_parent;
|
||||
}
|
||||
return Ref<BTTask>(task);
|
||||
}
|
||||
|
@ -86,11 +86,11 @@ void BTTask::initialize(Object *p_agent, Dictionary p_blackboard) {
|
|||
|
||||
Ref<BTTask> BTTask::clone() const {
|
||||
Ref<BTTask> inst = duplicate(true);
|
||||
inst.ptr()->_parent.unref();
|
||||
CRASH_COND(inst.ptr()->get_parent().is_valid());
|
||||
inst->_parent = nullptr;
|
||||
CRASH_COND(inst->get_parent().is_valid());
|
||||
for (int i = 0; i < _children.size(); i++) {
|
||||
Ref<BTTask> c = get_child(i)->clone();
|
||||
c->_parent = inst;
|
||||
c->_parent = inst.ptr();
|
||||
inst->_children.set(i, c);
|
||||
}
|
||||
return inst;
|
||||
|
@ -152,19 +152,19 @@ int BTTask::get_child_count() const {
|
|||
}
|
||||
|
||||
void BTTask::add_child(Ref<BTTask> p_child) {
|
||||
ERR_FAIL_COND_MSG(p_child.ptr()->get_parent().is_valid(), "p_child already has a parent!");
|
||||
p_child->_parent = Ref<BTTask>(this);
|
||||
ERR_FAIL_COND_MSG(p_child->get_parent().is_valid(), "p_child already has a parent!");
|
||||
p_child->_parent = this;
|
||||
_children.push_back(p_child);
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
void BTTask::add_child_at_index(Ref<BTTask> p_child, int p_idx) {
|
||||
ERR_FAIL_COND_MSG(p_child.ptr()->get_parent().is_valid(), "p_child already has a parent!");
|
||||
ERR_FAIL_COND_MSG(p_child->get_parent().is_valid(), "p_child already has a parent!");
|
||||
if (p_idx < 0 || p_idx > _children.size()) {
|
||||
p_idx = _children.size();
|
||||
}
|
||||
_children.insert(p_idx, p_child);
|
||||
p_child->_parent = Ref<BTTask>(this);
|
||||
p_child->_parent = this;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
|
@ -174,7 +174,7 @@ void BTTask::remove_child(Ref<BTTask> p_child) {
|
|||
ERR_FAIL_MSG("p_child not found!");
|
||||
} else {
|
||||
_children.remove(idx);
|
||||
p_child->_parent.unref();
|
||||
p_child->_parent = nullptr;
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ int BTTask::get_child_index(const Ref<BTTask> &p_child) const {
|
|||
}
|
||||
|
||||
Ref<BTTask> BTTask::next_sibling() const {
|
||||
if (_parent.is_valid()) {
|
||||
if (_parent != nullptr) {
|
||||
int idx = _parent->get_child_index(Ref<BTTask>(this));
|
||||
if (idx != -1 && _parent->get_child_count() > (idx + 1)) {
|
||||
return _parent->get_child(idx + 1);
|
||||
|
@ -276,7 +276,16 @@ void BTTask::_bind_methods() {
|
|||
BTTask::BTTask() {
|
||||
_custom_name = String();
|
||||
_agent = nullptr;
|
||||
_parent = nullptr;
|
||||
_blackboard = Dictionary();
|
||||
_children = Vector<Ref<BTTask>>();
|
||||
_status = FRESH;
|
||||
}
|
||||
|
||||
BTTask::~BTTask() {
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
ERR_FAIL_COND(!get_child(i).is_valid());
|
||||
get_child(i)->_parent = nullptr;
|
||||
get_child(i).unref();
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@
|
|||
#include "core/ustring.h"
|
||||
#include "core/vector.h"
|
||||
#include "scene/resources/texture.h"
|
||||
#include <cstddef>
|
||||
|
||||
class BTTask : public Resource {
|
||||
GDCLASS(BTTask, Resource);
|
||||
|
@ -21,18 +22,14 @@ public:
|
|||
FAILURE,
|
||||
SUCCESS,
|
||||
};
|
||||
enum TaskType {
|
||||
ACTION,
|
||||
CONDITION,
|
||||
COMPOSITE,
|
||||
DECORATOR,
|
||||
};
|
||||
|
||||
private:
|
||||
friend class BehaviorTree;
|
||||
|
||||
String _custom_name;
|
||||
Object *_agent;
|
||||
Dictionary _blackboard;
|
||||
Ref<BTTask> _parent;
|
||||
BTTask *_parent;
|
||||
Vector<Ref<BTTask>> _children;
|
||||
int _status;
|
||||
|
||||
|
@ -51,8 +48,8 @@ protected:
|
|||
public:
|
||||
Object *get_agent() const { return _agent; };
|
||||
Dictionary get_blackboard() const { return _blackboard; };
|
||||
Ref<BTTask> get_parent() const { return _parent; };
|
||||
bool is_root() const { return _parent.is_null(); };
|
||||
Ref<BTTask> get_parent() const { return Ref<BTTask>(_parent); };
|
||||
bool is_root() const { return _parent == nullptr; };
|
||||
Ref<BTTask> get_root() const;
|
||||
int get_status() const { return _status; };
|
||||
String get_custom_name() const { return _custom_name; };
|
||||
|
@ -76,6 +73,7 @@ public:
|
|||
void print_tree(int p_initial_tabs = 0) const;
|
||||
|
||||
BTTask();
|
||||
~BTTask();
|
||||
};
|
||||
|
||||
#endif // BTTASK_H
|
|
@ -0,0 +1 @@
|
|||
<svg enable-background="new 0 0 16 16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#cea4f1"><path d="m0 12h4v4h-4z"/><path d="m6 12h4v4h-4z"/><path d="m5 0h6v4h-6z"/><path d="m7.5 2.5h1v10h-1z"/><path d="m12 12h4v4h-4z"/><path d="m14.5 14h-1v-5.5h-11v3.86h-1v-4.86h13z"/></g></svg>
|
After Width: | Height: | Size: 301 B |
|
@ -0,0 +1 @@
|
|||
<svg enable-background="new 0 0 16 16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m16 10.03v-4h-6v1.5h-6.5v-3.53h2.5v-4h-6v4h2.5v10.5h.17.83 6.5v1.5h6v-4h-6v1.5h-6.5v-4.97h6.5v1.5z" fill="#cea4f1"/></svg>
|
After Width: | Height: | Size: 225 B |
|
@ -1,6 +1,7 @@
|
|||
/* limbo_string_names.cpp */
|
||||
|
||||
#include "limbo_string_names.h"
|
||||
#include "core/string_name.h"
|
||||
|
||||
LimboStringNames *LimboStringNames::singleton = nullptr;
|
||||
|
||||
|
@ -10,4 +11,5 @@ LimboStringNames::LimboStringNames() {
|
|||
_enter = StaticCString::create("_enter");
|
||||
_exit = StaticCString::create("_exit");
|
||||
_tick = StaticCString::create("_tick");
|
||||
behavior_tree_finished = StaticCString::create("behavior_tree_finished");
|
||||
}
|
|
@ -28,6 +28,7 @@ public:
|
|||
StringName _enter;
|
||||
StringName _exit;
|
||||
StringName _tick;
|
||||
StringName behavior_tree_finished;
|
||||
};
|
||||
|
||||
#endif // LIMBO_STRING_NAMES_H
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "core/class_db.h"
|
||||
|
||||
#include "bt/behavior_tree.h"
|
||||
#include "bt/bt_action.h"
|
||||
#include "bt/bt_always_fail.h"
|
||||
#include "bt/bt_always_succeed.h"
|
||||
|
@ -17,6 +18,7 @@
|
|||
#include "bt/bt_fail.h"
|
||||
#include "bt/bt_invert.h"
|
||||
#include "bt/bt_parallel.h"
|
||||
#include "bt/bt_player.h"
|
||||
#include "bt/bt_probability.h"
|
||||
#include "bt/bt_random_selector.h"
|
||||
#include "bt/bt_random_sequence.h"
|
||||
|
@ -36,6 +38,8 @@
|
|||
|
||||
void register_limboai_types() {
|
||||
ClassDB::register_class<BTTask>();
|
||||
ClassDB::register_class<BehaviorTree>();
|
||||
ClassDB::register_class<BTPlayer>();
|
||||
|
||||
ClassDB::register_class<BTComposite>();
|
||||
ClassDB::register_class<BTDecorator>();
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
extends KinematicBody2D
|
||||
|
||||
|
||||
onready var bt_player: BTPlayer = $BTPlayer
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_configure_ai()
|
||||
|
||||
|
||||
func _configure_ai() -> void:
|
||||
var tree := BehaviorTree.new()
|
||||
var seq := BTSequence.new()
|
||||
var print_task := BTPrintLine.new("Hello world!")
|
||||
seq.add_child(print_task)
|
||||
tree.root_task = seq
|
||||
bt_player.behavior_tree = tree
|
||||
print("Assigning tree second time")
|
||||
bt_player.behavior_tree = tree
|
|
@ -0,0 +1,9 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://Agent.gd" type="Script" id=2]
|
||||
|
||||
[node name="Agent" type="KinematicBody2D"]
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[node name="BTPlayer" type="BTPlayer" parent="."]
|
||||
active = true
|
|
@ -0,0 +1,7 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://Agent.tscn" type="PackedScene" id=1]
|
||||
|
||||
[node name="Test" type="Node2D"]
|
||||
|
||||
[node name="Agent" parent="." instance=ExtResource( 1 )]
|
|
@ -0,0 +1,14 @@
|
|||
class_name BTPrintLine
|
||||
extends BTTask
|
||||
|
||||
|
||||
export var line: String
|
||||
|
||||
|
||||
func _init(p_line: String = "") -> void:
|
||||
line = p_line
|
||||
|
||||
|
||||
func _tick(_delta: float) -> int:
|
||||
print(line)
|
||||
return SUCCESS
|
|
@ -0,0 +1,6 @@
|
|||
[gd_resource type="BehaviorTree" load_steps=2 format=2]
|
||||
|
||||
[sub_resource type="BTSequence" id=1]
|
||||
|
||||
[resource]
|
||||
root_task = SubResource( 1 )
|
|
@ -0,0 +1,7 @@
|
|||
[gd_resource type="Environment" load_steps=2 format=2]
|
||||
|
||||
[sub_resource type="ProceduralSky" id=1]
|
||||
|
||||
[resource]
|
||||
background_mode = 2
|
||||
background_sky = SubResource( 1 )
|
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
|
@ -0,0 +1,35 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://icon.png"
|
||||
dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
process/normal_map_invert_y=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
|
@ -0,0 +1,37 @@
|
|||
; Engine configuration file.
|
||||
; It's best edited using the editor UI and not directly,
|
||||
; since the parameters that go here are not all obvious.
|
||||
;
|
||||
; Format:
|
||||
; [section] ; section goes between []
|
||||
; param=value ; assign values to parameters
|
||||
|
||||
config_version=4
|
||||
|
||||
_global_script_classes=[ {
|
||||
"base": "BTTask",
|
||||
"class": "BTPrintLine",
|
||||
"language": "GDScript",
|
||||
"path": "res://ai/tasks/BTPrintLine.gd"
|
||||
} ]
|
||||
_global_script_class_icons={
|
||||
"BTPrintLine": ""
|
||||
}
|
||||
|
||||
[application]
|
||||
|
||||
config/name="LimboAI Test"
|
||||
run/main_scene="res://Test.tscn"
|
||||
config/icon="res://icon.png"
|
||||
|
||||
[gui]
|
||||
|
||||
common/drop_mouse_on_gui_input_disabled=true
|
||||
|
||||
[physics]
|
||||
|
||||
common/enable_pause_aware_picking=true
|
||||
|
||||
[rendering]
|
||||
|
||||
environment/default_environment="res://default_env.tres"
|
Loading…
Reference in New Issue