initial commit
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ImXui {
|
||||
|
||||
|
||||
class FontEngine {
|
||||
public:
|
||||
FontEngine();
|
||||
~FontEngine();
|
||||
|
||||
|
||||
bool loadFontFile(const std::string& path);
|
||||
|
||||
|
||||
bool loadFontMemory(const void* data, size_t size);
|
||||
|
||||
|
||||
bool loadSystemFont(const std::string& requestedName);
|
||||
|
||||
bool isLoaded() const { return m_font != nullptr; }
|
||||
|
||||
|
||||
float measureText(const std::wstring& text, float sizePx) const;
|
||||
|
||||
|
||||
float lineHeight(float sizePx) const;
|
||||
|
||||
|
||||
bool renderText(const std::wstring& text, float sizePx,
|
||||
std::vector<uint8_t>& outRgba, int& outW, int& outH) const;
|
||||
|
||||
const std::string& getLoadedPath() const { return m_path; }
|
||||
|
||||
private:
|
||||
struct FontData;
|
||||
FontData* m_font;
|
||||
std::vector<uint8_t> m_blob;
|
||||
const void* m_blobPtr;
|
||||
size_t m_blobSize;
|
||||
std::string m_path;
|
||||
};
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,833 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include <cstdint>
|
||||
#include "XurFormat.h"
|
||||
|
||||
|
||||
namespace ImXui {
|
||||
|
||||
const float BASE_SCENE_WIDTH = 1280.0f;
|
||||
const float BASE_SCENE_HEIGHT = 720.0f;
|
||||
|
||||
enum AnchorStyle : uint32_t {
|
||||
AnchorNone = 0,
|
||||
AnchorLeft = 0x01,
|
||||
AnchorTop = 0x02,
|
||||
AnchorRight = 0x04,
|
||||
AnchorBottom = 0x08,
|
||||
AnchorCenterX = 0x10,
|
||||
AnchorCenterY = 0x20,
|
||||
};
|
||||
|
||||
enum class Result {
|
||||
Success = 0,
|
||||
Error_General = -1,
|
||||
Error_NotFound = -2,
|
||||
Error_InvalidParam = -3,
|
||||
Error_OutOfMemory = -4,
|
||||
Error_InvalidFile = -5,
|
||||
Error_NotImplemented = -6,
|
||||
};
|
||||
|
||||
struct Vec2 {
|
||||
Vec2() : x(0), y(0) {}
|
||||
Vec2(float x_, float y_) : x(x_), y(y_) {}
|
||||
float x, y;
|
||||
};
|
||||
struct Vec3 {
|
||||
Vec3() : x(0), y(0), z(0) {}
|
||||
Vec3(float x_, float y_, float z_) : x(x_), y(y_), z(z_) {}
|
||||
float x, y, z;
|
||||
};
|
||||
struct Rect {
|
||||
Rect() : x(0), y(0), w(0), h(0) {}
|
||||
Rect(float x_, float y_, float w_, float h_) : x(x_), y(y_), w(w_), h(h_) {}
|
||||
float x, y, w, h;
|
||||
float left() const { return x; }
|
||||
float top() const { return y; }
|
||||
float right() const { return x + w; }
|
||||
float bottom() const { return y + h; }
|
||||
Vec2 center() const { return Vec2(x + w * 0.5f, y + h * 0.5f); }
|
||||
};
|
||||
|
||||
struct Color {
|
||||
Color() : r(1.0f), g(1.0f), b(1.0f), a(1.0f) {}
|
||||
Color(float r_, float g_, float b_, float a_) : r(r_), g(g_), b(b_), a(a_) {}
|
||||
float r, g, b, a;
|
||||
};
|
||||
|
||||
class Value {
|
||||
public:
|
||||
enum Type {
|
||||
Null, Boolean, Number, StringUTF8, StringUTF16,
|
||||
};
|
||||
|
||||
Value() : m_type(Null), m_number(0.0), m_bool(false) {}
|
||||
explicit Value(bool v) : m_type(Boolean), m_number(0.0), m_bool(v) {}
|
||||
explicit Value(double v) : m_type(Number), m_number(v), m_bool(false) {}
|
||||
explicit Value(float v) : m_type(Number), m_number((double)v), m_bool(false) {}
|
||||
explicit Value(int v) : m_type(Number), m_number((double)v), m_bool(false) {}
|
||||
explicit Value(const char* utf8) : m_type(StringUTF8), m_number(0.0), m_bool(false), m_string8(utf8 ? utf8 : "") {}
|
||||
explicit Value(const std::string& utf8) : m_type(StringUTF8), m_number(0.0), m_bool(false), m_string8(utf8) {}
|
||||
explicit Value(const wchar_t* utf16) : m_type(StringUTF16), m_number(0.0), m_bool(false), m_string16(utf16 ? utf16 : L"") {}
|
||||
explicit Value(const std::wstring& utf16) : m_type(StringUTF16), m_number(0.0), m_bool(false), m_string16(utf16) {}
|
||||
|
||||
Type type() const { return m_type; }
|
||||
bool isNull() const { return m_type == Null; }
|
||||
bool isBool() const { return m_type == Boolean; }
|
||||
bool isNumber() const { return m_type == Number; }
|
||||
bool isString() const { return m_type == StringUTF8 || m_type == StringUTF16; }
|
||||
|
||||
bool toBool() const { return m_type == Boolean ? m_bool : false; }
|
||||
double toNumber() const { return m_type == Number ? m_number : 0.0; }
|
||||
float toFloat() const { return (float)toNumber(); }
|
||||
int toInt() const { return (int)toNumber(); }
|
||||
const std::string& toString8() const { return m_string8; }
|
||||
const std::wstring& toString16() const { return m_string16; }
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
double m_number;
|
||||
bool m_bool;
|
||||
std::string m_string8;
|
||||
std::wstring m_string16;
|
||||
};
|
||||
|
||||
enum class EventType {
|
||||
None, Press, Release, FocusGained, FocusLost,
|
||||
ValueChanged, SelectionChanged, SliderMove,
|
||||
MouseEnter, MouseLeave, AnimationEnd,
|
||||
};
|
||||
|
||||
class Element;
|
||||
class Control;
|
||||
class Scene;
|
||||
class Canvas;
|
||||
class Application;
|
||||
|
||||
typedef std::function<Result(Scene*, void*)> InitCallback;
|
||||
typedef std::function<Result(Scene*, uint32_t)> TimerCallback;
|
||||
typedef std::function<Result(Scene*, uint32_t key, bool down)> InputCallback;
|
||||
typedef std::function<void(Scene*, void* region)> DrawCallback;
|
||||
typedef std::function<Value(const std::vector<Value>&)> MethodCallback;
|
||||
|
||||
class Element {
|
||||
public:
|
||||
Element();
|
||||
virtual ~Element();
|
||||
|
||||
void setId(const std::wstring& id) { m_id = id; }
|
||||
const std::wstring& getId() const { return m_id; }
|
||||
void setClassName(const std::wstring& name) { m_className = name; }
|
||||
const std::wstring& getClassName() const { return m_className; }
|
||||
|
||||
void setParent(Element* parent) { m_parent = parent; }
|
||||
Element* getParent() const { return m_parent; }
|
||||
Element* getChildById(const std::wstring& id);
|
||||
Element* findFirstChild(const std::wstring& id);
|
||||
|
||||
void setPosition(const Vec3& pos) { m_position = pos; markLayoutDirty(); }
|
||||
Vec3 getPosition() const { return m_position; }
|
||||
void setBounds(float w, float h) { m_bounds.w = w; m_bounds.h = h; markLayoutDirty(); }
|
||||
Vec2 getBounds() const { return Vec2(m_bounds.w, m_bounds.h); }
|
||||
|
||||
void setAnchor(uint32_t anchor) { m_anchor = anchor; markLayoutDirty(); }
|
||||
uint32_t getAnchor() const { return m_anchor; }
|
||||
Rect getComputedRect() const { return m_computedRect; }
|
||||
void markLayoutDirty() { m_layoutDirty = true; }
|
||||
bool isLayoutDirty() const { return m_layoutDirty; }
|
||||
void computeLayout(Rect parentRect);
|
||||
void computeLayout() { computeLayout(Rect(0, 0, 1280, 720)); }
|
||||
|
||||
void setShow(bool show) { m_visible = show; }
|
||||
bool isShown() const { return m_visible; }
|
||||
|
||||
void setOpacity(float opacity) { m_opacity = opacity; }
|
||||
float getOpacity() const { return m_opacity; }
|
||||
|
||||
void setScale(const Vec3& scale) { m_scale = scale; }
|
||||
Vec3 getScale() const { return m_scale; }
|
||||
|
||||
void setPivot(const Vec3& pivot) { m_pivot = pivot; }
|
||||
Vec3 getPivot() const { return m_pivot; }
|
||||
|
||||
void setRotation(const Vec3& rotation) { m_rotation = rotation; }
|
||||
Vec3 getRotation() const { return m_rotation; }
|
||||
|
||||
void setBlendMode(uint32_t mode) { m_blendMode = mode; }
|
||||
uint32_t getBlendMode() const { return m_blendMode; }
|
||||
|
||||
void setClipChildren(bool clip) { m_clipChildren = clip; }
|
||||
bool getClipChildren() const { return m_clipChildren; }
|
||||
|
||||
void setHittable(bool hittable) { m_hittable = hittable; }
|
||||
bool isHittable() const { return m_hittable; }
|
||||
|
||||
void setLayoutLineBreak(bool lb) { m_layoutLineBreak = lb; markLayoutDirty(); }
|
||||
bool getLayoutLineBreak() const { return m_layoutLineBreak; }
|
||||
|
||||
void setLayoutFloat(bool lf) { m_layoutFloat = lf; markLayoutDirty(); }
|
||||
bool getLayoutFloat() const { return m_layoutFloat; }
|
||||
|
||||
void setColumn(uint32_t col) { m_column = col; markLayoutDirty(); }
|
||||
uint32_t getColumn() const { return m_column; }
|
||||
void setRow(uint32_t row) { m_row = row; markLayoutDirty(); }
|
||||
uint32_t getRow() const { return m_row; }
|
||||
void setColumnSpan(uint32_t span) { m_columnSpan = span; markLayoutDirty(); }
|
||||
uint32_t getColumnSpan() const { return m_columnSpan; }
|
||||
void setRowSpan(uint32_t span) { m_rowSpan = span; markLayoutDirty(); }
|
||||
uint32_t getRowSpan() const { return m_rowSpan; }
|
||||
|
||||
void setColorFactor(const Color& c) { m_colorFactor = c; }
|
||||
Color getColorFactor() const { return m_colorFactor; }
|
||||
|
||||
void setImagePath(const std::wstring& path) { m_imagePath = path; }
|
||||
const std::wstring& getImagePath() const { return m_imagePath; }
|
||||
|
||||
void addChild(std::unique_ptr<Element> child);
|
||||
bool removeChildById(const std::wstring& id);
|
||||
const std::vector<std::unique_ptr<Element>>& getChildren() const { return m_children; }
|
||||
|
||||
virtual void onEvent(EventType type, const std::vector<Value>& args);
|
||||
virtual bool isControl() const { return false; }
|
||||
|
||||
protected:
|
||||
std::wstring m_id;
|
||||
std::wstring m_className;
|
||||
Element* m_parent;
|
||||
std::vector<std::unique_ptr<Element>> m_children;
|
||||
|
||||
Vec3 m_position;
|
||||
Rect m_bounds;
|
||||
Vec3 m_scale;
|
||||
Vec3 m_pivot;
|
||||
Vec3 m_rotation;
|
||||
float m_opacity;
|
||||
bool m_visible;
|
||||
Color m_colorFactor;
|
||||
std::wstring m_imagePath;
|
||||
|
||||
uint32_t m_anchor;
|
||||
uint32_t m_blendMode;
|
||||
bool m_clipChildren;
|
||||
bool m_hittable;
|
||||
bool m_layoutLineBreak;
|
||||
bool m_layoutFloat;
|
||||
uint32_t m_column;
|
||||
uint32_t m_row;
|
||||
uint32_t m_columnSpan;
|
||||
uint32_t m_rowSpan;
|
||||
Rect m_computedRect;
|
||||
bool m_layoutDirty;
|
||||
|
||||
|
||||
bool m_isNineGrid;
|
||||
uint32_t m_nineGridLeft;
|
||||
uint32_t m_nineGridTop;
|
||||
uint32_t m_nineGridRight;
|
||||
uint32_t m_nineGridBottom;
|
||||
bool m_nineGridNoCenter;
|
||||
std::wstring m_nineGridTexture;
|
||||
|
||||
|
||||
bool m_isFigure;
|
||||
bool m_figureClosed;
|
||||
uint32_t m_figureFillType;
|
||||
Color m_figureFillColor;
|
||||
std::wstring m_figureFillTexture;
|
||||
float m_figureFillRotation;
|
||||
Vec2 m_figureFillTranslation;
|
||||
Vec2 m_figureFillScale;
|
||||
uint32_t m_figureFillWrapX;
|
||||
uint32_t m_figureFillWrapY;
|
||||
float m_figureStrokeWidth;
|
||||
Color m_figureStrokeColor;
|
||||
std::vector<Vec2> m_figurePoints;
|
||||
|
||||
public:
|
||||
|
||||
void setIsNineGrid(bool v) { m_isNineGrid = v; }
|
||||
bool getIsNineGrid() const { return m_isNineGrid; }
|
||||
void setNineGridLeft(uint32_t v) { m_nineGridLeft = v; }
|
||||
uint32_t getNineGridLeft() const { return m_nineGridLeft; }
|
||||
void setNineGridTop(uint32_t v) { m_nineGridTop = v; }
|
||||
uint32_t getNineGridTop() const { return m_nineGridTop; }
|
||||
void setNineGridRight(uint32_t v) { m_nineGridRight = v; }
|
||||
uint32_t getNineGridRight() const { return m_nineGridRight; }
|
||||
void setNineGridBottom(uint32_t v) { m_nineGridBottom = v; }
|
||||
uint32_t getNineGridBottom() const { return m_nineGridBottom; }
|
||||
void setNineGridNoCenter(bool v) { m_nineGridNoCenter = v; }
|
||||
bool getNineGridNoCenter() const { return m_nineGridNoCenter; }
|
||||
void setNineGridTexture(const std::wstring& v) { m_nineGridTexture = v; }
|
||||
const std::wstring& getNineGridTexture() const { return m_nineGridTexture; }
|
||||
|
||||
|
||||
void setIsFigure(bool v) { m_isFigure = v; }
|
||||
bool getIsFigure() const { return m_isFigure; }
|
||||
void setFigureClosed(bool v) { m_figureClosed = v; }
|
||||
bool getFigureClosed() const { return m_figureClosed; }
|
||||
void setFigureFillType(uint32_t v) { m_figureFillType = v; }
|
||||
uint32_t getFigureFillType() const { return m_figureFillType; }
|
||||
void setFigureFillColor(const Color& c) { m_figureFillColor = c; }
|
||||
Color getFigureFillColor() const { return m_figureFillColor; }
|
||||
void setFigureFillTexture(const std::wstring& v) { m_figureFillTexture = v; }
|
||||
const std::wstring& getFigureFillTexture() const { return m_figureFillTexture; }
|
||||
void setFigureFillRotation(float v) { m_figureFillRotation = v; }
|
||||
float getFigureFillRotation() const { return m_figureFillRotation; }
|
||||
void setFigureFillTranslation(const Vec2& v) { m_figureFillTranslation = v; }
|
||||
Vec2 getFigureFillTranslation() const { return m_figureFillTranslation; }
|
||||
void setFigureFillScale(const Vec2& v) { m_figureFillScale = v; }
|
||||
Vec2 getFigureFillScale() const { return m_figureFillScale; }
|
||||
void setFigureFillWrapX(uint32_t v) { m_figureFillWrapX = v; }
|
||||
uint32_t getFigureFillWrapX() const { return m_figureFillWrapX; }
|
||||
void setFigureFillWrapY(uint32_t v) { m_figureFillWrapY = v; }
|
||||
uint32_t getFigureFillWrapY() const { return m_figureFillWrapY; }
|
||||
void setFigureStrokeWidth(float v) { m_figureStrokeWidth = v; }
|
||||
float getFigureStrokeWidth() const { return m_figureStrokeWidth; }
|
||||
void setFigureStrokeColor(const Color& c) { m_figureStrokeColor = c; }
|
||||
Color getFigureStrokeColor() const { return m_figureStrokeColor; }
|
||||
void setFigurePoints(const std::vector<Vec2>& pts) { m_figurePoints = pts; }
|
||||
const std::vector<Vec2>& getFigurePoints() const { return m_figurePoints; }
|
||||
};
|
||||
|
||||
class Control : public Element {
|
||||
public:
|
||||
Control();
|
||||
explicit Control(const std::wstring& id);
|
||||
~Control();
|
||||
|
||||
bool isControl() const override { return true; }
|
||||
|
||||
void setText(const std::wstring& text) { m_text = text; }
|
||||
const std::wstring& getText() const { return m_text; }
|
||||
void setFontName(const std::wstring& name) { m_fontName = name; }
|
||||
const std::wstring& getFontName() const { return m_fontName; }
|
||||
void setFontSize(float size) { m_fontSize = size; }
|
||||
float getFontSize() const { return m_fontSize; }
|
||||
|
||||
void setEnable(bool enable) { m_enabled = enable; }
|
||||
bool isEnabled() const { return m_enabled; }
|
||||
|
||||
void setFocused(bool focused);
|
||||
bool isFocused() const { return m_focused; }
|
||||
|
||||
virtual void press();
|
||||
void setOnPressCallback(const std::function<void()>& cb) { m_onPress = cb; }
|
||||
|
||||
virtual void onFocusGained();
|
||||
virtual void onFocusLost();
|
||||
void setOnFocusCallback(const std::function<void(bool)>& cb) { m_onFocus = cb; }
|
||||
|
||||
virtual void onValueChanged(const Value& newValue);
|
||||
void setOnValueChangedCallback(const std::function<void(const Value&)>& cb) { m_onValueChanged = cb; }
|
||||
|
||||
virtual void onSelectionChanged(int newSelection);
|
||||
void setOnSelectionChangedCallback(const std::function<void(int)>& cb) { m_onSelectionChanged = cb; }
|
||||
|
||||
void setVisual(const std::wstring& visual) { m_visual = visual; }
|
||||
const std::wstring& getVisual() const { return m_visual; }
|
||||
|
||||
void setProgressValue(int value) { m_progressValue = value; }
|
||||
int getProgressValue() const { return m_progressValue; }
|
||||
void setProgressRange(int min, int max) { m_progressMin = min; m_progressMax = max; }
|
||||
int getProgressMin() const { return m_progressMin; }
|
||||
int getProgressMax() const { return m_progressMax; }
|
||||
float getProgress() const {
|
||||
if (m_progressMax <= m_progressMin) return 0;
|
||||
return (float)(m_progressValue - m_progressMin) / (float)(m_progressMax - m_progressMin);
|
||||
}
|
||||
|
||||
void setNavUp(const std::wstring& id) { m_navUp = id; }
|
||||
const std::wstring& getNavUp() const { return m_navUp; }
|
||||
void setNavDown(const std::wstring& id) { m_navDown = id; }
|
||||
const std::wstring& getNavDown() const { return m_navDown; }
|
||||
void setNavLeft(const std::wstring& id) { m_navLeft = id; }
|
||||
const std::wstring& getNavLeft() const { return m_navLeft; }
|
||||
void setNavRight(const std::wstring& id) { m_navRight = id; }
|
||||
const std::wstring& getNavRight() const { return m_navRight; }
|
||||
void setNavTabForward(const std::wstring& id) { m_navTabForward = id; }
|
||||
const std::wstring& getNavTabForward() const { return m_navTabForward; }
|
||||
void setNavTabBackward(const std::wstring& id) { m_navTabBackward = id; }
|
||||
const std::wstring& getNavTabBackward() const { return m_navTabBackward; }
|
||||
|
||||
void setPressKey(uint32_t key) { m_pressKey = key; }
|
||||
uint32_t getPressKey() const { return m_pressKey; }
|
||||
void setPressAnimObject(const std::wstring& name) { m_pressAnimObject = name; }
|
||||
const std::wstring& getPressAnimObject() const { return m_pressAnimObject; }
|
||||
void setFocusAnimObject(const std::wstring& name) { m_focusAnimObject = name; }
|
||||
const std::wstring& getFocusAnimObject() const { return m_focusAnimObject; }
|
||||
|
||||
void setStep(int step) { m_step = step; }
|
||||
int getStep() const { return m_step; }
|
||||
void setVertical(bool vert) { m_vertical = vert; }
|
||||
bool isVertical() const { return m_vertical; }
|
||||
void setAccelInc(int inc) { m_accelInc = inc; }
|
||||
int getAccelInc() const { return m_accelInc; }
|
||||
void setAccelTime(uint32_t time) { m_accelTime = time; }
|
||||
uint32_t getAccelTime() const { return m_accelTime; }
|
||||
|
||||
virtual Value getProperty(const std::wstring& name);
|
||||
virtual bool setProperty(const std::wstring& name, const Value& value);
|
||||
|
||||
void setUserData(void* data) { m_userData = data; }
|
||||
void* getUserData() const { return m_userData; }
|
||||
|
||||
void onEvent(EventType type, const std::vector<Value>& args) override;
|
||||
|
||||
void setCustomDrawId(const std::wstring& id) { m_customDrawId = id; }
|
||||
const std::wstring& getCustomDrawId() const { return m_customDrawId; }
|
||||
|
||||
Control* getNavTarget(int direction) const;
|
||||
|
||||
protected:
|
||||
std::wstring m_text;
|
||||
std::wstring m_fontName;
|
||||
float m_fontSize;
|
||||
std::wstring m_visual;
|
||||
std::wstring m_customDrawId;
|
||||
bool m_enabled;
|
||||
bool m_focused;
|
||||
int m_progressValue;
|
||||
int m_progressMin;
|
||||
int m_progressMax;
|
||||
void* m_userData;
|
||||
|
||||
std::wstring m_navUp;
|
||||
std::wstring m_navDown;
|
||||
std::wstring m_navLeft;
|
||||
std::wstring m_navRight;
|
||||
std::wstring m_navTabForward;
|
||||
std::wstring m_navTabBackward;
|
||||
|
||||
uint32_t m_pressKey;
|
||||
std::wstring m_pressAnimObject;
|
||||
std::wstring m_focusAnimObject;
|
||||
|
||||
int m_step;
|
||||
bool m_vertical;
|
||||
int m_accelInc;
|
||||
uint32_t m_accelTime;
|
||||
|
||||
std::function<void()> m_onPress;
|
||||
std::function<void(bool)> m_onFocus;
|
||||
std::function<void(const Value&)> m_onValueChanged;
|
||||
std::function<void(int)> m_onSelectionChanged;
|
||||
};
|
||||
|
||||
class Scene {
|
||||
public:
|
||||
Scene();
|
||||
virtual ~Scene();
|
||||
|
||||
virtual Result onCreate(void* initData = nullptr);
|
||||
virtual Result onDestroy();
|
||||
virtual Result onTick(float deltaTime);
|
||||
virtual Result onKeyDown(uint32_t key);
|
||||
virtual Result onKeyUp(uint32_t key);
|
||||
virtual Result onTimer(uint32_t timerId);
|
||||
virtual Result onTransitionStart(uint32_t transAction, uint32_t transType);
|
||||
virtual Result onGetSourceText(int dataIndex, std::wstring& outText);
|
||||
virtual Result onGetSourceImage(int dataIndex, std::wstring& outImagePath);
|
||||
virtual Result onGetItemCount(int& outCount);
|
||||
virtual Result onGetItemEnable(int itemIndex, bool& outEnabled);
|
||||
|
||||
Element* getRootElement() const { return m_root.get(); }
|
||||
Control* findControl(const std::wstring& id);
|
||||
Element* findElement(const std::wstring& id);
|
||||
Element* findElementRecursive(Element* root, const std::wstring& id);
|
||||
|
||||
void setClassOverride(const std::wstring& className) { m_className = className; }
|
||||
const std::wstring& getClassOverride() const { return m_className; }
|
||||
|
||||
void addSubScene(std::unique_ptr<Scene> subScene);
|
||||
Scene* findSubScene(const std::wstring& id);
|
||||
|
||||
void setDisplaySize(float width, float height);
|
||||
float getDisplayWidth() const { return m_displayWidth; }
|
||||
float getDisplayHeight() const { return m_displayHeight; }
|
||||
|
||||
void setMovieWidth(float w) { m_movieWidth = w; }
|
||||
float getMovieWidth() const { return m_movieWidth; }
|
||||
void setMovieHeight(float h) { m_movieHeight = h; }
|
||||
float getMovieHeight() const { return m_movieHeight; }
|
||||
void setFrameRate(float fps) { m_frameRate = fps; }
|
||||
float getFrameRate() const { return m_frameRate; }
|
||||
|
||||
void setUserData(void* data) { m_userData = data; }
|
||||
void* getUserData() const { return m_userData; }
|
||||
|
||||
void setDefaultFocus(const std::wstring& id) { m_defaultFocus = id; }
|
||||
const std::wstring& getDefaultFocus() const { return m_defaultFocus; }
|
||||
|
||||
void addTimer(uint32_t id, int intervalMs);
|
||||
void killTimer(uint32_t id);
|
||||
void updateTimers(float deltaTime);
|
||||
|
||||
void sendMessage(uint32_t msgId, void* data, Element* source = nullptr);
|
||||
void broadcastMessage(uint32_t msgId, void* data, Element* source = nullptr);
|
||||
void setOnMessageCallback(const std::function<bool(uint32_t, void*, Element*)>& cb) { m_messageCallback = cb; }
|
||||
|
||||
void playTimeline(const std::wstring& elementName, int startFrame, int endFrame, bool loop, bool pause);
|
||||
void stopTimeline(const std::wstring& elementName, bool gotoEnd);
|
||||
int findNamedFrame(const std::wstring& elementName, const std::wstring& frameName);
|
||||
|
||||
void loadTimelines(const std::vector<XurFormat::XurTimeline>& timelines,
|
||||
const std::vector<XurFormat::XurNamedFrame>& namedFrames);
|
||||
void startTimeline(const std::wstring& elementName);
|
||||
|
||||
void updateAnimations(float deltaTime);
|
||||
|
||||
void setFocusedControl(Control* ctrl);
|
||||
Control* getFocusedControl() const { return m_focusedControl; }
|
||||
void navigateFocus(int direction);
|
||||
|
||||
virtual Value callMethod(const std::wstring& methodName, const std::vector<Value>& args);
|
||||
void registerMethod(const std::wstring& name, const MethodCallback& cb);
|
||||
|
||||
virtual void dispatchEvent(const std::wstring& targetId, EventType type, const std::vector<Value>& args);
|
||||
|
||||
typedef std::function<bool(const std::wstring& funcName, const std::vector<Value>& args)> ExternalCallback;
|
||||
void setExternalCallback(const ExternalCallback& cb) { m_externalCallback = cb; }
|
||||
|
||||
protected:
|
||||
std::unique_ptr<Element> m_root;
|
||||
std::wstring m_className;
|
||||
std::vector<std::unique_ptr<Scene>> m_subScenes;
|
||||
|
||||
struct TimerEntry {
|
||||
uint32_t id;
|
||||
int intervalMs;
|
||||
float accumulated;
|
||||
};
|
||||
std::vector<TimerEntry> m_timers;
|
||||
|
||||
float m_displayWidth;
|
||||
float m_displayHeight;
|
||||
float m_movieWidth;
|
||||
float m_movieHeight;
|
||||
float m_frameRate;
|
||||
void* m_userData;
|
||||
|
||||
std::wstring m_defaultFocus;
|
||||
std::wstring m_transTo;
|
||||
std::wstring m_transFrom;
|
||||
std::wstring m_transBackTo;
|
||||
std::wstring m_transBackFrom;
|
||||
bool m_ignorePresses;
|
||||
|
||||
Control* m_focusedControl;
|
||||
|
||||
std::unordered_map<std::wstring, MethodCallback> m_methods;
|
||||
ExternalCallback m_externalCallback;
|
||||
std::function<bool(uint32_t, void*, Element*)> m_messageCallback;
|
||||
|
||||
struct AnimationState {
|
||||
std::wstring elementName;
|
||||
int currentFrame;
|
||||
int startFrame;
|
||||
int endFrame;
|
||||
bool loop;
|
||||
bool paused;
|
||||
float timeAccum;
|
||||
struct KFProp {
|
||||
std::string name;
|
||||
XurFormat::XurPropertyValue value;
|
||||
};
|
||||
struct Keyframe {
|
||||
int time;
|
||||
uint8_t interpolation;
|
||||
uint8_t easeIn;
|
||||
uint8_t easeOut;
|
||||
std::vector<KFProp> properties;
|
||||
};
|
||||
std::vector<Keyframe> keyframes;
|
||||
};
|
||||
std::vector<AnimationState> m_animations;
|
||||
|
||||
struct NamedFrame {
|
||||
std::wstring name;
|
||||
int keyframe;
|
||||
uint32_t command;
|
||||
std::wstring targetParameter;
|
||||
};
|
||||
std::vector<NamedFrame> m_namedFrames;
|
||||
|
||||
struct TimelineData {
|
||||
std::wstring elementName;
|
||||
struct KFProperty {
|
||||
std::string name;
|
||||
XurFormat::XurPropertyValue value;
|
||||
};
|
||||
struct KeyframeData {
|
||||
int time;
|
||||
uint8_t interpolation;
|
||||
uint8_t easeIn;
|
||||
uint8_t easeOut;
|
||||
std::vector<KFProperty> properties;
|
||||
};
|
||||
std::vector<KeyframeData> keyframes;
|
||||
};
|
||||
std::vector<TimelineData> m_timelines;
|
||||
|
||||
struct TransitionState {
|
||||
bool active;
|
||||
float elapsed;
|
||||
float duration;
|
||||
std::wstring transType;
|
||||
std::wstring transScenePath;
|
||||
std::unique_ptr<Scene> transScene;
|
||||
};
|
||||
TransitionState m_transition;
|
||||
|
||||
void applyKeyframeProperty(Element* target, const AnimationState::KFProp& prop);
|
||||
void interpolateKeyframeProperty(Element* target,
|
||||
const AnimationState::KFProp& propA,
|
||||
const AnimationState::KFProp& propB,
|
||||
float t);
|
||||
|
||||
public:
|
||||
void setTransitionTo(const std::wstring& path) { m_transTo = path; }
|
||||
const std::wstring& getTransitionTo() const { return m_transTo; }
|
||||
void setTransitionFrom(const std::wstring& path) { m_transFrom = path; }
|
||||
const std::wstring& getTransitionFrom() const { return m_transFrom; }
|
||||
void setTransitionBackTo(const std::wstring& path) { m_transBackTo = path; }
|
||||
const std::wstring& getTransitionBackTo() const { return m_transBackTo; }
|
||||
void setTransitionBackFrom(const std::wstring& path) { m_transBackFrom = path; }
|
||||
const std::wstring& getTransitionBackFrom() const { return m_transBackFrom; }
|
||||
void setIgnorePresses(bool v) { m_ignorePresses = v; }
|
||||
bool getIgnorePresses() const { return m_ignorePresses; }
|
||||
|
||||
void startTransition(const std::wstring& type, float duration = 0.5f);
|
||||
void updateTransition(float deltaTime);
|
||||
bool isTransitioning() const { return m_transition.active; }
|
||||
float getTransitionProgress() const;
|
||||
Scene* getTransitionScene() const { return m_transition.transScene.get(); }
|
||||
|
||||
Value builtinSetAlpha(const std::vector<Value>& args);
|
||||
Value builtinSetFocus(const std::vector<Value>& args);
|
||||
Value builtinSetSafeZone(const std::vector<Value>& args);
|
||||
Value builtinRemoveObject(const std::vector<Value>& args);
|
||||
Value builtinSlideLeft(const std::vector<Value>& args);
|
||||
Value builtinSlideRight(const std::vector<Value>& args);
|
||||
Value builtinDoHorizontalResizeCheck(const std::vector<Value>& args);
|
||||
};
|
||||
|
||||
class Canvas {
|
||||
public:
|
||||
Canvas();
|
||||
~Canvas();
|
||||
|
||||
Result loadFromXui(const std::string& path);
|
||||
Result loadFromXuiString(const std::wstring& xmlContent);
|
||||
Result loadFromXur(const std::string& path);
|
||||
Result loadFromXurMemory(const void* data, size_t size);
|
||||
|
||||
float getWidth() const { return m_width; }
|
||||
float getHeight() const { return m_height; }
|
||||
|
||||
Scene* getScene() const { return m_scene.get(); }
|
||||
void setScene(std::unique_ptr<Scene> scene) { m_scene = std::move(scene); }
|
||||
|
||||
Result parseXuiXml(const std::wstring& xml);
|
||||
|
||||
private:
|
||||
float m_width;
|
||||
float m_height;
|
||||
std::unique_ptr<Scene> m_scene;
|
||||
|
||||
std::unique_ptr<Element> parseElementNode(const std::wstring& xml, size_t& pos);
|
||||
std::wstring readProperty(const std::wstring& xml, size_t& pos);
|
||||
};
|
||||
|
||||
typedef void* HXUIBRUSH;
|
||||
|
||||
class Brush {
|
||||
public:
|
||||
Brush();
|
||||
~Brush();
|
||||
|
||||
void setImagePath(const std::wstring& path) { m_imagePath = path; }
|
||||
const std::wstring& getImagePath() const { return m_imagePath; }
|
||||
void setColor(const Color& c) { m_color = c; }
|
||||
Color getColor() const { return m_color; }
|
||||
void setOpacity(float opacity) { m_opacity = opacity; }
|
||||
float getOpacity() const { return m_opacity; }
|
||||
|
||||
private:
|
||||
std::wstring m_imagePath;
|
||||
Color m_color;
|
||||
float m_opacity;
|
||||
};
|
||||
|
||||
class ProgressBar : public Control {
|
||||
public:
|
||||
ProgressBar();
|
||||
explicit ProgressBar(const std::wstring& id);
|
||||
~ProgressBar();
|
||||
|
||||
void setRange(int min, int max) { setProgressRange(min, max); }
|
||||
void setValue(int value) { setProgressValue(value); }
|
||||
int getValue() const { return getProgressValue(); }
|
||||
void getRange(int* min, int* max) const { *min = getProgressMin(); *max = getProgressMax(); }
|
||||
};
|
||||
|
||||
class Slider : public Control {
|
||||
public:
|
||||
Slider();
|
||||
explicit Slider(const std::wstring& id);
|
||||
~Slider();
|
||||
|
||||
void setRange(int min, int max) { setProgressRange(min, max); }
|
||||
void setValue(int value) { setProgressValue(value); }
|
||||
int getValue() const { return getProgressValue(); }
|
||||
void getRange(int* min, int* max) const { *min = getProgressMin(); *max = getProgressMax(); }
|
||||
void setStep(int step) { Control::setStep(step); }
|
||||
int getStep() const { return Control::getStep(); }
|
||||
void setVertical(bool vert) { Control::setVertical(vert); }
|
||||
bool isVertical() const { return Control::isVertical(); }
|
||||
};
|
||||
|
||||
struct ListItemInfo {
|
||||
std::wstring text;
|
||||
std::wstring imagePath;
|
||||
HXUIBRUSH brush;
|
||||
bool checked;
|
||||
bool enabled;
|
||||
int userData;
|
||||
int index;
|
||||
int sortIndex;
|
||||
|
||||
ListItemInfo() : brush(0), checked(false), enabled(true), userData(0), index(0), sortIndex(0) {}
|
||||
};
|
||||
|
||||
class List : public Control {
|
||||
public:
|
||||
List();
|
||||
explicit List(const std::wstring& id);
|
||||
~List();
|
||||
|
||||
void addItem(const ListItemInfo& item);
|
||||
void removeAllItems();
|
||||
void updateItemText(int item, const std::wstring& text);
|
||||
void updateItemGraphic(int item, HXUIBRUSH brush);
|
||||
void selectByUserData(int userData);
|
||||
int getIndexByUserData(int userData) const;
|
||||
ListItemInfo& getData(int index);
|
||||
ListItemInfo& getDataByUserData(int userData);
|
||||
int getItemCount() const { return (int)m_items.size(); }
|
||||
|
||||
void setSelectionChangedHandler(Control* handler) { m_selectionChangedHandler = handler; }
|
||||
void setWrap(bool wrap) { m_wrap = wrap; }
|
||||
bool getWrap() const { return m_wrap; }
|
||||
|
||||
void setOnGetSourceText(const std::function<std::wstring(int)>& cb) { m_onGetSourceText = cb; }
|
||||
void setOnGetSourceImage(const std::function<std::wstring(int)>& cb) { m_onGetSourceImage = cb; }
|
||||
void setOnGetItemCount(const std::function<int()>& cb) { m_onGetItemCount = cb; }
|
||||
void setOnGetItemEnable(const std::function<bool(int)>& cb) { m_onGetItemEnable = cb; }
|
||||
void setOnSelectionChanged(const std::function<void(int)>& cb) { m_onSelectionChangedIdx = cb; }
|
||||
|
||||
std::wstring getSourceText(int index);
|
||||
std::wstring getSourceImage(int index);
|
||||
bool getItemEnable(int index);
|
||||
|
||||
private:
|
||||
std::vector<ListItemInfo> m_items;
|
||||
Control* m_selectionChangedHandler;
|
||||
bool m_wrap;
|
||||
std::function<std::wstring(int)> m_onGetSourceText;
|
||||
std::function<std::wstring(int)> m_onGetSourceImage;
|
||||
std::function<int()> m_onGetItemCount;
|
||||
std::function<bool(int)> m_onGetItemEnable;
|
||||
std::function<void(int)> m_onSelectionChangedIdx;
|
||||
};
|
||||
|
||||
class Sound : public Element {
|
||||
public:
|
||||
Sound();
|
||||
~Sound();
|
||||
|
||||
void play();
|
||||
void stop();
|
||||
|
||||
void setCue(const std::wstring& cue) { m_cue = cue; }
|
||||
const std::wstring& getCue() const { return m_cue; }
|
||||
void setSoundBank(const std::wstring& bank) { m_soundBank = bank; }
|
||||
const std::wstring& getSoundBank() const { return m_soundBank; }
|
||||
void setWaveBank(const std::wstring& bank) { m_waveBank = bank; }
|
||||
const std::wstring& getWaveBank() const { return m_waveBank; }
|
||||
void setVolume(float vol) { m_volume = vol; }
|
||||
float getVolume() const { return m_volume; }
|
||||
void setLoop(bool loop) { m_loop = loop; }
|
||||
bool getLoop() const { return m_loop; }
|
||||
|
||||
private:
|
||||
std::wstring m_cue;
|
||||
std::wstring m_soundBank;
|
||||
std::wstring m_waveBank;
|
||||
float m_volume;
|
||||
bool m_loop;
|
||||
};
|
||||
|
||||
class ElementImplBase {
|
||||
public:
|
||||
virtual ~ElementImplBase() {}
|
||||
virtual Result OnInit(void* initData) { (void)initData; return Result_Success; }
|
||||
virtual Result OnDestroy() { return Result_Success; }
|
||||
};
|
||||
|
||||
class ControlImplBase {
|
||||
public:
|
||||
virtual ~ControlImplBase() {}
|
||||
virtual Result OnInit(void* hObj, void* initData) { (void)hObj; (void)initData; return Result_Success; }
|
||||
virtual Result OnDestroy(void* hObj) { (void)hObj; return Result_Success; }
|
||||
virtual Result OnControlNavigate(void* hObj, void* navData) { (void)hObj; (void)navData; return Result_Success; }
|
||||
virtual Result OnKeyDown(void* hObj, void* inputData) { (void)hObj; (void)inputData; return Result_Success; }
|
||||
virtual Result OnCustomMessage_GetSlotItem(void* hObj, void* pData) { (void)hObj; (void)pData; return Result_Success; }
|
||||
};
|
||||
|
||||
class ListImpl : public Control {
|
||||
public:
|
||||
ListImpl();
|
||||
~ListImpl();
|
||||
};
|
||||
|
||||
class ProgressBarImpl : public ProgressBar {
|
||||
public:
|
||||
ProgressBarImpl();
|
||||
~ProgressBarImpl();
|
||||
};
|
||||
|
||||
class Application {
|
||||
public:
|
||||
Application();
|
||||
~Application();
|
||||
|
||||
Result init();
|
||||
Result shutdown();
|
||||
|
||||
Result navigateToScene(int pad, Scene* scene, void* initData = nullptr);
|
||||
Result navigateBack(int pad);
|
||||
Result closeScene(int pad, Scene* scene);
|
||||
|
||||
void tick(float deltaTime);
|
||||
void render();
|
||||
|
||||
Result sendKeyEvent(int pad, uint32_t key, bool down);
|
||||
|
||||
void loadStringTable(const std::wstring& path);
|
||||
const wchar_t* getString(int id) const;
|
||||
|
||||
static Application* getInstance() { return s_instance; }
|
||||
|
||||
private:
|
||||
static Application* s_instance;
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> m_impl;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace ImXui {
|
||||
|
||||
|
||||
struct ImageData {
|
||||
ImageData() : w(0), h(0) {}
|
||||
int w;
|
||||
int h;
|
||||
std::vector<uint8_t> rgba;
|
||||
bool valid() const { return w > 0 && h > 0 && !rgba.empty(); }
|
||||
};
|
||||
|
||||
|
||||
struct MemoryTexture {
|
||||
int w;
|
||||
int h;
|
||||
std::vector<uint8_t> rgba;
|
||||
MemoryTexture() : w(0), h(0) {}
|
||||
};
|
||||
|
||||
void registerMemoryTexture(const std::string& name, const void* rgba,
|
||||
int w, int h);
|
||||
const MemoryTexture* findMemoryTexture(const std::string& name);
|
||||
void clearMemoryTextures();
|
||||
|
||||
|
||||
struct MemoryTextureRaw {
|
||||
std::vector<uint8_t> encoded;
|
||||
};
|
||||
void registerMemoryTextureRaw(const std::string& name, const void* data, size_t size);
|
||||
const MemoryTextureRaw* findMemoryTextureRaw(const std::string& name);
|
||||
bool unregisterMemoryTexture(const std::string& name);
|
||||
|
||||
class ImageManager {
|
||||
public:
|
||||
ImageManager();
|
||||
~ImageManager();
|
||||
|
||||
void setBasePath(const std::string& path) { m_basePath = path; }
|
||||
const std::string& getBasePath() const { return m_basePath; }
|
||||
|
||||
|
||||
const ImageData* load(const std::string& path);
|
||||
|
||||
|
||||
static bool decodeFile(const std::string& path, ImageData& out);
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
std::string m_basePath;
|
||||
std::unordered_map<std::string, ImageData> m_cache;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
#pragma once
|
||||
|
||||
#include "ImXui.h"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ImXui {
|
||||
|
||||
|
||||
enum RenderCommandType {
|
||||
RenderCommandType_BeginScene,
|
||||
RenderCommandType_PushTransform,
|
||||
RenderCommandType_PopTransform,
|
||||
RenderCommandType_PushClip,
|
||||
RenderCommandType_PopClip,
|
||||
RenderCommandType_ColoredQuad,
|
||||
RenderCommandType_TexturedQuad,
|
||||
RenderCommandType_NineGrid,
|
||||
RenderCommandType_Figure,
|
||||
RenderCommandType_Text,
|
||||
|
||||
|
||||
RenderCommandType_CustomDraw,
|
||||
RenderCommandType_SetBlendMode,
|
||||
RenderCommandType_EndScene,
|
||||
};
|
||||
|
||||
struct Transform2D {
|
||||
float m00, m01, m10, m11, tx, ty;
|
||||
|
||||
Transform2D()
|
||||
: m00(1.0f), m01(0.0f), m10(0.0f), m11(1.0f), tx(0.0f), ty(0.0f) {}
|
||||
};
|
||||
|
||||
struct RenderCommand {
|
||||
RenderCommandType type;
|
||||
Rect rect;
|
||||
Color color;
|
||||
Color strokeColor;
|
||||
float opacity;
|
||||
float strokeWidth;
|
||||
uint32_t blendMode;
|
||||
uint32_t leftInset;
|
||||
uint32_t topInset;
|
||||
uint32_t rightInset;
|
||||
uint32_t bottomInset;
|
||||
bool noCenter;
|
||||
bool closed;
|
||||
Transform2D transform;
|
||||
std::wstring resource;
|
||||
std::wstring text;
|
||||
std::wstring fontName;
|
||||
float fontSize;
|
||||
bool centered;
|
||||
std::vector<Vec2> points;
|
||||
|
||||
RenderCommand()
|
||||
: type(RenderCommandType_BeginScene)
|
||||
, rect()
|
||||
, color()
|
||||
, strokeColor()
|
||||
, opacity(1.0f)
|
||||
, strokeWidth(0.0f)
|
||||
, blendMode(0)
|
||||
, leftInset(0)
|
||||
, topInset(0)
|
||||
, rightInset(0)
|
||||
, bottomInset(0)
|
||||
, noCenter(false)
|
||||
, closed(false)
|
||||
, transform()
|
||||
, fontSize(0.0f)
|
||||
, centered(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class IRenderCommandSink {
|
||||
public:
|
||||
virtual ~IRenderCommandSink() {}
|
||||
|
||||
virtual void beginScene(float width, float height) = 0;
|
||||
virtual void drawColoredQuad(const Rect& rect, const Color& color, float opacity) = 0;
|
||||
virtual void drawTexturedQuad(const Rect& rect, const std::wstring& resource,
|
||||
const Color& color, float opacity) = 0;
|
||||
virtual void drawText(const Rect& rect, const std::wstring& text,
|
||||
const std::wstring& fontName, float fontSize,
|
||||
const Color& color, float opacity, bool centered) = 0;
|
||||
virtual void endScene() = 0;
|
||||
|
||||
|
||||
virtual void pushTransform(const Transform2D&) {}
|
||||
virtual void popTransform() {}
|
||||
virtual void pushClip(const Rect&) {}
|
||||
virtual void popClip() {}
|
||||
virtual void drawNineGrid(const Rect&, const std::wstring&, const Color&, float,
|
||||
uint32_t, uint32_t, uint32_t, uint32_t, bool) {}
|
||||
virtual void drawFigure(const Rect&, const std::vector<Vec2>&, bool,
|
||||
const Color&, const Color&, float, float, uint32_t) {}
|
||||
virtual void setBlendMode(uint32_t) {}
|
||||
|
||||
virtual void drawCustom(const std::wstring& drawId, const Rect&, float opacity) {
|
||||
(void)drawId; (void)opacity;
|
||||
}
|
||||
};
|
||||
|
||||
class RenderCommandBuffer : public IRenderCommandSink {
|
||||
public:
|
||||
RenderCommandBuffer() : m_width(0.0f), m_height(0.0f) {}
|
||||
|
||||
void clear();
|
||||
const std::vector<RenderCommand>& getCommands() const { return m_commands; }
|
||||
std::vector<RenderCommand>& getCommands() { return m_commands; }
|
||||
float getWidth() const { return m_width; }
|
||||
float getHeight() const { return m_height; }
|
||||
|
||||
void beginScene(float width, float height);
|
||||
void drawColoredQuad(const Rect& rect, const Color& color, float opacity);
|
||||
void drawTexturedQuad(const Rect& rect, const std::wstring& resource,
|
||||
const Color& color, float opacity);
|
||||
void drawText(const Rect& rect, const std::wstring& text,
|
||||
const std::wstring& fontName, float fontSize,
|
||||
const Color& color, float opacity, bool centered);
|
||||
void endScene();
|
||||
|
||||
void pushTransform(const Transform2D& transform);
|
||||
void popTransform();
|
||||
void pushClip(const Rect& rect);
|
||||
void popClip();
|
||||
void drawNineGrid(const Rect& rect, const std::wstring& resource,
|
||||
const Color& color, float opacity,
|
||||
uint32_t leftInset, uint32_t topInset,
|
||||
uint32_t rightInset, uint32_t bottomInset,
|
||||
bool noCenter);
|
||||
void drawFigure(const Rect& rect, const std::vector<Vec2>& points, bool closed,
|
||||
const Color& fillColor, const Color& strokeColor,
|
||||
float opacity, float strokeWidth, uint32_t blendMode);
|
||||
void setBlendMode(uint32_t blendMode);
|
||||
void drawCustom(const std::wstring& drawId, const Rect& rect, float opacity);
|
||||
|
||||
private:
|
||||
float m_width;
|
||||
float m_height;
|
||||
std::vector<RenderCommand> m_commands;
|
||||
};
|
||||
|
||||
|
||||
void emitRenderCommands(const Scene* scene, IRenderCommandSink* sink);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
#pragma once
|
||||
|
||||
#include "ImXui.h"
|
||||
#include "TextureManager.h"
|
||||
#include "Skin.h"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
|
||||
struct ID3D11Device;
|
||||
struct ID3D11DeviceContext;
|
||||
struct ID3D11Buffer;
|
||||
struct ID3D11VertexShader;
|
||||
struct ID3D11PixelShader;
|
||||
struct ID3D11InputLayout;
|
||||
struct ID3D11BlendState;
|
||||
struct ID3D11SamplerState;
|
||||
struct ID3D11RasterizerState;
|
||||
struct ID3D11ShaderResourceView;
|
||||
struct IDWriteFactory;
|
||||
struct ID2D1Factory;
|
||||
struct IDXGIDevice;
|
||||
struct IDXGIFactory2;
|
||||
struct IDXGISwapChain1;
|
||||
struct IDCompositionDevice;
|
||||
struct IDCompositionTarget;
|
||||
struct IDCompositionVisual;
|
||||
|
||||
namespace ImXui {
|
||||
|
||||
struct RendererVertex2D { float x, y, u, v, r, g, b, a; };
|
||||
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
virtual ~Renderer() {}
|
||||
|
||||
|
||||
virtual bool init(void* nativeWindow, int width, int height) = 0;
|
||||
virtual void shutdown() = 0;
|
||||
|
||||
virtual bool resize(int width, int height) = 0;
|
||||
|
||||
virtual bool beginFrame(float clearR = 0, float clearG = 0, float clearB = 0, float clearA = 1) = 0;
|
||||
|
||||
|
||||
virtual void endFrame(bool vsync = true) = 0;
|
||||
|
||||
virtual void renderScene(const Scene* scene) = 0;
|
||||
virtual void setTextureManager(TextureManager* mgr) = 0;
|
||||
virtual void setSkin(const Skin* skin) = 0;
|
||||
virtual const Skin* getSkin() const = 0;
|
||||
|
||||
virtual bool loadFont(const wchar_t* path) = 0;
|
||||
virtual bool initTextRendering() = 0;
|
||||
virtual void shutdownTextRendering() = 0;
|
||||
|
||||
virtual void drawTexturedQuad(float x, float y, float w, float h, const wchar_t* texturePath,
|
||||
float r = 1, float g = 1, float b = 1, float a = 1) = 0;
|
||||
virtual void drawFigure(float x, float y, float w, float h,
|
||||
const std::vector<Vec2>& points, bool closed,
|
||||
float fillR, float fillG, float fillB, float fillA,
|
||||
float strokeR, float strokeG, float strokeB, float strokeA,
|
||||
float strokeWidth) = 0;
|
||||
virtual void drawColoredQuad(float x, float y, float w, float h,
|
||||
float r, float g, float b, float a) = 0;
|
||||
virtual void drawTextString(float x, float y, float w, float h,
|
||||
const std::wstring& text, const std::wstring& fontName, float fontSize,
|
||||
float r = 1, float g = 1, float b = 1, float a = 1,
|
||||
bool centered = false) = 0;
|
||||
|
||||
virtual int getWidth() const = 0;
|
||||
virtual int getHeight() const = 0;
|
||||
};
|
||||
|
||||
|
||||
class D3D11Renderer : public Renderer {
|
||||
public:
|
||||
D3D11Renderer();
|
||||
~D3D11Renderer();
|
||||
|
||||
bool init(void* hwnd, int width, int height) override;
|
||||
bool initExternal(ID3D11Device* device, ID3D11DeviceContext* context);
|
||||
void shutdown() override;
|
||||
|
||||
bool resize(int width, int height) override;
|
||||
|
||||
bool beginFrame(float clearR = 0, float clearG = 0, float clearB = 0, float clearA = 1) override;
|
||||
void endFrame(bool vsync = true) override;
|
||||
|
||||
void renderScene(const Scene* scene) override;
|
||||
void setTextureManager(TextureManager* mgr) override { m_textureMgr = mgr; }
|
||||
void setSkin(const Skin* skin) override { m_skin = skin; }
|
||||
const Skin* getSkin() const override { return m_skin; }
|
||||
|
||||
ID3D11Device* getDevice() const { return m_device; }
|
||||
ID3D11DeviceContext* getContext() const { return m_context; }
|
||||
|
||||
bool loadFont(const wchar_t* path) override;
|
||||
bool initTextRendering() override;
|
||||
void shutdownTextRendering() override;
|
||||
|
||||
void drawTexturedQuad(float x, float y, float w, float h, const wchar_t* texturePath,
|
||||
float r = 1, float g = 1, float b = 1, float a = 1) override;
|
||||
void drawTexturedQuadSRV(float x, float y, float w, float h, ID3D11ShaderResourceView* srv,
|
||||
float r = 1, float g = 1, float b = 1, float a = 1);
|
||||
void drawNineGrid(float x, float y, float w, float h, ID3D11ShaderResourceView* srv,
|
||||
uint32_t leftInset, uint32_t topInset, uint32_t rightInset, uint32_t bottomInset,
|
||||
bool noCenter, float r = 1, float g = 1, float b = 1, float a = 1);
|
||||
void drawFigure(float x, float y, float w, float h,
|
||||
const std::vector<Vec2>& points, bool closed,
|
||||
float fillR, float fillG, float fillB, float fillA,
|
||||
float strokeR, float strokeG, float strokeB, float strokeA,
|
||||
float strokeWidth) override;
|
||||
void drawColoredQuad(float x, float y, float w, float h,
|
||||
float r, float g, float b, float a) override;
|
||||
void drawTextString(float x, float y, float w, float h,
|
||||
const std::wstring& text, const std::wstring& fontName, float fontSize,
|
||||
float r = 1, float g = 1, float b = 1, float a = 1,
|
||||
bool centered = false) override;
|
||||
|
||||
int getWidth() const override { return m_width; }
|
||||
int getHeight() const override { return m_height; }
|
||||
|
||||
private:
|
||||
bool createShadersAndStates();
|
||||
bool createQuadBuffer();
|
||||
bool createWhiteTexture();
|
||||
void drawElement(const Element* el);
|
||||
void drawTexturedElement(const Element* el);
|
||||
void drawVisualImages(const std::vector<VisualImage>& images, const Rect& elementRect, float offsetX, float offsetY, float alpha);
|
||||
Rect computeImageRect(const VisualImage& img, const Rect& visualBounds, const Rect& elementRect);
|
||||
|
||||
ID3D11ShaderResourceView* getOrCreateTextTexture(const std::wstring& text, const std::wstring& fontName, float fontSize, uint32_t textStyle, float maxWidth, int& outW, int& outH);
|
||||
void drawText(const Control* ctrl, const Rect& rect, float alpha, const std::wstring& fontName, float fontSize, float textR = 1, float textG = 1, float textB = 1, float textA = 1, uint32_t textStyle = 0);
|
||||
|
||||
ID3D11Device* m_device;
|
||||
ID3D11DeviceContext* m_context;
|
||||
bool m_ownsDevice;
|
||||
|
||||
void* m_swapChain;
|
||||
|
||||
IDCompositionDevice* m_dcompDevice;
|
||||
IDCompositionTarget* m_dcompTarget;
|
||||
IDCompositionVisual* m_dcompVisual;
|
||||
|
||||
ID3D11VertexShader* m_vs;
|
||||
ID3D11PixelShader* m_psTex;
|
||||
ID3D11InputLayout* m_inputLayout;
|
||||
ID3D11BlendState* m_blendState;
|
||||
ID3D11BlendState* m_textBlendState;
|
||||
ID3D11SamplerState* m_sampler;
|
||||
ID3D11ShaderResourceView* m_whiteSRV;
|
||||
ID3D11RasterizerState* m_scissorRS;
|
||||
ID3D11RasterizerState* m_normalRS;
|
||||
|
||||
std::stack<Rect> m_clipStack;
|
||||
|
||||
ID3D11Buffer* m_quadVB;
|
||||
|
||||
RendererVertex2D* m_batchPtr;
|
||||
int m_batchCount;
|
||||
|
||||
int m_width;
|
||||
int m_height;
|
||||
|
||||
TextureManager* m_textureMgr;
|
||||
const Skin* m_skin;
|
||||
|
||||
IDWriteFactory* m_dwriteFactory;
|
||||
ID2D1Factory* m_d2dFactory;
|
||||
struct TextCacheEntry { ID3D11ShaderResourceView* srv; int w; int h; TextCacheEntry() : srv(nullptr), w(0), h(0) {} };
|
||||
|
||||
|
||||
std::map<std::wstring, TextCacheEntry> m_textCache;
|
||||
std::list<std::wstring> m_textLru;
|
||||
static const size_t TEXT_CACHE_MAX = 128;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <cstdint>
|
||||
|
||||
namespace ImXui {
|
||||
|
||||
struct VisualImage {
|
||||
std::string imagePath;
|
||||
float x, y, z, w, h;
|
||||
uint32_t anchor;
|
||||
VisualImage() : x(0), y(0), z(0), w(0), h(0), anchor(0) {}
|
||||
};
|
||||
|
||||
struct TextProperties {
|
||||
bool hasColor;
|
||||
uint8_t textColorA, textColorR, textColorG, textColorB;
|
||||
float pointSize;
|
||||
bool hasPointSize;
|
||||
std::string font;
|
||||
bool hasFont;
|
||||
uint32_t textStyle;
|
||||
bool hasTextStyle;
|
||||
TextProperties()
|
||||
: hasColor(false), textColorA(255), textColorR(255), textColorG(255), textColorB(255)
|
||||
, pointSize(12.0f), hasPointSize(false), hasFont(false), textStyle(0), hasTextStyle(false) {}
|
||||
};
|
||||
|
||||
struct VisualEntry {
|
||||
std::string id;
|
||||
float templateWidth, templateHeight;
|
||||
float posX, posY;
|
||||
std::vector<VisualImage> images;
|
||||
TextProperties textProps;
|
||||
VisualEntry() : templateWidth(0), templateHeight(0), posX(0), posY(0) {}
|
||||
};
|
||||
|
||||
class Skin {
|
||||
public:
|
||||
bool loadFromXui(const std::string& path);
|
||||
bool loadFromString(const std::string& xml);
|
||||
const std::vector<VisualImage>* getImages(const std::string& visualName) const;
|
||||
const VisualEntry* getEntry(const std::string& visualName) const;
|
||||
const std::vector<VisualEntry>& getAllEntries() const { return m_entries; }
|
||||
int count() const { return (int)m_entryMap.size(); }
|
||||
|
||||
private:
|
||||
void parseVisualBlock(const std::string& xml, size_t start, size_t end);
|
||||
std::string readProp(const std::string& xml, const std::string& propName, size_t from, size_t to);
|
||||
std::vector<VisualEntry> m_entries;
|
||||
std::unordered_map<std::string, int> m_entryMap;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
#include "Renderer.h"
|
||||
#include "FontEngine.h"
|
||||
#include "ImageManager.h"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
|
||||
namespace ImXui {
|
||||
|
||||
|
||||
class SoftwareRenderer : public Renderer {
|
||||
public:
|
||||
SoftwareRenderer();
|
||||
~SoftwareRenderer();
|
||||
|
||||
bool init(void* nativeWindow, int width, int height) override;
|
||||
void shutdown() override;
|
||||
bool resize(int width, int height) override;
|
||||
|
||||
bool beginFrame(float clearR = 0, float clearG = 0, float clearB = 0, float clearA = 1) override;
|
||||
void endFrame(bool vsync = true) override;
|
||||
|
||||
void renderScene(const Scene* scene) override;
|
||||
void setTextureManager(TextureManager* mgr) override { (void)mgr; }
|
||||
void setSkin(const Skin* skin) override { m_skin = skin; }
|
||||
const Skin* getSkin() const override { return m_skin; }
|
||||
|
||||
bool loadFont(const wchar_t* path) override;
|
||||
bool loadSystemFont(const std::string& name);
|
||||
bool initTextRendering() override;
|
||||
void shutdownTextRendering() override;
|
||||
|
||||
float measureText(const std::wstring& text, float sizePx) const;
|
||||
float lineHeight(float sizePx) const;
|
||||
|
||||
void drawTexturedQuad(float x, float y, float w, float h, const wchar_t* texturePath,
|
||||
float r = 1, float g = 1, float b = 1, float a = 1) override;
|
||||
void drawFigure(float x, float y, float w, float h,
|
||||
const std::vector<Vec2>& points, bool closed,
|
||||
float fillR, float fillG, float fillB, float fillA,
|
||||
float strokeR, float strokeG, float strokeB, float strokeA,
|
||||
float strokeWidth) override;
|
||||
void drawColoredQuad(float x, float y, float w, float h,
|
||||
float r, float g, float b, float a) override;
|
||||
void drawTextString(float x, float y, float w, float h,
|
||||
const std::wstring& text, const std::wstring& fontName, float fontSize,
|
||||
float r = 1, float g = 1, float b = 1, float a = 1,
|
||||
bool centered = false) override;
|
||||
|
||||
int getWidth() const override { return m_width; }
|
||||
int getHeight() const override { return m_height; }
|
||||
|
||||
|
||||
const uint8_t* getFramebuffer() const { return m_fb.empty() ? nullptr : m_fb.data(); }
|
||||
size_t getFramebufferSize() const { return m_fb.size(); }
|
||||
|
||||
uint32_t pixel(int x, int y) const;
|
||||
bool savePng(const char* path) const;
|
||||
bool saveBmp(const char* path) const;
|
||||
|
||||
private:
|
||||
void drawElement(const Element* el);
|
||||
void drawTexturedElement(const Element* el);
|
||||
void drawNineGridRect(float x, float y, float w, float h, const ImageData& img,
|
||||
uint32_t leftInset, uint32_t topInset, uint32_t rightInset, uint32_t bottomInset,
|
||||
bool noCenter, float r, float g, float b, float a);
|
||||
void fillRect(float x, float y, float w, float h, float r, float g, float b, float a);
|
||||
void fillTriangle(float x0, float y0, float x1, float y1, float x2, float y2,
|
||||
float r, float g, float b, float a);
|
||||
void blitImage(int dx, int dy, int dw, int dh, const ImageData& img,
|
||||
float tintR, float tintG, float tintB, float alpha);
|
||||
void strokeSegment(float x0, float y0, float x1, float y1, float width,
|
||||
float r, float g, float b, float a);
|
||||
|
||||
void pushClip(const Rect& r);
|
||||
void popClip();
|
||||
|
||||
bool clipRect(Rect& r) const;
|
||||
|
||||
std::vector<uint8_t> m_fb;
|
||||
int m_width;
|
||||
int m_height;
|
||||
FontEngine m_font;
|
||||
ImageManager m_images;
|
||||
const Skin* m_skin;
|
||||
std::stack<Rect> m_clipStack;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <cstdint>
|
||||
|
||||
struct ID3D11Device;
|
||||
struct ID3D11ShaderResourceView;
|
||||
|
||||
namespace ImXui {
|
||||
|
||||
class TextureManager {
|
||||
public:
|
||||
TextureManager() : m_device(nullptr) {}
|
||||
~TextureManager() { shutdown(); }
|
||||
|
||||
bool init(ID3D11Device* device);
|
||||
void shutdown();
|
||||
|
||||
void setBasePath(const std::string& path) { m_basePath = path; }
|
||||
const std::string& getBasePath() const { return m_basePath; }
|
||||
|
||||
ID3D11ShaderResourceView* load(const std::string& relativePath);
|
||||
|
||||
bool getSize(const std::string& relativePath, int& w, int& h) const;
|
||||
|
||||
private:
|
||||
ID3D11Device* m_device;
|
||||
std::string m_basePath;
|
||||
std::unordered_map<std::string, ID3D11ShaderResourceView*> m_cache;
|
||||
std::unordered_map<std::string, int> m_widths;
|
||||
std::unordered_map<std::string, int> m_heights;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "ImXui/RenderCommands.h"
|
||||
#include "xui.h"
|
||||
|
||||
namespace ImXui {
|
||||
|
||||
class X360RenderSink : public IRenderCommandSink {
|
||||
public:
|
||||
X360RenderSink();
|
||||
|
||||
|
||||
void setDevice(void* d3dDevice);
|
||||
void setDelegateSink(IRenderCommandSink* sink);
|
||||
void setFontRenderer(class IXuiFontRenderer* renderer);
|
||||
void setFontTypeface(const wchar_t* typeface);
|
||||
|
||||
|
||||
HXUIDC getDeviceContext() const { return m_hDC; }
|
||||
void beginFrame(float width, float height);
|
||||
void endFrame();
|
||||
|
||||
|
||||
void beginScene(float width, float height);
|
||||
void drawColoredQuad(const Rect& rect, const Color& color, float opacity);
|
||||
void drawTexturedQuad(const Rect& rect, const std::wstring& resource,
|
||||
const Color& color, float opacity);
|
||||
void drawText(const Rect& rect, const std::wstring& text,
|
||||
const std::wstring& fontName, float fontSize,
|
||||
const Color& color, float opacity, bool centered);
|
||||
void pushTransform(const Transform2D& t);
|
||||
void popTransform();
|
||||
void pushClip(const Rect& r);
|
||||
void popClip();
|
||||
void drawNineGrid(const Rect&, const std::wstring&, const Color&, float,
|
||||
uint32_t, uint32_t, uint32_t, uint32_t, bool);
|
||||
void drawFigure(const Rect&, const std::vector<Vec2>&, bool,
|
||||
const Color&, const Color&, float, float, uint32_t);
|
||||
void setBlendMode(uint32_t mode);
|
||||
void drawCustom(const std::wstring& drawId, const Rect&, float opacity);
|
||||
void endScene();
|
||||
|
||||
private:
|
||||
bool drawQuadD3D(const Rect& rect, uint32_t abgr);
|
||||
void flushText(const Rect& rect, const std::wstring& text,
|
||||
const Color& color, float fontSize, bool centered);
|
||||
|
||||
void* m_device;
|
||||
IRenderCommandSink* m_delegate;
|
||||
class IXuiFontRenderer* m_fontRenderer;
|
||||
HFONTOBJ m_font;
|
||||
std::wstring m_typeface;
|
||||
HXUIDC m_hDC;
|
||||
Transform2D m_transform;
|
||||
Rect m_clip;
|
||||
uint32_t m_blendMode;
|
||||
float m_width;
|
||||
float m_height;
|
||||
int m_clipDepth;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
namespace ImXui {
|
||||
|
||||
class Element;
|
||||
class Control;
|
||||
class Scene;
|
||||
|
||||
class XuiXmlWriter {
|
||||
public:
|
||||
static bool writeFile(const std::string& path, const Scene* scene);
|
||||
static std::string serialize(const Scene* scene);
|
||||
|
||||
private:
|
||||
static void writeElement(std::ostringstream& out, const Element* el, int indent);
|
||||
static void writeControlProps(std::ostringstream& out, const Control* ctrl, int indent);
|
||||
static void writeSceneProps(std::ostringstream& out, const Scene* scene, int indent);
|
||||
static void indentLine(std::ostringstream& out, int level);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace ImXui {
|
||||
namespace XurFormat {
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
# include <stdlib.h>
|
||||
# define BSWAP16(x) _byteswap_ushort((unsigned short)(x))
|
||||
# define BSWAP32(x) _byteswap_ulong((unsigned long)(x))
|
||||
#else
|
||||
# define BSWAP16(x) (((x) >> 8) | ((x) << 8))
|
||||
# define BSWAP32(x) ((((x) >> 24) & 0xFF) | (((x) >> 8) & 0xFF00) | (((x) << 8) & 0xFF0000) | (((x) << 24) & 0xFF000000))
|
||||
#endif
|
||||
|
||||
|
||||
inline uint16_t swap16(uint16_t v) { return BSWAP16(v); }
|
||||
inline uint32_t swap32(uint32_t v) { return BSWAP32(v); }
|
||||
inline float swapFloat(uint32_t v) {
|
||||
uint32_t swapped = swap32(v);
|
||||
float result;
|
||||
memcpy(&result, &swapped, 4);
|
||||
return result;
|
||||
}
|
||||
|
||||
const uint32_t MAGIC_XUIB = 0x58554942;
|
||||
const uint32_t MAGIC_STRN = 0x5354524E;
|
||||
const uint32_t MAGIC_VECT = 0x56454354;
|
||||
const uint32_t MAGIC_QUAT = 0x51554154;
|
||||
const uint32_t MAGIC_CUST = 0x43555354;
|
||||
const uint32_t MAGIC_DATA = 0x44415441;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct XurHeader {
|
||||
char magic[4];
|
||||
uint32_t version;
|
||||
uint32_t flags;
|
||||
uint16_t toolVersion;
|
||||
uint32_t fileSize;
|
||||
uint16_t sectionsCount;
|
||||
|
||||
bool isValid() const {
|
||||
return memcmp(magic, "XUIB", 4) == 0 && swap32(version) == 5;
|
||||
}
|
||||
uint32_t getFlags() const { return swap32(flags); }
|
||||
uint32_t getFileSize() const { return swap32(fileSize); }
|
||||
uint16_t getSectionsCount() const { return swap16(sectionsCount); }
|
||||
};
|
||||
|
||||
struct XurCountHeader {
|
||||
uint32_t totalObjectsCount;
|
||||
uint32_t totalPropertiesCount;
|
||||
uint32_t totalPropertiesArrayCount;
|
||||
uint32_t keyframePropertiesCount;
|
||||
uint32_t totalKeyframePropertyClassDepth;
|
||||
uint32_t keyframePropertyDefinitionsCount;
|
||||
uint32_t keyframesCount;
|
||||
uint32_t timelinesCount;
|
||||
uint32_t namedFramesCount;
|
||||
uint32_t objectsWithChildrenCount;
|
||||
|
||||
void fromBE() {
|
||||
totalObjectsCount = swap32(totalObjectsCount);
|
||||
totalPropertiesCount = swap32(totalPropertiesCount);
|
||||
totalPropertiesArrayCount = swap32(totalPropertiesArrayCount);
|
||||
keyframePropertiesCount = swap32(keyframePropertiesCount);
|
||||
totalKeyframePropertyClassDepth = swap32(totalKeyframePropertyClassDepth);
|
||||
keyframePropertyDefinitionsCount = swap32(keyframePropertyDefinitionsCount);
|
||||
keyframesCount = swap32(keyframesCount);
|
||||
timelinesCount = swap32(timelinesCount);
|
||||
namedFramesCount = swap32(namedFramesCount);
|
||||
objectsWithChildrenCount = swap32(objectsWithChildrenCount);
|
||||
}
|
||||
};
|
||||
|
||||
struct XurSectionEntry {
|
||||
uint32_t magic;
|
||||
uint32_t offset;
|
||||
uint32_t length;
|
||||
|
||||
void fromBE() {
|
||||
magic = swap32(magic);
|
||||
offset = swap32(offset);
|
||||
length = swap32(length);
|
||||
}
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct XurVector { float x, y, z; };
|
||||
struct XurQuaternion { float x, y, z, w; };
|
||||
struct XurPoint { float x, y; };
|
||||
struct XurBezierPoint { XurPoint point; XurPoint controlOne; XurPoint controlTwo; };
|
||||
struct XurFigure { XurPoint boundingBox; std::vector<XurBezierPoint> points; };
|
||||
struct XurColor { uint8_t a, r, g, b; };
|
||||
|
||||
|
||||
enum XurPropertyType {
|
||||
XurPropertyType_Bool = 0,
|
||||
XurPropertyType_Integer = 1,
|
||||
XurPropertyType_Unsigned = 2,
|
||||
XurPropertyType_Float = 3,
|
||||
XurPropertyType_String = 4,
|
||||
XurPropertyType_Vector = 5,
|
||||
XurPropertyType_Object = 6,
|
||||
XurPropertyType_Colour = 7,
|
||||
XurPropertyType_Custom = 8,
|
||||
XurPropertyType_Quaternion = 9,
|
||||
};
|
||||
|
||||
struct XurProperty;
|
||||
|
||||
class XurPropertyValue {
|
||||
public:
|
||||
XurPropertyType type;
|
||||
|
||||
bool boolVal;
|
||||
int32_t intVal;
|
||||
uint32_t uintVal;
|
||||
float floatVal;
|
||||
std::wstring stringVal;
|
||||
XurVector vectorVal;
|
||||
XurQuaternion quatVal;
|
||||
XurColor colorVal;
|
||||
XurFigure figureVal;
|
||||
std::vector<XurProperty> compoundVal;
|
||||
|
||||
XurPropertyValue();
|
||||
explicit XurPropertyValue(bool v);
|
||||
explicit XurPropertyValue(int32_t v);
|
||||
explicit XurPropertyValue(uint32_t v);
|
||||
explicit XurPropertyValue(float v);
|
||||
explicit XurPropertyValue(const std::wstring& v);
|
||||
explicit XurPropertyValue(const XurVector& v);
|
||||
explicit XurPropertyValue(const XurQuaternion& v);
|
||||
explicit XurPropertyValue(const XurColor& v);
|
||||
explicit XurPropertyValue(const XurFigure& v);
|
||||
explicit XurPropertyValue(const std::vector<XurProperty>& v);
|
||||
XurPropertyValue(const XurPropertyValue& other);
|
||||
XurPropertyValue& operator=(const XurPropertyValue& other);
|
||||
~XurPropertyValue();
|
||||
};
|
||||
|
||||
struct XurProperty {
|
||||
std::string name;
|
||||
XurPropertyType type;
|
||||
XurPropertyValue value;
|
||||
};
|
||||
|
||||
enum XurNamedFrameCommand {
|
||||
XurNamedFrameCommand_None = 0,
|
||||
XurNamedFrameCommand_Stop = 1,
|
||||
XurNamedFrameCommand_GotoAndStop = 2,
|
||||
XurNamedFrameCommand_GotoAndPlay = 3,
|
||||
XurNamedFrameCommand_Play = 4,
|
||||
};
|
||||
|
||||
struct XurNamedFrame {
|
||||
std::wstring name;
|
||||
int32_t keyframe;
|
||||
XurNamedFrameCommand command;
|
||||
std::wstring targetParameter;
|
||||
};
|
||||
|
||||
enum XurInterpolationType {
|
||||
XurInterpolationType_None = 0,
|
||||
XurInterpolationType_Linear = 1,
|
||||
XurInterpolationType_EaseIn = 2,
|
||||
XurInterpolationType_EaseOut = 3,
|
||||
XurInterpolationType_EaseInOut = 4,
|
||||
};
|
||||
|
||||
struct XurKeyframe {
|
||||
int32_t time;
|
||||
XurInterpolationType interpolation;
|
||||
uint8_t easeIn;
|
||||
uint8_t easeOut;
|
||||
uint8_t easeScale;
|
||||
std::vector<XurProperty> properties;
|
||||
};
|
||||
|
||||
struct XurTimeline {
|
||||
std::wstring elementName;
|
||||
std::vector<XurKeyframe> keyframes;
|
||||
};
|
||||
|
||||
struct XurObject {
|
||||
std::string className;
|
||||
std::vector<XurProperty> properties;
|
||||
std::vector<XurObject> children;
|
||||
std::vector<XurNamedFrame> namedFrames;
|
||||
std::vector<XurTimeline> timelines;
|
||||
};
|
||||
|
||||
struct XurDocument {
|
||||
XurHeader header;
|
||||
std::vector<std::wstring> strings;
|
||||
std::vector<XurVector> vectors;
|
||||
std::vector<XurQuaternion> quaternions;
|
||||
std::vector<XurFigure> figures;
|
||||
XurObject rootObject;
|
||||
std::vector<uint8_t> rawData;
|
||||
};
|
||||
|
||||
struct XuiPropDef {
|
||||
std::string name;
|
||||
XurPropertyType type;
|
||||
bool indexed;
|
||||
};
|
||||
|
||||
struct XuiClassInfo {
|
||||
std::string name;
|
||||
std::string baseClass;
|
||||
std::vector<XuiPropDef> props;
|
||||
};
|
||||
|
||||
class XuiClassRegistry {
|
||||
public:
|
||||
static const XuiClassInfo* findClass(const std::string& name);
|
||||
static std::vector<const XuiClassInfo*> getHierarchy(const std::string& className);
|
||||
static void initialize();
|
||||
};
|
||||
|
||||
class XurParser {
|
||||
public:
|
||||
static std::unique_ptr<XurDocument> parse(const void* data, size_t size);
|
||||
static std::unique_ptr<XurDocument> parseFromFile(const std::string& path);
|
||||
static bool validate(const XurDocument* doc);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include "XurFormat.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
namespace ImXui {
|
||||
|
||||
class Element;
|
||||
class Scene;
|
||||
|
||||
namespace XurFormat {
|
||||
|
||||
struct MemBuf {
|
||||
std::vector<uint8_t> data;
|
||||
void write(const void* d, size_t sz);
|
||||
template<typename T> void writeBE(T v);
|
||||
void writeU8(uint8_t v);
|
||||
void writeU16BE(uint16_t v);
|
||||
void writeU32BE(uint32_t v);
|
||||
void writeS16BE(int16_t v);
|
||||
void writeS32BE(int32_t v);
|
||||
void writeFloatBE(float v);
|
||||
uint32_t tell() const;
|
||||
};
|
||||
|
||||
struct WriteContext {
|
||||
std::vector<std::wstring> strings;
|
||||
std::vector<XurVector> vectors;
|
||||
std::vector<XurQuaternion> quaternions;
|
||||
std::vector<XurFigure> figures;
|
||||
|
||||
int addString(const std::wstring& s);
|
||||
int addVector(const XurVector& v);
|
||||
int addQuaternion(const XurQuaternion& q);
|
||||
int addFigure(const XurFigure& f);
|
||||
};
|
||||
|
||||
class XurWriter {
|
||||
public:
|
||||
static bool writeToFile(const std::string& path, const XurObject& root);
|
||||
static std::vector<uint8_t> serialize(const XurObject& root);
|
||||
|
||||
private:
|
||||
static void writePropValue(MemBuf& buf, WriteContext& ctx, const XurPropertyValue& val);
|
||||
static void writeProperties(MemBuf& buf, WriteContext& ctx, const XurObject& obj);
|
||||
static void writeObject(MemBuf& buf, WriteContext& ctx, const XurObject& obj);
|
||||
static void writeStrnSection(MemBuf& out, WriteContext& ctx);
|
||||
static void writeVectSection(MemBuf& out, WriteContext& ctx);
|
||||
static void writeQuatSection(MemBuf& out, WriteContext& ctx);
|
||||
static void writeCustSection(MemBuf& out, WriteContext& ctx);
|
||||
static void writeDataSection(MemBuf& out, WriteContext& ctx, const XurObject& root);
|
||||
};
|
||||
|
||||
XurObject elementToXurObject(const Element* el);
|
||||
XurObject sceneToXurObject(const Scene* scene);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "XurFormat.h"
|
||||
#include <string>
|
||||
|
||||
namespace ImXui {
|
||||
namespace XurFormat {
|
||||
|
||||
|
||||
XurObject xuiXmlToObject(const std::string& xml);
|
||||
|
||||
|
||||
std::string xurObjectToXuiXml(const XurObject& root);
|
||||
bool xurObjectToXuiXml(const XurObject& root, const std::string& path);
|
||||
|
||||
|
||||
XurObject xuiFileToObject(const std::string& path);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ImXui {
|
||||
|
||||
|
||||
class XzpPackage {
|
||||
public:
|
||||
struct Entry {
|
||||
std::string name;
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
Entry() : offset(0), size(0) {}
|
||||
};
|
||||
|
||||
XzpPackage();
|
||||
~XzpPackage();
|
||||
|
||||
|
||||
bool openMemory(const void* data, size_t size);
|
||||
bool openFile(const std::string& path);
|
||||
|
||||
bool isOpen() const { return m_open; }
|
||||
int getVersion() const { return m_version; }
|
||||
size_t getEntryCount() const { return m_entries.size(); }
|
||||
const std::vector<Entry>& getEntries() const { return m_entries; }
|
||||
|
||||
|
||||
const Entry* findEntry(const std::string& name) const;
|
||||
|
||||
|
||||
bool readEntry(const Entry& entry, std::vector<uint8_t>& out) const;
|
||||
bool readEntryByName(const std::string& name, std::vector<uint8_t>& out) const;
|
||||
|
||||
|
||||
const uint8_t* entryData(const Entry& entry) const;
|
||||
|
||||
private:
|
||||
void reset();
|
||||
|
||||
bool m_open;
|
||||
int m_version;
|
||||
std::vector<uint8_t> m_buffer;
|
||||
std::vector<Entry> m_entries;
|
||||
std::map<std::string, size_t> m_byName;
|
||||
};
|
||||
|
||||
|
||||
class XzpWriter {
|
||||
public:
|
||||
void addFile(const std::string& name, const void* data, size_t size);
|
||||
bool build(std::vector<uint8_t>& out) const;
|
||||
|
||||
private:
|
||||
struct Item {
|
||||
std::string name;
|
||||
std::vector<uint8_t> data;
|
||||
};
|
||||
std::vector<Item> m_items;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user