diff --git a/story-editor/CMakeLists.txt b/story-editor/CMakeLists.txt index 3b1458d..6377592 100644 --- a/story-editor/CMakeLists.txt +++ b/story-editor/CMakeLists.txt @@ -119,6 +119,9 @@ set(SRCS src/resources_window.cpp src/resources_window.h + src/node_properties_window.cpp + src/node_properties_window.h + src/gui.h src/gui.cpp diff --git a/story-editor/assets/build.png b/story-editor/assets/build.png new file mode 100644 index 0000000..b22ec59 Binary files /dev/null and b/story-editor/assets/build.png differ diff --git a/story-editor/assets/build.svg b/story-editor/assets/build.svg new file mode 100644 index 0000000..38bbfc9 --- /dev/null +++ b/story-editor/assets/build.svg @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + diff --git a/story-editor/assets/check-mark.png b/story-editor/assets/check-mark.png new file mode 100644 index 0000000..9a25900 Binary files /dev/null and b/story-editor/assets/check-mark.png differ diff --git a/story-editor/assets/close-outline.svg b/story-editor/assets/close-outline.svg new file mode 100644 index 0000000..6673e6f --- /dev/null +++ b/story-editor/assets/close-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/story-editor/assets/file-document-plus-outline.png b/story-editor/assets/file-document-plus-outline.png new file mode 100644 index 0000000..65856af Binary files /dev/null and b/story-editor/assets/file-document-plus-outline.png differ diff --git a/story-editor/assets/file-document-plus-outline.svg b/story-editor/assets/file-document-plus-outline.svg new file mode 100644 index 0000000..958e091 --- /dev/null +++ b/story-editor/assets/file-document-plus-outline.svg @@ -0,0 +1,39 @@ + + + + + + diff --git a/story-editor/assets/floppy.svg b/story-editor/assets/floppy.svg new file mode 100644 index 0000000..9d1a063 --- /dev/null +++ b/story-editor/assets/floppy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/story-editor/assets/folder-open-outline.svg b/story-editor/assets/folder-open-outline.svg new file mode 100644 index 0000000..28af2ad --- /dev/null +++ b/story-editor/assets/folder-open-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/story-editor/assets/folder-open.svg b/story-editor/assets/folder-open.svg new file mode 100644 index 0000000..1257da2 --- /dev/null +++ b/story-editor/assets/folder-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/story-editor/assets/home.png b/story-editor/assets/home.png new file mode 100644 index 0000000..f7698bf Binary files /dev/null and b/story-editor/assets/home.png differ diff --git a/story-editor/assets/left.png b/story-editor/assets/left.png new file mode 100644 index 0000000..7fd799b Binary files /dev/null and b/story-editor/assets/left.png differ diff --git a/story-editor/assets/pause.png b/story-editor/assets/pause.png new file mode 100644 index 0000000..9aa3e3c Binary files /dev/null and b/story-editor/assets/pause.png differ diff --git a/story-editor/assets/play-circle-green.svg b/story-editor/assets/play-circle-green.svg new file mode 100644 index 0000000..ac6e09a --- /dev/null +++ b/story-editor/assets/play-circle-green.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/story-editor/assets/play-circle.png b/story-editor/assets/play-circle.png new file mode 100644 index 0000000..d90b7a3 Binary files /dev/null and b/story-editor/assets/play-circle.png differ diff --git a/story-editor/assets/play-circle.svg b/story-editor/assets/play-circle.svg new file mode 100644 index 0000000..e152677 --- /dev/null +++ b/story-editor/assets/play-circle.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/story-editor/assets/play.png b/story-editor/assets/play.png new file mode 100644 index 0000000..8c7d84b Binary files /dev/null and b/story-editor/assets/play.png differ diff --git a/story-editor/assets/right.png b/story-editor/assets/right.png new file mode 100644 index 0000000..e274d8b Binary files /dev/null and b/story-editor/assets/right.png differ diff --git a/story-editor/assets/volume-high.svg b/story-editor/assets/volume-high.svg new file mode 100644 index 0000000..e261a16 --- /dev/null +++ b/story-editor/assets/volume-high.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/story-editor/assets/volume-off.png b/story-editor/assets/volume-off.png new file mode 100644 index 0000000..181a0c3 Binary files /dev/null and b/story-editor/assets/volume-off.png differ diff --git a/story-editor/assets/volume-off.svg b/story-editor/assets/volume-off.svg new file mode 100644 index 0000000..39affc4 --- /dev/null +++ b/story-editor/assets/volume-off.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/story-editor/assets/welcome.png b/story-editor/assets/welcome.png new file mode 100644 index 0000000..efc8524 Binary files /dev/null and b/story-editor/assets/welcome.png differ diff --git a/story-editor/src/base_node.h b/story-editor/src/base_node.h index 376c63b..79c1c8b 100644 --- a/story-editor/src/base_node.h +++ b/story-editor/src/base_node.h @@ -106,6 +106,8 @@ public: virtual void Draw() = 0; + virtual void DrawProperties() = 0; + void SetPosition(int x, int y); void FrameStart(); @@ -115,9 +117,19 @@ public: uint32_t Outputs() const { return m_node->Outputs.size(); } + void SetType(const std::string &type) + { + m_type = type; + } + + std::string GetType() const + { + return m_type; + } + void SetId(const int id) { m_id = id; } int GetId() const { return m_id; } - int GetInternalId() const { return m_node->ID.Get(); } + unsigned long GetInternalId() const { return m_node->ID.Get(); } void seTitle(const std::string &title) { m_title = title; } std::string getTitle() const { return m_title; } diff --git a/story-editor/src/emulator_window.cpp b/story-editor/src/emulator_window.cpp index c2a5ad6..9abedbb 100644 --- a/story-editor/src/emulator_window.cpp +++ b/story-editor/src/emulator_window.cpp @@ -5,6 +5,7 @@ EmulatorWindow::EmulatorWindow() : WindowBase("Emulator") { + Gui::LoadRawImage("assets/play.png", m_playImage); } void EmulatorWindow::Initialize() { @@ -21,16 +22,19 @@ void EmulatorWindow::Draw() // return; // } - + static ImVec2 size(320.0f, 240.0f); WindowBase::BeginDraw(); ImGui::SetWindowSize(ImVec2(626, 744), ImGuiCond_FirstUseEver); // ImGui::Image((void*)(intptr_t)my_image_texture, ImVec2(313, 367)); - float sz = ImGui::GetTextLineHeight(); +// float sz = ImGui::GetTextLineHeight(); ImVec2 p = ImGui::GetCursorScreenPos(); - ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + sz, p.y + sz), ImGui::GetColorU32(ImVec4(1.0, 1.0, 1.0, 1.0))); + ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + 320, p.y + 240), ImGui::GetColorU32(ImVec4(1.0, 1.0, 1.0, 1.0))); + + ImGui::SetCursorScreenPos(ImVec2(p.x, p.y + 240)); + ImGui::ImageButton("play", m_playImage.texture, ImVec2(45, 45)); WindowBase::EndDraw(); } diff --git a/story-editor/src/emulator_window.h b/story-editor/src/emulator_window.h index f0a6d90..2ed1d61 100644 --- a/story-editor/src/emulator_window.h +++ b/story-editor/src/emulator_window.h @@ -1,6 +1,7 @@ #pragma once #include "window_base.h" +#include "gui.h" class EmulatorWindow : public WindowBase { @@ -11,6 +12,9 @@ public: virtual void Draw() override; private: + Gui::Image m_playImage; + Gui::Image m_pauseImage; + Gui::Image m_homeImage; }; diff --git a/story-editor/src/main_window.cpp b/story-editor/src/main_window.cpp index 259364e..16a028b 100644 --- a/story-editor/src/main_window.cpp +++ b/story-editor/src/main_window.cpp @@ -165,6 +165,7 @@ void MainWindow::Initialize() editor.Initialize(); m_emulatorWindow.Initialize(); m_nodeEditorWindow.Initialize(); + m_nodePropertiesWindow.Initialize(); LoadParams(); } @@ -596,6 +597,8 @@ void MainWindow::Loop() m_resourcesWindow.Draw(); m_nodeEditorWindow.Draw(); + m_nodePropertiesWindow.SetSelectedNode(m_nodeEditorWindow.GetSelectedNode()); + m_nodePropertiesWindow.Draw(); ShowOptionsWindow(); diff --git a/story-editor/src/main_window.h b/story-editor/src/main_window.h index c889588..a33ab81 100644 --- a/story-editor/src/main_window.h +++ b/story-editor/src/main_window.h @@ -8,6 +8,7 @@ #include "emulator_window.h" #include "resources_window.h" #include "node_editor_window.h" +#include "node_properties_window.h" #include "chip32_assembler.h" #include "chip32_vm.h" @@ -106,6 +107,9 @@ private: NodeEditorWindow m_nodeEditorWindow; + NodePropertiesWindow m_nodePropertiesWindow; + + char mBufAddress[200]; char mBufReceivePath[200]; char mBufSendPath[200]; diff --git a/story-editor/src/media_node.cpp b/story-editor/src/media_node.cpp index 92b5925..9938728 100644 --- a/story-editor/src/media_node.cpp +++ b/story-editor/src/media_node.cpp @@ -57,40 +57,9 @@ void MediaNode::Draw() - ImGui::AlignTextToFramePadding(); - ImGui::Text("Image"); - ImGui::SameLine(); - - ImGui::Text("%s", m_image.name.c_str()); - - ImGui::SameLine(); - - bool do_popup = false; - std::string type = "sound"; - if (ImGui::Button("Select...")) { - do_popup = true; // Instead of saying OpenPopup() here, we set this bool, which is used later in the Deferred Pop-up Section - type = "image"; - } - // Use AlignTextToFramePadding() to align text baseline to the baseline of framed elements // (otherwise a Text+SameLine+Button sequence will have the text a little too high by default) - ImGui::AlignTextToFramePadding(); - ImGui::Text("Sound"); - ImGui::SameLine(); - - ImGui::Text("%s", m_soundName.c_str()); - - ImGui::SameLine(); - - if (ImGui::Button(m_buttonUniqueName.c_str())) - { - m_project.PlaySoundFile(m_soundPath); - } - - if (ImGui::Button("Select...")) { - do_popup = true; // Instead of saying OpenPopup() here, we set this bool, which is used later in the Deferred Pop-up Section - } ImGui::AlignTextToFramePadding(); ImGui::Text("Outputs:"); @@ -119,47 +88,9 @@ void MediaNode::Draw() DrawPins(); - if (do_popup) { - ImGui::OpenPopup("popup_button"); // Cause openpopup to stick open. - do_popup = false; // disable bool so that if we click off the popup, it doesn't open the next frame. - } - - // This is the actual popup Gui drawing section. - if (ImGui::BeginPopup("popup_button")) { - // Note: if it weren't for the child window, we would have to PushItemWidth() here to avoid a crash! - ImGui::TextDisabled("Choose media file:"); - - - static int item_current_idx = 0; // Here we store our selection data as an index. - if (ImGui::BeginListBox("listbox media")) - { - auto [filtreDebut, filtreFin] = m_project.Sounds(); - int n = 0; - for (auto it = filtreDebut; it != filtreFin; ++it, n++) - { - const bool is_selected = (item_current_idx == n); - if (ImGui::Selectable((*it)->file.c_str(), is_selected)) - item_current_idx = n; - - // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndListBox(); - } - - - if (ImGui::Button("Ok")) { - - ImGui::CloseCurrentPopup(); // These calls revoke the popup open state, which was set by OpenPopup above. - } - - ImGui::EndChild(); - ImGui::EndPopup(); // Note this does not do anything to the popup open/close state. It just terminates the content declaration. - } - BaseNode::FrameEnd(); + } /* @@ -179,3 +110,57 @@ void MediaNode::FromJson(nlohmann::json &j) m_soundName = j["sound"].get(); m_soundPath = m_project.BuildFullAssetsPath(m_soundName); } + +void MediaNode::DrawProperties() +{ + ImGui::AlignTextToFramePadding(); + ImGui::Text("Image"); + ImGui::SameLine(); + + ImGui::Text("%s", m_image.name.c_str()); + + ImGui::SameLine(); + + std::string type = "sound"; + if (ImGui::Button("Select...##image")) { + type = "image"; + ImGui::OpenPopup("popup_button"); + } + + ImGui::AlignTextToFramePadding(); + ImGui::Text("Sound"); + ImGui::SameLine(); + + ImGui::Text("%s", m_soundName.c_str()); + + ImGui::SameLine(); + + if (ImGui::Button(m_buttonUniqueName.c_str())) + { + m_project.PlaySoundFile(m_soundPath); + } + + if (ImGui::Button("Select...##sound")) { + ImGui::OpenPopup("popup_button"); + } + + + // This is the actual popup Gui drawing section. + if (ImGui::BeginPopup("popup_button")) { + ImGui::SeparatorText("Sounds"); + + static int item_current_idx = 0; // Here we store our selection data as an index. + + + auto [filtreDebut, filtreFin] = m_project.Sounds(); + int n = 0; + for (auto it = filtreDebut; it != filtreFin; ++it, n++) + { + if (ImGui::Selectable((*it)->file.c_str()), n == item_current_idx) + item_current_idx = n; + } + + ImGui::EndPopup(); // Note this does not do anything to the popup open/close state. It just terminates the content declaration. + } + +} diff --git a/story-editor/src/media_node.h b/story-editor/src/media_node.h index e78cd94..5e85554 100644 --- a/story-editor/src/media_node.h +++ b/story-editor/src/media_node.h @@ -20,11 +20,15 @@ public: virtual void FromJson(nlohmann::json &j) override; + virtual void DrawProperties() override; + private: IStoryProject &m_project; Gui::Image m_image; std::string m_soundName; std::string m_soundPath; + std::string m_id; + std::string m_buttonUniqueName; }; diff --git a/story-editor/src/node_editor_window.cpp b/story-editor/src/node_editor_window.cpp index 25b3a58..e1a5c7a 100644 --- a/story-editor/src/node_editor_window.cpp +++ b/story-editor/src/node_editor_window.cpp @@ -50,13 +50,14 @@ void NodeEditorWindow::LoadNode(const nlohmann::json &nodeJson) auto n = createNode(type, "", m_project); if (n) { + n->SetType(type); // FIXME: set type in createNode factory? n->SetId(restoredNodeId); nlohmann::json posJson = nodeJson["position"]; n->SetOutputs(nodeJson["outPortCount"].get()); n->SetPosition(posJson["x"].get(), posJson["y"].get()); n->FromJson(internalDataJson); - m_nodes[restoredNodeId] = n; + m_nodes[n->GetInternalId()] = n; } else { @@ -71,7 +72,7 @@ void NodeEditorWindow::LoadNode(const nlohmann::json &nodeJson) } -ed::PinId NodeEditorWindow::GetInputPin(int modelNodeId, int pinIndex) +ed::PinId NodeEditorWindow::GetInputPin(unsigned long modelNodeId, int pinIndex) { ed::PinId id = -1; @@ -86,7 +87,7 @@ ed::PinId NodeEditorWindow::GetInputPin(int modelNodeId, int pinIndex) return id; } -ed::PinId NodeEditorWindow::GetOutputPin(int modelNodeId, int pinIndex) +ed::PinId NodeEditorWindow::GetOutputPin(unsigned long modelNodeId, int pinIndex) { ed::PinId id = -1; @@ -126,17 +127,39 @@ void NodeEditorWindow::Load(const nlohmann::json &model) // ImGui stuff for links - conn->Id = 100000 + BaseNode::GetNextId(); + conn->Id = BaseNode::GetNextId(); conn->InputId = GetInputPin(conn->model.inNodeId, conn->model.inPortIndex); conn->OutputId = GetOutputPin(conn->model.outNodeId, conn->model.outPortIndex); // Since we accepted new link, lets add one to our list of links. m_links.push_back(conn); } - - } +std::shared_ptr NodeEditorWindow::GetSelectedNode() +{ + std::shared_ptr selected; + + ed::SetCurrentEditor(m_context); + if (ed::GetSelectedObjectCount() > 0) + { + ed::NodeId nId; + int nodeCount = ed::GetSelectedNodes(&nId, 1); + + if (nodeCount > 0) + { + if (m_nodes.contains(nId.Get())) + { + selected = m_nodes[nId.Get()]; + } + } + } + ed::SetCurrentEditor(nullptr); + + return selected; +} + + void NodeEditorWindow::Draw() { if (WindowBase::BeginDraw()) @@ -148,7 +171,9 @@ void NodeEditorWindow::Draw() for (const auto & n : m_nodes) { + ImGui::PushID(n.first); n.second->Draw(); + ImGui::PopID(); } for (const auto& linkInfo : m_links) @@ -180,10 +205,10 @@ void NodeEditorWindow::Draw() if (ed::AcceptNewItem()) { // Since we accepted new link, lets add one to our list of links. - // m_Links.push_back({ ed::LinkId(BaseNode::GetNextId()), inputPinId, outputPinId }); +// m_Links.push_back({ ed::LinkId(BaseNode::GetNextId()), inputPinId, outputPinId }); // Draw new link. - // ed::Link(m_Links.back().Id, m_Links.back().InputId, m_Links.back().OutputId); +// ed::Link(m_Links.back().Id, m_Links.back().InputId, m_Links.back().OutputId); } // You may choose to reject connection between these nodes diff --git a/story-editor/src/node_editor_window.h b/story-editor/src/node_editor_window.h index 1e548f4..d48db36 100644 --- a/story-editor/src/node_editor_window.h +++ b/story-editor/src/node_editor_window.h @@ -47,13 +47,14 @@ public: void Clear(); void Load(const nlohmann::json &model); + std::shared_ptr GetSelectedNode(); private: IStoryProject &m_project; ed::EditorContext* m_context = nullptr; // key: Id - std::map> m_nodes; + std::map> m_nodes; std::vector> m_links; // List of live links. It is dynamic unless you want to create read-only view over nodes. void ToolbarUI(); @@ -99,7 +100,7 @@ private: } void LoadNode(const nlohmann::json &nodeJson); - ed::PinId GetInputPin(int modelNodeId, int pinIndex); - ed::PinId GetOutputPin(int modelNodeId, int pinIndex); + ed::PinId GetInputPin(unsigned long modelNodeId, int pinIndex); + ed::PinId GetOutputPin(unsigned long modelNodeId, int pinIndex); }; diff --git a/story-editor/src/node_properties_window.cpp b/story-editor/src/node_properties_window.cpp new file mode 100644 index 0000000..42ca70a --- /dev/null +++ b/story-editor/src/node_properties_window.cpp @@ -0,0 +1,42 @@ +#include "node_properties_window.h" +#include "gui.h" + +NodePropertiesWindow::NodePropertiesWindow() + : WindowBase("Properties") +{ + +} + +void NodePropertiesWindow::Initialize() { + + int my_image_width = 0; + int my_image_height = 0; + +} + +void NodePropertiesWindow::Draw() +{ +// if (!IsVisible()) +// { +// return; +// } + + + WindowBase::BeginDraw(); + ImGui::SetWindowSize(ImVec2(626, 744), ImGuiCond_FirstUseEver); + + + static char buf1[32] = ""; ImGui::InputText("Title", buf1, 32); + + if (m_selectedNode) + { + m_selectedNode->DrawProperties(); + } + + WindowBase::EndDraw(); +} + +void NodePropertiesWindow::SetSelectedNode(std::shared_ptr node) +{ + m_selectedNode = node; +} diff --git a/story-editor/src/node_properties_window.h b/story-editor/src/node_properties_window.h new file mode 100644 index 0000000..5c4fb04 --- /dev/null +++ b/story-editor/src/node_properties_window.h @@ -0,0 +1,22 @@ +#pragma once + +#include "window_base.h" +#include "gui.h" + +#include "base_node.h" + +class NodePropertiesWindow : public WindowBase +{ +public: + NodePropertiesWindow(); + + void Initialize(); + virtual void Draw() override; + + void SetSelectedNode(std::shared_ptr node); + +private: + std::shared_ptr m_selectedNode; + +}; +