# Stage 1.7
- Added File to Memory and FastHashMomory - Add Protection that only one app can exist - Add a Trace exist Variable as GetTraceRef automatically creates a trace - Outsource the LI::Rect to its own header - Add a CurrentScreen func - Use Rect for uv (to manually set all corners) - Rect still supports to use vec4 for uv - Add tex3ds Spritesheet support - Add T3X Loader to Texture (if single tex) - Integrate an autounload into Texture as in case of spritesheet the Tex needs to be unloaded manually - Safe some performance in texture loading by combining the Loops (best thing ive ever found) - Use the Momory Hash to only render one error icon into the TTF Texture - Also Try loading the whole 16-Bit range - Use GPU_A8 format for TTF rendering to save 24Bits per pixel and use the same Rendermode as System Font - Simplify Quad Command by using modern vec api - Integrate Text aligning - Fix FPS displayed twice in Performance overlay - UI7 DrawList now has its own AST system - TODO: do the same layering for the objects as Text uses - Map Drawcommands with a bool that declares either bottom or top screen was active - Add first basic Manu functions - Fix Typos in Theme - Add a basic UI7 Context Handler ## Extra - Added JetBrainsMono font in Test app ## Bugs: - Performance Overlay Freezes 3ds hardware and crashes Citra with Vulkan when System Font is used - UI7 Menu scrolling is as scruffed as back in RenderD7 0.9.5
This commit is contained in:
parent
d55f485b8d
commit
2914f2c8e5
@ -32,6 +32,7 @@ set(SRC_FILES
|
||||
source/common/sys.cpp
|
||||
source/common/lang.cpp
|
||||
source/common/error.cpp
|
||||
source/common/io.cpp
|
||||
# Controls
|
||||
source/controls/hid.cpp
|
||||
# Maths
|
||||
@ -40,6 +41,7 @@ set(SRC_FILES
|
||||
source/maths/img_convert.cpp
|
||||
# Graphics
|
||||
source/graphics/texture.cpp
|
||||
source/graphics/spritesheet.cpp
|
||||
source/graphics/li7_shader.cpp
|
||||
source/graphics/lithium.cpp
|
||||
# Overlays
|
||||
@ -51,6 +53,7 @@ set(SRC_FILES
|
||||
source/tools/gamepad_icons.cpp
|
||||
# UI7
|
||||
source/ui7/drawlist.cpp
|
||||
source/ui7/menu.cpp
|
||||
source/ui7/theme.cpp
|
||||
source/ui7/ui7.cpp
|
||||
# External
|
||||
|
@ -32,6 +32,7 @@ SOFTWARE.
|
||||
#include <pd/common/timetrace.hpp>
|
||||
// Graphics
|
||||
#include <pd/graphics/lithium.hpp>
|
||||
#include <pd/graphics/spritesheet.hpp>
|
||||
#include <pd/graphics/texture.hpp>
|
||||
// Maths
|
||||
#include <pd/maths/bit_util.hpp>
|
||||
@ -46,4 +47,11 @@ SOFTWARE.
|
||||
// UI7
|
||||
#include <pd/ui7/ui7.hpp>
|
||||
|
||||
/// Setup these as non Namespaced access by default
|
||||
#ifndef PD_MATH_NAMESPACED
|
||||
using vec2 = PD::vec2;
|
||||
using vec3 = PD::vec3;
|
||||
using vec4 = PD::vec4;
|
||||
#endif
|
||||
|
||||
// namespace Palladium = PD;
|
@ -32,9 +32,14 @@ SOFTWARE.
|
||||
|
||||
namespace PD {
|
||||
/// @brief Template Class for User Application
|
||||
class App : public SmartCtor<App> {
|
||||
class App {
|
||||
public:
|
||||
App() = default;
|
||||
App() {
|
||||
if (too) {
|
||||
Error("Only one App can be created at the same time!");
|
||||
}
|
||||
too++;
|
||||
}
|
||||
~App() = default;
|
||||
|
||||
/// @brief Templete function where the user can Init his stuff
|
||||
@ -50,8 +55,8 @@ class App : public SmartCtor<App> {
|
||||
|
||||
/// @brief Function to run the App
|
||||
/// (int main() {
|
||||
/// auto app = PD::New<UserApp>();
|
||||
/// app->Run();
|
||||
/// UserApp app;
|
||||
/// app.Run();
|
||||
/// return 0;
|
||||
/// })
|
||||
void Run();
|
||||
@ -71,5 +76,8 @@ class App : public SmartCtor<App> {
|
||||
u64 last_time;
|
||||
float app_time;
|
||||
float fps;
|
||||
|
||||
/// The Only One
|
||||
static int too;
|
||||
};
|
||||
} // namespace PD
|
10
include/pd/common/io.hpp
Normal file
10
include/pd/common/io.hpp
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <pd/common/common.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace IO {
|
||||
std::vector<u8> LoadFile2Mem(const std::string& path);
|
||||
u32 HashMemory(const std::vector<u8>& data);
|
||||
} // namespace IO
|
||||
} // namespace PD
|
@ -32,6 +32,7 @@ using TraceMap = std::map<std::string, TT::Res::Ref>;
|
||||
u64 GetTime();
|
||||
u64 GetNanoTime();
|
||||
TT::Res::Ref& GetTraceRef(const std::string& id);
|
||||
bool TraceExist(const std::string& id);
|
||||
TraceMap& GetTraceMap();
|
||||
} // namespace Sys
|
||||
} // namespace PD
|
||||
|
@ -26,6 +26,7 @@ SOFTWARE.
|
||||
|
||||
#include <pd/common/common.hpp>
|
||||
#include <pd/common/memory.hpp>
|
||||
#include <pd/graphics/rect.hpp>
|
||||
#include <pd/graphics/screen.hpp>
|
||||
#include <pd/graphics/texture.hpp>
|
||||
#include <pd/maths/vec.hpp>
|
||||
@ -46,32 +47,6 @@ enum LITextFlags_ {
|
||||
|
||||
namespace PD {
|
||||
namespace LI {
|
||||
/// @brief Container that holds top and bottom corners of a quad
|
||||
class Rect {
|
||||
public:
|
||||
Rect() = default;
|
||||
Rect(const vec4& t, const vec4& b) {
|
||||
top = t;
|
||||
bot = b;
|
||||
}
|
||||
Rect(const vec2& tl, const vec2& tr, const vec2& bl, const vec2& br) {
|
||||
top = vec4(tl, tr);
|
||||
bot = vec4(bl, br);
|
||||
}
|
||||
~Rect() = default;
|
||||
|
||||
vec4 Top() const { return top; }
|
||||
vec4 Bot() const { return bot; }
|
||||
|
||||
vec2 TopLeft() const { return vec2(top[0], top[1]); }
|
||||
vec2 TopRight() const { return vec2(top[2], top[3]); }
|
||||
vec2 BotLeft() const { return vec2(bot[0], bot[1]); }
|
||||
vec2 BotRight() const { return vec2(bot[2], bot[3]); }
|
||||
|
||||
private:
|
||||
vec4 top;
|
||||
vec4 bot;
|
||||
};
|
||||
class Font : public SmartCtor<Font> {
|
||||
public:
|
||||
class Codepoint {
|
||||
@ -172,7 +147,7 @@ class Vertex {
|
||||
/// @brief Required to Set the TexENV
|
||||
enum RenderMode {
|
||||
RenderMode_RGBA,
|
||||
RenderMode_SysFont,
|
||||
RenderMode_Font,
|
||||
};
|
||||
/// @brief Reform the Drawcommand by generating the Vertexbuffer into it
|
||||
class Command : public SmartCtor<Command> {
|
||||
@ -362,6 +337,7 @@ class Renderer : public SmartCtor<Renderer> {
|
||||
|
||||
void SetColor(u32 col);
|
||||
void SetPos(const vec2& pos);
|
||||
void SetLayer(int l);
|
||||
|
||||
void SetUnused() { used = false; }
|
||||
bool Used() const { return used; }
|
||||
@ -397,6 +373,10 @@ class Renderer : public SmartCtor<Renderer> {
|
||||
area_size = bottom ? bot->GetSize() : top->GetSize();
|
||||
}
|
||||
|
||||
Screen::Screen_ CurrentScreen() const {
|
||||
return bottom ? Screen::Bottom : Screen::Top;
|
||||
}
|
||||
|
||||
void Rotation(float v) { rot = v; }
|
||||
float Rotation() const { return rot; }
|
||||
void TextScale(float v) { text_size = v; }
|
||||
@ -404,6 +384,7 @@ class Renderer : public SmartCtor<Renderer> {
|
||||
float TextScale() const { return text_size; }
|
||||
void Layer(int v) { current_layer = v; }
|
||||
int Layer() const { return current_layer; }
|
||||
RenderFlags& GetFlags() { return flags; }
|
||||
void Font(Font::Ref v) {
|
||||
font = v;
|
||||
font_update = true;
|
||||
@ -424,7 +405,7 @@ class Renderer : public SmartCtor<Renderer> {
|
||||
/// @param color Color
|
||||
/// @param uv UV Map
|
||||
void DrawRect(const vec2& pos, const vec2& size, u32 color,
|
||||
const vec4& uv = vec4(0.f, 1.f, 1.f, 0.f));
|
||||
const Rect& uv = vec4(0.f, 1.f, 1.f, 0.f));
|
||||
/// @brief Draw a Solid Rect (uses white tex)
|
||||
/// @note acts as a simplified Draw rect Wrapper
|
||||
/// @param pos Position
|
||||
@ -488,7 +469,7 @@ class Renderer : public SmartCtor<Renderer> {
|
||||
/// @brief Automatically sets up a command
|
||||
void SetupCommand(Command::Ref cmd);
|
||||
/// @brief Creates a default Quad Render Command
|
||||
void QuadCommand(Command::Ref cmd, const Rect& quad, const vec4& uv, u32 col);
|
||||
void QuadCommand(Command::Ref cmd, const Rect& quad, const Rect& uv, u32 col);
|
||||
/// @brief Create a Default Triangle
|
||||
void TriangleCommand(Command::Ref cmd, const vec2& a, const vec2& b,
|
||||
const vec2& c, u32 col);
|
||||
|
82
include/pd/graphics/rect.hpp
Normal file
82
include/pd/graphics/rect.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include <pd/common/common.hpp>
|
||||
#include <pd/maths/vec.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace LI {
|
||||
/// @brief Container that holds top and bottom corners of a quad
|
||||
class Rect {
|
||||
public:
|
||||
Rect() = default;
|
||||
Rect(const vec4& t, const vec4& b) {
|
||||
top = t;
|
||||
bot = b;
|
||||
}
|
||||
Rect(const vec2& tl, const vec2& tr, const vec2& bl, const vec2& br) {
|
||||
top = vec4(tl, tr);
|
||||
bot = vec4(bl, br);
|
||||
}
|
||||
/// This Constructor Fixes the issue of rewriting some Stuff in the Text
|
||||
/// Renderer
|
||||
Rect(const vec4& uv) {
|
||||
top = vec4(uv.x(), uv.y(), uv.z(), uv.y());
|
||||
bot = vec4(uv.x(), uv.w(), uv.z(), uv.w());
|
||||
}
|
||||
~Rect() = default;
|
||||
|
||||
vec4 Top() const { return top; }
|
||||
vec4 Bot() const { return bot; }
|
||||
|
||||
Rect& Top(const vec4& v) {
|
||||
top = v;
|
||||
return *this;
|
||||
}
|
||||
Rect& Bot(const vec4& v) {
|
||||
bot = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
vec2 TopLeft() const { return vec2(top[0], top[1]); }
|
||||
vec2 TopRight() const { return vec2(top[2], top[3]); }
|
||||
vec2 BotLeft() const { return vec2(bot[0], bot[1]); }
|
||||
vec2 BotRight() const { return vec2(bot[2], bot[3]); }
|
||||
|
||||
Rect& TopLeft(const vec2& v) {
|
||||
top[0] = v[0];
|
||||
top[1] = v[1];
|
||||
return *this;
|
||||
}
|
||||
Rect& TopRight(const vec2& v) {
|
||||
top[2] = v[0];
|
||||
top[3] = v[1];
|
||||
return *this;
|
||||
}
|
||||
Rect& BotLeft(const vec2& v) {
|
||||
bot[0] = v[0];
|
||||
bot[1] = v[1];
|
||||
return *this;
|
||||
}
|
||||
Rect& BotRight(const vec2& v) {
|
||||
bot[2] = v[0];
|
||||
bot[3] = v[1];
|
||||
return *this;
|
||||
}
|
||||
|
||||
void SwapVec2XY() {
|
||||
for (int i = 0; i < 4; i += 2) {
|
||||
float t = top[i];
|
||||
top[i] = top[i + 1];
|
||||
top[i + 1] = t;
|
||||
t = bot[i];
|
||||
bot[i] = bot[i + 1];
|
||||
bot[i + 1] = t;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
vec4 top;
|
||||
vec4 bot;
|
||||
};
|
||||
} // namespace LI
|
||||
} // namespace PD
|
26
include/pd/graphics/spritesheet.hpp
Normal file
26
include/pd/graphics/spritesheet.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <citro3d.h>
|
||||
#include <tex3ds.h>
|
||||
|
||||
#include <pd/common/common.hpp>
|
||||
#include <pd/graphics/lithium.hpp>
|
||||
#include <pd/graphics/texture.hpp>
|
||||
|
||||
namespace PD {
|
||||
class SpriteSheet {
|
||||
public:
|
||||
SpriteSheet() {}
|
||||
SpriteSheet(const std::string& path) { this->LoadFile(path); }
|
||||
~SpriteSheet();
|
||||
|
||||
void LoadFile(const std::string& path);
|
||||
Texture::Ref Get(int idx);
|
||||
int NumTextures() const;
|
||||
|
||||
Texture::Ref operator[](int idx) { return Get(idx); }
|
||||
|
||||
private:
|
||||
std::vector<Texture::Ref> textures;
|
||||
};
|
||||
} // namespace PD
|
@ -27,6 +27,7 @@ SOFTWARE.
|
||||
#include <citro3d.h>
|
||||
|
||||
#include <pd/common/common.hpp>
|
||||
#include <pd/graphics/rect.hpp>
|
||||
#include <pd/maths/vec.hpp>
|
||||
|
||||
namespace PD {
|
||||
@ -46,8 +47,12 @@ class Texture : public SmartCtor<Texture> {
|
||||
Texture() : uv(0.f, 1.f, 1.f, 0.f) {}
|
||||
/// @brief Load file Constructor
|
||||
/// @param path path to file
|
||||
Texture(const std::string& path) : uv(0.f, 1.f, 1.f, 0.f) {
|
||||
this->LoadFile(path);
|
||||
Texture(const std::string& path, bool t3x = false) : uv(0.f, 1.f, 1.f, 0.f) {
|
||||
if (t3x) {
|
||||
this->LoadT3X(path);
|
||||
} else {
|
||||
this->LoadFile(path);
|
||||
}
|
||||
}
|
||||
/// @brief Load Memory constructor
|
||||
/// @param data File Data reference
|
||||
@ -66,7 +71,11 @@ class Texture : public SmartCtor<Texture> {
|
||||
this->LoadPixels(data, w, h, type, filter);
|
||||
}
|
||||
/// @brief Deconstructor (aka auto delete)
|
||||
~Texture() { Delete(); }
|
||||
~Texture() {
|
||||
if (autounload) {
|
||||
Delete();
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Deletes image (if not already unloaded)
|
||||
void Delete();
|
||||
@ -86,11 +95,17 @@ class Texture : public SmartCtor<Texture> {
|
||||
void LoadPixels(const std::vector<u8>& data, int w, int h, Type type = RGBA32,
|
||||
Filter filter = NEAREST);
|
||||
|
||||
/// @brief Load a texture of a T3X File
|
||||
/// @note This is used for single texture T3X
|
||||
/// Not for SpriteSheets
|
||||
/// @param path path to .t3x file
|
||||
void LoadT3X(const std::string& path);
|
||||
|
||||
/// @brief Input a Texture that you had set up on your own
|
||||
/// @param tex Texture reference (deletes itself)
|
||||
/// @param rszs The size of the source image
|
||||
/// @param uvs Your uv Setup
|
||||
void LoadExternal(C3D_Tex* tex, vec2 rszs, vec4 uvs) {
|
||||
void LoadExternal(C3D_Tex* tex, vec2 rszs, LI::Rect uvs) {
|
||||
this->Delete();
|
||||
this->tex = tex;
|
||||
this->size = rszs;
|
||||
@ -105,19 +120,23 @@ class Texture : public SmartCtor<Texture> {
|
||||
}
|
||||
vec2 GetSize() const { return size; }
|
||||
C3D_Tex* GetTex() const { return tex; };
|
||||
vec4 GetUV() const { return uv; }
|
||||
LI::Rect GetUV() const { return uv; }
|
||||
bool IsValid() const { return tex != 0; }
|
||||
|
||||
bool AutoUnLoad() const { return autounload; }
|
||||
void AutoUnLoad(bool v) { autounload = v; }
|
||||
|
||||
operator C3D_Tex*() const { return tex; }
|
||||
operator vec2() const { return size; }
|
||||
operator vec4() const { return uv; }
|
||||
operator LI::Rect() const { return uv; }
|
||||
operator bool() const { return tex != 0; }
|
||||
|
||||
private:
|
||||
void MakeTex(std::vector<u8>& buf, int w, int h, Type type = RGBA32,
|
||||
Filter filter = NEAREST);
|
||||
vec2 size;
|
||||
vec4 uv;
|
||||
LI::Rect uv;
|
||||
C3D_Tex* tex = nullptr;
|
||||
bool autounload = true;
|
||||
};
|
||||
} // namespace PD
|
@ -21,16 +21,16 @@ class MessageMgr : public PD::SmartCtor<MessageMgr> {
|
||||
bool ShouldBeRemoved() const { return (tbr && pos.IsFinished()) || kill; }
|
||||
|
||||
private:
|
||||
PD::Color col_bg; // Background Color
|
||||
PD::Color col_text; // Text Color
|
||||
float lifetime = 0.f; // LifeTime
|
||||
PD::Tween<vec2> pos; // Position effect
|
||||
std::string title; // Title
|
||||
std::string msg; // Message
|
||||
vec2 size; // Size of the Background
|
||||
bool tbr = false; // To be Removed ?
|
||||
bool kill = false; // Instant Kill
|
||||
int s = 0; // Slot
|
||||
PD::Color col_bg; // Background Color
|
||||
PD::Color col_text; // Text Color
|
||||
float lifetime = 0.f; // LifeTime
|
||||
PD::Tween<vec2> pos; // Position effect
|
||||
std::string title; // Title
|
||||
std::string msg; // Message
|
||||
vec2 size; // Size of the Background
|
||||
bool tbr = false; // To be Removed ?
|
||||
bool kill = false; // Instant Kill
|
||||
int s = 0; // Slot
|
||||
};
|
||||
MessageMgr(PD::LI::Renderer::Ref r) { ren = r; }
|
||||
~MessageMgr() {}
|
||||
|
@ -38,7 +38,7 @@ class DrawList : public SmartCtor<DrawList> {
|
||||
void AddTriangle(vec2 pos0, vec2 pos1, vec2 pos2, const UI7Color& clr);
|
||||
void AddText(vec2 pos, const std::string& text, const UI7Color& clr,
|
||||
LITextFlags flags = 0, vec2 box = vec2());
|
||||
void AddImage(vec2 pos, Texture::Ref img);
|
||||
void AddImage(vec2 pos, Texture::Ref img, vec2 size = 0.f);
|
||||
|
||||
void Clear();
|
||||
void Process();
|
||||
@ -47,9 +47,22 @@ class DrawList : public SmartCtor<DrawList> {
|
||||
void Layer(int v) { layer = v; }
|
||||
|
||||
private:
|
||||
/// @brief Base Layer offset (Internal Used)
|
||||
int BaseLayer() const { return base; }
|
||||
/// @brief Base Layer offset (Internal Used)
|
||||
void BaseLayer(int v) { base = v; }
|
||||
|
||||
/// @brief Exopose Renderer here for Menus [DONT KNOW IF THIUS GETS REMOVED]
|
||||
LI::Renderer::Ref GetRenderer() { return ren; }
|
||||
|
||||
friend class Menu;
|
||||
friend class Context;
|
||||
|
||||
int layer;
|
||||
int base;
|
||||
LI::Renderer::Ref ren;
|
||||
std::vector<LI::Command::Ref> commands;
|
||||
std::unordered_map<u32, LI::Renderer::StaticText::Ref> static_text;
|
||||
std::vector<std::pair<bool, LI::Command::Ref>> commands;
|
||||
};
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -7,13 +7,23 @@ namespace PD {
|
||||
namespace UI7 {
|
||||
class ID {
|
||||
public:
|
||||
ID(const std::string& text) { id = PD::Strings::FastHash(text); }
|
||||
ID(const std::string& text) {
|
||||
id = PD::Strings::FastHash(text);
|
||||
name = text;
|
||||
}
|
||||
ID(const char* text) {
|
||||
id = PD::Strings::FastHash(text);
|
||||
name = text;
|
||||
}
|
||||
~ID() {}
|
||||
|
||||
std::string GetName() const { return name; }
|
||||
|
||||
operator u32() const { return id; }
|
||||
|
||||
private:
|
||||
u32 id;
|
||||
std::string name;
|
||||
};
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -23,14 +23,20 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/controls/hid.hpp>
|
||||
#include <pd/ui7/drawlist.hpp>
|
||||
#include <pd/ui7/flags.hpp>
|
||||
#include <pd/ui7/id.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
class Menu : public SmartCtor<Menu> {
|
||||
public:
|
||||
Menu(u32 id) {
|
||||
Menu(ID id, Theme* tl, Hid::Ref h) {
|
||||
linked_theme = tl;
|
||||
this->inp = h;
|
||||
this->id = id;
|
||||
this->name = id.GetName();
|
||||
scrolling[0] = false;
|
||||
scrolling[1] = false;
|
||||
scrollbar[0] = false;
|
||||
@ -38,10 +44,75 @@ class Menu : public SmartCtor<Menu> {
|
||||
scroll_allowed[0] = false;
|
||||
scroll_allowed[1] = false;
|
||||
};
|
||||
~Menu() {};
|
||||
~Menu() {}
|
||||
|
||||
/// Objects
|
||||
void Label(const std::string& label);
|
||||
bool Button(const std::string& label);
|
||||
void Checkbox(const std::string& label, bool& v);
|
||||
void Image(Texture::Ref img, vec2 size = 0.f);
|
||||
|
||||
/// Basic API
|
||||
void SameLine();
|
||||
void Separator();
|
||||
void SeparatorText(const std::string& label);
|
||||
|
||||
/// API for Custom Objects
|
||||
bool HandleScrolling(vec2& pos, const vec2& size);
|
||||
vec2 Cursor() const { return cursor; }
|
||||
void Cursor(const vec2& v) {
|
||||
bcursor = cursor;
|
||||
cursor = v;
|
||||
}
|
||||
void RestoreCursor() {
|
||||
cursor = bcursor;
|
||||
bcursor = vec2();
|
||||
}
|
||||
|
||||
/// Draw Lists
|
||||
DrawList::Ref BackList() { return back; }
|
||||
void BackList(DrawList::Ref v) { back = v; }
|
||||
DrawList::Ref MainList() { return main; }
|
||||
void MainList(DrawList::Ref v) { main = v; }
|
||||
DrawList::Ref FrontList() { return front; }
|
||||
void FrontList(DrawList::Ref v) { front = v; }
|
||||
|
||||
/// Advanced
|
||||
void DebugLabels();
|
||||
|
||||
/// Uneditable Stuff
|
||||
std::string GetName() const { return name; }
|
||||
u32 GetID() const { return id; }
|
||||
|
||||
private:
|
||||
/// Advanced Handlers
|
||||
void PreHandler(UI7MenuFlags flags);
|
||||
void PostHandler();
|
||||
/// Basic Settings
|
||||
vec2 BackupCursor() const { return bcursor; }
|
||||
void BackupCursor(const vec2& v) { bcursor = v; }
|
||||
vec2 SameLineCursor() const { return slcursor; }
|
||||
void SameLineCursor(const vec2& v) { slcursor = v; }
|
||||
vec4 ViewArea() const { return view_area; }
|
||||
void ViewArea(const vec4& v) { view_area = v; }
|
||||
vec2 ScrollOffset() const { return scrolling_off; }
|
||||
void ScrollOffset(const vec2& v) { scrolling_off = v; }
|
||||
vec2 ScrollMod() const { return scroll_mod; }
|
||||
void ScrollMod(const vec2& v) { scroll_mod = v; }
|
||||
|
||||
/// Advanced
|
||||
void CursorMove(const vec2& szs);
|
||||
|
||||
/// Internal Processing
|
||||
void Update(float delta);
|
||||
|
||||
/// This ability is crazy useful
|
||||
friend class Context;
|
||||
|
||||
/// Data
|
||||
UI7MenuFlags flags = 0;
|
||||
u32 id;
|
||||
std::string name;
|
||||
vec2 cursor;
|
||||
vec2 bcursor;
|
||||
vec2 slcursor;
|
||||
@ -65,6 +136,12 @@ class Menu : public SmartCtor<Menu> {
|
||||
vec2 mouse;
|
||||
vec2 bslpos;
|
||||
vec2 last_size;
|
||||
|
||||
// Theme
|
||||
Theme* linked_theme;
|
||||
|
||||
// Input Reference
|
||||
Hid::Ref inp;
|
||||
};
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -32,14 +32,14 @@ enum UI7Color_ {
|
||||
UI7Color_Button,
|
||||
UI7Color_ButtonDead,
|
||||
UI7Color_ButtonActive,
|
||||
UI7Color_ButtonDisabled,
|
||||
UI7Color_ButtonHovered,
|
||||
UI7Color_Text,
|
||||
UI7Color_TextDead,
|
||||
UI7Color_Header,
|
||||
UI7Color_Selector,
|
||||
UI7Color_Checkmark,
|
||||
UI7Color_FrameBackground,
|
||||
UI7Color_FragmeBackgroundHovered,
|
||||
UI7Color_FrameBackgroundHovered,
|
||||
UI7Color_Progressbar,
|
||||
UI7Color_ListEven,
|
||||
UI7Color_ListOdd,
|
||||
@ -115,20 +115,4 @@ class Theme {
|
||||
std::vector<std::pair<UI7Color, u32>> changes;
|
||||
};
|
||||
} // namespace UI7
|
||||
/// Using UI7Color as a Class to be able to
|
||||
/// define it as struct as well as using it as enum
|
||||
class UI7Color {
|
||||
public:
|
||||
UI7Color() {
|
||||
/// No Color
|
||||
}
|
||||
UI7Color(unsigned int c) { color = c; }
|
||||
UI7Color(UI7Color_ c) {}
|
||||
~UI7Color() {}
|
||||
|
||||
operator u32() const { return color; }
|
||||
|
||||
private:
|
||||
u32 color;
|
||||
};
|
||||
} // namespace PD
|
@ -23,23 +23,45 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/controls/hid.hpp> //// WOW A NON UI/ Header
|
||||
#include <pd/ui7/drawlist.hpp>
|
||||
#include <pd/ui7/flags.hpp>
|
||||
#include <pd/ui7/id.hpp>
|
||||
#include <pd/ui7/menu.hpp>
|
||||
#include <pd/ui7/theme.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
class Context : public SmartCtor<Context> {
|
||||
public:
|
||||
Context() {}
|
||||
Context(LI::Renderer::Ref ren, Hid::Ref hid) {
|
||||
this->ren = ren;
|
||||
this->inp = hid;
|
||||
Theme::Default(theme);
|
||||
back = DrawList::New(ren);
|
||||
front = DrawList::New(ren);
|
||||
}
|
||||
~Context() {}
|
||||
|
||||
bool BeginMenu(const ID& id, UI7MenuFlags flags = 0);
|
||||
Menu::Ref GetCurrentMenu();
|
||||
void EndMenu();
|
||||
|
||||
/// Theme Management
|
||||
Theme& GetTheme() { return theme; }
|
||||
|
||||
/// @brief Update Context (Render menus)
|
||||
/// @param delta deltatime
|
||||
void Update(float delta);
|
||||
|
||||
/// Expose DrawLists
|
||||
DrawList::Ref BackList() { return back; }
|
||||
DrawList::Ref FrontList() { return front; }
|
||||
|
||||
private:
|
||||
// Linked Renderer / Hid
|
||||
LI::Renderer::Ref ren;
|
||||
Hid::Ref inp;
|
||||
// Timing
|
||||
float delta;
|
||||
float time;
|
||||
@ -50,11 +72,14 @@ class Context : public SmartCtor<Context> {
|
||||
bool debugging;
|
||||
// Menu Handlers
|
||||
std::unordered_map<u32, Menu::Ref> menus;
|
||||
std::vector<u32> amenus; // Active ones
|
||||
Menu::Ref current;
|
||||
// Context DrawList
|
||||
DrawList::Ref debug;
|
||||
DrawList::Ref front;
|
||||
DrawList::Ref back;
|
||||
// Theme
|
||||
Theme theme;
|
||||
// Promt Handler
|
||||
};
|
||||
} // namespace UI7
|
||||
|
@ -28,6 +28,8 @@ SOFTWARE.
|
||||
#include <pd/common/sys.hpp>
|
||||
|
||||
namespace PD {
|
||||
int App::too;
|
||||
|
||||
void App::Run() {
|
||||
this->PreInit();
|
||||
this->Init();
|
||||
@ -45,7 +47,10 @@ void App::Run() {
|
||||
}
|
||||
PD::TT::End("App_MainLoop");
|
||||
PD::TT::Beg("Ovl_Update");
|
||||
renderer->Layer(90);
|
||||
overlay_mgr->Update(dt);
|
||||
/// Messages have their own special Layer
|
||||
renderer->Layer(93);
|
||||
msg_mgr->Update(dt);
|
||||
PD::TT::End("Ovl_Update");
|
||||
renderer->Render();
|
||||
|
26
source/common/io.cpp
Normal file
26
source/common/io.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include <pd/common/io.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace IO {
|
||||
std::vector<u8> LoadFile2Mem(const std::string& path) {
|
||||
std::ifstream iff(path, std::ios::binary);
|
||||
if (!iff) {
|
||||
return std::vector<u8>();
|
||||
}
|
||||
iff.seekg(0, std::ios::end);
|
||||
size_t szs = iff.tellg();
|
||||
iff.seekg(0, std::ios::beg);
|
||||
std::vector<u8> res(szs, 0);
|
||||
iff.read(reinterpret_cast<char*>(res.data()), res.size());
|
||||
iff.close();
|
||||
return res;
|
||||
}
|
||||
u32 HashMemory(const std::vector<u8>& data) {
|
||||
u32 hash = 4477;
|
||||
for (auto& it : data) {
|
||||
hash = (hash * 33) + it;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
} // namespace IO
|
||||
} // namespace PD
|
@ -44,5 +44,8 @@ TT::Res::Ref& GetTraceRef(const std::string& id) {
|
||||
}
|
||||
return pd_sys_tm[id];
|
||||
}
|
||||
bool TraceExist(const std::string& id) {
|
||||
return pd_sys_tm.find(id) != pd_sys_tm.end();
|
||||
}
|
||||
TraceMap& GetTraceMap() { return pd_sys_tm; }
|
||||
} // namespace PD::Sys
|
@ -23,6 +23,7 @@ SOFTWARE.
|
||||
|
||||
#include <pd/external/stb_truetype.h>
|
||||
|
||||
#include <pd/common/io.hpp>
|
||||
#include <pd/common/strings.hpp>
|
||||
#include <pd/common/sys.hpp>
|
||||
#include <pd/graphics/li7_shader.hpp>
|
||||
@ -45,31 +46,44 @@ void Font::LoadTTF(const std::string& path, int height) {
|
||||
loader.read(reinterpret_cast<char*>(buffer), len);
|
||||
loader.close();
|
||||
stbtt_InitFont(&inf, buffer, 0);
|
||||
std::vector<unsigned char> font_tex(quad * quad * 4);
|
||||
std::vector<unsigned char> font_tex(quad * quad);
|
||||
float scale = stbtt_ScaleForPixelHeight(&inf, pixel_height);
|
||||
|
||||
int ascent, descent, lineGap;
|
||||
stbtt_GetFontVMetrics(&inf, &ascent, &descent, &lineGap);
|
||||
int baseline = static_cast<int>(ascent * scale);
|
||||
|
||||
std::map<u32, int> buf_cache;
|
||||
|
||||
auto tex = Texture::New();
|
||||
vec2 off;
|
||||
for (int i = 0; i < 255; i++) {
|
||||
Codepoint c;
|
||||
for (u32 ii = 0x0000; ii < 0xFFFF; ii++) {
|
||||
int i = stbtt_FindGlyphIndex(&inf, ii);
|
||||
if (i == 0) {
|
||||
continue;
|
||||
}
|
||||
if (stbtt_IsGlyphEmpty(&inf, i)) {
|
||||
c.cp(i);
|
||||
c.tex(tex);
|
||||
c.invalid(true);
|
||||
cpmap[i] = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
Codepoint c;
|
||||
int w = 0, h = 0, xo = 0, yo = 0;
|
||||
unsigned char* bitmap =
|
||||
stbtt_GetCodepointBitmap(&inf, scale, scale, i, &w, &h, &xo, &yo);
|
||||
int x0, y0, x1, y1;
|
||||
stbtt_GetCodepointBitmapBox(&inf, i, scale, scale, &x0, &y0, &x1, &y1);
|
||||
|
||||
u32 hashed_map = IO::HashMemory(std::vector<u8>(bitmap, bitmap + (w * h)));
|
||||
if (buf_cache.find(hashed_map) != buf_cache.end()) {
|
||||
c = GetCodepoint(buf_cache[hashed_map]);
|
||||
c.cp(i);
|
||||
cpmap[i] = c;
|
||||
free(bitmap);
|
||||
continue;
|
||||
} else {
|
||||
buf_cache[hashed_map] = i;
|
||||
}
|
||||
|
||||
if (off[0] + w > quad) {
|
||||
off[1] += pixel_height;
|
||||
off[0] = 0;
|
||||
@ -88,24 +102,25 @@ void Font::LoadTTF(const std::string& path, int height) {
|
||||
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
int map_pos = ((off[1] + y) * quad + (off[0] + x)) * 4;
|
||||
|
||||
font_tex[map_pos + 0] = 255;
|
||||
font_tex[map_pos + 1] = 255;
|
||||
font_tex[map_pos + 2] = 255;
|
||||
font_tex[map_pos + 3] = bitmap[x + y * w];
|
||||
int map_pos = ((off[1] + y) * quad + (off[0] + x));
|
||||
font_tex[map_pos] = bitmap[x + y * w];
|
||||
}
|
||||
}
|
||||
|
||||
free(bitmap);
|
||||
cpmap[i] = c;
|
||||
|
||||
// Small Patch to avoid some possible artifacts
|
||||
off[0] += w + 1;
|
||||
if (off[0] + w > quad) {
|
||||
off[1] += pixel_height;
|
||||
if (off[1] + pixel_height > quad) {
|
||||
break;
|
||||
}
|
||||
off[0] = 0;
|
||||
}
|
||||
free(bitmap);
|
||||
cpmap[i] = c;
|
||||
}
|
||||
tex->LoadPixels(font_tex, quad, quad, Texture::RGBA32, Texture::LINEAR);
|
||||
tex->LoadPixels(font_tex, quad, quad, Texture::A8, Texture::LINEAR);
|
||||
textures.push_back(tex);
|
||||
}
|
||||
|
||||
@ -143,6 +158,7 @@ void Font::LoadSystemFont() {
|
||||
tx->border = 0xffffffff;
|
||||
tx->lodParam = 0;
|
||||
stex->LoadExternal(tx, vec2(tx->width, tx->height), vec4(0, 1, 1, 0));
|
||||
stex->AutoUnLoad(false);
|
||||
textures[i] = stex;
|
||||
}
|
||||
std::vector<unsigned int> charSet;
|
||||
@ -192,8 +208,10 @@ void Font::LoadSystemFont() {
|
||||
codepoint.uv(vec4(dat.texcoord.left, dat.texcoord.top, dat.texcoord.right,
|
||||
dat.texcoord.bottom));
|
||||
|
||||
if (textures.at(dat.sheetIndex) != nullptr) {
|
||||
if (dat.sheetIndex < (int)textures.size()) {
|
||||
codepoint.tex(textures[dat.sheetIndex]);
|
||||
} else {
|
||||
codepoint.invalid(true);
|
||||
}
|
||||
codepoint.size(vec2(dat.vtxcoord.right, dat.vtxcoord.bottom));
|
||||
codepoint.off(0);
|
||||
@ -250,7 +268,9 @@ void Renderer::StaticText::Setup(Renderer* ren, const vec2& pos, u32 clr,
|
||||
this->pos = pos;
|
||||
this->ren = ren;
|
||||
this->text = StaticObject::New();
|
||||
ren->TextCommand(this->text->List(), pos, clr, text, flags, box);
|
||||
/// Ensure that it also renders Out of Screen i guess
|
||||
ren->TextCommand(this->text->List(), pos, clr, text,
|
||||
flags | LITextFlags_RenderOOS, box);
|
||||
OptiCommandList(this->text->List());
|
||||
}
|
||||
|
||||
@ -267,6 +287,8 @@ void Renderer::StaticText::SetPos(const vec2& pos) {
|
||||
text->MoveIt(pos - this->pos);
|
||||
}
|
||||
|
||||
void Renderer::StaticText::SetLayer(int layer) { text->ReLayer(layer); }
|
||||
|
||||
bool Renderer::InBox(const vec2& pos, const vec2& szs, const vec4& rect) {
|
||||
return (pos[0] < rect[2] || pos[1] < rect[3] || pos[0] + szs[0] > rect[0] ||
|
||||
pos[1] + szs[1] > rect[1]);
|
||||
@ -341,18 +363,14 @@ void Renderer::SetupCommand(Command::Ref cmd) {
|
||||
cmd->Index(cmd_idx++).Layer(current_layer).Tex(current_tex);
|
||||
}
|
||||
|
||||
void Renderer::QuadCommand(Command::Ref cmd, const Rect& quad, const vec4& uv,
|
||||
void Renderer::QuadCommand(Command::Ref cmd, const Rect& quad, const Rect& uv,
|
||||
u32 col) {
|
||||
cmd->PushIndex(0).PushIndex(1).PushIndex(2);
|
||||
cmd->PushIndex(0).PushIndex(2).PushIndex(3);
|
||||
cmd->PushVertex(
|
||||
Vertex(vec2(quad.Bot().z(), quad.Bot().w()), vec2(uv.z(), uv.w()), col));
|
||||
cmd->PushVertex(
|
||||
Vertex(vec2(quad.Top().z(), quad.Top().w()), vec2(uv.z(), uv.y()), col));
|
||||
cmd->PushVertex(
|
||||
Vertex(vec2(quad.Top().x(), quad.Top().y()), vec2(uv.x(), uv.y()), col));
|
||||
cmd->PushVertex(
|
||||
Vertex(vec2(quad.Bot().x(), quad.Bot().y()), vec2(uv.x(), uv.w()), col));
|
||||
cmd->PushVertex(Vertex(quad.BotRight(), uv.BotRight(), col));
|
||||
cmd->PushVertex(Vertex(quad.TopRight(), uv.TopRight(), col));
|
||||
cmd->PushVertex(Vertex(quad.TopLeft(), uv.TopLeft(), col));
|
||||
cmd->PushVertex(Vertex(quad.BotLeft(), uv.BotLeft(), col));
|
||||
}
|
||||
|
||||
void Renderer::TriangleCommand(Command::Ref cmd, const vec2& a, const vec2& b,
|
||||
@ -364,7 +382,6 @@ void Renderer::TriangleCommand(Command::Ref cmd, const vec2& a, const vec2& b,
|
||||
cmd->PushVertex(Vertex(c, vec2(1.f, 0.f), col));
|
||||
}
|
||||
|
||||
/// TO BE REWRITTEN
|
||||
void Renderer::TextCommand(std::vector<Command::Ref>& cmds, const vec2& pos,
|
||||
u32 color, const std::string& text,
|
||||
LITextFlags flags, const vec2& box) {
|
||||
@ -375,6 +392,23 @@ void Renderer::TextCommand(std::vector<Command::Ref>& cmds, const vec2& pos,
|
||||
float cfs = (default_font_h * text_size) / (float)font->PixelHeight();
|
||||
float lh = (float)font->PixelHeight() * cfs;
|
||||
vec2 td;
|
||||
vec2 rpos = pos;
|
||||
vec2 rbox = box;
|
||||
if (flags & (LITextFlags_AlignMid | LITextFlags_AlignRight)) {
|
||||
td = GetTextDimensions(text);
|
||||
if (rbox[0] == 0.f) {
|
||||
rbox[0] = area_size.x();
|
||||
}
|
||||
if (rbox[1] == 0.f) {
|
||||
rbox[1] = area_size.y();
|
||||
}
|
||||
}
|
||||
if (flags & LITextFlags_AlignMid) {
|
||||
rpos = rbox * 0.5 - td * 0.5 + pos;
|
||||
}
|
||||
if (flags & LITextFlags_AlignRight) {
|
||||
rpos[0] = rbox[0] - td[0];
|
||||
}
|
||||
|
||||
std::vector<std::string> lines;
|
||||
std::istringstream iss(text);
|
||||
@ -384,10 +418,10 @@ void Renderer::TextCommand(std::vector<Command::Ref>& cmds, const vec2& pos,
|
||||
}
|
||||
|
||||
for (auto& it : lines) {
|
||||
if (pos[1] + off[1] + lh < 0) {
|
||||
if (rpos[1] + off[1] + lh < 0) {
|
||||
off[1] += lh;
|
||||
continue;
|
||||
} else if (pos[1] + off[1] > GetViewport().w() &&
|
||||
} else if (rpos[1] + off[1] > GetViewport().w() &&
|
||||
!(flags & LITextFlags_RenderOOS)) {
|
||||
// Break cause next lines would be out of screen
|
||||
break;
|
||||
@ -396,9 +430,7 @@ void Renderer::TextCommand(std::vector<Command::Ref>& cmds, const vec2& pos,
|
||||
auto cmd = Command::New();
|
||||
current_tex = font->GetCodepoint(wline[0]).tex();
|
||||
SetupCommand(cmd);
|
||||
if (font->SystemFont()) {
|
||||
cmd->Rendermode(RenderMode_SysFont);
|
||||
}
|
||||
cmd->Rendermode(RenderMode_Font);
|
||||
for (auto& jt : wline) {
|
||||
auto cp = font->GetCodepoint(jt);
|
||||
if (cp.invalid() && jt != '\n' && jt != '\t') {
|
||||
@ -409,9 +441,7 @@ void Renderer::TextCommand(std::vector<Command::Ref>& cmds, const vec2& pos,
|
||||
cmd = Command::New();
|
||||
current_tex = cp.tex();
|
||||
SetupCommand(cmd);
|
||||
if (font->SystemFont()) {
|
||||
cmd->Rendermode(RenderMode_SysFont);
|
||||
}
|
||||
cmd->Rendermode(RenderMode_Font);
|
||||
}
|
||||
if (jt == '\t') {
|
||||
off[0] += 16 * cfs;
|
||||
@ -421,13 +451,13 @@ void Renderer::TextCommand(std::vector<Command::Ref>& cmds, const vec2& pos,
|
||||
if (flags & LITextFlags_Shaddow) {
|
||||
// Draw
|
||||
Rect rec = CreateRect(
|
||||
pos + vec2(off[0] + 1, off[1] + (cp.off() * cfs)) + 1,
|
||||
rpos + vec2(off[0] + 1, off[1] + (cp.off() * cfs)) + 1,
|
||||
cp.size() * cfs, 0.f);
|
||||
QuadCommand(cmd, rec, cp.uv(), 0xff111111);
|
||||
current_layer++;
|
||||
}
|
||||
// Draw
|
||||
Rect rec = CreateRect(pos + off + vec2(0, (cp.off() * cfs)),
|
||||
Rect rec = CreateRect(rpos + off + vec2(0, (cp.off() * cfs)),
|
||||
cp.size() * cfs, 0.f);
|
||||
QuadCommand(cmd, rec, cp.uv(), color);
|
||||
current_layer = lr;
|
||||
@ -450,7 +480,6 @@ vec4 Renderer::GetViewport() {
|
||||
return vec4(0, 0, screen[0], screen[1]);
|
||||
}
|
||||
|
||||
/// TO BE REWRITTEN
|
||||
vec2 Renderer::GetTextDimensions(const std::string& text) {
|
||||
if (!font) {
|
||||
// No font no size (oder so)
|
||||
@ -516,7 +545,8 @@ vec2 Renderer::GetTextDimensions(const std::string& text) {
|
||||
void Renderer::UpdateRenderMode(const RenderMode& mode) {
|
||||
C3D_TexEnv* env = C3D_GetTexEnv(0);
|
||||
switch (mode) {
|
||||
case RenderMode_SysFont:
|
||||
case RenderMode_Font:
|
||||
/// Sets Only Alpha Using the Color and Replase RGB with vertex color
|
||||
C3D_TexEnvInit(env);
|
||||
C3D_TexEnvSrc(env, C3D_RGB, GPU_PRIMARY_COLOR);
|
||||
C3D_TexEnvFunc(env, C3D_RGB, GPU_REPLACE);
|
||||
@ -526,6 +556,7 @@ void Renderer::UpdateRenderMode(const RenderMode& mode) {
|
||||
// Fall trough instead of defining twice
|
||||
case RenderMode_RGBA:
|
||||
default:
|
||||
/// Use Texture for RGBA and vertexcolor for visibility
|
||||
C3D_TexEnvInit(env);
|
||||
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0);
|
||||
C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE);
|
||||
@ -536,23 +567,17 @@ void Renderer::UpdateRenderMode(const RenderMode& mode) {
|
||||
void Renderer::RenderOn(bool bot) {
|
||||
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection,
|
||||
(bot ? &bot_proj : &top_proj));
|
||||
|
||||
C3D_DepthTest(false, GPU_GREATER, GPU_WRITE_ALL);
|
||||
|
||||
UpdateRenderMode(RenderMode_RGBA);
|
||||
|
||||
int total_vertices = 0;
|
||||
int total_indices = 0;
|
||||
drawcalls = 0;
|
||||
auto& cmds = draw_list[bot];
|
||||
|
||||
commands = cmds.size();
|
||||
size_t index = 0;
|
||||
|
||||
if (flags & RenderFlags_LRS) {
|
||||
OptiCommandList(cmds);
|
||||
}
|
||||
|
||||
while (index < cmds.size()) {
|
||||
C3D_Tex* tex = cmds[index]->Tex()->GetTex();
|
||||
auto mode = cmds[index]->Rendermode();
|
||||
@ -572,6 +597,7 @@ void Renderer::RenderOn(bool bot) {
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
C3D_TexBind(0, tex);
|
||||
|
||||
auto bufInfo = C3D_GetBufInfo();
|
||||
@ -580,6 +606,7 @@ void Renderer::RenderOn(bool bot) {
|
||||
|
||||
C3D_DrawElements(GPU_TRIANGLES, index_idx - start_idx, C3D_UNSIGNED_SHORT,
|
||||
index_buf.data() + start_idx);
|
||||
|
||||
drawcalls++;
|
||||
total_vertices += vertex_idx - start_vtx;
|
||||
total_indices += index_idx - start_idx;
|
||||
@ -629,6 +656,8 @@ void Renderer::Render() {
|
||||
if (Sys::GetTime() - it.second.TimeCreated() > 5) rem.push_back(it.first);
|
||||
}
|
||||
for (auto it : rem) tms.erase(it);
|
||||
} else {
|
||||
tms.clear();
|
||||
}
|
||||
if (flags & RenderFlags_AST) {
|
||||
std::vector<u32> rem;
|
||||
@ -641,11 +670,13 @@ void Renderer::Render() {
|
||||
for (auto& it : rem) {
|
||||
ast.erase(it);
|
||||
}
|
||||
} else {
|
||||
ast.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::DrawRect(const vec2& pos, const vec2& size, u32 color,
|
||||
const vec4& uv) {
|
||||
const Rect& uv) {
|
||||
if (!InBox(pos, size, GetViewport())) {
|
||||
// Instand abort as it is out of screen
|
||||
return;
|
||||
@ -659,7 +690,7 @@ void Renderer::DrawRect(const vec2& pos, const vec2& size, u32 color,
|
||||
|
||||
void Renderer::DrawRectSolid(const vec2& pos, const vec2& size, u32 color) {
|
||||
UseTex();
|
||||
DrawRect(pos, size, color);
|
||||
DrawRect(pos, size, color, vec4(0.f, 1.f, 1.f, 0.f));
|
||||
}
|
||||
|
||||
void Renderer::DrawTriangle(const vec2& a, const vec2& b, const vec2& c,
|
||||
|
44
source/graphics/spritesheet.cpp
Normal file
44
source/graphics/spritesheet.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include <pd/common/io.hpp>
|
||||
#include <pd/graphics/spritesheet.hpp>
|
||||
|
||||
namespace PD {
|
||||
SpriteSheet::~SpriteSheet() { textures.clear(); }
|
||||
|
||||
void SpriteSheet::LoadFile(const std::string& path) {
|
||||
auto file = IO::LoadFile2Mem(path);
|
||||
if (file.size() == 0) {
|
||||
Error("Unable to load file:\n" + path);
|
||||
}
|
||||
C3D_Tex* tex = new C3D_Tex;
|
||||
auto t3x =
|
||||
Tex3DS_TextureImport(file.data(), file.size(), tex, nullptr, false);
|
||||
if (!t3x) {
|
||||
Error("Unable to import:\n" + path);
|
||||
}
|
||||
tex->border = 0;
|
||||
C3D_TexSetWrap(tex, GPU_CLAMP_TO_BORDER, GPU_CLAMP_TO_BORDER);
|
||||
C3D_TexSetFilter(tex, GPU_LINEAR, GPU_NEAREST);
|
||||
textures.reserve(Tex3DS_GetNumSubTextures(t3x) + 1);
|
||||
for (int i = 0; i < (int)Tex3DS_GetNumSubTextures(t3x); i++) {
|
||||
auto t = Texture::New();
|
||||
auto st = Tex3DS_GetSubTexture(t3x, i);
|
||||
LI::Rect uv(vec2(st->left, st->top), vec2(st->right, st->top),
|
||||
vec2(st->left, st->bottom), vec2(st->right, st->bottom));
|
||||
if (st->top < st->bottom) {
|
||||
uv.SwapVec2XY();
|
||||
}
|
||||
t->LoadExternal(tex, vec2(st->width, st->height), uv);
|
||||
textures.push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
Texture::Ref SpriteSheet::Get(int idx) {
|
||||
if (idx >= (int)textures.size()) {
|
||||
Error("Trying to Access Texture " + std::to_string(idx + 1) + " of " +
|
||||
std::to_string(NumTextures()));
|
||||
}
|
||||
return textures[idx];
|
||||
}
|
||||
|
||||
int SpriteSheet::NumTextures() const { return textures.size(); }
|
||||
} // namespace PD
|
@ -24,12 +24,14 @@ SOFTWARE.
|
||||
|
||||
#include <3ds.h>
|
||||
#include <pd/external/stb_image.h>
|
||||
#include <tex3ds.h>
|
||||
|
||||
#include <pd/common/error.hpp>
|
||||
#include <pd/common/io.hpp>
|
||||
#include <pd/common/timetrace.hpp>
|
||||
#include <pd/graphics/texture.hpp>
|
||||
#include <pd/maths/bit_util.hpp>
|
||||
#include <pd/maths/img_convert.hpp>
|
||||
#include <pd/common/error.hpp>
|
||||
|
||||
namespace PD {
|
||||
GPU_TEXCOLOR GetTexFmt(Texture::Type type) {
|
||||
@ -54,36 +56,6 @@ void Texture::MakeTex(std::vector<u8>& buf, int w, int h, Texture::Type type,
|
||||
Filter filter) {
|
||||
// Don't check here as check done before
|
||||
int bpp = GetBPP(type);
|
||||
if (bpp == 4) {
|
||||
// RGBA -> Abgr
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int pos = (x + y * w) * bpp;
|
||||
auto r = buf[pos + 0];
|
||||
auto g = buf[pos + 1];
|
||||
auto b = buf[pos + 2];
|
||||
auto a = buf[pos + 3];
|
||||
buf[pos + 0] = a;
|
||||
buf[pos + 1] = b;
|
||||
buf[pos + 2] = g;
|
||||
buf[pos + 3] = r;
|
||||
}
|
||||
}
|
||||
} else if (bpp == 3) {
|
||||
// RGBA -> Abgr
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int pos = (x + y * w) * bpp;
|
||||
auto r = buf[pos + 0];
|
||||
auto g = buf[pos + 1];
|
||||
auto b = buf[pos + 2];
|
||||
buf[pos + 0] = b;
|
||||
buf[pos + 1] = g;
|
||||
buf[pos + 2] = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vec2 tex_size(w, h);
|
||||
// Pow2
|
||||
if (!PD::BitUtil::IsSingleBit(w)) {
|
||||
@ -95,10 +67,8 @@ void Texture::MakeTex(std::vector<u8>& buf, int w, int h, Texture::Type type,
|
||||
|
||||
this->size.x() = (u16)w;
|
||||
this->size.y() = (u16)h;
|
||||
this->uv.x() = 0.0f;
|
||||
this->uv.y() = 1.0f;
|
||||
this->uv.z() = ((float)w / (float)tex_size.x());
|
||||
this->uv.w() = 1.0 - ((float)h / (float)tex_size.y());
|
||||
this->uv = vec4(0.f, 1.f, ((float)w / (float)tex_size.x()),
|
||||
1.0 - ((float)h / (float)tex_size.y()));
|
||||
|
||||
// Texture Setup
|
||||
auto fltr = (filter == NEAREST ? GPU_NEAREST : GPU_LINEAR);
|
||||
@ -109,7 +79,9 @@ void Texture::MakeTex(std::vector<u8>& buf, int w, int h, Texture::Type type,
|
||||
|
||||
memset(tex->data, 0, tex->size);
|
||||
|
||||
if (bpp == 3 || bpp == 4) {
|
||||
/// Probably Remove this if statement in future
|
||||
/// This are the things confirmed as working
|
||||
if (bpp == 3 || bpp == 4 || bpp == 1) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int dst_pos = ((((y >> 3) * ((int)tex_size.x() >> 3) + (x >> 3)) << 6) +
|
||||
@ -117,13 +89,13 @@ void Texture::MakeTex(std::vector<u8>& buf, int w, int h, Texture::Type type,
|
||||
((y & 2) << 2) | ((x & 4) << 2) | ((y & 4) << 3))) *
|
||||
bpp;
|
||||
int src_pos = (y * w + x) * bpp;
|
||||
|
||||
memcpy(&((u8*)tex->data)[dst_pos], &buf[src_pos], bpp);
|
||||
/// Best idea i had
|
||||
for (int i = 0; i < bpp; i++) {
|
||||
((u8*)tex->data)[dst_pos + bpp - 1 - i] = buf[src_pos + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
C3D_TexFlush(tex);
|
||||
} else if (bpp == 1) {
|
||||
C3D_TexLoadImage(tex, buf.data(), GPU_TEXFACE_2D, 0);
|
||||
}
|
||||
|
||||
tex->border = 0x00000000;
|
||||
@ -200,4 +172,23 @@ void Texture::LoadPixels(const std::vector<u8>& pixels, int w, int h, Type type,
|
||||
std::vector<u8> cpy(pixels);
|
||||
MakeTex(cpy, w, h, type, filter);
|
||||
}
|
||||
|
||||
void Texture::LoadT3X(const std::string& path) {
|
||||
this->Delete();
|
||||
auto file = IO::LoadFile2Mem(path);
|
||||
if (file.size() == 0) {
|
||||
Error("Unable to load file:\n" + path);
|
||||
}
|
||||
this->tex = new C3D_Tex;
|
||||
auto t3x =
|
||||
Tex3DS_TextureImport(file.data(), file.size(), this->tex, nullptr, false);
|
||||
if (!t3x) {
|
||||
Error("Unable to import:\n" + path);
|
||||
}
|
||||
auto st = Tex3DS_GetSubTexture(t3x, 0);
|
||||
this->uv = vec4(st->left, st->top, st->right, st->bottom);
|
||||
this->size[0] = st->width;
|
||||
this->size[1] = st->height;
|
||||
Tex3DS_TextureFree(t3x);
|
||||
}
|
||||
} // namespace PD
|
@ -484,8 +484,6 @@ void Keyboard::Update(float delta, LI::Renderer::Ref ren, Hid::Ref inp) {
|
||||
/// Process Controller Movement
|
||||
Movement(inp);
|
||||
|
||||
/// Declare RenderLayer (10 above the latest)
|
||||
ren->Layer(ren->Layer() + 10);
|
||||
/// Update animations
|
||||
flymgr.Update(delta);
|
||||
selector.Update(delta);
|
||||
|
@ -104,8 +104,6 @@ void MessageMgr::Push(const std::string& title, const std::string& text) {
|
||||
}
|
||||
|
||||
void MessageMgr::Update(float delta) {
|
||||
// Go two layers up and Render on Top
|
||||
ren->Layer(ren->Layer() + 2);
|
||||
ren->OnScreen(Screen::Top);
|
||||
for (size_t i = 0; i < msgs.size(); i++) {
|
||||
// Update the Animation Handlers and Move older
|
||||
|
@ -12,8 +12,7 @@ void Performance::Update(float delta, LI::Renderer::Ref ren, Hid::Ref inp) {
|
||||
ren->OnScreen(Screen::Top);
|
||||
ren->TextScale(0.6);
|
||||
vec2 pos;
|
||||
Line(pos, std::format("FPS {:.1f} FPS / {:.2f}ms", 1000.f / delta, delta),
|
||||
ren);
|
||||
Line(pos, std::format("{:.1f} FPS / {:.2f}ms", 1000.f / delta, delta), ren);
|
||||
Line(pos, "Ren [AVG]: " + TSA("LI_RenderAll"), ren);
|
||||
Line(pos, "App [AVG]: " + TSA("App_MainLoop"), ren);
|
||||
Line(pos, "Ovl [AVG]: " + TSA("Ovl_Update"), ren);
|
||||
|
@ -21,6 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/common/strings.hpp>
|
||||
#include <pd/ui7/drawlist.hpp>
|
||||
|
||||
namespace PD {
|
||||
@ -31,11 +32,12 @@ void DrawList::AddRectangle(vec2 pos, vec2 szs, const UI7Color& clr) {
|
||||
}
|
||||
auto rect = ren->CreateRect(pos, szs, 0.f);
|
||||
auto cmd = LI::Command::New();
|
||||
ren->SetupCommand(cmd);
|
||||
ren->UseTex();
|
||||
ren->SetupCommand(cmd);
|
||||
cmd->Layer(layer);
|
||||
ren->QuadCommand(cmd, rect, vec4(0.f, 1.f, 1.f, 0.f), clr);
|
||||
commands.push_back(cmd);
|
||||
commands.push_back(
|
||||
std::make_pair(ren->CurrentScreen() == Screen::Bottom, cmd));
|
||||
}
|
||||
|
||||
void DrawList::AddTriangle(vec2 pos0, vec2 pos1, vec2 pos2,
|
||||
@ -44,41 +46,82 @@ void DrawList::AddTriangle(vec2 pos0, vec2 pos1, vec2 pos2,
|
||||
return;
|
||||
}
|
||||
auto cmd = LI::Command::New();
|
||||
ren->SetupCommand(cmd);
|
||||
ren->UseTex();
|
||||
ren->SetupCommand(cmd);
|
||||
cmd->Layer(layer);
|
||||
ren->TriangleCommand(cmd, pos0, pos1, pos2, clr);
|
||||
commands.push_back(cmd);
|
||||
commands.push_back(
|
||||
std::make_pair(ren->CurrentScreen() == Screen::Bottom, cmd));
|
||||
}
|
||||
|
||||
void DrawList::AddText(vec2 pos, const std::string& text, const UI7Color& clr,
|
||||
LITextFlags flags, vec2 box) {
|
||||
u32 id = Strings::FastHash(text);
|
||||
auto e = static_text.find(id);
|
||||
if (e == static_text.end()) {
|
||||
static_text[id] = LI::Renderer::StaticText::New();
|
||||
e = static_text.find(id);
|
||||
}
|
||||
if (!e->second->IsSetup()) {
|
||||
e->second->Setup(&(*ren), pos, clr, text, flags, box);
|
||||
}
|
||||
e->second->SetPos(pos);
|
||||
e->second->SetColor(clr);
|
||||
e->second->SetLayer(base + layer);
|
||||
e->second->Draw();
|
||||
|
||||
////// STILL LEAVING THE OLD CODE BELOW AS IT IS MAYBE NEEDED //////
|
||||
////// IF STATIC TEXT SYSTEM SHOULD HAVE AN DISABLE OPTION //////
|
||||
|
||||
// Dont create a Command here as TextCommand has autosetup
|
||||
// cause it needs to generate multiple commands if
|
||||
// Font uses multiple textures
|
||||
ren->TextCommand(commands, pos, clr, text, flags, box);
|
||||
// Oh and Handle Layer management here as well
|
||||
// int l = ren->Layer();
|
||||
// ren->Layer(layer);
|
||||
// std::vector<LI::Command::Ref> cmds;
|
||||
// ren->TextCommand(cmds, pos, clr, text, flags, box);
|
||||
// ren->Layer(l);
|
||||
// for (auto c : cmds) {
|
||||
// commands.push_back(
|
||||
// std::make_pair(ren->CurrentScreen() == Screen::Bottom, c));
|
||||
// }
|
||||
}
|
||||
|
||||
void DrawList::AddImage(vec2 pos, Texture::Ref img) {
|
||||
if (!ren->InBox(pos, img->GetSize(), ren->GetViewport())) {
|
||||
void DrawList::AddImage(vec2 pos, Texture::Ref img, vec2 size) {
|
||||
size = size == 0.f ? img->GetSize() : size;
|
||||
if (!ren->InBox(pos, size, ren->GetViewport())) {
|
||||
return;
|
||||
}
|
||||
auto rect = ren->CreateRect(pos, img->GetSize(), 0.f);
|
||||
auto rect = ren->CreateRect(pos, size, 0.f);
|
||||
auto cmd = LI::Command::New();
|
||||
ren->SetupCommand(cmd);
|
||||
ren->UseTex(img);
|
||||
ren->SetupCommand(cmd);
|
||||
cmd->Layer(layer);
|
||||
ren->QuadCommand(cmd, rect, vec4(0.f, 1.f, 1.f, 0.f), 0xffffffff);
|
||||
commands.push_back(cmd);
|
||||
ren->QuadCommand(cmd, rect, img->GetUV(), 0xffffffff);
|
||||
commands.push_back(
|
||||
std::make_pair(ren->CurrentScreen() == Screen::Bottom, cmd));
|
||||
}
|
||||
|
||||
void DrawList::Clear() { commands.clear(); }
|
||||
|
||||
void DrawList::Process() {
|
||||
// UI7 Commands Use LI7 as default feature
|
||||
ren->OptiCommandList(commands);
|
||||
for (auto command : commands) {
|
||||
ren->PushCommand(command);
|
||||
command.second->Layer(command.second->Layer() + base);
|
||||
ren->OnScreen(command.first ? Screen::Bottom : Screen::Top);
|
||||
ren->PushCommand(command.second);
|
||||
}
|
||||
commands.clear();
|
||||
layer = 0;
|
||||
std::vector<u32> rem;
|
||||
for (auto it : static_text) {
|
||||
if (!it.second->Used()) {
|
||||
rem.push_back(it.first);
|
||||
}
|
||||
it.second->SetUnused();
|
||||
}
|
||||
for (auto& it : rem) {
|
||||
static_text.erase(it);
|
||||
}
|
||||
}
|
||||
} // namespace UI7
|
||||
|
331
source/ui7/menu.cpp
Normal file
331
source/ui7/menu.cpp
Normal file
@ -0,0 +1,331 @@
|
||||
#include <pd/common/sys.hpp>
|
||||
#include <pd/common/timetrace.hpp>
|
||||
#include <pd/ui7/menu.hpp>
|
||||
|
||||
//////////////////////////////
|
||||
//////// OBJECT SETUP ////////
|
||||
////// Setup Variables ///////
|
||||
///////// Move Cursor ////////
|
||||
//// Check Scrolling State ///
|
||||
/////// Handle Controls //////
|
||||
////////// Render ////////////
|
||||
//////////////////////////////
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
void UI7::Menu::Label(const std::string& label) {
|
||||
vec2 size = this->back->GetRenderer()->GetTextDimensions(label);
|
||||
vec2 pos = Cursor();
|
||||
CursorMove(size - vec2(0, 4)); // Fix to make gap not to large
|
||||
|
||||
if (HandleScrolling(pos, size)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/// To Draw a Label above the head bar you should
|
||||
/// use the m->GetFrontList() instead
|
||||
|
||||
main->AddText(pos, label, linked_theme->Get(UI7Color_Text), 0,
|
||||
vec2(view_area.z(), 20));
|
||||
}
|
||||
|
||||
bool UI7::Menu::Button(const std::string& label) {
|
||||
bool ret = false;
|
||||
auto tszs = this->back->GetRenderer()->GetTextDimensions(label);
|
||||
vec2 size = tszs + vec2(8, 4);
|
||||
vec2 pos = Cursor();
|
||||
UI7Color clr = UI7Color_Button;
|
||||
CursorMove(size);
|
||||
/////// SCROLLING HANDLER HERE ////////
|
||||
if (HandleScrolling(pos, size)) {
|
||||
return false;
|
||||
}
|
||||
/// CONTROLS ///
|
||||
if (has_touch) {
|
||||
if (inp->IsHeld(inp->Touch) &&
|
||||
LI::Renderer::InBox(inp->TouchPos(), vec4(pos, size))) {
|
||||
clr = UI7Color_ButtonHovered;
|
||||
}
|
||||
if (inp->IsUp(inp->Touch) &&
|
||||
LI::Renderer::InBox(inp->TouchPosLast(), vec4(pos, size))) {
|
||||
clr = UI7Color_ButtonActive;
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
/// Rendering ///
|
||||
main->AddRectangle(pos, size, linked_theme->Get(clr));
|
||||
main->AddText(pos + size * 0.5 - tszs * 0.5, label,
|
||||
linked_theme->Get(UI7Color_Text));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void UI7::Menu::Checkbox(const std::string& label, bool& v) {
|
||||
vec2 pos = Cursor();
|
||||
vec2 tdim = front->ren->GetTextDimensions(label);
|
||||
vec2 cbs(18);
|
||||
vec2 size = cbs + vec2(tdim.x() + 5, 0);
|
||||
CursorMove(size);
|
||||
|
||||
if (HandleScrolling(pos, size)) {
|
||||
return;
|
||||
}
|
||||
|
||||
UI7Color cbbg = UI7Color_FrameBackground;
|
||||
|
||||
if (has_touch) {
|
||||
if (inp->IsHeld(inp->Touch) &&
|
||||
LI::Renderer::InBox(inp->TouchPos(), vec4(pos, size))) {
|
||||
cbbg = UI7Color_FrameBackgroundHovered;
|
||||
}
|
||||
if (inp->IsUp(inp->Touch) &&
|
||||
LI::Renderer::InBox(inp->TouchPosLast(), vec4(pos, size))) {
|
||||
cbbg = UI7Color_FrameBackgroundHovered;
|
||||
v = !v;
|
||||
}
|
||||
}
|
||||
|
||||
main->AddRectangle(pos, cbs, linked_theme->Get(cbbg));
|
||||
if (v) {
|
||||
main->AddRectangle(pos + 2, cbs - 4, linked_theme->Get(UI7Color_Checkmark));
|
||||
}
|
||||
main->AddText(pos + vec2(cbs.x() + 5, cbs.y() * 0.5 - tdim.y() * 0.5), label,
|
||||
linked_theme->Get(UI7Color_Text));
|
||||
}
|
||||
|
||||
void UI7::Menu::Image(Texture::Ref img, vec2 size) {
|
||||
/// Variable Setup Stage ///
|
||||
size = size == 0.f ? img->GetSize() : size;
|
||||
vec2 pos = Cursor();
|
||||
CursorMove(size);
|
||||
/// Scrolling Handler ///
|
||||
if (HandleScrolling(pos, size)) {
|
||||
return;
|
||||
}
|
||||
/// Rendering Stage ///
|
||||
main->AddImage(pos, img, size);
|
||||
}
|
||||
|
||||
void UI7::Menu::DebugLabels() {
|
||||
std::stringstream s;
|
||||
s << "Name: " << name << " [";
|
||||
s << std::hex << std::setw(8) << std::setfill('0') << id;
|
||||
s << std::dec << "]";
|
||||
this->Label(s.str());
|
||||
this->Label(
|
||||
"Pre: " +
|
||||
Strings::FormatNanos(
|
||||
Sys::GetTraceRef("MPRE_" + name)->GetProtocol()->GetAverage()));
|
||||
this->Label(
|
||||
"Post: " +
|
||||
Strings::FormatNanos(
|
||||
Sys::GetTraceRef("MPOS_" + name)->GetProtocol()->GetAverage()));
|
||||
this->Label(
|
||||
"Update: " +
|
||||
Strings::FormatNanos(
|
||||
Sys::GetTraceRef("MUPT_" + name)->GetProtocol()->GetAverage()));
|
||||
this->Label(
|
||||
"MUser: " +
|
||||
Strings::FormatNanos(
|
||||
Sys::GetTraceRef("MUSR_" + name)->GetProtocol()->GetAverage()));
|
||||
}
|
||||
|
||||
void UI7::Menu::Update(float delta) {
|
||||
TT::Scope st("MUPT_" + name);
|
||||
this->back->BaseLayer(30);
|
||||
this->back->Process();
|
||||
this->main->BaseLayer(40);
|
||||
this->main->Process();
|
||||
this->front->BaseLayer(50);
|
||||
this->front->Process();
|
||||
}
|
||||
|
||||
void UI7::Menu::CursorMove(const vec2& size) {
|
||||
last_size = size;
|
||||
slcursor = cursor + vec2(size[0] + 5, 0);
|
||||
if (bslpos[1]) {
|
||||
cursor = vec2(5, cursor[1] + bslpos[1] + 5);
|
||||
bslpos = vec2();
|
||||
} else {
|
||||
cursor = vec2(5, cursor[1] + size[1] + 5);
|
||||
}
|
||||
max = vec2(slcursor[0], cursor[1]);
|
||||
}
|
||||
|
||||
void UI7::Menu::PreHandler(UI7MenuFlags flags) {
|
||||
TT::Scope st("MPRE_" + name);
|
||||
TT::Beg("MUSR_" + name);
|
||||
Cursor(vec2(5, 5));
|
||||
this->flags = flags;
|
||||
this->scrolling[0] = flags & UI7MenuFlags_HzScrolling;
|
||||
this->scrolling[1] = flags & UI7MenuFlags_VtScrolling;
|
||||
has_touch = main->GetRenderer()->CurrentScreen() == Screen::Bottom;
|
||||
if (!(flags & UI7MenuFlags_NoBackground)) {
|
||||
back->AddRectangle(0, view_area.zw(), UI7Color_Background);
|
||||
}
|
||||
if (!(flags & UI7MenuFlags_NoTitlebar)) {
|
||||
tbh = front->GetRenderer()->TextScale() * 30.f;
|
||||
front->AddRectangle(0, vec2(view_area.z(), tbh),
|
||||
linked_theme->Get(UI7Color_Header));
|
||||
vec2 tpos(5, tbh * 0.5 - front->ren->GetTextDimensions(name).y() * 0.5);
|
||||
LITextFlags tflags = LITextFlags_None;
|
||||
if (flags & UI7MenuFlags_CenterTitle) {
|
||||
tpos = 0;
|
||||
tflags = LITextFlags_AlignMid;
|
||||
}
|
||||
front->AddText(tpos, this->name, linked_theme->Get(UI7Color_Text), tflags,
|
||||
vec2(view_area.z(), tbh));
|
||||
Cursor(vec2(5, tbh + 5));
|
||||
}
|
||||
}
|
||||
|
||||
void UI7::Menu::PostHandler() {
|
||||
TT::Scope st("MPOS_" + name);
|
||||
if (scrolling[1]) {
|
||||
scroll_allowed[1] = (max[1] > 235);
|
||||
scrollbar[1] = scroll_allowed[1];
|
||||
|
||||
if (scrollbar[1]) {
|
||||
/// Setup Some Variables hare [they are self described]
|
||||
int screen_w = view_area.z();
|
||||
int tsp = 5 + tbh;
|
||||
int slider_w = 4;
|
||||
int szs = view_area.w() - tsp - 5;
|
||||
/// Actually dont have a Horizontal bar yet
|
||||
if (scrollbar[0]) szs -= slider_w - 2;
|
||||
int lslider_h = 20; // Dont go less heigt for the drag
|
||||
float slider_h = (szs - 4) * (float(szs - 4) / max[1]);
|
||||
/// Visual Slider Height (How it looks in the end)
|
||||
int vslider_h = std::clamp(slider_h, float(lslider_h), float(szs - 4));
|
||||
|
||||
/// Check if we overscroll to the bottom and Auto scroll back...
|
||||
/// Probably schould use Tween ENgine here
|
||||
if (scrolling_off[1] > max[1] - view_area[3] && max[1] != 0.f &&
|
||||
max[1] >= view_area[3] - 5) {
|
||||
scrolling_off[1] -= 3.f;
|
||||
if (scrolling_off[1] < max[1] - view_area[3]) {
|
||||
scrolling_off[1] = max[1] - view_area[3];
|
||||
}
|
||||
}
|
||||
|
||||
/// Do the Same as above just for Overscroll back to the top
|
||||
if (scrolling_off[1] < 0) {
|
||||
scrolling_off[1] += 3.f;
|
||||
if (scrolling_off[1] > 0) {
|
||||
scrolling_off[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Dont overscroll to much
|
||||
if (scrolling_off[1] < -40 ||
|
||||
scrolling_off[1] > max[1] - view_area[3] + 40) {
|
||||
scroll_mod[1] = 0.f;
|
||||
}
|
||||
|
||||
/// The pain :(
|
||||
if (has_touch) {
|
||||
vec2 tpos = inp->TouchPos();
|
||||
if (inp->IsDown(inp->Touch)) {
|
||||
mouse = tpos;
|
||||
} else if (inp->IsUp(inp->Touch)) {
|
||||
mouse = vec2();
|
||||
}
|
||||
if (inp->IsHeld(inp->Touch)) {
|
||||
if (!front->ren->InBox(tpos, vec4(view_area[2] - 13, tbh + 5, 8,
|
||||
view_area[3] - tbh - 10))) {
|
||||
if (scrolling_off[1] < max[1] - view_area[3] + 40 &&
|
||||
scrolling_off[1] > -40) {
|
||||
/// Cursor Mod
|
||||
float cm = mouse[1] - tpos[1];
|
||||
if (scroll_mod[1] <= 4.f && scroll_mod[1] >= -4.f && cm != 0) {
|
||||
scroll_mod[1] = cm;
|
||||
}
|
||||
}
|
||||
mouse = tpos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Effect
|
||||
if (scroll_mod[1] != 0) {
|
||||
scrolling_off[1] += scroll_mod[1];
|
||||
}
|
||||
if (scroll_mod[1] < 0.f) {
|
||||
scroll_mod[1] += 0.4f;
|
||||
if (scroll_mod[1] > 0.f) {
|
||||
scroll_mod[1] = 0;
|
||||
}
|
||||
}
|
||||
if (scroll_mod[1] > 0.f) {
|
||||
scroll_mod[1] -= 0.4f;
|
||||
if (scroll_mod[1] < 0.f) {
|
||||
scroll_mod[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int srpos =
|
||||
tsp + std::clamp(float(szs - vslider_h - 4) *
|
||||
(scrolling_off[1] / (max[1] - view_area[3])),
|
||||
0.f, float(szs - vslider_h - 4));
|
||||
|
||||
/// Rendering Stage
|
||||
front->AddRectangle(vec2(screen_w - 12, tsp), vec2(slider_w * 2, szs),
|
||||
linked_theme->Get(UI7Color_FrameBackground));
|
||||
front->AddRectangle(vec2(screen_w - 10, tsp + 2), vec2(slider_w, szs - 4),
|
||||
linked_theme->Get(UI7Color_FrameBackgroundHovered));
|
||||
front->AddRectangle(vec2(screen_w - 10, srpos + 2),
|
||||
vec2(slider_w, vslider_h),
|
||||
linked_theme->Get(UI7Color_Button));
|
||||
}
|
||||
}
|
||||
TT::End("MUSR_" + name);
|
||||
}
|
||||
|
||||
void UI7::Menu::SameLine() {
|
||||
bslpos = last_size;
|
||||
cursor = slcursor;
|
||||
}
|
||||
|
||||
void UI7::Menu::Separator() {
|
||||
vec2 pos = Cursor();
|
||||
vec2 size = vec2(view_area.z() - (scrollbar[1] ? 24 : 10), 1);
|
||||
CursorMove(size);
|
||||
if (HandleScrolling(pos, size)) {
|
||||
return;
|
||||
}
|
||||
main->AddRectangle(pos, size, linked_theme->Get(UI7Color_TextDead));
|
||||
}
|
||||
|
||||
void UI7::Menu::SeparatorText(const std::string& label) {
|
||||
vec2 size = vec2(view_area.z() - (scrollbar[1] ? 24 : 10), 1);
|
||||
vec2 tdim = this->back->GetRenderer()->GetTextDimensions(label);
|
||||
vec2 pos = Cursor();
|
||||
CursorMove(vec2(size.x(), tdim.y() - 4)); // Fix to make gap not to large
|
||||
|
||||
if (HandleScrolling(pos, size)) {
|
||||
return;
|
||||
}
|
||||
/// Label pos for better overview
|
||||
vec2 lpos = pos + vec2((view_area.z() - 10) * 0.5 - tdim.x() * 0.5, 0);
|
||||
main->AddRectangle(pos + vec2(0, tdim.y() * 0.5),
|
||||
vec2(lpos.x() - pos.x() - 5, size.y()),
|
||||
linked_theme->Get(UI7Color_TextDead));
|
||||
main->AddRectangle(pos + vec2(lpos.x() + tdim.x(), tdim.y() * 0.5),
|
||||
vec2(size.x() - (lpos.x() + tdim.x()), size.y()),
|
||||
linked_theme->Get(UI7Color_TextDead));
|
||||
main->AddText(lpos, label, linked_theme->Get(UI7Color_Text), 0,
|
||||
vec2(view_area.z(), 20));
|
||||
}
|
||||
|
||||
bool UI7::Menu::HandleScrolling(vec2& pos, const vec2& size) {
|
||||
if (scrolling[1]) {
|
||||
vec2 p = pos;
|
||||
pos -= vec2(0, scrolling_off.y());
|
||||
if (pos.y() > view_area.w() ||
|
||||
(pos.y() + size.y() < tbh - 5 && p.y() > tbh)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -10,12 +10,12 @@ void Theme::Default(Theme& theme) {
|
||||
theme.Set(UI7Color_Button, Color("#111111FF"));
|
||||
theme.Set(UI7Color_ButtonDead, Color("#080808FF"));
|
||||
theme.Set(UI7Color_ButtonActive, Color("#2A2A2AFF"));
|
||||
theme.Set(UI7Color_ButtonDisabled, Color("#222222FF"));
|
||||
theme.Set(UI7Color_ButtonHovered, Color("#222222FF"));
|
||||
theme.Set(UI7Color_Header, Color("#111111FF"));
|
||||
theme.Set(UI7Color_Selector, Color("#222222FF"));
|
||||
theme.Set(UI7Color_Checkmark, Color("#2A2A2AFF"));
|
||||
theme.Set(UI7Color_FrameBackground, Color("#555555FF"));
|
||||
theme.Set(UI7Color_FragmeBackgroundHovered, Color("#777777FF"));
|
||||
theme.Set(UI7Color_FrameBackgroundHovered, Color("#777777FF"));
|
||||
theme.Set(UI7Color_Progressbar, Color("#00FF00FF"));
|
||||
theme.Set(UI7Color_ListEven, Color("#CCCCCCFF"));
|
||||
theme.Set(UI7Color_ListOdd, Color("#BBBBBBFF"));
|
||||
|
@ -0,0 +1,52 @@
|
||||
#include <pd/common/timetrace.hpp>
|
||||
#include <pd/ui7/ui7.hpp>
|
||||
|
||||
namespace PD {
|
||||
bool UI7::Context::BeginMenu(const ID& id, UI7MenuFlags flags) {
|
||||
Assert(!this->current, "You are already in another Menu!");
|
||||
Assert(std::find(amenus.begin(), amenus.end(), (u32)id) == amenus.end(),
|
||||
"Menu Name Already used or\nContext::Update not called!");
|
||||
auto menu = this->menus.find(id);
|
||||
if (menu == this->menus.end()) {
|
||||
this->menus[id] = Menu::New(id, &theme, inp);
|
||||
menu = this->menus.find(id);
|
||||
}
|
||||
this->current = menu->second;
|
||||
if (!this->current->BackList()) {
|
||||
this->current->BackList(DrawList::New(ren));
|
||||
}
|
||||
if (!this->current->MainList()) {
|
||||
this->current->MainList(DrawList::New(ren));
|
||||
}
|
||||
if (!this->current->FrontList()) {
|
||||
this->current->FrontList(DrawList::New(ren));
|
||||
}
|
||||
this->current->ViewArea(this->ren->GetViewport());
|
||||
this->current->PreHandler(flags);
|
||||
amenus.push_back(this->current->GetID());
|
||||
return true;
|
||||
}
|
||||
|
||||
UI7::Menu::Ref UI7::Context::GetCurrentMenu() {
|
||||
Assert(current != nullptr, "Not in a Menu!");
|
||||
return current;
|
||||
}
|
||||
|
||||
void UI7::Context::EndMenu() {
|
||||
this->current->PostHandler();
|
||||
this->current = nullptr;
|
||||
}
|
||||
|
||||
void UI7::Context::Update(float delta) {
|
||||
TT::Scope st("UI7_Update");
|
||||
Assert(current == nullptr, "Still in a Menu!");
|
||||
this->back->BaseLayer(10);
|
||||
this->back->Process();
|
||||
for (auto it : amenus) {
|
||||
menus[it]->Update(delta);
|
||||
}
|
||||
this->front->BaseLayer(60);
|
||||
this->front->Process();
|
||||
this->amenus.clear();
|
||||
}
|
||||
} // namespace PD
|
@ -27,54 +27,82 @@ SOFTWARE.
|
||||
#include <pd.hpp>
|
||||
#include <pd/maths/tween.hpp>
|
||||
|
||||
using vec2 = PD::vec2;
|
||||
using vec3 = PD::vec3;
|
||||
using vec4 = PD::vec4;
|
||||
|
||||
class Test : public PD::App {
|
||||
public:
|
||||
Test() = default;
|
||||
~Test() = default;
|
||||
|
||||
void Init() override {
|
||||
ren = Renderer();
|
||||
inp = Input();
|
||||
test = PD::Texture::New("romfs:/icon.png");
|
||||
Overlays()->Push(PD::New<PD::Performance>(dbg, dbg_screen));
|
||||
// Performance Overlay freezes N3DS
|
||||
// Overlays()->Push(PD::New<PD::Performance>(dbg, dbg_screen));
|
||||
font = PD::LI::Font::New();
|
||||
// font->LoadSystemFont();
|
||||
font->LoadTTF("romfs:/ComicNeue.ttf", 32);
|
||||
Renderer()->Font(font);
|
||||
ui7 = PD::UI7::Context::New();
|
||||
// font->LoadTTF("romfs:/fonts/ComicNeue.ttf", 32);
|
||||
font->LoadTTF("romfs:/fonts/JetBrainsMono-Medium.ttf", 32);
|
||||
ren->Font(font);
|
||||
ui7 = PD::UI7::Context::New(ren, inp);
|
||||
}
|
||||
|
||||
bool MainLoop(float delta, float time) override {
|
||||
DrawFancyBG(time);
|
||||
Renderer()->OnScreen(PD::Screen::Bottom);
|
||||
Renderer()->DrawRectSolid(0, vec2(320, 240), PD::Color("#222222"));
|
||||
Renderer()->UseTex(test);
|
||||
Renderer()->Layer(Renderer()->Layer() + 1);
|
||||
Renderer()->DrawImage(
|
||||
Renderer()->GetViewport().zw() * 0.5 - test->GetSize() * 0.5, test);
|
||||
Renderer()->DrawText(5, 0xffffffff, "Hello World!", LITextFlags_None);
|
||||
if (Input()->IsDown(PD::Hid::Start)) {
|
||||
ren->OnScreen(PD::Screen::Bottom);
|
||||
// ren->DrawRectSolid(0, vec2(320, 240), PD::Color("#222222"));
|
||||
// ren->Layer(ren->Layer() + 1);
|
||||
// ren->DrawImage(ren->GetViewport().zw() * 0.5 - test->GetSize() * 0.5,
|
||||
// test); ren->DrawText(5, 0xffffffff, "Hello World!", LITextFlags_None);
|
||||
if (ui7->BeginMenu("Test",
|
||||
UI7MenuFlags_Scrolling | UI7MenuFlags_CenterTitle)) {
|
||||
auto m = ui7->GetCurrentMenu();
|
||||
m->SeparatorText("Menu Timings");
|
||||
m->DebugLabels();
|
||||
m->SeparatorText("Lithium Settings");
|
||||
FlagBox(m, "LI AST", PD::LI::RenderFlags_AST);
|
||||
FlagBox(m, "LI LRS", PD::LI::RenderFlags_LRS);
|
||||
FlagBox(m, "LI TMS", PD::LI::RenderFlags_TMS);
|
||||
m->SeparatorText("UI7 Tests");
|
||||
m->Label("This seems to be a label");
|
||||
m->Separator();
|
||||
m->Button("Button?");
|
||||
m->SeparatorText("SeparatorText");
|
||||
m->Checkbox("Test", cbtest);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
m->Label("Label: " + std::to_string(i));
|
||||
}
|
||||
ui7->EndMenu();
|
||||
}
|
||||
ui7->Update(delta);
|
||||
if (inp->IsDown(PD::Hid::Start)) {
|
||||
return false;
|
||||
}
|
||||
if (Input()->IsDown(Input()->A)) {
|
||||
if (inp->IsDown(inp->A)) {
|
||||
Overlays()->Push(PD::New<PD::Performance>(dbg, dbg_screen));
|
||||
Messages()->Push("Test", "Oder SO");
|
||||
// what.To(vec2(5, 200)).From(vec2(-100,
|
||||
// 200)).In(0.5).As(what.EaseInQuad);
|
||||
}
|
||||
if (Input()->IsUp(Input()->B)) {
|
||||
if (inp->IsUp(inp->B)) {
|
||||
Overlays()->Push(PD::New<PD::Keyboard>(text, state));
|
||||
// what.To(vec2(5, 180)).From(vec2(5, 200)).In(0.5).As(what.EaseOutQuad);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Deinit() override {}
|
||||
|
||||
void FlagBox(PD::UI7::Menu::Ref m, const std::string& label,
|
||||
PD::LI::RenderFlags flag) {
|
||||
bool has_flag = ren->GetFlags() & flag;
|
||||
m->Checkbox(label, has_flag);
|
||||
if (has_flag != (ren->GetFlags() & flag)) {
|
||||
if (has_flag) {
|
||||
ren->GetFlags() |= flag;
|
||||
} else {
|
||||
ren->GetFlags() &= ~flag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawFancyBG(float time) {
|
||||
Renderer()->DrawRect(vec2(0, 0), vec2(400, 240), 0xff64c9fd);
|
||||
ren->DrawRect(vec2(0, 0), vec2(400, 240), 0xff64c9fd);
|
||||
for (int i = 0; i < 44; i++) Append(i, vec2(0, 0), vec2(400, 240), time);
|
||||
}
|
||||
|
||||
@ -90,7 +118,7 @@ class Test : public PD::App {
|
||||
sin(offset + time) * 10 + 30;
|
||||
float color_effect = 1 - exp(-(index / 11) / 3.0f);
|
||||
|
||||
Renderer()->DrawTriangle(
|
||||
ren->DrawTriangle(
|
||||
vec2(x_position, y_position), vec2(x_position + 300, y_position + (90)),
|
||||
vec2(x_position - 300, y_position + (90)),
|
||||
PD::Color(.94f - .17f * color_effect, .61f - .25f * color_effect,
|
||||
@ -98,8 +126,13 @@ class Test : public PD::App {
|
||||
}
|
||||
|
||||
private:
|
||||
/// Shorter Acess to Renderer / Input
|
||||
PD::LI::Renderer::Ref ren;
|
||||
PD::Hid::Ref inp;
|
||||
/// Other Data
|
||||
PD::Texture::Ref test;
|
||||
bool dbg = false, dbg_screen = false;
|
||||
bool cbtest = true;
|
||||
std::string text;
|
||||
PD::Keyboard::State state;
|
||||
PD::UI7::Context::Ref ui7;
|
||||
@ -108,7 +141,7 @@ class Test : public PD::App {
|
||||
};
|
||||
|
||||
int main() {
|
||||
auto app = PD::New<Test>();
|
||||
app->Run();
|
||||
Test app;
|
||||
app.Run();
|
||||
return 0;
|
||||
}
|
93
test/romfs/fonts/ComicNeue.md
Normal file
93
test/romfs/fonts/ComicNeue.md
Normal file
@ -0,0 +1,93 @@
|
||||
Copyright 2014 The Comic Neue Project Authors (https://github.com/crozynski/comicneue)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
https://openfontlicense.org
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
BIN
test/romfs/fonts/JetBrainsMono-Medium.ttf
Normal file
BIN
test/romfs/fonts/JetBrainsMono-Medium.ttf
Normal file
Binary file not shown.
93
test/romfs/fonts/JetBrainsMono.txt
Normal file
93
test/romfs/fonts/JetBrainsMono.txt
Normal file
@ -0,0 +1,93 @@
|
||||
Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
https://openfontlicense.org
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
Loading…
Reference in New Issue
Block a user