Readded file tabs
This commit is contained in:
parent
26c9be8318
commit
3c5e41af94
17 changed files with 297 additions and 213 deletions
|
|
@ -1,21 +1,26 @@
|
|||
#include "CustomEvents.hpp"
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_events.h>
|
||||
#include <queue>
|
||||
|
||||
namespace CustomEvents {
|
||||
|
||||
bool alreadyInitialized = false;
|
||||
|
||||
uint32_t PASTE_EVENT;
|
||||
std::queue<PasteEventData> pasteEventData;
|
||||
|
||||
void init() {
|
||||
if(!alreadyInitialized) {
|
||||
PASTE_EVENT = SDL_RegisterEvents(1);
|
||||
OPEN_INFINIPAINT_FILE_EVENT = SDL_RegisterEvents(1);
|
||||
alreadyInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Paste event
|
||||
|
||||
uint32_t PASTE_EVENT;
|
||||
std::queue<PasteEventData> pasteEventData;
|
||||
|
||||
bool emit_paste_event(const PasteEventData& pasteData) {
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
|
|
@ -35,4 +40,29 @@ void pop_paste_event_data() {
|
|||
pasteEventData.pop();
|
||||
}
|
||||
|
||||
|
||||
// Open InfiniPaint file event
|
||||
|
||||
uint32_t OPEN_INFINIPAINT_FILE_EVENT;
|
||||
std::queue<OpenInfiniPaintFileEventData> openInfiniPaintFileEventData;
|
||||
|
||||
bool emit_open_infinipaint_file_event(const OpenInfiniPaintFileEventData& openData) {
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
event.type = OPEN_INFINIPAINT_FILE_EVENT;
|
||||
if(SDL_PushEvent(&event)) {
|
||||
openInfiniPaintFileEventData.push(openData);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const OpenInfiniPaintFileEventData& get_open_infinipaint_file_event_data() {
|
||||
return openInfiniPaintFileEventData.front();
|
||||
}
|
||||
|
||||
void pop_open_infinipaint_file_event_data() {
|
||||
openInfiniPaintFileEventData.pop();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
namespace CustomEvents {
|
||||
void init();
|
||||
|
||||
// Paste event
|
||||
enum class PasteEventDataType {
|
||||
TEXT,
|
||||
IMAGE
|
||||
|
|
@ -23,4 +24,21 @@ namespace CustomEvents {
|
|||
void pop_paste_event_data();
|
||||
|
||||
extern uint32_t PASTE_EVENT;
|
||||
|
||||
|
||||
// Open InfiniPaint file event
|
||||
|
||||
struct OpenInfiniPaintFileEventData {
|
||||
bool isClient;
|
||||
std::optional<std::filesystem::path> filePathSource;
|
||||
std::string netSource;
|
||||
std::string serverLocalID;
|
||||
std::string_view fileDataBuffer;
|
||||
};
|
||||
|
||||
bool emit_open_infinipaint_file_event(const OpenInfiniPaintFileEventData& openData);
|
||||
const OpenInfiniPaintFileEventData& get_open_infinipaint_file_event_data();
|
||||
void pop_open_infinipaint_file_event_data();
|
||||
|
||||
extern uint32_t OPEN_INFINIPAINT_FILE_EVENT;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,3 +162,8 @@ void GUIHolder::input_finger_touch_callback(const InputManager::FingerTouchCallb
|
|||
|
||||
void GUIHolder::input_finger_motion_callback(const InputManager::FingerMotionCallbackArgs& motion) {
|
||||
}
|
||||
|
||||
void GUIHolder::post_callback() {
|
||||
gui.run_post_callback_func();
|
||||
gui.layout_if_necessary();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ class GUIHolder {
|
|||
void input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel);
|
||||
void input_finger_touch_callback(const InputManager::FingerTouchCallbackArgs& touch);
|
||||
void input_finger_motion_callback(const InputManager::FingerMotionCallbackArgs& motion);
|
||||
void post_callback();
|
||||
|
||||
float final_gui_scale();
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -3,65 +3,83 @@
|
|||
#include "../GUIManager.hpp"
|
||||
#include <iostream>
|
||||
|
||||
#include "../ElementHelpers/ButtonHelpers.hpp"
|
||||
#include "../ElementHelpers/TextLabelHelpers.hpp"
|
||||
#include "SVGIcon.hpp"
|
||||
|
||||
namespace GUIStuff {
|
||||
|
||||
using namespace ElementHelpers;
|
||||
|
||||
MovableTabList::MovableTabList(GUIManager& gui): Element(gui) {}
|
||||
|
||||
void MovableTabList::layout(const Clay_ElementId& id, const Data& d) {
|
||||
//CLAY_AUTO_ID({.layout = {
|
||||
// .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(GUIStuff::GUIManager::BIG_BUTTON_SIZE)},
|
||||
// .padding = CLAY_PADDING_ALL(0),
|
||||
// .childGap = 4,
|
||||
// .childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER },
|
||||
// .layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
// },
|
||||
// .clip = {.horizontal = true, .childOffset = Clay_GetScrollOffset()}
|
||||
//}) {
|
||||
// for(size_t i = 0; i < d.tabNames.size(); i++) {
|
||||
// CLAY_AUTO_ID({.layout = {
|
||||
// .sizing = {.width = CLAY_SIZING_FIT(200), .height = CLAY_SIZING_GROW(0)},
|
||||
// }
|
||||
// }) {
|
||||
// buttons[i].update(io, SelectableButton::DrawType::FILLED, [&](SelectionHelper& s, bool iS) {
|
||||
// CLAY_AUTO_ID({.layout = {
|
||||
// .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},
|
||||
// .padding = CLAY_PADDING_ALL(0),
|
||||
// .childGap = 4,
|
||||
// .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
|
||||
// .layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
// }
|
||||
// }) {
|
||||
// if(!tabNames[i].first.empty()) {
|
||||
// CLAY_AUTO_ID({.layout = {
|
||||
// .sizing = {.width = CLAY_SIZING_FIXED(GUIStuff::GUIManager::SMALL_BUTTON_SIZE), .height = CLAY_SIZING_FIXED(GUIStuff::GUIManager::SMALL_BUTTON_SIZE)},
|
||||
// .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
|
||||
// .layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
// }
|
||||
// }) {
|
||||
// tabIcons[i].update(io, tabNames[i].first, iS, nullptr);
|
||||
// }
|
||||
// }
|
||||
// CLAY_TEXT(io.strArena->std_str_to_clay_str(tabNames[i].second), CLAY_TEXT_CONFIG({.textColor = convert_vec4<Clay_Color>(io.theme->frontColor1), .fontSize = io.fontSize }));
|
||||
// if(s.clicked)
|
||||
// selectedTab = i;
|
||||
// CLAY_AUTO_ID({.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}}) {}
|
||||
// CLAY_AUTO_ID({.layout = {
|
||||
// .sizing = {.width = CLAY_SIZING_FIXED(GUIStuff::GUIManager::SMALL_BUTTON_SIZE), .height = CLAY_SIZING_FIXED(GUIStuff::GUIManager::SMALL_BUTTON_SIZE)},
|
||||
// .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
|
||||
// .layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
// }
|
||||
// }) {
|
||||
// closeButtons[i].update(io, SelectableButton::DrawType::TRANSPARENT_ALL, [&](SelectionHelper& s, bool iS) {
|
||||
// if(s.clicked)
|
||||
// closedTab = i;
|
||||
// closeIcons[i].update(io, "data/icons/close.svg", s.held || s.hovered, nullptr);
|
||||
// }, false);
|
||||
// }
|
||||
// }
|
||||
// }, currentSelectedTab == i);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
void MovableTabList::layout(const Clay_ElementId& id, const MovableTabListData& newData) {
|
||||
d = newData;
|
||||
CLAY(id, {.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(BIG_BUTTON_SIZE)},
|
||||
.padding = CLAY_PADDING_ALL(0),
|
||||
.childGap = 4,
|
||||
.childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER },
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
},
|
||||
.clip = {.horizontal = true, .childOffset = Clay_GetScrollOffset()}
|
||||
}) {
|
||||
for(size_t i = 0; i < d.tabNames.size(); i++) {
|
||||
CLAY_AUTO_ID({.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIT(200), .height = CLAY_SIZING_GROW(0)},
|
||||
}
|
||||
}) {
|
||||
gui.new_id(i, [&] {
|
||||
gui.element<SelectableButton>("b", SelectableButton::Data{
|
||||
.drawType = SelectableButton::DrawType::FILLED,
|
||||
.isSelected = d.selectedTab == i,
|
||||
.onClick = [&, i] {
|
||||
if(d.selectedTab != i && d.changeSelectedTab) d.changeSelectedTab(i);
|
||||
},
|
||||
.innerContent = [&] (const SelectableButton::InnerContentCallbackParameters&) {
|
||||
CLAY_AUTO_ID({.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},
|
||||
.padding = CLAY_PADDING_ALL(0),
|
||||
.childGap = 4,
|
||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
}
|
||||
}) {
|
||||
if(!d.tabNames[i].iconPath.empty()) {
|
||||
CLAY_AUTO_ID({.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIXED(SMALL_BUTTON_SIZE), .height = CLAY_SIZING_FIXED(SMALL_BUTTON_SIZE)},
|
||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
}
|
||||
}) {
|
||||
gui.element<SVGIcon>("icon", d.tabNames[i].iconPath);
|
||||
}
|
||||
}
|
||||
text_label(gui, d.tabNames[i].name);
|
||||
CLAY_AUTO_ID({.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}}) {}
|
||||
CLAY_AUTO_ID({.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIXED(SMALL_BUTTON_SIZE), .height = CLAY_SIZING_FIXED(SMALL_BUTTON_SIZE)},
|
||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
}
|
||||
}) {
|
||||
gui.element<SelectableButton>("close button", SelectableButton::Data {
|
||||
.drawType = SelectableButton::DrawType::TRANSPARENT_ALL,
|
||||
.onClick = [&, i] {
|
||||
if(d.closeTab) d.closeTab(i);
|
||||
},
|
||||
.innerContent = [&] (const SelectableButton::InnerContentCallbackParameters&) {
|
||||
gui.element<SVGIcon>("close", "data/icons/close.svg");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,17 +5,23 @@
|
|||
|
||||
namespace GUIStuff {
|
||||
|
||||
struct MovableTabListData {
|
||||
struct IconNamePair {
|
||||
std::string iconPath;
|
||||
std::string name;
|
||||
};
|
||||
std::vector<IconNamePair> tabNames;
|
||||
size_t selectedTab = 0;
|
||||
std::function<void(size_t)> changeSelectedTab;
|
||||
std::function<void(size_t)> closeTab;
|
||||
};
|
||||
|
||||
class MovableTabList : public Element {
|
||||
public:
|
||||
struct Data {
|
||||
std::vector<std::pair<std::string, std::string>> tabNames;
|
||||
size_t selectedTab = 0;
|
||||
std::function<void(size_t)> changeSelectedTab;
|
||||
std::function<void(size_t)> closeTab;
|
||||
};
|
||||
|
||||
MovableTabList(GUIManager& gui);
|
||||
void layout(const Clay_ElementId& id, const Data& d);
|
||||
void layout(const Clay_ElementId& id, const MovableTabListData& newData = {});
|
||||
private:
|
||||
MovableTabListData d;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace GUIStuff {
|
|||
class SVGIcon : public Element {
|
||||
public:
|
||||
SVGIcon(GUIManager& gui);
|
||||
void layout(const Clay_ElementId& id, const std::string& newSvgPath, bool newIsHighlighted);
|
||||
void layout(const Clay_ElementId& id, const std::string& newSvgPath, bool newIsHighlighted = false);
|
||||
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
|
||||
private:
|
||||
bool highlighted;
|
||||
|
|
|
|||
|
|
@ -347,29 +347,21 @@ bool GUIManager::cursor_obstructed() const {
|
|||
void GUIManager::input_paste_callback(const CustomEvents::PasteEventData& paste) {
|
||||
for(ElementContainer* e : orderedElements)
|
||||
e->elem->input_paste_callback(paste);
|
||||
run_post_callback_func();
|
||||
layout_if_necessary();
|
||||
}
|
||||
|
||||
void GUIManager::input_text_key_callback(const InputManager::KeyCallbackArgs& key) {
|
||||
for(ElementContainer* e : orderedElements)
|
||||
e->elem->input_text_key_callback(key);
|
||||
run_post_callback_func();
|
||||
layout_if_necessary();
|
||||
}
|
||||
|
||||
void GUIManager::input_text_callback(const InputManager::TextCallbackArgs& text) {
|
||||
for(ElementContainer* e : orderedElements)
|
||||
e->elem->input_text_callback(text);
|
||||
run_post_callback_func();
|
||||
layout_if_necessary();
|
||||
}
|
||||
|
||||
void GUIManager::input_key_callback(const InputManager::KeyCallbackArgs& key) {
|
||||
for(ElementContainer* e : orderedElements)
|
||||
e->elem->input_key_callback(key);
|
||||
run_post_callback_func();
|
||||
layout_if_necessary();
|
||||
}
|
||||
|
||||
void GUIManager::input_mouse_button_callback(InputManager::MouseButtonCallbackArgs button) {
|
||||
|
|
@ -411,9 +403,6 @@ void GUIManager::mouse_callback(const Vector2f& mousePos, const std::function<vo
|
|||
|
||||
for(ElementContainer* e : orderedElements)
|
||||
f(e);
|
||||
|
||||
run_post_callback_func();
|
||||
layout_if_necessary();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -362,6 +362,11 @@ uint32_t InputManager::make_generic_key_mod(SDL_Keymod m) {
|
|||
return toRet;
|
||||
}
|
||||
|
||||
void InputManager::backend_open_infinipaint_file_event() {
|
||||
main.input_open_infinipaint_file_callback(CustomEvents::get_open_infinipaint_file_event_data());
|
||||
CustomEvents::pop_open_infinipaint_file_event_data();
|
||||
}
|
||||
|
||||
void InputManager::backend_paste_event() {
|
||||
main.input_paste_callback(CustomEvents::get_paste_event_data());
|
||||
CustomEvents::pop_paste_event_data();
|
||||
|
|
|
|||
|
|
@ -262,6 +262,7 @@ struct InputManager {
|
|||
void touch_finger_do_mouse_up(const SDL_TouchFingerEvent& f);
|
||||
void touch_finger_do_mouse_motion(const SDL_TouchFingerEvent& f);
|
||||
|
||||
void backend_open_infinipaint_file_event();
|
||||
void backend_paste_event();
|
||||
void backend_input_text_event(const std::string& str);
|
||||
void backend_drop_file_event(const SDL_DropEvent& e);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "MainProgram.hpp"
|
||||
#include "CustomEvents.hpp"
|
||||
#include "VersionConstants.hpp"
|
||||
#include <SDL3/SDL_render.h>
|
||||
#include <SDL3/SDL_video.h>
|
||||
|
|
@ -69,27 +70,6 @@ void MainProgram::update() {
|
|||
|
||||
input.update();
|
||||
|
||||
for(auto& s : setTabsToClose)
|
||||
std::erase(worlds, s.lock());
|
||||
|
||||
std::erase_if(worlds, [&](const std::shared_ptr<World>& w) {
|
||||
return w->setToDestroy;
|
||||
});
|
||||
|
||||
if(worldIndex >= worlds.size())
|
||||
worldIndex = worlds.size() - 1;
|
||||
if(worlds.size() == 0)
|
||||
new_tab({
|
||||
.isClient = false
|
||||
}, true);
|
||||
|
||||
std::shared_ptr<World> oldWorld = world;
|
||||
world = worlds[worldIndex];
|
||||
if(oldWorld != world) {
|
||||
if(oldWorld)
|
||||
oldWorld->on_tab_out();
|
||||
}
|
||||
|
||||
deltaTime.update_time_since();
|
||||
deltaTime.update_time_point();
|
||||
|
||||
|
|
@ -103,13 +83,6 @@ void MainProgram::update() {
|
|||
g.update();
|
||||
|
||||
NetLibrary::update();
|
||||
|
||||
if(tabSetToOpen) {
|
||||
tabSetToOpen = false;
|
||||
new_tab_open();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool MainProgram::app_close_requested() {
|
||||
|
|
@ -123,31 +96,6 @@ void MainProgram::update_display_names() {
|
|||
}
|
||||
}
|
||||
|
||||
void MainProgram::new_tab(const World::OpenWorldInfo& tabInfo, bool createSameThread) {
|
||||
newTabToOpenInfo = tabInfo;
|
||||
if(createSameThread)
|
||||
new_tab_open();
|
||||
else
|
||||
tabSetToOpen = true;
|
||||
}
|
||||
|
||||
void MainProgram::new_tab_open() {
|
||||
std::unique_ptr<World> newWorld;
|
||||
try {
|
||||
newWorld = std::make_unique<World>(*this, newTabToOpenInfo);
|
||||
}
|
||||
catch(const std::runtime_error& e) {
|
||||
Logger::get().log("WORLDFATAL", "Failed to open canvas: " + (newTabToOpenInfo.filePathSource.has_value() ? newTabToOpenInfo.filePathSource.value().string() : "NO PATH") + " with error: " + e.what());
|
||||
return;
|
||||
}
|
||||
worlds.emplace_back(std::move(newWorld));
|
||||
worldIndex = worlds.size() - 1;
|
||||
}
|
||||
|
||||
void MainProgram::set_tab_to_close(const std::weak_ptr<World>& tabToClose) {
|
||||
setTabsToClose.emplace_back(tabToClose);
|
||||
}
|
||||
|
||||
void MainProgram::init_net_library() {
|
||||
NetLibrary::init(configPath / "p2p.json");
|
||||
}
|
||||
|
|
@ -317,10 +265,44 @@ sk_sp<SkSurface> MainProgram::create_native_surface(Vector2i resolution, bool is
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void MainProgram::create_new_tab(const CustomEvents::OpenInfiniPaintFileEventData& openFile) {
|
||||
std::shared_ptr<World> newWorld;
|
||||
try {
|
||||
newWorld = std::make_shared<World>(*this, openFile);
|
||||
}
|
||||
catch(const std::runtime_error& e) {
|
||||
Logger::get().log("WORLDFATAL", "Failed to open canvas: " + (openFile.filePathSource.has_value() ? openFile.filePathSource.value().string() : "NO PATH") + " with error: " + e.what());
|
||||
return;
|
||||
}
|
||||
worlds.emplace_back(newWorld);
|
||||
switch_to_tab(worlds.size() - 1);
|
||||
g.gui.set_to_layout();
|
||||
}
|
||||
|
||||
void MainProgram::set_tab_to_close(World* world) {
|
||||
tabsToClose.emplace(world);
|
||||
}
|
||||
|
||||
void MainProgram::switch_to_tab(size_t wIndex) {
|
||||
world = worlds[wIndex];
|
||||
worldIndex = wIndex;
|
||||
}
|
||||
|
||||
void MainProgram::post_callback() {
|
||||
close_set_to_close_tabs();
|
||||
g.post_callback();
|
||||
}
|
||||
|
||||
void MainProgram::input_open_infinipaint_file_callback(const CustomEvents::OpenInfiniPaintFileEventData& openFile) {
|
||||
create_new_tab(openFile);
|
||||
post_callback();
|
||||
}
|
||||
|
||||
void MainProgram::input_paste_callback(const CustomEvents::PasteEventData& paste) {
|
||||
g.input_paste_callback(paste);
|
||||
if(world)
|
||||
world->input_paste_callback(paste);
|
||||
post_callback();
|
||||
}
|
||||
|
||||
bool MainProgram::input_keybind_callback(const Vector2ui32& newKey) {
|
||||
|
|
@ -345,10 +327,10 @@ void MainProgram::input_drop_file_callback(const InputManager::DropCallbackArgs&
|
|||
if(std::filesystem::is_regular_file(drop.data)) {
|
||||
std::filesystem::path droppedFilePath(drop.data);
|
||||
if(droppedFilePath.has_extension() && droppedFilePath.extension().string() == std::string("." + World::FILE_EXTENSION)) {
|
||||
new_tab({
|
||||
CustomEvents::emit_open_infinipaint_file_event({
|
||||
.isClient = false,
|
||||
.filePathSource = droppedFilePath
|
||||
}, true);
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -378,36 +360,42 @@ void MainProgram::input_key_callback(const InputManager::KeyCallbackArgs& key) {
|
|||
g.input_key_callback(key);
|
||||
if(world)
|
||||
world->input_key_callback(key);
|
||||
post_callback();
|
||||
}
|
||||
|
||||
void MainProgram::input_text_key_callback(const InputManager::KeyCallbackArgs& key) {
|
||||
g.input_text_key_callback(key);
|
||||
if(world)
|
||||
world->input_text_key_callback(key);
|
||||
post_callback();
|
||||
}
|
||||
|
||||
void MainProgram::input_text_callback(const InputManager::TextCallbackArgs& text) {
|
||||
g.input_text_callback(text);
|
||||
if(world)
|
||||
world->input_text_callback(text);
|
||||
post_callback();
|
||||
}
|
||||
|
||||
void MainProgram::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) {
|
||||
g.input_mouse_button_callback(button);
|
||||
if(world)
|
||||
world->input_mouse_button_callback(button);
|
||||
post_callback();
|
||||
}
|
||||
|
||||
void MainProgram::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) {
|
||||
g.input_mouse_motion_callback(motion);
|
||||
if(world)
|
||||
world->input_mouse_motion_callback(motion);
|
||||
post_callback();
|
||||
}
|
||||
|
||||
void MainProgram::input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel) {
|
||||
g.input_mouse_wheel_callback(wheel);
|
||||
if(world)
|
||||
world->input_mouse_wheel_callback(wheel);
|
||||
post_callback();
|
||||
}
|
||||
|
||||
void MainProgram::input_pen_button_callback(const InputManager::PenButtonCallbackArgs& button) {
|
||||
|
|
@ -446,6 +434,29 @@ void MainProgram::input_finger_touch_callback(const InputManager::FingerTouchCal
|
|||
void MainProgram::input_finger_motion_callback(const InputManager::FingerMotionCallbackArgs& motion) {
|
||||
}
|
||||
|
||||
void MainProgram::close_set_to_close_tabs() {
|
||||
if(!tabsToClose.empty()) {
|
||||
std::erase_if(worlds, [&](auto& w) {
|
||||
if(tabsToClose.contains(w.get())) {
|
||||
if(w == world)
|
||||
world = nullptr;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if(worlds.empty())
|
||||
create_new_tab({
|
||||
.isClient = false
|
||||
});
|
||||
else if(world)
|
||||
worldIndex = std::find(worlds.begin(), worlds.end(), world) - worlds.begin();
|
||||
else
|
||||
switch_to_tab(0);
|
||||
tabsToClose.clear();
|
||||
g.gui.set_to_layout();
|
||||
}
|
||||
}
|
||||
|
||||
bool MainProgram::network_being_used() {
|
||||
for(auto& w : worlds) {
|
||||
if(w->netObjMan.is_connected())
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@ class MainProgram {
|
|||
TimePoint deltaTime;
|
||||
Toolbar toolbar;
|
||||
GUIHolder g;
|
||||
std::shared_ptr<World> world;
|
||||
ToolConfiguration toolConfig;
|
||||
|
||||
std::ofstream* logFile;
|
||||
|
|
@ -93,8 +92,6 @@ class MainProgram {
|
|||
|
||||
void early_destroy();
|
||||
|
||||
void new_tab(const World::OpenWorldInfo& tabInfo, bool createSameThread = false);
|
||||
void set_tab_to_close(const std::weak_ptr<World>& tabToClose);
|
||||
bool network_being_used();
|
||||
bool net_server_hosted();
|
||||
void update_display_names();
|
||||
|
|
@ -117,11 +114,13 @@ class MainProgram {
|
|||
bool drawGui = true;
|
||||
|
||||
size_t worldIndex = 0;
|
||||
std::shared_ptr<World> world;
|
||||
std::vector<std::shared_ptr<World>> worlds;
|
||||
|
||||
GlobalConfig conf;
|
||||
|
||||
std::optional<unsigned> keybindWaiting;
|
||||
void input_open_infinipaint_file_callback(const CustomEvents::OpenInfiniPaintFileEventData& openFile);
|
||||
void input_paste_callback(const CustomEvents::PasteEventData& paste);
|
||||
bool input_keybind_callback(const Vector2ui32& newKey);
|
||||
void input_drop_file_callback(const InputManager::DropCallbackArgs& drop);
|
||||
|
|
@ -141,13 +140,15 @@ class MainProgram {
|
|||
void input_finger_touch_callback(const InputManager::FingerTouchCallbackArgs& touch);
|
||||
void input_finger_motion_callback(const InputManager::FingerMotionCallbackArgs& motion);
|
||||
|
||||
void create_new_tab(const CustomEvents::OpenInfiniPaintFileEventData& openFile);
|
||||
void set_tab_to_close(World* world);
|
||||
void switch_to_tab(size_t wIndex);
|
||||
|
||||
~MainProgram();
|
||||
private:
|
||||
void new_tab_open();
|
||||
std::atomic<bool> tabSetToOpen = false;
|
||||
World::OpenWorldInfo newTabToOpenInfo;
|
||||
|
||||
std::vector<std::weak_ptr<World>> setTabsToClose;
|
||||
std::unordered_set<World*> tabsToClose;
|
||||
void close_set_to_close_tabs();
|
||||
void post_callback();
|
||||
|
||||
std::string gen_random_display_name();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "Toolbar.hpp"
|
||||
#include "CustomEvents.hpp"
|
||||
#include "DrawingProgram/Tools/DrawingProgramToolBase.hpp"
|
||||
#include "DrawingProgram/Tools/ScreenshotTool.hpp"
|
||||
#include "FileHelpers.hpp"
|
||||
|
|
@ -50,6 +51,7 @@
|
|||
#include "GUIStuff/Elements/LayoutElement.hpp"
|
||||
#include "GUIStuff/Elements/DropDown.hpp"
|
||||
#include "GUIStuff/Elements/SVGIcon.hpp"
|
||||
#include "GUIStuff/Elements/MovableTabList.hpp"
|
||||
|
||||
#define UPDATE_DOWNLOAD_URL "https://infinipaint.com/download.html"
|
||||
#define UPDATE_NOTIFICATION_URL "https://infinipaint.com/updateNotificationVersion.txt"
|
||||
|
|
@ -320,6 +322,7 @@ void Toolbar::add_world_to_close_popup_data(const std::shared_ptr<World>& w) {
|
|||
});
|
||||
if(it == closePopupData.worldsToClose.end())
|
||||
closePopupData.worldsToClose.emplace_back(w, true);
|
||||
main.g.gui.set_to_layout();
|
||||
}
|
||||
|
||||
void Toolbar::close_popup_gui() {
|
||||
|
|
@ -388,7 +391,7 @@ void Toolbar::close_popup_gui() {
|
|||
else
|
||||
wLock->save_to_file(wLock->filePath);
|
||||
}
|
||||
main.set_tab_to_close(w);
|
||||
main.set_tab_to_close(wLock.get());
|
||||
}
|
||||
closePopupData.worldsToClose.clear();
|
||||
if(closePopupData.closeAppWhenDone)
|
||||
|
|
@ -398,8 +401,11 @@ void Toolbar::close_popup_gui() {
|
|||
text_button(gui, "Discard All", "Discard All", {
|
||||
.wide = true,
|
||||
.onClick = [&] {
|
||||
for(auto& [w, setToSave] : closePopupData.worldsToClose)
|
||||
main.set_tab_to_close(w);
|
||||
for(auto& [w, setToSave] : closePopupData.worldsToClose) {
|
||||
auto wLock = w.lock();
|
||||
if(wLock)
|
||||
main.set_tab_to_close(wLock.get());
|
||||
}
|
||||
closePopupData.worldsToClose.clear();
|
||||
if(closePopupData.closeAppWhenDone)
|
||||
main.setToQuit = true;
|
||||
|
|
@ -495,31 +501,26 @@ void Toolbar::top_toolbar() {
|
|||
menuPopUpOpen = !menuPopUpOpen;
|
||||
});
|
||||
|
||||
std::vector<MovableTabListData::IconNamePair> tabNames;
|
||||
for(size_t i = 0; i < main.worlds.size(); i++) {
|
||||
auto& w = main.worlds[i];
|
||||
bool shouldAddStarNextToName = w->should_ask_before_closing() && !w->netServer && !w->netClient;
|
||||
tabNames.emplace_back(w->netObjMan.is_connected() ? "data/icons/network.svg" : "", w->name + (shouldAddStarNextToName ? "*" : ""));
|
||||
}
|
||||
|
||||
// Temporary gap between buttons while tab list is being fixed
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) },
|
||||
gui.element<MovableTabList>("file tab list", MovableTabListData{
|
||||
.tabNames = tabNames,
|
||||
.selectedTab = main.worldIndex,
|
||||
.changeSelectedTab = [&] (size_t i) {
|
||||
main.switch_to_tab(i);
|
||||
},
|
||||
.closeTab = [&] (size_t i) {
|
||||
if(main.worlds[i]->should_ask_before_closing())
|
||||
add_world_to_close_popup_data(main.worlds[i]);
|
||||
else
|
||||
main.set_tab_to_close(main.worlds[i].get());
|
||||
}
|
||||
}) { }
|
||||
|
||||
|
||||
//std::vector<std::pair<std::string, std::string>> tabNames;
|
||||
//for(size_t i = 0; i < main.worlds.size(); i++) {
|
||||
// auto& w = main.worlds[i];
|
||||
// bool shouldAddStarNextToName = w->should_ask_before_closing() && !w->netServer && !w->netClient;
|
||||
// tabNames.emplace_back(w->netObjMan.is_connected() ? "data/icons/network.svg" : "", w->name + (shouldAddStarNextToName ? "*" : ""));
|
||||
//}
|
||||
|
||||
//std::optional<size_t> closedTab;
|
||||
//gui.tab_list("file tab list", tabNames, main.worldIndex, closedTab);
|
||||
//if(closedTab) {
|
||||
// auto& closedWorldPtr = main.worlds[closedTab.value()];
|
||||
// if(closedWorldPtr->should_ask_before_closing())
|
||||
// add_world_to_close_popup_data(closedWorldPtr);
|
||||
// else
|
||||
// main.set_tab_to_close(closedWorldPtr);
|
||||
//}
|
||||
});
|
||||
|
||||
if(!main.world->clientStillConnecting) {
|
||||
if(main.world->netObjMan.is_connected()) {
|
||||
|
|
@ -596,9 +597,9 @@ void Toolbar::top_toolbar() {
|
|||
});
|
||||
};
|
||||
menu_popup_text_button("new file local", "New File", [&] {
|
||||
main.new_tab({
|
||||
CustomEvents::emit_open_infinipaint_file_event({
|
||||
.isClient = false
|
||||
}, true);
|
||||
});
|
||||
});
|
||||
menu_popup_text_button("open file", "Open", [&] { open_world_file(false, "", ""); });
|
||||
if(!main.world->clientStillConnecting) {
|
||||
|
|
@ -1454,18 +1455,8 @@ void Toolbar::player_list() {
|
|||
auto& gui = main.g.gui;
|
||||
auto& io = gui.io;
|
||||
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIT(500), .height = CLAY_SIZING_FIT(0) },
|
||||
.padding = CLAY_PADDING_ALL(io.theme->padding1),
|
||||
.childGap = io.theme->childGap1,
|
||||
.childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_TOP},
|
||||
.layoutDirection = CLAY_TOP_TO_BOTTOM
|
||||
},
|
||||
.backgroundColor = convert_vec4<Clay_Color>(io.theme->backColor1),
|
||||
.cornerRadius = CLAY_CORNER_RADIUS(io.theme->windowCorners1),
|
||||
.floating = {.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT}
|
||||
}) {
|
||||
|
||||
center_obstructing_window_gui("player client list", CLAY_SIZING_FIT(500), CLAY_SIZING_FIT(0), [&] {
|
||||
gui.new_id("client list", [&] {
|
||||
text_label_centered(gui, "Player List");
|
||||
if(!main.world->clientStillConnecting) {
|
||||
|
|
@ -1505,7 +1496,7 @@ void Toolbar::player_list() {
|
|||
playerMenuOpen = false;
|
||||
}});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Toolbar::open_world_file(bool isClient, const std::string& netSource, const std::string& serverLocalID2) {
|
||||
|
|
@ -1534,7 +1525,7 @@ void Toolbar::open_world_file(bool isClient, const std::string& netSource, const
|
|||
}, &uploadData);
|
||||
#else
|
||||
open_file_selector("Open", {{"InfiniPaint Canvas", World::FILE_EXTENSION}, {"Any File", "*"}}, [&, isClient = isClient, netSource = netSource, serverLocalID2 = serverLocalID2](const std::filesystem::path& p, const auto& e) {
|
||||
main.new_tab({
|
||||
CustomEvents::emit_open_infinipaint_file_event({
|
||||
.isClient = isClient,
|
||||
.filePathSource = p,
|
||||
.netSource = netSource,
|
||||
|
|
@ -1611,10 +1602,10 @@ void Toolbar::options_menu() {
|
|||
else if(serverToConnectTo.substr(0, NetLibrary::GLOBALID_LEN) == NetLibrary::get_global_id())
|
||||
Logger::get().log("USERINFO", "Connect issue: Can't connect to your own address");
|
||||
else {
|
||||
main.new_tab({
|
||||
CustomEvents::emit_open_infinipaint_file_event({
|
||||
.isClient = true,
|
||||
.netSource = serverToConnectTo
|
||||
}, true);
|
||||
});
|
||||
optionsMenuOpen = false;
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
#include <EmscriptenHelpers/emscripten_browser_file.h>
|
||||
#endif
|
||||
|
||||
World::World(MainProgram& initMain, OpenWorldInfo& worldInfo):
|
||||
World::World(MainProgram& initMain, const CustomEvents::OpenInfiniPaintFileEventData& worldInfo):
|
||||
netObjMan(!worldInfo.isClient),
|
||||
main(initMain),
|
||||
undo(*this),
|
||||
|
|
@ -151,12 +151,15 @@ void World::init_client(const std::string& serverFullID) {
|
|||
#endif
|
||||
|
||||
clientStillConnecting = false;
|
||||
drawProg.world.main.g.gui.set_to_layout();
|
||||
});
|
||||
netClient->add_recv_callback(CLIENT_UPDATE_NETWORK_OBJECT, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
netObjMan.read_update_message(message, nullptr);
|
||||
drawProg.world.main.g.gui.set_to_layout();
|
||||
});
|
||||
netClient->add_recv_callback(CLIENT_UPDATE_MANY_NETWORK_OBJECTS, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
netObjMan.read_many_update_message(message, nullptr);
|
||||
drawProg.world.main.g.gui.set_to_layout();
|
||||
});
|
||||
netClient->add_recv_callback(CLIENT_KEEP_ALIVE, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
});
|
||||
|
|
@ -165,8 +168,7 @@ void World::init_client(const std::string& serverFullID) {
|
|||
}
|
||||
|
||||
void World::focus_update() {
|
||||
connection_update();
|
||||
if(setToDestroy)
|
||||
if(!connection_update())
|
||||
return;
|
||||
|
||||
if(!clientStillConnecting) {
|
||||
|
|
@ -190,7 +192,7 @@ void World::focus_update() {
|
|||
rMan.update();
|
||||
}
|
||||
|
||||
void World::connection_update() {
|
||||
bool World::connection_update() {
|
||||
if(netServer) {
|
||||
if(netServer->is_disconnected()) {
|
||||
Logger::get().log("USERINFO", "Host connection failed");
|
||||
|
|
@ -209,8 +211,9 @@ void World::connection_update() {
|
|||
else if(netClient) {
|
||||
if(netClient->is_disconnected()) {
|
||||
Logger::get().log("USERINFO", "Client connection failed");
|
||||
setToDestroy = true;
|
||||
netObjMan.disconnect();
|
||||
main.set_tab_to_close(this);
|
||||
return false;
|
||||
}
|
||||
netClient->update();
|
||||
if(std::chrono::steady_clock::now() - lastKeepAliveSent > std::chrono::seconds(2)) {
|
||||
|
|
@ -218,6 +221,7 @@ void World::connection_update() {
|
|||
lastKeepAliveSent = std::chrono::steady_clock::now();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool World::is_focus() {
|
||||
|
|
@ -236,8 +240,6 @@ void World::redo_with_checks() {
|
|||
|
||||
void World::unfocus_update() {
|
||||
connection_update();
|
||||
if(setToDestroy)
|
||||
return;
|
||||
}
|
||||
|
||||
void World::on_tab_out() {
|
||||
|
|
@ -582,6 +584,13 @@ bool World::should_ask_before_closing() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void World::set_has_unsaved_local_changes(bool newHasUnsavedLocalChangesVal) {
|
||||
bool oldHasUnsavedLocalChanges = hasUnsavedLocalChanges;
|
||||
hasUnsavedLocalChanges = newHasUnsavedLocalChangesVal;
|
||||
if(oldHasUnsavedLocalChanges != hasUnsavedLocalChanges)
|
||||
main.g.gui.set_to_layout();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ORDERED_LIST_TEST
|
||||
void World::list_debug_test_update() {
|
||||
if(std::chrono::steady_clock::now() < (listDebugTestTimeStart + std::chrono::minutes(1))) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <Helpers/NetworkingObjects/DelayUpdateSerializedClassManager.hpp>
|
||||
#include <Helpers/NetworkingObjects/NetObjOrderedList.hpp>
|
||||
#include "CustomEvents.hpp"
|
||||
#include "Helpers/NetworkingObjects/NetObjUnorderedSet.hpp"
|
||||
#include "WorldUndoManager.hpp"
|
||||
#include "Bookmarks/BookmarkManager.hpp"
|
||||
|
|
@ -24,15 +25,7 @@ class World {
|
|||
static constexpr std::string FILE_EXTENSION = "infpnt";
|
||||
static constexpr size_t CHAT_SIZE = 10;
|
||||
|
||||
struct OpenWorldInfo {
|
||||
bool isClient;
|
||||
std::optional<std::filesystem::path> filePathSource;
|
||||
std::string netSource;
|
||||
std::string serverLocalID;
|
||||
std::string_view fileDataBuffer;
|
||||
};
|
||||
|
||||
World(MainProgram& initMain, OpenWorldInfo& worldInfo);
|
||||
World(MainProgram& initMain, const CustomEvents::OpenInfiniPaintFileEventData& worldInfo);
|
||||
|
||||
// NOTE: Keep at the very beginning so that it's destroyed last
|
||||
NetworkingObjects::NetObjManager netObjMan;
|
||||
|
|
@ -87,10 +80,9 @@ class World {
|
|||
void scale_up_step();
|
||||
|
||||
bool should_ask_before_closing();
|
||||
void set_has_unsaved_local_changes(bool newHasUnsavedLocalChangesVal);
|
||||
bool is_focus();
|
||||
|
||||
bool hasUnsavedLocalChanges = false;
|
||||
bool setToDestroy = false;
|
||||
NetworkingObjects::DelayUpdateSerializedClassManager delayedUpdateObjectManager;
|
||||
|
||||
std::shared_ptr<NetServer> netServer;
|
||||
|
|
@ -112,6 +104,9 @@ class World {
|
|||
void input_multi_finger_touch_callback(const InputManager::MultiFingerTouchCallbackArgs& touch);
|
||||
void input_multi_finger_motion_callback(const InputManager::MultiFingerMotionCallbackArgs& motion);
|
||||
private:
|
||||
|
||||
bool hasUnsavedLocalChanges = false;
|
||||
|
||||
void load_empty_canvas();
|
||||
|
||||
Vector3f get_random_cursor_color();
|
||||
|
|
@ -125,7 +120,7 @@ class World {
|
|||
void draw_other_player_cursors(SkCanvas* canvas, const DrawData& drawData);
|
||||
void ensure_display_name_unique(std::string& displayName);
|
||||
|
||||
void connection_update();
|
||||
bool connection_update();
|
||||
|
||||
TimePoint timeToSendCameraData;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ bool WorldUndoManager::can_redo() {
|
|||
void WorldUndoManager::push(std::unique_ptr<WorldUndoAction> undoAction) {
|
||||
push_undo(std::move(undoAction));
|
||||
redoQueue.clear();
|
||||
world.hasUnsavedLocalChanges = true;
|
||||
world.set_has_unsaved_local_changes(true);
|
||||
}
|
||||
|
||||
void WorldUndoManager::push_undo(std::unique_ptr<WorldUndoAction> undoAction) {
|
||||
|
|
@ -160,7 +160,7 @@ void WorldUndoManager::set_save_action() {
|
|||
undoActionSavedAt = nullptr;
|
||||
else
|
||||
undoActionSavedAt = undoQueue.back().get();
|
||||
world.hasUnsavedLocalChanges = false;
|
||||
world.set_has_unsaved_local_changes(false);
|
||||
}
|
||||
|
||||
void WorldUndoManager::set_world_has_unsaved_local_changes() {
|
||||
|
|
@ -169,11 +169,11 @@ void WorldUndoManager::set_world_has_unsaved_local_changes() {
|
|||
// - nullptr: The file was saved when undoQueue was empty
|
||||
// - nullopt: The undo action the file was saved at was lost
|
||||
if(!undoActionSavedAt.has_value())
|
||||
world.hasUnsavedLocalChanges = true;
|
||||
world.set_has_unsaved_local_changes(true);
|
||||
else {
|
||||
if(undoQueue.empty())
|
||||
world.hasUnsavedLocalChanges = undoActionSavedAt.value() != nullptr;
|
||||
world.set_has_unsaved_local_changes(undoActionSavedAt.value() != nullptr);
|
||||
else
|
||||
world.hasUnsavedLocalChanges = undoActionSavedAt.value() != undoQueue.back().get();
|
||||
world.set_has_unsaved_local_changes(undoActionSavedAt.value() != undoQueue.back().get());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
12
src/main.cpp
12
src/main.cpp
|
|
@ -436,6 +436,8 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
|
|||
|
||||
initialize_sdl(mS, initWidth, initHeight);
|
||||
|
||||
CustomEvents::init();
|
||||
|
||||
int32_t cursorData[2] = {0, 0};
|
||||
mS.hiddenCursor = SDL_CreateCursor((Uint8 *)cursorData, (Uint8 *)cursorData, 8, 8, 4, 4);
|
||||
|
||||
|
|
@ -548,16 +550,16 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
|
|||
resize_window(mS);
|
||||
|
||||
if(listOfFilesToOpenFromCommand.empty()) {
|
||||
mS.m->new_tab({
|
||||
mS.m->create_new_tab({
|
||||
.isClient = false
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
else {
|
||||
for(std::filesystem::path& f : listOfFilesToOpenFromCommand) {
|
||||
mS.m->new_tab({
|
||||
mS.m->create_new_tab({
|
||||
.isClient = false,
|
||||
.filePathSource = f
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -837,6 +839,8 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
|
|||
default: {
|
||||
if(event->type == CustomEvents::PASTE_EVENT)
|
||||
mS.m->input.backend_paste_event();
|
||||
else if(event->type == CustomEvents::OPEN_INFINIPAINT_FILE_EVENT)
|
||||
mS.m->input.backend_open_infinipaint_file_event();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue