12 const std::string EmptyFile =
"<no file selected>";
14 using namespace bl::gui;
21 , filePicker(
core::Properties::NpcPath(), {
"npc"},
22 std::bind(&NpcEditorWindow::onChooseFile,
this, std::placeholders::_1),
25 window->setForceFocus(
true);
27 , animWindow(
true, std::bind(&NpcEditorWindow::onChooseAnimation,
this, std::placeholders::_1),
28 std::bind(&NpcEditorWindow::forceWindowOnTop,
this))
30 std::bind(&NpcEditorWindow::makeDirty,
this), [
this]() { window->setForceFocus(
false); },
31 std::bind(&NpcEditorWindow::forceWindowOnTop,
this))
32 , conversationWindow(std::bind(&NpcEditorWindow::onChooseConversation,
this, std::placeholders::_1),
33 std::bind(&NpcEditorWindow::forceWindowOnTop,
this)) {
34 window = Window::create(LinePacker::create(LinePacker::Vertical, 8),
"NPC Editor");
35 window->getSignal(Event::Closed).willAlwaysCall([
this](
const Event&, Element*) { hide(); });
37 Box::Ptr row = Box::create(LinePacker::create(LinePacker::Horizontal, 4));
38 Button::Ptr newBut = Button::create(
"New");
39 newBut->setTooltip(
"Create a new NPC file");
40 newBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
41 if (confirmDiscard()) {
43 window->setForceFocus(
false);
44 filePicker.open(FilePicker::CreateNew,
"New NPC", parent,
true);
47 Button::Ptr setBut = Button::create(
"Set File");
48 setBut->setTooltip(
"Change the file to save this NPC to");
49 setBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
50 if (fileLabel->getText() == EmptyFile || confirmDiscard()) {
52 window->setForceFocus(
false);
53 filePicker.open(FilePicker::CreateOrPick,
"Set NPC File", parent,
false);
56 Button::Ptr openBut = Button::create(
"Open");
57 openBut->setTooltip(
"Open a different NPC file");
58 openBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
59 if (confirmDiscard()) {
61 window->setForceFocus(
false);
62 filePicker.open(FilePicker::PickExisting,
"Open NPC", parent,
false);
65 saveBut = Button::create(
"Save");
66 saveBut->setTooltip(
"Overwrite the current NPC file");
67 saveBut->setColor(sf::Color::Yellow, sf::Color::Blue);
68 saveBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
71 npc.
name() = nameEntry->getInput();
74 npc.
behavior() = behaviorEditor.getValue();
76 fileLabel->getText()))) {
77 bl::dialog::tinyfd_messageBox(
"Error",
"Failed to save NPC",
"ok",
"error", 1);
82 fileLabel = Label::create(
"filename.npc");
83 fileLabel->setColor(sf::Color::Cyan, sf::Color::Cyan);
84 row->pack(newBut,
false,
true);
85 row->pack(setBut,
false,
true);
86 row->pack(openBut,
false,
true);
87 row->pack(saveBut,
false,
true);
88 row->pack(fileLabel,
true,
true);
89 window->pack(row,
true,
false);
91 row = Box::create(LinePacker::create(LinePacker::Horizontal, 4));
92 Label::Ptr label = Label::create(
"Name:");
93 nameEntry = TextEntry::create();
94 nameEntry->getSignal(Event::ValueChanged)
95 .willAlwaysCall(std::bind(&NpcEditorWindow::makeDirty,
this));
96 row->pack(label,
false,
true);
97 row->pack(nameEntry,
true,
true);
98 window->pack(row,
true,
false);
100 row = Box::create(LinePacker::create(LinePacker::Horizontal, 4));
101 Button::Ptr animBut = Button::create(
"Select Anim");
102 animBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
103 window->setForceFocus(
false);
106 animLabel = Label::create(
"animation.anim");
107 animLabel->setColor(sf::Color::Cyan, sf::Color::Cyan);
108 row->pack(animBut,
false,
true);
109 row->pack(animLabel,
true,
true);
110 window->pack(row,
true,
false);
112 row = Box::create(LinePacker::create(LinePacker::Horizontal, 4));
113 Button::Ptr convBut = Button::create(
"Select Conversation");
114 convBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
115 window->setForceFocus(
false);
116 conversationWindow.open(parent, convLabel->getText());
118 convLabel = Label::create(
"conversation.conv");
119 convLabel->setColor(sf::Color::Cyan, sf::Color::Cyan);
120 row->pack(convBut,
false,
true);
121 row->pack(convLabel,
true,
true);
122 window->pack(row,
true,
false);
124 row = Box::create(LinePacker::create(LinePacker::Horizontal, 4));
125 behaviorEditor.pack(row);
126 window->pack(row,
true,
false);
128 row = Box::create(LinePacker::create(LinePacker::Horizontal, 4));
129 Button::Ptr selectBut = Button::create(
"Use NPC");
130 selectBut->setTooltip(
"Use the current NPC file");
131 selectBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
132 if (confirmDiscard()) {
133 if (validate(
false)) {
134 selectCb(fileLabel->getText());
139 selectBut->setColor(sf::Color::Blue, sf::Color::Black);
140 Button::Ptr cancelBut = Button::create(
"Cancel");
141 cancelBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
144 cancelBut->setColor(sf::Color::Red, sf::Color::Black);
145 row->pack(selectBut,
false,
true);
146 row->pack(cancelBut,
false,
true);
147 window->pack(row,
true,
false);
154 fileLabel->setText(file);
158 parent->pack(window);
159 window->setForceFocus(
true);
162 void NpcEditorWindow::onChooseFile(
const std::string& file) {
163 const std::string f =
168 window->setForceFocus(
true);
169 if (makingNew) { makeDirty(); }
175 fileLabel->setText(f);
178 void NpcEditorWindow::makeClean() {
179 saveBut->setColor(sf::Color::Green, sf::Color::Blue);
183 void NpcEditorWindow::makeDirty() {
184 saveBut->setColor(sf::Color::Yellow, sf::Color::Blue);
188 void NpcEditorWindow::reset() {
189 fileLabel->setText(EmptyFile);
190 nameEntry->setInput(
"");
191 animLabel->setText(
"<no anim selected>");
192 convLabel->setText(
"<no conv selected>");
196 void NpcEditorWindow::load(
const std::string& file) {
199 nameEntry->setInput(npc.
name());
205 bl::dialog::tinyfd_messageBox(
206 "Error", std::string(
"Failed to load NPC:\n" + file).c_str(),
"ok",
"error", 1);
210 bool NpcEditorWindow::validate(
bool saving)
const {
212 if (fileLabel->getText() == EmptyFile) {
213 bl::dialog::tinyfd_messageBox(
"Warning",
"Please select a file",
"ok",
"warning", 1);
218 if (!FileUtil::exists(
220 bl::dialog::tinyfd_messageBox(
"Warning",
"Bad file selected",
"ok",
"warning", 1);
224 if (nameEntry->getInput().empty()) {
225 bl::dialog::tinyfd_messageBox(
"Warning",
"Enter a name",
"ok",
"warning", 1);
228 if (!FileUtil::directoryExists(
230 bl::dialog::tinyfd_messageBox(
"Warning",
"Bad animation",
"ok",
"warning", 1);
233 const std::string p =
235 if (!FileUtil::exists(p)) {
236 bl::dialog::tinyfd_messageBox(
"Warning",
"Bad conversation",
"ok",
"warning", 1);
239 if (behaviorEditor.
getValue().
type() == core::file::Behavior::Type::FollowingPath &&
241 bl::dialog::tinyfd_messageBox(
"Warning",
"Behavior path is empty",
"ok",
"warning", 1);
247 bool NpcEditorWindow::confirmDiscard()
const {
249 return 1 == bl::dialog::tinyfd_messageBox(
250 "Warning",
"Discard unsaved changes?",
"yesno",
"warning", 0);
259 behaviorEditor.
hide();
260 window->setForceFocus(
false);
264 void NpcEditorWindow::onChooseAnimation(
const std::string& f) {
265 animLabel->setText(f);
269 void NpcEditorWindow::onChooseConversation(
const std::string& c) {
270 convLabel->setText(c);
271 window->setForceFocus(
true);
275 void NpcEditorWindow::forceWindowOnTop() { window->setForceFocus(
true); }
Core classes and functionality for both the editor and game.
All classes and functionality used for implementing the game editor.
bl::util::FileUtil FileUtil
Type type() const
The type of behavior this is.
Path & path()
The data for path following.
std::vector< Pace > paces
The sections of the path.
bool save(const std::string &file) const
Saves the NPC data to the given file.
std::string & conversation()
The conversation file of the NPC.
Behavior & behavior()
The behavior of the NPC.
std::string & name()
The name of the NPC.
bool load(const std::string &file, bl::tmap::Direction spawnDir=bl::tmap::Direction::Up)
Loads the NPC data from the given file.
std::string & animation()
The directory of the movement animations.
static const std::string & NpcFileExtension()
static const std::string & ConversationPath()
static const std::string & NpcPath()
static const std::string & CharacterAnimationPath()
void hide()
Removes the window from view.
const core::file::Behavior & getValue() const
Returns the behavior value.
void hide()
Hides the editor window if opened.
void configure(bl::gui::GUI *parent, const core::file::Behavior &behavior)
Sets the parent GUI object and current value. Call before using.
std::function< void(const std::string &file)> SelectCb
Callback for when an NPC file is selected.
void hide()
Hides the window and all created child windows.
NpcEditorWindow(const SelectCb &cb, const CloseCb &closeCb)
Construct a new Npc Editor Window.
void show(bl::gui::GUI *parent, const std::string &file)
Opens the NPC editor.
std::function< void()> CloseCb
Called when the window is closed.