7 using namespace bl::gui;
17 case T::FollowingPath:
36 bool isNumber(
const std::string& i) {
37 if (i.empty())
return false;
39 if (c < '0' || c >
'9')
return false;
51 window = Window::create(LinePacker::create(LinePacker::Vertical, 8),
"Behavior Editor");
52 window->getSignal(Event::Closed).willAlwaysCall([
this](
const Event&, Element*) {
hide(); });
54 typeLabel = Label::create(
"");
55 notebook = Notebook::create();
57 Box::Ptr page = Box::create(LinePacker::create(LinePacker::Vertical, 4));
58 Box::Ptr row = Box::create(LinePacker::create(LinePacker::Horizontal, 4));
59 dirBox = ComboBox::create();
60 dirBox->addOption(
"Up");
61 dirBox->addOption(
"Right");
62 dirBox->addOption(
"Down");
63 dirBox->addOption(
"Left");
64 dirBox->setSelectedOption(0);
65 row->pack(Label::create(
"Direction:"));
67 page->pack(row,
true,
true);
68 notebook->addPage(
"stand",
"Stand Still", page);
70 page = Box::create(LinePacker::create(LinePacker::Vertical, 4));
71 row = Box::create(LinePacker::create(LinePacker::Horizontal, 4));
72 spinBox = ComboBox::create();
73 spinBox->addOption(
"Clockwise");
74 spinBox->addOption(
"Counter-Clockwise");
75 spinBox->addOption(
"Random");
76 spinBox->setSelectedOption(0);
77 row->pack(Label::create(
"Spin Direction:"));
79 page->pack(row,
true,
true);
80 notebook->addPage(
"spin",
"Spin", page);
82 page = Box::create(LinePacker::create(LinePacker::Vertical, 4));
83 pathEditor.pack(page);
84 notebook->addPage(
"path",
"Path", page);
86 page = Box::create(LinePacker::create(LinePacker::Vertical, 4));
87 row = Box::create(LinePacker::create(LinePacker::Horizontal, 4));
88 row->pack(Label::create(
"Radius (tiles):"),
false,
false);
89 radiusEntry = TextEntry::create();
90 radiusEntry->setInput(
"7");
91 radiusEntry->setMode(TextEntry::Mode::Integer);
92 row->pack(radiusEntry,
true,
false);
93 page->pack(row,
true,
true);
94 notebook->addPage(
"wander",
"Wander", page);
96 row = Box::create(LinePacker::create(LinePacker::Horizontal, 4));
97 Button::Ptr setBut = Button::create(
"Save");
98 setBut->setColor(sf::Color::Green, sf::Color::Black);
99 setBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
101 switch (notebook->getActivePageIndex()) {
103 value.setType(T::StandStill);
104 value.standing().facedir =
105 static_cast<bl::tmap::Direction>(dirBox->getSelectedOption());
109 value.setType(T::SpinInPlace);
110 value.spinning().spinDir = static_cast<core::file::Behavior::Spinning::Direction>(
111 spinBox->getSelectedOption());
115 value.setType(T::FollowingPath);
116 value.path() = pathEditor.getValue();
120 if (isNumber(radiusEntry->getInput())) {
121 value.setType(T::Wandering);
122 value.wander().radius = std::atoi(radiusEntry->getInput().c_str());
125 bl::dialog::tinyfd_messageBox(
126 "Error",
"Radius must be a positive integer",
"ok",
"error", 1);
132 typeLabel->setText(getLabel(value.
type()));
136 row->pack(setBut,
false,
true);
137 Button::Ptr cancelBut = Button::create(
"Cancel");
138 cancelBut->setColor(sf::Color::Red, sf::Color::Black);
139 cancelBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
143 row->pack(cancelBut,
false,
true);
144 window->pack(notebook,
true,
true);
145 window->pack(row,
true,
false);
148 void BehaviorEditor::pack(Box::Ptr row) {
149 row->pack(typeLabel,
true,
true);
150 Button::Ptr editBut = Button::create(
"Edit Behavior");
151 editBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
154 parent->pack(window);
155 window->setForceFocus(
true);
157 row->pack(editBut,
false,
true);
164 value = ogValue = behavior;
166 typeLabel->setText(getLabel(behavior.
type()));
167 switch (behavior.
type()) {
169 notebook->makePageActive(0);
170 dirBox->setSelectedOption(
static_cast<int>(behavior.
standing().
facedir));
174 notebook->makePageActive(1);
175 spinBox->setSelectedOption(
static_cast<int>(behavior.
spinning().
spinDir));
178 case T::FollowingPath:
179 notebook->makePageActive(2);
180 pathEditor.init(behavior.
path());
184 notebook->makePageActive(3);
185 radiusEntry->setInput(std::to_string(behavior.
wander().
radius));
190 void BehaviorEditor::hide() {
192 window->setForceFocus(
false);
198 BehaviorEditor::PathEditor::PathEditor() {
199 container = ScrollArea::create(LinePacker::create(LinePacker::Vertical, 6));
200 container->setOutlineThickness(1);
201 container->setColor(sf::Color::Transparent, sf::Color::Black);
202 container->setMaxSize({10000.f, 300.f});
203 container->includeScrollbarsInRequisition(
true);
206 void BehaviorEditor::PathEditor::pack(Box::Ptr parent) {
207 Box::Ptr row = Box::create(LinePacker::create(LinePacker::Horizontal, 4));
208 toggle = CheckButton::create(
"Reverse Path At End");
209 toggle->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
210 value.reverse = toggle->getValue();
212 row->pack(toggle,
false,
true);
214 parent->pack(Label::create(
"Paces:"));
215 parent->pack(container,
true,
true);
217 Button::Ptr appendBut = Button::create(
"Add Pace");
218 appendBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element* e) {
219 value.paces.emplace_back(bl::tmap::Direction::Down, 1);
220 e->queueUpdateAction(std::bind(&BehaviorEditor::PathEditor::sync,
this));
222 parent->pack(appendBut);
232 void BehaviorEditor::PathEditor::sync() {
233 container->clearChildren(
true);
235 for (
unsigned int i = 0; i < value.paces.size(); ++i) {
236 auto& pace = value.
paces[i];
237 Box::Ptr row = Box::create(LinePacker::create(LinePacker::Horizontal));
238 ComboBox::Ptr dirBox = ComboBox::create();
239 dirBox->addOption(
"Up");
240 dirBox->addOption(
"Right");
241 dirBox->addOption(
"Down");
242 dirBox->addOption(
"Left");
243 dirBox->getSignal(Event::ValueChanged)
244 .willAlwaysCall([&pace, dirBox](
const Event&, Element*) {
246 static_cast<bl::tmap::Direction
>(dirBox->getSelectedOption());
248 dirBox->setSelectedOption(
static_cast<int>(pace.direction));
249 row->pack(dirBox,
false,
true);
251 TextEntry::Ptr stepEntry = TextEntry::create();
252 stepEntry->setInput(std::to_string(pace.steps));
253 stepEntry->setColor(sf::Color::Green, sf::Color::Transparent);
254 stepEntry->getSignal(Event::TextEntered)
255 .willAlwaysCall([&pace, stepEntry](
const Event&, Element*) {
256 if (isNumber(stepEntry->getInput())) {
257 stepEntry->setColor(sf::Color::Green, sf::Color::Transparent);
258 pace.steps = std::atoi(stepEntry->getInput().c_str());
260 else { stepEntry->setColor(sf::Color::Red, sf::Color::Transparent); }
262 stepEntry->setRequisition({80, 1});
263 row->pack(Label::create(
"Steps:"),
false,
true);
264 row->pack(stepEntry,
true,
true);
266 Button::Ptr beforeBut = Button::create(
"Add Before");
267 beforeBut->getSignal(Event::LeftClicked)
268 .willAlwaysCall([
this, i](
const Event&, Element* e) {
269 value.paces.insert(value.paces.begin() + i, {bl::tmap::Direction::Down, 1});
270 e->queueUpdateAction(std::bind(&BehaviorEditor::PathEditor::sync,
this));
272 row->pack(beforeBut,
false,
true);
274 Button::Ptr afterBut = Button::create(
"Add After");
275 afterBut->getSignal(Event::LeftClicked).willAlwaysCall([
this, i](
const Event&, Element* e) {
276 value.paces.insert(value.paces.begin() + i + 1, {bl::tmap::Direction::Down, 1});
277 e->queueUpdateAction(std::bind(&BehaviorEditor::PathEditor::sync,
this));
279 row->pack(afterBut,
false,
true);
281 Button::Ptr delBut = Button::create(
"Remove");
282 delBut->setColor(sf::Color::Red, sf::Color::Black);
283 delBut->getSignal(Event::LeftClicked).willAlwaysCall([
this, i](
const Event&, Element* e) {
284 value.paces.erase(value.paces.begin() + i);
285 e->queueUpdateAction(std::bind(&BehaviorEditor::PathEditor::sync,
this));
287 row->pack(delBut,
false,
true);
289 container->pack(row,
false,
true);
All classes and functionality used for implementing the game editor.
Set of behaviors for NPCs and trainers.
Spinning & spinning()
The data for spinning.
Type type() const
The type of behavior this is.
Wander & wander()
The data for wandering.
Standing & standing()
The data for standing still.
Type
The type of behavior.
Path & path()
The data for path following.
bl::tmap::Direction facedir
The direction to face.
enum core::file::Behavior::Spinning::Direction spinDir
Contains data for when the behavior type is following a path.
std::vector< Pace > paces
The sections of the path.
std::uint32_t radius
The radius to stay within, in tiles.
std::function< void()> OnSetCb
BehaviorEditor(const OnSetCb &cb, const NotifyWindowCb &onOpen, const NotifyWindowCb &onClose)
Construct a new Behavior Editor.
void hide()
Hides the editor window if opened.
std::function< void()> NotifyWindowCb