Readded chat box
This commit is contained in:
parent
99c2657434
commit
60af55d4db
19 changed files with 307 additions and 249 deletions
|
|
@ -355,12 +355,14 @@ void BookmarkManager::setup_list_gui() {
|
|||
});
|
||||
});
|
||||
|
||||
if(editingBookmark) {
|
||||
text_label_centered(gui, editingBookmark->is_folder() ? "Edit Bookmark Folder" : "Edit Bookmark");
|
||||
auto editingBookmarkLock = editingBookmark.lock();
|
||||
if(editingBookmarkLock) {
|
||||
text_label_centered(gui, editingBookmarkLock->is_folder() ? "Edit Bookmark Folder" : "Edit Bookmark");
|
||||
input_text_field(gui, "input edit name", "Name", &nameToEdit, {
|
||||
.onEdit = [&] {
|
||||
if(editingBookmark) { // This can be set to null on the way here (close bookmark popup when textbox is selected)
|
||||
editingBookmark->set_name(world.delayedUpdateObjectManager, nameToEdit);
|
||||
auto editingBookmarkLock = editingBookmark.lock();
|
||||
if(editingBookmarkLock) { // This can be set to null on the way here (close bookmark popup when textbox is selected)
|
||||
editingBookmarkLock->set_name(world.delayedUpdateObjectManager, nameToEdit);
|
||||
world.main.g.gui.set_to_layout();
|
||||
}
|
||||
}
|
||||
|
|
@ -572,18 +574,19 @@ void BookmarkManager::editing_bookmark_check() {
|
|||
WorldUndoManager::UndoObjectID undoID;
|
||||
};
|
||||
|
||||
if(editingBookmark) {
|
||||
const std::string& currentNameData = editingBookmark->get_name();
|
||||
auto editingBookmarkLock = editingBookmark.lock();
|
||||
if(editingBookmarkLock) {
|
||||
const std::string& currentNameData = editingBookmarkLock->get_name();
|
||||
if(currentNameData != editingBookmarkOldName.value())
|
||||
world.undo.push(std::make_unique<EditBookmarkWorldUndoAction>(editingBookmarkOldName.value(), world.undo.get_undoid_from_netid(editingBookmark.get_net_id())));
|
||||
}
|
||||
|
||||
if(selectedBookmarkIndices.size() == 1) {
|
||||
editingBookmark = get_bookmark_from_obj_index(*selectedBookmarkIndices.begin());
|
||||
editingBookmarkOldName = editingBookmark->get_name();
|
||||
editingBookmarkOldName = editingBookmark.lock()->get_name();
|
||||
}
|
||||
else {
|
||||
editingBookmark = NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem>();
|
||||
editingBookmark.reset();
|
||||
editingBookmarkOldName = std::nullopt;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class BookmarkManager {
|
|||
|
||||
std::set<GUIStuff::TreeListingObjIndexList> selectedBookmarkIndices;
|
||||
|
||||
NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem> editingBookmark;
|
||||
NetworkingObjects::NetObjWeakPtr<BookmarkListItem> editingBookmark;
|
||||
std::optional<std::string> editingBookmarkOldName;
|
||||
|
||||
void editing_bookmark_check();
|
||||
|
|
|
|||
|
|
@ -391,12 +391,14 @@ void DrawingProgramLayerManagerGUI::setup_list_gui() {
|
|||
});
|
||||
});
|
||||
|
||||
if(editingLayer) {
|
||||
text_label_centered(gui, editingLayer->is_folder() ? "Edit Layer Folder" : "Edit Layer");
|
||||
auto editingLayerLock = editingLayer.lock();
|
||||
if(editingLayerLock) {
|
||||
text_label_centered(gui, editingLayerLock->is_folder() ? "Edit Layer Folder" : "Edit Layer");
|
||||
input_text_field(gui, "input edit name", "Name", &nameToEdit, {
|
||||
.onEdit = [&] {
|
||||
if(editingLayer) { // This can be set to null on the way here (close layer popup when textbox is selected)
|
||||
editingLayer->set_name(world.delayedUpdateObjectManager, nameToEdit);
|
||||
auto editingLayerLock = editingLayer.lock();
|
||||
if(editingLayerLock) { // This can be set to null on the way here (close layer popup when textbox is selected)
|
||||
editingLayerLock->set_name(world.delayedUpdateObjectManager, nameToEdit);
|
||||
world.main.g.gui.set_to_layout();
|
||||
}
|
||||
}
|
||||
|
|
@ -404,9 +406,10 @@ void DrawingProgramLayerManagerGUI::setup_list_gui() {
|
|||
slider_scalar_field(gui, "input alpha slider", "Alpha", &alphaValToEdit, 0.0f, 1.0f, {
|
||||
.decimalPrecision = 2,
|
||||
.onEdit = [&] {
|
||||
if(editingLayer) {
|
||||
editingLayer->set_name(world.delayedUpdateObjectManager, nameToEdit);
|
||||
editingLayer->set_alpha(layerMan, alphaValToEdit);
|
||||
auto editingLayerLock = editingLayer.lock();
|
||||
if(editingLayerLock) {
|
||||
editingLayerLock->set_name(world.delayedUpdateObjectManager, nameToEdit);
|
||||
editingLayerLock->set_alpha(layerMan, alphaValToEdit);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -415,8 +418,9 @@ void DrawingProgramLayerManagerGUI::setup_list_gui() {
|
|||
gui.element<DropDown<size_t>>("input blend mode", &blendModeValToEdit, get_blend_mode_useful_name_list(), DropdownOptions{
|
||||
.width = 190.0f,
|
||||
.onClick = [&] {
|
||||
if(editingLayer)
|
||||
editingLayer->set_blend_mode(layerMan, get_blend_mode_useful_list()[blendModeValToEdit]);
|
||||
auto editingLayerLock = editingLayer.lock();
|
||||
if(editingLayerLock)
|
||||
editingLayerLock->set_blend_mode(layerMan, get_blend_mode_useful_list()[blendModeValToEdit]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -603,19 +607,19 @@ void DrawingProgramLayerManagerGUI::editing_layer_check() {
|
|||
WorldUndoManager::UndoObjectID undoID;
|
||||
};
|
||||
|
||||
|
||||
if(editingLayer) {
|
||||
const DrawingProgramLayerListItemMetaInfo& currentMetaData = editingLayer->get_metainfo();
|
||||
auto editingLayerLock = editingLayer.lock();
|
||||
if(editingLayerLock) {
|
||||
const DrawingProgramLayerListItemMetaInfo& currentMetaData = editingLayerLock->get_metainfo();
|
||||
if(currentMetaData != editingLayerOldMetainfo.value())
|
||||
world.undo.push(std::make_unique<EditLayerWorldUndoAction>(std::make_unique<DrawingProgramLayerListItemMetaInfo>(editingLayerOldMetainfo.value()), world.undo.get_undoid_from_netid(editingLayer.get_net_id())));
|
||||
}
|
||||
|
||||
if(selectedLayerIndices.size() == 1) {
|
||||
editingLayer = get_layer_from_obj_index(*selectedLayerIndices.begin());
|
||||
editingLayerOldMetainfo = editingLayer->get_metainfo();
|
||||
editingLayerOldMetainfo = editingLayer.lock()->get_metainfo();
|
||||
}
|
||||
else {
|
||||
editingLayer = NetworkingObjects::NetObjTemporaryPtr<DrawingProgramLayerListItem>();
|
||||
editingLayer.reset();
|
||||
editingLayerOldMetainfo = std::nullopt;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class DrawingProgramLayerManagerGUI {
|
|||
size_t blendModeValToEdit = 0;
|
||||
|
||||
std::set<GUIStuff::TreeListingObjIndexList> selectedLayerIndices;
|
||||
NetworkingObjects::NetObjTemporaryPtr<DrawingProgramLayerListItem> editingLayer;
|
||||
NetworkingObjects::NetObjWeakPtr<DrawingProgramLayerListItem> editingLayer;
|
||||
|
||||
std::optional<DrawingProgramLayerListItemMetaInfo> editingLayerOldMetainfo;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ template <typename OptT> SelectableButton::Data selectable_button_options_to_dat
|
|||
SelectableButton::Data toRet;
|
||||
toRet.onClick = options.onClick;
|
||||
toRet.isSelected = options.isSelected;
|
||||
toRet.instantResponse = options.instantResponse;
|
||||
toRet.drawType = options.drawType;
|
||||
toRet.onClickButton = options.onClickButton;
|
||||
return toRet;
|
||||
|
|
@ -20,6 +21,7 @@ template <typename OptT> SelectableButton::Data selectable_button_options_to_dat
|
|||
struct TextButtonOptions {
|
||||
SelectableButton::DrawType drawType = SelectableButton::DrawType::FILLED;
|
||||
bool isSelected = false;
|
||||
bool instantResponse = false;
|
||||
bool wide = false;
|
||||
bool centered = true;
|
||||
|
||||
|
|
@ -30,6 +32,7 @@ struct TextButtonOptions {
|
|||
struct SVGButtonOptions {
|
||||
SelectableButton::DrawType drawType = SelectableButton::DrawType::FILLED;
|
||||
bool isSelected = false;
|
||||
bool instantResponse = false;
|
||||
float size = BIG_BUTTON_SIZE;
|
||||
|
||||
std::function<void()> onClick;
|
||||
|
|
@ -39,6 +42,7 @@ struct SVGButtonOptions {
|
|||
struct FixedSizeColorButtonOptions {
|
||||
SelectableButton::DrawType drawType = SelectableButton::DrawType::FILLED;
|
||||
bool isSelected = false;
|
||||
bool instantResponse = false;
|
||||
bool hasAlpha = true;
|
||||
float size = BIG_BUTTON_SIZE;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ namespace GUIStuff { namespace ElementHelpers {
|
|||
|
||||
template <typename T, typename OptT> TextBoxData<T> textbox_options_to_data(const OptT& options) {
|
||||
TextBoxData<T> toRet;
|
||||
toRet.updateEveryEdit = options.updateEveryEdit;
|
||||
toRet.onEnter = options.onEnter;
|
||||
toRet.onEdit = options.onEdit;
|
||||
toRet.immutable = options.immutable;
|
||||
|
|
@ -18,7 +17,6 @@ template <typename T, typename OptT> TextBoxData<T> textbox_options_to_data(cons
|
|||
}
|
||||
|
||||
struct TextBoxOptions {
|
||||
bool updateEveryEdit = true;
|
||||
bool immutable = false;
|
||||
std::function<void()> onEnter;
|
||||
std::function<void()> onEdit;
|
||||
|
|
@ -28,7 +26,6 @@ struct TextBoxOptions {
|
|||
|
||||
struct TextBoxScalarOptions {
|
||||
int decimalPrecision = 0;
|
||||
bool updateEveryEdit = true;
|
||||
bool immutable = false;
|
||||
std::function<void()> onEnter;
|
||||
std::function<void()> onEdit;
|
||||
|
|
@ -38,7 +35,6 @@ struct TextBoxScalarOptions {
|
|||
|
||||
struct TextBoxScalarsOptions {
|
||||
int decimalPrecision = 0;
|
||||
bool updateEveryEdit = true;
|
||||
bool immutable = false;
|
||||
std::function<void(size_t)> onEnter;
|
||||
std::function<void(size_t)> onEdit;
|
||||
|
|
@ -48,7 +44,6 @@ struct TextBoxScalarsOptions {
|
|||
|
||||
struct TextBoxPathOptions {
|
||||
std::filesystem::file_type fileTypeRestriction;
|
||||
bool updateEveryEdit = true;
|
||||
bool immutable = false;
|
||||
std::function<void()> onEnter;
|
||||
std::function<void()> onEdit;
|
||||
|
|
@ -58,7 +53,6 @@ struct TextBoxPathOptions {
|
|||
|
||||
struct TextBoxHexColorOptions {
|
||||
bool hasAlpha = true;
|
||||
bool updateEveryEdit = true;
|
||||
bool immutable = false;
|
||||
std::function<void()> onEnter;
|
||||
std::function<void()> onEdit;
|
||||
|
|
@ -122,7 +116,6 @@ template <typename TContainer, typename T> void input_scalars_field(GUIManager&
|
|||
for(size_t i = 0; i < elemCount; i++) {
|
||||
gui.new_id(i, [&] { input_scalar<T>(gui, "field", &(*val)[i], minVal, maxVal, TextBoxScalarOptions {
|
||||
.decimalPrecision = options.decimalPrecision,
|
||||
.updateEveryEdit = options.updateEveryEdit,
|
||||
.immutable = options.immutable,
|
||||
.onEnter = [f = options.onEnter, i] { if(f) f(i); },
|
||||
.onEdit = [f = options.onEdit, i] { if(f) f(i); },
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ namespace GUIStuff {
|
|||
gui(initGUI) {}
|
||||
|
||||
void Element::update() {}
|
||||
void Element::deselect() {}
|
||||
|
||||
void Element::input_paste_callback(const CustomEvents::PasteEventData& paste) { }
|
||||
void Element::input_text_key_callback(const InputManager::KeyCallbackArgs& key) { }
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ namespace GUIStuff {
|
|||
Element* parent = nullptr;
|
||||
|
||||
virtual void update();
|
||||
virtual void deselect();
|
||||
|
||||
virtual void input_paste_callback(const CustomEvents::PasteEventData& paste);
|
||||
virtual void input_text_key_callback(const InputManager::KeyCallbackArgs& key);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ void SelectableButton::layout(const Clay_ElementId& id, const Data& d) {
|
|||
SkColor4f backgroundColorHighlight;
|
||||
SkColor4f backgroundColor;
|
||||
|
||||
instantResponse = d.instantResponse;
|
||||
onClick = [&, this, d] {
|
||||
if(d.onClickButton)
|
||||
d.onClickButton(this);
|
||||
|
|
@ -70,10 +71,16 @@ void SelectableButton::layout(const Clay_ElementId& id, const Data& d) {
|
|||
void SelectableButton::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) {
|
||||
bool oldIsHeld = isHeld;
|
||||
isHeld = mouseHovering && button.button == InputManager::MouseButton::LEFT && button.down;
|
||||
if(isHeld)
|
||||
if(isHeld) {
|
||||
if(instantResponse) {
|
||||
std::cout << "INSTANT" << std::endl;
|
||||
gui.set_post_callback_func(onClick);
|
||||
}
|
||||
gui.set_to_layout();
|
||||
}
|
||||
else if(mouseHovering && oldIsHeld && button.button == InputManager::MouseButton::LEFT && !button.down) {
|
||||
gui.set_post_callback_func(onClick);
|
||||
if(!instantResponse)
|
||||
gui.set_post_callback_func(onClick);
|
||||
gui.set_to_layout();
|
||||
}
|
||||
else if(mouseHovering != oldIsHovering || isHeld != oldIsHeld)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ class SelectableButton : public Element {
|
|||
struct Data {
|
||||
DrawType drawType = DrawType::TRANSPARENT_ALL;
|
||||
bool isSelected = false;
|
||||
bool instantResponse = false;
|
||||
std::function<void()> onClick;
|
||||
std::function<void(SelectableButton*)> onClickButton;
|
||||
std::function<void(const InnerContentCallbackParameters&)> innerContent;
|
||||
|
|
@ -32,6 +33,7 @@ class SelectableButton : public Element {
|
|||
virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) override;
|
||||
|
||||
private:
|
||||
bool instantResponse = false;
|
||||
bool isHeld = false;
|
||||
bool oldIsHovering = false;
|
||||
std::function<void()> onClick;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ template <typename T> struct TextBoxData {
|
|||
std::function<std::optional<T>(const std::string&)> fromStr;
|
||||
std::function<std::string(const T&)> toStr;
|
||||
bool singleLine = true;
|
||||
bool updateEveryEdit = true;
|
||||
bool immutable = false;
|
||||
InputManager::TextInputProperties textInputProps;
|
||||
std::function<void()> onEdit;
|
||||
|
|
@ -38,7 +37,9 @@ template <typename T> class TextBox : public Element {
|
|||
TextBox(GUIManager& gui);
|
||||
|
||||
void layout(const Clay_ElementId& id, const TextBoxData<T>& userInfo);
|
||||
virtual void update();
|
||||
void select();
|
||||
virtual void update() override;
|
||||
virtual void deselect() override;
|
||||
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
|
||||
virtual void input_paste_callback(const CustomEvents::PasteEventData& paste) override;
|
||||
virtual void input_text_key_callback(const InputManager::KeyCallbackArgs& key) override;
|
||||
|
|
|
|||
|
|
@ -71,6 +71,23 @@ template <typename T> void TextBox<T>::clay_draw(SkCanvas* canvas, UpdateInputDa
|
|||
canvas->restore();
|
||||
}
|
||||
|
||||
template <typename T> void TextBox<T>::select() {
|
||||
if(!is_selected()) {
|
||||
SCollision::AABB<float> rect = {(boundingBox.value().min + gui.io.windowPos) * gui.io.guiScaleMultiplier, (boundingBox.value().max + gui.io.windowPos) * gui.io.guiScaleMultiplier};
|
||||
unsigned id = gui.io.input->set_text_box_front(rect, userInfo.textInputProps);
|
||||
edit = TextEditData(id, textbox, cur);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> void TextBox<T>::deselect() {
|
||||
if(is_selected()) {
|
||||
gui.io.input->remove_text_box(edit.value().textboxInputID);
|
||||
if(userInfo.onDeselect) userInfo.onDeselect();
|
||||
reset_textbox_text();
|
||||
edit = std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> bool TextBox<T>::is_selected() const {
|
||||
return edit.has_value();
|
||||
}
|
||||
|
|
@ -101,7 +118,7 @@ template <typename T> void TextBox<T>::after_text_input_callback() {
|
|||
if(userInfo.immutable)
|
||||
cur->pos = cur->selectionBeginPos = cur->selectionEndPos = textbox->insert({0, 0}, userInfo.toStr(*userInfo.data));
|
||||
else {
|
||||
if(userInfo.updateEveryEdit && update_data() && userInfo.onEdit)
|
||||
if(update_data() && userInfo.onEdit)
|
||||
gui.set_post_callback_func_high_priority(userInfo.onEdit);
|
||||
}
|
||||
}
|
||||
|
|
@ -114,37 +131,22 @@ template <typename T> void TextBox<T>::input_text_callback(const InputManager::T
|
|||
}
|
||||
|
||||
template <typename T> void TextBox<T>::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) {
|
||||
auto& io = gui.io;
|
||||
|
||||
isHeld = false;
|
||||
|
||||
if(button.button == InputManager::MouseButton::LEFT && boundingBox.has_value()) {
|
||||
if(button.down) {
|
||||
if(mouseHovering) {
|
||||
if(!is_selected()) {
|
||||
SCollision::AABB<float> rect = {(boundingBox.value().min + io.windowPos) * io.guiScaleMultiplier, (boundingBox.value().max + io.windowPos) * io.guiScaleMultiplier};
|
||||
unsigned id = gui.io.input->set_text_box_front(rect, userInfo.textInputProps);
|
||||
edit = TextEditData(id, textbox, cur);
|
||||
select();
|
||||
gui.set_post_callback_func_high_priority([&] {
|
||||
if(userInfo.onSelect) userInfo.onSelect();
|
||||
});
|
||||
}
|
||||
isHeld = true;
|
||||
textbox->process_mouse_left_button(*cur, button.pos - boundingBox.value().min, button.clicks, isHeld, gui.io.input->key(InputManager::KEY_GENERIC_LSHIFT).held);
|
||||
}
|
||||
else if(is_selected()) {
|
||||
gui.io.input->remove_text_box(edit.value().textboxInputID);
|
||||
gui.set_post_callback_func_high_priority([&] {
|
||||
if(update_data())
|
||||
if(userInfo.onEdit) userInfo.onEdit();
|
||||
if(userInfo.onDeselect) userInfo.onDeselect();
|
||||
});
|
||||
reset_textbox_text();
|
||||
edit = std::nullopt;
|
||||
textbox->process_mouse_left_button(*cur, button.pos - boundingBox.value().min, button.clicks, true, gui.io.input->key(InputManager::KEY_GENERIC_LSHIFT).held);
|
||||
}
|
||||
else if(is_selected())
|
||||
deselect();
|
||||
}
|
||||
else {
|
||||
textbox->process_mouse_left_button(*cur, button.pos - boundingBox.value().min, 0, isHeld, gui.io.input->key(InputManager::KEY_GENERIC_LSHIFT).held);
|
||||
textbox->process_mouse_left_button(*cur, button.pos - boundingBox.value().min, 0, false, gui.io.input->key(InputManager::KEY_GENERIC_LSHIFT).held);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,6 +482,11 @@ bool GUIManager::cursor_obstructed() const {
|
|||
return cursorObstructed;
|
||||
}
|
||||
|
||||
void GUIManager::deselect_all() {
|
||||
for(ElementContainer* e : orderedElements)
|
||||
e->elem->deselect();
|
||||
}
|
||||
|
||||
void GUIManager::input_paste_callback(const CustomEvents::PasteEventData& paste) {
|
||||
for(ElementContainer* e : orderedElements)
|
||||
e->elem->input_paste_callback(paste);
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ class GUIManager {
|
|||
template <typename ElementType, typename... Args> ElementType* element(const char* id, const Args&... a) {
|
||||
push_id(id);
|
||||
|
||||
Element* oldParent = parentElement;
|
||||
ElementType* elem = insert_element<ElementType>();
|
||||
Element* oldParent = parentElement;
|
||||
elem->parent = parentElement;
|
||||
parentElement = elem;
|
||||
|
||||
|
|
@ -61,9 +61,8 @@ class GUIManager {
|
|||
|
||||
template <typename ElementType, typename... Args> ElementType* clipping_element(const char* id, const Args&... a) {
|
||||
push_id(id);
|
||||
|
||||
Element* oldParent = parentElement;
|
||||
ElementType* elem = insert_element<ElementType>();
|
||||
Element* oldParent = parentElement;
|
||||
elem->parent = parentElement;
|
||||
parentElement = elem;
|
||||
|
||||
|
|
@ -83,11 +82,12 @@ class GUIManager {
|
|||
clippingRegion = oldClippingRegion;
|
||||
|
||||
parentElement = oldParent;
|
||||
|
||||
pop_id();
|
||||
return elem;
|
||||
}
|
||||
|
||||
void deselect_all();
|
||||
|
||||
DefaultStringArena strArena;
|
||||
|
||||
void input_paste_callback(const CustomEvents::PasteEventData& paste);
|
||||
|
|
|
|||
|
|
@ -332,18 +332,18 @@ const InputManager::KeyData& InputManager::key(KeyCode kCode) {
|
|||
return keys[kCode];
|
||||
}
|
||||
|
||||
void InputManager::set_key_down(const SDL_KeyboardEvent& e, KeyCode kCode) {
|
||||
void InputManager::set_key_down(const SDL_KeyboardEvent& e, KeyCode kCode, bool acceptingTextInput) {
|
||||
auto& k = keys[kCode];
|
||||
k.held = true;
|
||||
if(text.is_accepting_input())
|
||||
if(acceptingTextInput)
|
||||
main.input_text_key_callback(KeyCallbackArgs{.key = kCode, .down = e.down, .repeat = e.repeat});
|
||||
else
|
||||
main.input_key_callback(KeyCallbackArgs{.key = kCode, .down = e.down, .repeat = e.repeat});
|
||||
}
|
||||
|
||||
void InputManager::set_key_up(const SDL_KeyboardEvent& e, KeyCode kCode) {
|
||||
void InputManager::set_key_up(const SDL_KeyboardEvent& e, KeyCode kCode, bool acceptingTextInput) {
|
||||
keys[kCode].held = false;
|
||||
if(text.is_accepting_input())
|
||||
if(acceptingTextInput)
|
||||
main.input_text_key_callback(KeyCallbackArgs{.key = kCode, .down = e.down, .repeat = e.repeat});
|
||||
// Send key up even if text input is happening
|
||||
main.input_key_callback(KeyCallbackArgs{.key = kCode, .down = e.down, .repeat = e.repeat});
|
||||
|
|
@ -852,76 +852,78 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) {
|
|||
return;
|
||||
}
|
||||
|
||||
bool acceptingTextInput = text.is_accepting_input();
|
||||
|
||||
switch(kPress) {
|
||||
case SDLK_UP:
|
||||
set_key_down(e, KEY_GENERIC_UP);
|
||||
set_key_down(e, KEY_GENERIC_UP, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
set_key_down(e, KEY_GENERIC_DOWN);
|
||||
set_key_down(e, KEY_GENERIC_DOWN, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_LEFT:
|
||||
set_key_down(e, KEY_GENERIC_LEFT);
|
||||
set_key_down(e, KEY_GENERIC_LEFT, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
set_key_down(e, KEY_GENERIC_RIGHT);
|
||||
set_key_down(e, KEY_GENERIC_RIGHT, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_BACKSPACE:
|
||||
set_key_down(e, KEY_TEXT_BACKSPACE);
|
||||
set_key_down(e, KEY_TEXT_BACKSPACE, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_DELETE:
|
||||
set_key_down(e, KEY_TEXT_DELETE);
|
||||
set_key_down(e, KEY_TEXT_DELETE, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_HOME:
|
||||
set_key_down(e, KEY_TEXT_HOME);
|
||||
set_key_down(e, KEY_TEXT_HOME, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_END:
|
||||
set_key_down(e, KEY_TEXT_END);
|
||||
set_key_down(e, KEY_TEXT_END, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_LSHIFT:
|
||||
set_key_down(e, KEY_GENERIC_LSHIFT);
|
||||
set_key_down(e, KEY_GENERIC_LSHIFT, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_LALT:
|
||||
set_key_down(e, KEY_GENERIC_LALT);
|
||||
set_key_down(e, KEY_GENERIC_LALT, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_LCTRL:
|
||||
set_key_down(e, KEY_GENERIC_LCTRL);
|
||||
set_key_down(e, KEY_GENERIC_LCTRL, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_LMETA:
|
||||
set_key_down(e, KEY_GENERIC_LMETA);
|
||||
set_key_down(e, KEY_GENERIC_LMETA, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_C:
|
||||
// Use either Ctrl or Meta (command for Mac) keys. We do either instead of checking, since checking can get complicated on Emscripten
|
||||
if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL))
|
||||
set_key_down(e, KEY_TEXT_COPY);
|
||||
set_key_down(e, KEY_TEXT_COPY, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_X:
|
||||
if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL))
|
||||
set_key_down(e, KEY_TEXT_CUT);
|
||||
set_key_down(e, KEY_TEXT_CUT, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_V:
|
||||
if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL))
|
||||
set_key_down(e, KEY_TEXT_PASTE);
|
||||
set_key_down(e, KEY_TEXT_PASTE, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_A:
|
||||
if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL))
|
||||
set_key_down(e, KEY_TEXT_SELECTALL);
|
||||
set_key_down(e, KEY_TEXT_SELECTALL, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_Z:
|
||||
if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL))
|
||||
set_key_down(e, KEY_TEXT_UNDO);
|
||||
set_key_down(e, KEY_TEXT_UNDO, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_R:
|
||||
if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL))
|
||||
set_key_down(e, KEY_TEXT_REDO);
|
||||
set_key_down(e, KEY_TEXT_REDO, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_RETURN:
|
||||
set_key_down(e, KEY_GENERIC_ENTER);
|
||||
set_key_down(e, KEY_GENERIC_ENTER, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_TAB:
|
||||
set_key_down(e, KEY_TEXT_TAB);
|
||||
set_key_down(e, KEY_TEXT_TAB, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_ESCAPE:
|
||||
set_key_down(e, KEY_GENERIC_ESCAPE);
|
||||
set_key_down(e, KEY_GENERIC_ESCAPE, acceptingTextInput);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -929,7 +931,7 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) {
|
|||
|
||||
auto f = keyAssignments.find({make_generic_key_mod(kMod), kPress});
|
||||
if(f != keyAssignments.end())
|
||||
set_key_down(e, f->second);
|
||||
set_key_down(e, f->second, acceptingTextInput);
|
||||
}
|
||||
|
||||
void InputManager::call_paste(CustomEvents::PasteEventDataType type, const InputManagerCallPasteInfo& info) {
|
||||
|
|
@ -968,66 +970,68 @@ bool InputManager::ctrl_or_meta_held() {
|
|||
void InputManager::backend_key_up_update(const SDL_KeyboardEvent& e) {
|
||||
auto kPress = e.key;
|
||||
|
||||
bool acceptingTextInput = text.is_accepting_input();
|
||||
|
||||
switch(kPress) {
|
||||
case SDLK_UP:
|
||||
set_key_up(e, KEY_GENERIC_UP);
|
||||
set_key_up(e, KEY_GENERIC_UP, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
set_key_up(e, KEY_GENERIC_DOWN);
|
||||
set_key_up(e, KEY_GENERIC_DOWN, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_LEFT:
|
||||
set_key_up(e, KEY_GENERIC_LEFT);
|
||||
set_key_up(e, KEY_GENERIC_LEFT, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
set_key_up(e, KEY_GENERIC_RIGHT);
|
||||
set_key_up(e, KEY_GENERIC_RIGHT, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_BACKSPACE:
|
||||
set_key_up(e, KEY_TEXT_BACKSPACE);
|
||||
set_key_up(e, KEY_TEXT_BACKSPACE, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_DELETE:
|
||||
set_key_up(e, KEY_TEXT_DELETE);
|
||||
set_key_up(e, KEY_TEXT_DELETE, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_HOME:
|
||||
set_key_up(e, KEY_TEXT_HOME);
|
||||
set_key_up(e, KEY_TEXT_HOME, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_END:
|
||||
set_key_up(e, KEY_TEXT_END);
|
||||
set_key_up(e, KEY_TEXT_END, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_LSHIFT:
|
||||
set_key_up(e, KEY_GENERIC_LSHIFT);
|
||||
set_key_up(e, KEY_GENERIC_LSHIFT, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_LALT:
|
||||
set_key_up(e, KEY_GENERIC_LALT);
|
||||
set_key_up(e, KEY_GENERIC_LALT, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_LCTRL:
|
||||
set_key_up(e, KEY_GENERIC_LCTRL);
|
||||
set_key_up(e, KEY_GENERIC_LCTRL, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_C:
|
||||
set_key_up(e, KEY_TEXT_COPY);
|
||||
set_key_up(e, KEY_TEXT_COPY, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_X:
|
||||
set_key_up(e, KEY_TEXT_CUT);
|
||||
set_key_up(e, KEY_TEXT_CUT, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_V:
|
||||
set_key_up(e, KEY_TEXT_PASTE);
|
||||
set_key_up(e, KEY_TEXT_PASTE, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_A:
|
||||
set_key_up(e, KEY_TEXT_SELECTALL);
|
||||
set_key_up(e, KEY_TEXT_SELECTALL, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_Z:
|
||||
set_key_up(e, KEY_TEXT_UNDO);
|
||||
set_key_up(e, KEY_TEXT_UNDO, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_R:
|
||||
set_key_up(e, KEY_TEXT_REDO);
|
||||
set_key_up(e, KEY_TEXT_REDO, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_RETURN:
|
||||
set_key_up(e, KEY_GENERIC_ENTER);
|
||||
set_key_up(e, KEY_GENERIC_ENTER, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_TAB:
|
||||
set_key_up(e, KEY_TEXT_TAB);
|
||||
set_key_up(e, KEY_TEXT_TAB, acceptingTextInput);
|
||||
break;
|
||||
case SDLK_ESCAPE:
|
||||
set_key_up(e, KEY_GENERIC_ESCAPE);
|
||||
set_key_up(e, KEY_GENERIC_ESCAPE, acceptingTextInput);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -1035,7 +1039,7 @@ void InputManager::backend_key_up_update(const SDL_KeyboardEvent& e) {
|
|||
|
||||
for(auto& p : keyAssignments)
|
||||
if(p.first.y() == kPress) // Dont try matching modifiers when setting key to go up
|
||||
set_key_up(e, p.second);
|
||||
set_key_up(e, p.second, acceptingTextInput);
|
||||
}
|
||||
|
||||
void InputManager::Mouse::set_pos(const Vector2f& newPos) {
|
||||
|
|
|
|||
|
|
@ -252,8 +252,8 @@ struct InputManager {
|
|||
|
||||
bool ctrl_or_meta_held();
|
||||
uint32_t make_generic_key_mod(SDL_Keymod m);
|
||||
void set_key_up(const SDL_KeyboardEvent& e, KeyCode kCode);
|
||||
void set_key_down(const SDL_KeyboardEvent& e, KeyCode kCode);
|
||||
void set_key_up(const SDL_KeyboardEvent& e, KeyCode kCode, bool acceptingTextInput);
|
||||
void set_key_down(const SDL_KeyboardEvent& e, KeyCode kCode, bool acceptingTextInput);
|
||||
std::vector<Vector2f> get_multiple_finger_positions();
|
||||
std::vector<Vector2f> get_multiple_finger_motions();
|
||||
void touch_finger_do_mouse_down();
|
||||
|
|
|
|||
|
|
@ -370,6 +370,11 @@ void MainProgram::input_key_callback(const InputManager::KeyCallbackArgs& key) {
|
|||
toolbar.save_as_func();
|
||||
break;
|
||||
}
|
||||
case InputManager::KEY_OPEN_CHAT: {
|
||||
if(key.down && !key.repeat)
|
||||
toolbar.open_chatbox();
|
||||
break;
|
||||
}
|
||||
}
|
||||
g.input_key_callback(key);
|
||||
if(world)
|
||||
|
|
@ -378,6 +383,13 @@ void MainProgram::input_key_callback(const InputManager::KeyCallbackArgs& key) {
|
|||
}
|
||||
|
||||
void MainProgram::input_text_key_callback(const InputManager::KeyCallbackArgs& key) {
|
||||
switch(key.key) {
|
||||
case InputManager::KEY_GENERIC_ESCAPE: {
|
||||
if(key.down && !key.repeat)
|
||||
toolbar.close_chatbox();
|
||||
break;
|
||||
}
|
||||
}
|
||||
g.input_text_key_callback(key);
|
||||
if(world)
|
||||
world->input_text_key_callback(key);
|
||||
|
|
|
|||
285
src/Toolbar.cpp
285
src/Toolbar.cpp
|
|
@ -16,6 +16,7 @@
|
|||
#include "MainProgram.hpp"
|
||||
#include "InputManager.hpp"
|
||||
#include "ResourceDisplay/ImageResourceDisplay.hpp"
|
||||
#include "RichText/TextStyleModifier.hpp"
|
||||
#include "VersionConstants.hpp"
|
||||
#include "World.hpp"
|
||||
#include <SDL3/SDL_dialog.h>
|
||||
|
|
@ -52,6 +53,7 @@
|
|||
#include "GUIStuff/Elements/DropDown.hpp"
|
||||
#include "GUIStuff/Elements/SVGIcon.hpp"
|
||||
#include "GUIStuff/Elements/MovableTabList.hpp"
|
||||
#include "GUIStuff/Elements/TextParagraph.hpp"
|
||||
|
||||
#define UPDATE_DOWNLOAD_URL "https://infinipaint.com/download.html"
|
||||
#define UPDATE_NOTIFICATION_URL "https://infinipaint.com/updateNotificationVersion.txt"
|
||||
|
|
@ -257,6 +259,31 @@ void Toolbar::update() {
|
|||
}
|
||||
return false;
|
||||
});
|
||||
if(!chatboxOpen) {
|
||||
for(auto& chatMessage : main.world->chatMessages) {
|
||||
bool wasShown = chatMessage.time < ChatMessage::DISPLAY_TIME;
|
||||
chatMessage.time.update_time_since();
|
||||
bool isShown = chatMessage.time < ChatMessage::DISPLAY_TIME;
|
||||
bool isFading = chatMessage.time >= ChatMessage::FADE_START_TIME;
|
||||
if((isFading && isShown) || (wasShown && !isShown))
|
||||
main.g.gui.set_to_layout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Toolbar::open_chatbox() {
|
||||
if(!chatboxOpen) {
|
||||
chatMessageInput.clear();
|
||||
chatboxOpen = true;
|
||||
main.g.gui.set_to_layout();
|
||||
}
|
||||
}
|
||||
|
||||
void Toolbar::close_chatbox() {
|
||||
if(chatboxOpen) {
|
||||
chatboxOpen = false;
|
||||
main.g.gui.set_to_layout();
|
||||
}
|
||||
}
|
||||
|
||||
void Toolbar::layout_run() {
|
||||
|
|
@ -1021,149 +1048,139 @@ void Toolbar::layer_menu(Element* layerMenuButton) {
|
|||
});
|
||||
}
|
||||
|
||||
std::unique_ptr<skia::textlayout::Paragraph> Toolbar::build_paragraph_from_chat_message(const ChatMessage& message, float alpha) {
|
||||
RichText::TextData Toolbar::build_paragraph_from_chat_message(const ChatMessage& message, float alpha) {
|
||||
auto& gui = main.g.gui;
|
||||
auto& io = gui.io;
|
||||
|
||||
skia::textlayout::ParagraphStyle pStyle;
|
||||
pStyle.setTextAlign(skia::textlayout::TextAlign::kLeft);
|
||||
skia::textlayout::TextStyle tStyle;
|
||||
tStyle.setFontSize(io.fontSize);
|
||||
tStyle.setFontFamilies(main.fonts->get_default_font_families());
|
||||
tStyle.setFontStyle(SkFontStyle::Bold());
|
||||
tStyle.setForegroundColor(SkPaint{color_mul_alpha(message.type == ChatMessage::JOIN ? io.theme->warningColor : io.theme->frontColor1, alpha)});
|
||||
pStyle.setTextStyle(tStyle);
|
||||
RichText::TextData toRet;
|
||||
|
||||
skia::textlayout::ParagraphBuilderImpl a(pStyle, io.fonts->collection, SkUnicodes::ICU::Make());
|
||||
if(message.type == ChatMessage::JOIN) {
|
||||
std::string messageName = message.name + " ";
|
||||
a.addText(messageName.c_str(), messageName.length());
|
||||
}
|
||||
else {
|
||||
std::string messageName = "[" + message.name + "] ";
|
||||
a.addText(messageName.c_str(), messageName.length());
|
||||
}
|
||||
auto& par = toRet.paragraphs.emplace_back();
|
||||
|
||||
tStyle.setFontStyle(SkFontStyle::Normal());
|
||||
a.pushStyle(tStyle);
|
||||
a.addText(message.message.c_str(), message.message.length());
|
||||
RichText::PositionedTextStyleMod& positionedModInit = toRet.tStyleMods.emplace_back();
|
||||
positionedModInit.pos = {0, 0};
|
||||
positionedModInit.mods[RichText::TextStyleModifier::ModifierType::WEIGHT] = std::make_shared<RichText::WeightTextStyleModifier>(SkFontStyle::Weight::kBold_Weight);
|
||||
positionedModInit.mods[RichText::TextStyleModifier::ModifierType::COLOR] = std::make_shared<RichText::ColorTextStyleModifier>(convert_vec4<Vector4f>(color_mul_alpha(message.type == ChatMessage::JOIN ? io.theme->warningColor : io.theme->frontColor1, alpha)));
|
||||
if(message.type == ChatMessage::JOIN)
|
||||
par.text += message.name + " ";
|
||||
else
|
||||
par.text += "[" + message.name + "] ";
|
||||
|
||||
return a.Build();
|
||||
RichText::PositionedTextStyleMod& positionedModMessage = toRet.tStyleMods.emplace_back();
|
||||
positionedModMessage.pos = {0, par.text.size()};
|
||||
positionedModMessage.mods[RichText::TextStyleModifier::ModifierType::WEIGHT] = std::make_shared<RichText::WeightTextStyleModifier>(SkFontStyle::Weight::kNormal_Weight);
|
||||
par.text += message.message;
|
||||
|
||||
return toRet;
|
||||
}
|
||||
|
||||
void Toolbar::chat_box() {
|
||||
//constexpr float CHATBOX_WIDTH = 700;
|
||||
//if(main.world->netObjMan.is_connected()) {
|
||||
// Clay_ElementId localId = CLAY_ID_LOCAL("INFINIPAINT CHAT BOX OPEN BUTTON");
|
||||
// CLAY(localId, {
|
||||
// .layout = {
|
||||
// .layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
// },
|
||||
// .floating = {.offset = {static_cast<float>(io.theme->padding1), -static_cast<float>(io.theme->padding1)}, .attachPoints = {.element = CLAY_ATTACH_POINT_LEFT_BOTTOM, .parent = CLAY_ATTACH_POINT_LEFT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT}
|
||||
// }) {
|
||||
// gui.obstructing_window(localId);
|
||||
// gui.push_id("chat box open button");
|
||||
// if(gui.svg_icon_button("Chat Open Button", "data/icons/chat.svg", chatBoxState != CHATBOXSTATE_CLOSE)) {
|
||||
// if(chatBoxState == CHATBOXSTATE_CLOSE)
|
||||
// chatBoxState = CHATBOXSTATE_JUSTOPEN;
|
||||
// else
|
||||
// chatBoxState = CHATBOXSTATE_CLOSE;
|
||||
// }
|
||||
// gui.pop_id();
|
||||
// }
|
||||
//}
|
||||
//Clay_ElementId localId = CLAY_ID_LOCAL("INFINIPAINT CHAT BOX OPEN");
|
||||
//CLAY(localId, {
|
||||
// .layout = {
|
||||
// .sizing = {.width = CLAY_SIZING_FIXED(CHATBOX_WIDTH), .height = CLAY_SIZING_FIT(0) },
|
||||
// .childGap = 0,
|
||||
// .childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_BOTTOM},
|
||||
// .layoutDirection = CLAY_TOP_TO_BOTTOM
|
||||
// },
|
||||
// .floating = {.offset = {60 + static_cast<float>(io.theme->padding1), -static_cast<float>(io.theme->padding1)}, .attachPoints = {.element = CLAY_ATTACH_POINT_LEFT_BOTTOM, .parent = CLAY_ATTACH_POINT_LEFT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT}
|
||||
//}) {
|
||||
// gui.obstructing_window(localId);
|
||||
// gui.push_id("chat box");
|
||||
// if(chatBoxState == CHATBOXSTATE_JUSTOPEN || chatBoxState == CHATBOXSTATE_OPEN) {
|
||||
// gui.push_id("messages");
|
||||
// CLAY_AUTO_ID({
|
||||
// .layout = {
|
||||
// .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) },
|
||||
// .padding = CLAY_PADDING_ALL(0),
|
||||
// .childGap = 0,
|
||||
// .childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_BOTTOM},
|
||||
// .layoutDirection = CLAY_TOP_TO_BOTTOM
|
||||
// },
|
||||
// .backgroundColor = convert_vec4<Clay_Color>(io.theme->backColor1)
|
||||
// }) {
|
||||
// int id = 0;
|
||||
// for(auto& chatMessage : main.world->chatMessages | std::views::reverse) {
|
||||
// gui.push_id(id);
|
||||
// gui.text_paragraph("text", build_paragraph_from_chat_message(chatMessage, 1.0f), CHATBOX_WIDTH);
|
||||
// gui.pop_id();
|
||||
// id++;
|
||||
// }
|
||||
// }
|
||||
// gui.pop_id();
|
||||
auto& gui = main.g.gui;
|
||||
auto& io = gui.io;
|
||||
|
||||
// gui.left_to_right_line_layout([&]() {
|
||||
// gui.input_text("message input", &chatMessageInput);
|
||||
// if(gui.text_button("send button", "Send", false, true)) {
|
||||
// if(!chatMessageInput.empty())
|
||||
// main.world->send_chat_message(chatMessageInput);
|
||||
// }
|
||||
// });
|
||||
// gui.push_id("message input");
|
||||
// GUIStuff::GUIManager::ElementContainer& a = gui.elements[gui.idStack];
|
||||
// GUIStuff::TextBox<std::string>& t = *(GUIStuff::TextBox<std::string>*)a.elem.get();
|
||||
// gui.pop_id();
|
||||
// if(chatBoxState == CHATBOXSTATE_JUSTOPEN) {
|
||||
// t.selection.selected = true;
|
||||
// chatBoxState = CHATBOXSTATE_OPEN;
|
||||
// }
|
||||
// if(io.key.escape)
|
||||
// t.selection.selected = false;
|
||||
// if(io.key.enter) {
|
||||
// main.world->send_chat_message(chatMessageInput);
|
||||
// t.selection.selected = false;
|
||||
// }
|
||||
// if(!t.selection.selected) {
|
||||
// chatMessageInput.clear();
|
||||
// chatBoxState = CHATBOXSTATE_CLOSE;
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// constexpr float DISPLAY_TIME = 8.0f;
|
||||
// constexpr float FADE_START_TIME = 7.0f;
|
||||
// gui.push_id("messages popup");
|
||||
// int id = 0;
|
||||
// for(auto& chatMessage : main.world->chatMessages | std::views::reverse) {
|
||||
// chatMessage.time.update_time_since();
|
||||
// if(chatMessage.time < DISPLAY_TIME) {
|
||||
// float a = 1.0f - lerp_time<float>(chatMessage.time, DISPLAY_TIME, FADE_START_TIME);
|
||||
// Clay_ElementId elemId = CLAY_IDI_LOCAL("CHAT MESSAGE ID", id);
|
||||
// CLAY(elemId, {
|
||||
// .layout = {
|
||||
// .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) },
|
||||
// .padding = CLAY_PADDING_ALL(0),
|
||||
// .childGap = 0,
|
||||
// .childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_TOP},
|
||||
// .layoutDirection = CLAY_TOP_TO_BOTTOM
|
||||
// },
|
||||
// .backgroundColor = convert_vec4<Clay_Color>(color_mul_alpha(io.theme->backColor1, a)),
|
||||
// }) {
|
||||
// gui.push_id(id);
|
||||
// gui.obstructing_window(elemId);
|
||||
// gui.text_paragraph("text", build_paragraph_from_chat_message(chatMessage, a), CHATBOX_WIDTH);
|
||||
// gui.pop_id();
|
||||
// }
|
||||
// }
|
||||
// id++;
|
||||
// }
|
||||
// gui.pop_id();
|
||||
// }
|
||||
// gui.pop_id();
|
||||
//}
|
||||
constexpr float CHATBOX_WIDTH = 700;
|
||||
if(main.world->netObjMan.is_connected()) {
|
||||
gui.element<LayoutElement>("Infinipaint chat box open button", [&](LayoutElement*, const Clay_ElementId& lId) {
|
||||
CLAY(lId, {
|
||||
.layout = {
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
},
|
||||
.floating = {.offset = {static_cast<float>(io.theme->padding1), -static_cast<float>(io.theme->padding1)}, .zIndex = gui.get_z_index(), .attachPoints = {.element = CLAY_ATTACH_POINT_LEFT_BOTTOM, .parent = CLAY_ATTACH_POINT_LEFT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT}
|
||||
}) {
|
||||
svg_icon_button(gui, "Chat open button", "data/icons/chat.svg", {
|
||||
.onClick = [&] {
|
||||
chatboxOpen = !chatboxOpen;
|
||||
chatMessageInput.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
gui.element<LayoutElement>("Infinipaint chat box", [&](LayoutElement*, const Clay_ElementId& lId) {
|
||||
CLAY(lId, {
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIXED(CHATBOX_WIDTH), .height = CLAY_SIZING_FIT(0) },
|
||||
.childGap = 0,
|
||||
.childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_BOTTOM},
|
||||
.layoutDirection = CLAY_TOP_TO_BOTTOM
|
||||
},
|
||||
.floating = {.offset = {60 + static_cast<float>(io.theme->padding1), -static_cast<float>(io.theme->padding1)}, .zIndex = gui.get_z_index(), .attachPoints = {.element = CLAY_ATTACH_POINT_LEFT_BOTTOM, .parent = CLAY_ATTACH_POINT_LEFT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT}
|
||||
}) {
|
||||
if(chatboxOpen) {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) },
|
||||
.padding = CLAY_PADDING_ALL(0),
|
||||
.childGap = 0,
|
||||
.childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_BOTTOM},
|
||||
.layoutDirection = CLAY_TOP_TO_BOTTOM
|
||||
},
|
||||
.backgroundColor = convert_vec4<Clay_Color>(io.theme->backColor1)
|
||||
}) {
|
||||
int id = 0;
|
||||
for(auto& chatMessage : main.world->chatMessages | std::views::reverse) {
|
||||
gui.new_id(id++, [&] {
|
||||
gui.element<TextParagraph>("text", TextParagraph::Data{
|
||||
.text = build_paragraph_from_chat_message(chatMessage, 1.0f),
|
||||
.width = CHATBOX_WIDTH
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
left_to_right_line_layout(gui, [&] {
|
||||
input_text(gui, "message input", &chatMessageInput, {
|
||||
.onEnter = [&] {
|
||||
if(!chatMessageInput.empty())
|
||||
main.world->send_chat_message(chatMessageInput);
|
||||
chatboxOpen = false;
|
||||
},
|
||||
.onDeselect = [&] {
|
||||
chatboxOpen = false;
|
||||
gui.set_to_layout();
|
||||
}
|
||||
})->select();
|
||||
text_button(gui, "send button", "Send", {
|
||||
.instantResponse = true,
|
||||
.onClick = [&] {
|
||||
if(!chatMessageInput.empty())
|
||||
main.world->send_chat_message(chatMessageInput);
|
||||
chatboxOpen = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
gui.new_id("Message popups", [&] {
|
||||
int id = 0;
|
||||
for(auto& chatMessage : main.world->chatMessages | std::views::reverse) {
|
||||
chatMessage.time.update_time_since();
|
||||
if(chatMessage.time < ChatMessage::DISPLAY_TIME) {
|
||||
gui.new_id(id++, [&] {
|
||||
float a = 1.0f - lerp_time<float>(chatMessage.time, ChatMessage::DISPLAY_TIME, ChatMessage::FADE_START_TIME);
|
||||
gui.element<LayoutElement>("Chat message", [&](LayoutElement*, const Clay_ElementId& lId) {
|
||||
CLAY(lId, {
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) },
|
||||
.padding = CLAY_PADDING_ALL(0),
|
||||
.childGap = 0,
|
||||
.childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_TOP},
|
||||
.layoutDirection = CLAY_TOP_TO_BOTTOM
|
||||
},
|
||||
.backgroundColor = convert_vec4<Clay_Color>(color_mul_alpha(io.theme->backColor1, a)),
|
||||
}) {
|
||||
gui.element<TextParagraph>("message", TextParagraph::Data{
|
||||
.text = build_paragraph_from_chat_message(chatMessage, a),
|
||||
.width = CHATBOX_WIDTH
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Toolbar::global_log() {
|
||||
|
|
@ -2136,7 +2153,7 @@ void Toolbar::file_picker_gui() {
|
|||
}
|
||||
});
|
||||
input_path_field(gui, "file picker path", "Path", &filePicker.currentSearchPath, {
|
||||
.updateEveryEdit = false,
|
||||
.fileTypeRestriction = std::filesystem::file_type::directory,
|
||||
.onEdit = [&] {
|
||||
file_picker_gui_refresh_entries();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "GUIStuff/Elements/ScrollArea.hpp"
|
||||
#include "GUIStuff/Elements/TextParagraph.hpp"
|
||||
#include "GUIStuff/GUIManager.hpp"
|
||||
#include "DrawData.hpp"
|
||||
#include "Helpers/FileDownloader.hpp"
|
||||
|
|
@ -26,6 +27,8 @@ class Toolbar {
|
|||
};
|
||||
|
||||
struct ChatMessage {
|
||||
static constexpr float DISPLAY_TIME = 8.0f;
|
||||
static constexpr float FADE_START_TIME = 7.0f;
|
||||
std::string name;
|
||||
std::string message;
|
||||
enum Type {
|
||||
|
|
@ -73,6 +76,9 @@ class Toolbar {
|
|||
void load_palettes();
|
||||
void load_licenses();
|
||||
|
||||
void open_chatbox();
|
||||
void close_chatbox();
|
||||
|
||||
GUIStuff::Element* colorLeftButton;
|
||||
Vector4f* colorLeft = nullptr;
|
||||
ColorSelectorData colorLeftData;
|
||||
|
|
@ -171,11 +177,7 @@ class Toolbar {
|
|||
|
||||
float finalCalculatedGuiScale = 1.0f;
|
||||
|
||||
enum {
|
||||
CHATBOXSTATE_OPEN,
|
||||
CHATBOXSTATE_JUSTOPEN,
|
||||
CHATBOXSTATE_CLOSE
|
||||
} chatBoxState = CHATBOXSTATE_CLOSE;
|
||||
bool chatboxOpen = false;
|
||||
|
||||
enum OptionsMenuType {
|
||||
HOST_MENU,
|
||||
|
|
@ -226,7 +228,7 @@ class Toolbar {
|
|||
};
|
||||
static NativeFilePicker nativeFilePicker;
|
||||
|
||||
std::unique_ptr<skia::textlayout::Paragraph> build_paragraph_from_chat_message(const ChatMessage& message, float alpha);
|
||||
RichText::TextData build_paragraph_from_chat_message(const ChatMessage& message, float alpha);
|
||||
|
||||
void load_icons_at(const std::filesystem::path& pathToLoad);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue