2020-04-05 21:16:16 +02:00
|
|
|
// ftpd is a server implementation based on the following:
|
|
|
|
// - RFC 959 (https://tools.ietf.org/html/rfc959)
|
|
|
|
// - RFC 3659 (https://tools.ietf.org/html/rfc3659)
|
|
|
|
// - suggested implementation details from https://cr.yp.to/ftp/filesystem.html
|
|
|
|
//
|
|
|
|
// Copyright (C) 2020 Michael Theall
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
2020-04-17 22:32:39 +02:00
|
|
|
#ifndef CLASSIC
|
2020-04-05 21:16:16 +02:00
|
|
|
#include "imgui_ctru.h"
|
|
|
|
|
|
|
|
#include "imgui.h"
|
|
|
|
|
2020-04-24 22:51:43 +02:00
|
|
|
#include "../imgui/imgui_internal.h"
|
|
|
|
|
2020-04-05 21:16:16 +02:00
|
|
|
#include "fs.h"
|
2020-04-06 07:36:03 +02:00
|
|
|
#include "platform.h"
|
2020-04-05 21:16:16 +02:00
|
|
|
|
|
|
|
#include <chrono>
|
|
|
|
#include <cstring>
|
|
|
|
#include <functional>
|
|
|
|
#include <string>
|
|
|
|
#include <tuple>
|
|
|
|
using namespace std::chrono_literals;
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
2020-04-06 07:36:03 +02:00
|
|
|
/// \brief Clipboard
|
2020-04-05 21:16:16 +02:00
|
|
|
std::string s_clipboard;
|
|
|
|
|
2020-04-06 07:36:03 +02:00
|
|
|
/// \brief Get clipboard text callback
|
|
|
|
/// \param userData_ User data
|
2020-04-05 21:16:16 +02:00
|
|
|
char const *getClipboardText (void *const userData_)
|
|
|
|
{
|
|
|
|
(void)userData_;
|
|
|
|
return s_clipboard.c_str ();
|
|
|
|
}
|
|
|
|
|
2020-04-06 07:36:03 +02:00
|
|
|
/// \brief Set clipboard text callback
|
|
|
|
/// \param userData_ User data
|
|
|
|
/// \param text_ Clipboard text
|
2020-04-05 21:16:16 +02:00
|
|
|
void setClipboardText (void *const userData_, char const *const text_)
|
|
|
|
{
|
|
|
|
(void)userData_;
|
|
|
|
s_clipboard = text_;
|
|
|
|
}
|
|
|
|
|
2020-04-06 07:36:03 +02:00
|
|
|
/// \brief Update touch position
|
|
|
|
/// \param io_ ImGui IO
|
2020-04-05 21:16:16 +02:00
|
|
|
void updateTouch (ImGuiIO &io_)
|
|
|
|
{
|
2020-04-24 06:09:59 +02:00
|
|
|
// check if touchpad was released
|
|
|
|
if (hidKeysUp () & KEY_TOUCH)
|
|
|
|
{
|
|
|
|
// keep mouse position for one frame for release event
|
|
|
|
io_.MouseDown[0] = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check if touchpad is touched
|
2020-04-06 07:36:03 +02:00
|
|
|
if (!(hidKeysHeld () & KEY_TOUCH))
|
2020-04-05 21:16:16 +02:00
|
|
|
{
|
2020-04-06 07:36:03 +02:00
|
|
|
// set mouse cursor off-screen
|
2020-04-05 21:16:16 +02:00
|
|
|
io_.MousePos = ImVec2 (-10.0f, -10.0f);
|
|
|
|
io_.MouseDown[0] = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-04-06 07:36:03 +02:00
|
|
|
// read touch position
|
2020-04-05 21:16:16 +02:00
|
|
|
touchPosition pos;
|
|
|
|
hidTouchRead (&pos);
|
|
|
|
|
|
|
|
// transform to bottom-screen space
|
2020-04-24 06:09:59 +02:00
|
|
|
io_.MousePos = ImVec2 (pos.px + 40.0f, pos.py + 240.0f);
|
2020-04-05 21:16:16 +02:00
|
|
|
io_.MouseDown[0] = true;
|
|
|
|
}
|
|
|
|
|
2020-04-06 07:36:03 +02:00
|
|
|
/// \brief Update gamepad inputs
|
|
|
|
/// \param io_ ImGui IO
|
2020-04-05 21:16:16 +02:00
|
|
|
void updateGamepads (ImGuiIO &io_)
|
|
|
|
{
|
2020-04-06 07:36:03 +02:00
|
|
|
// clear navigation inputs
|
2020-04-05 21:16:16 +02:00
|
|
|
std::memset (io_.NavInputs, 0, sizeof (io_.NavInputs));
|
|
|
|
|
|
|
|
auto const buttonMapping = {
|
|
|
|
std::make_pair (KEY_A, ImGuiNavInput_Activate),
|
|
|
|
std::make_pair (KEY_B, ImGuiNavInput_Cancel),
|
|
|
|
std::make_pair (KEY_X, ImGuiNavInput_Input),
|
|
|
|
std::make_pair (KEY_Y, ImGuiNavInput_Menu),
|
|
|
|
std::make_pair (KEY_L, ImGuiNavInput_FocusPrev),
|
|
|
|
std::make_pair (KEY_L, ImGuiNavInput_TweakSlow),
|
2020-04-08 23:35:43 +02:00
|
|
|
std::make_pair (KEY_ZL, ImGuiNavInput_FocusPrev),
|
|
|
|
std::make_pair (KEY_ZL, ImGuiNavInput_TweakSlow),
|
2020-04-05 21:16:16 +02:00
|
|
|
std::make_pair (KEY_R, ImGuiNavInput_FocusNext),
|
|
|
|
std::make_pair (KEY_R, ImGuiNavInput_TweakFast),
|
2020-04-08 23:35:43 +02:00
|
|
|
std::make_pair (KEY_ZR, ImGuiNavInput_FocusNext),
|
|
|
|
std::make_pair (KEY_ZR, ImGuiNavInput_TweakFast),
|
2020-04-05 21:16:16 +02:00
|
|
|
std::make_pair (KEY_DUP, ImGuiNavInput_DpadUp),
|
|
|
|
std::make_pair (KEY_DRIGHT, ImGuiNavInput_DpadRight),
|
|
|
|
std::make_pair (KEY_DDOWN, ImGuiNavInput_DpadDown),
|
|
|
|
std::make_pair (KEY_DLEFT, ImGuiNavInput_DpadLeft),
|
|
|
|
};
|
|
|
|
|
2020-04-06 07:36:03 +02:00
|
|
|
// read buttons from 3DS
|
2020-04-05 21:16:16 +02:00
|
|
|
auto const keys = hidKeysHeld ();
|
|
|
|
for (auto const &[in, out] : buttonMapping)
|
|
|
|
{
|
|
|
|
if (keys & in)
|
|
|
|
io_.NavInputs[out] = 1.0f;
|
|
|
|
}
|
|
|
|
|
2020-04-06 07:36:03 +02:00
|
|
|
// update joystick
|
2020-04-05 21:16:16 +02:00
|
|
|
circlePosition cpad;
|
|
|
|
auto const analogMapping = {
|
|
|
|
std::make_tuple (std::ref (cpad.dx), ImGuiNavInput_LStickLeft, -0.3f, -0.9f),
|
|
|
|
std::make_tuple (std::ref (cpad.dx), ImGuiNavInput_LStickRight, +0.3f, +0.9f),
|
|
|
|
std::make_tuple (std::ref (cpad.dy), ImGuiNavInput_LStickUp, +0.3f, +0.9f),
|
|
|
|
std::make_tuple (std::ref (cpad.dy), ImGuiNavInput_LStickDown, -0.3f, -0.9f),
|
|
|
|
};
|
|
|
|
|
2020-04-06 07:36:03 +02:00
|
|
|
// read left joystick from circle pad
|
2020-04-05 21:16:16 +02:00
|
|
|
hidCircleRead (&cpad);
|
|
|
|
for (auto const &[in, out, min, max] : analogMapping)
|
|
|
|
{
|
|
|
|
auto const value = in / static_cast<float> (0x9C);
|
2020-04-06 07:36:03 +02:00
|
|
|
io_.NavInputs[out] = std::clamp ((value - min) / (max - min), 0.0f, 1.0f);
|
2020-04-05 21:16:16 +02:00
|
|
|
}
|
|
|
|
}
|
2020-04-24 22:51:43 +02:00
|
|
|
|
|
|
|
/// \brief Update keyboard inputs
|
|
|
|
/// \param io_ ImGui IO
|
|
|
|
void updateKeyboard (ImGuiIO &io_)
|
|
|
|
{
|
|
|
|
static enum {
|
|
|
|
INACTIVE,
|
|
|
|
KEYBOARD,
|
|
|
|
CLEARED,
|
|
|
|
} state = INACTIVE;
|
|
|
|
|
|
|
|
switch (state)
|
|
|
|
{
|
|
|
|
case INACTIVE:
|
|
|
|
{
|
|
|
|
if (!io_.WantTextInput)
|
|
|
|
return;
|
|
|
|
|
|
|
|
auto &textState = ImGui::GetCurrentContext ()->InputTextState;
|
|
|
|
|
|
|
|
SwkbdState kbd;
|
|
|
|
|
|
|
|
swkbdInit (&kbd, SWKBD_TYPE_NORMAL, 2, -1);
|
|
|
|
swkbdSetButton (&kbd, SWKBD_BUTTON_LEFT, "Cancel", false);
|
|
|
|
swkbdSetButton (&kbd, SWKBD_BUTTON_RIGHT, "OK", true);
|
|
|
|
swkbdSetInitialText (
|
|
|
|
&kbd, std::string (textState.InitialTextA.Data, textState.InitialTextA.Size).c_str ());
|
|
|
|
|
|
|
|
if (textState.UserFlags & ImGuiInputTextFlags_Password)
|
|
|
|
swkbdSetPasswordMode (&kbd, SWKBD_PASSWORD_HIDE_DELAY);
|
|
|
|
|
|
|
|
char buffer[32] = {0};
|
|
|
|
auto const button = swkbdInputText (&kbd, buffer, sizeof (buffer));
|
|
|
|
if (button == SWKBD_BUTTON_RIGHT)
|
|
|
|
io_.AddInputCharactersUTF8 (buffer);
|
|
|
|
|
|
|
|
state = KEYBOARD;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case KEYBOARD:
|
|
|
|
// need to skip a frame for active id to really be cleared
|
|
|
|
ImGui::ClearActiveID ();
|
|
|
|
state = CLEARED;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CLEARED:
|
|
|
|
state = INACTIVE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-04-05 21:16:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool imgui::ctru::init ()
|
|
|
|
{
|
2020-04-07 05:38:14 +02:00
|
|
|
auto &io = ImGui::GetIO ();
|
2020-04-05 21:16:16 +02:00
|
|
|
|
2020-04-06 07:36:03 +02:00
|
|
|
// setup config flags
|
2020-04-05 21:16:16 +02:00
|
|
|
io.ConfigFlags |= ImGuiConfigFlags_IsTouchScreen;
|
|
|
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
|
|
|
|
|
2020-04-06 07:36:03 +02:00
|
|
|
// setup platform backend
|
2020-04-05 21:16:16 +02:00
|
|
|
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
2020-04-06 07:36:03 +02:00
|
|
|
io.BackendPlatformName = "3DS";
|
2020-04-05 21:16:16 +02:00
|
|
|
|
2020-04-06 07:36:03 +02:00
|
|
|
// disable mouse cursor
|
2020-04-05 21:16:16 +02:00
|
|
|
io.MouseDrawCursor = false;
|
|
|
|
|
2020-04-06 07:36:03 +02:00
|
|
|
// clipboard callbacks
|
2020-04-05 21:16:16 +02:00
|
|
|
io.SetClipboardTextFn = setClipboardText;
|
|
|
|
io.GetClipboardTextFn = getClipboardText;
|
|
|
|
io.ClipboardUserData = nullptr;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void imgui::ctru::newFrame ()
|
|
|
|
{
|
2020-04-07 05:38:14 +02:00
|
|
|
auto &io = ImGui::GetIO ();
|
2020-04-05 21:16:16 +02:00
|
|
|
|
2020-04-06 07:36:03 +02:00
|
|
|
// check that font was built
|
2020-04-05 21:16:16 +02:00
|
|
|
IM_ASSERT (io.Fonts->IsBuilt () &&
|
|
|
|
"Font atlas not built! It is generally built by the renderer back-end. Missing call "
|
|
|
|
"to renderer _NewFrame() function?");
|
|
|
|
|
2020-04-06 07:36:03 +02:00
|
|
|
// time step
|
|
|
|
static auto const start = platform::steady_clock::now ();
|
2020-04-05 21:16:16 +02:00
|
|
|
static auto prev = start;
|
2020-04-06 07:36:03 +02:00
|
|
|
auto const now = platform::steady_clock::now ();
|
2020-04-05 21:16:16 +02:00
|
|
|
|
2020-04-06 07:36:03 +02:00
|
|
|
io.DeltaTime = std::chrono::duration<float> (now - prev).count ();
|
2020-04-05 21:16:16 +02:00
|
|
|
prev = now;
|
|
|
|
|
|
|
|
updateTouch (io);
|
|
|
|
updateGamepads (io);
|
2020-04-24 22:51:43 +02:00
|
|
|
updateKeyboard (io);
|
2020-04-05 21:16:16 +02:00
|
|
|
}
|
2020-04-17 22:32:39 +02:00
|
|
|
#endif
|