255 lines
5.6 KiB
C++
255 lines
5.6 KiB
C++
#pragma once
|
|
|
|
#include <extra2d/core/math_types.h>
|
|
#include <extra2d/core/types.h>
|
|
#include <string>
|
|
|
|
namespace extra2d {
|
|
|
|
/**
|
|
* @brief 视口缩放模式
|
|
*/
|
|
enum class ViewportScaleMode {
|
|
None, // 无缩放
|
|
Letterbox, // 保持宽高比,黑边
|
|
Crop, // 保持宽高比,裁剪
|
|
Stretch, // 拉伸填充
|
|
IntegerScale // 整数缩放
|
|
};
|
|
|
|
/**
|
|
* @brief 视口对齐方式
|
|
*/
|
|
enum class ViewportAlign {
|
|
Center,
|
|
TopLeft,
|
|
TopCenter,
|
|
TopRight,
|
|
CenterLeft,
|
|
CenterRight,
|
|
BottomLeft,
|
|
BottomCenter,
|
|
BottomRight
|
|
};
|
|
|
|
/**
|
|
* @brief 视口配置
|
|
*/
|
|
struct ViewportConfig {
|
|
float designWidth = 1280.0f;
|
|
float designHeight = 720.0f;
|
|
ViewportScaleMode scaleMode = ViewportScaleMode::Letterbox;
|
|
ViewportAlign align = ViewportAlign::Center;
|
|
bool integerScaleOnly = false;
|
|
float minScale = 0.5f;
|
|
float maxScale = 4.0f;
|
|
|
|
ViewportConfig() = default;
|
|
|
|
ViewportConfig(float width, float height,
|
|
ViewportScaleMode mode = ViewportScaleMode::Letterbox)
|
|
: designWidth(width), designHeight(height), scaleMode(mode) {}
|
|
|
|
/**
|
|
* @brief 创建 HD (1280x720) 配置
|
|
*/
|
|
static ViewportConfig hd() {
|
|
return ViewportConfig(1280.0f, 720.0f);
|
|
}
|
|
|
|
/**
|
|
* @brief 创建 Full HD (1920x1080) 配置
|
|
*/
|
|
static ViewportConfig fullHd() {
|
|
return ViewportConfig(1920.0f, 1080.0f);
|
|
}
|
|
|
|
/**
|
|
* @brief 创建 4K (3840x2160) 配置
|
|
*/
|
|
static ViewportConfig uhd4k() {
|
|
return ViewportConfig(3840.0f, 2160.0f);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @brief 视口计算结果
|
|
*/
|
|
struct ViewportResult {
|
|
float x = 0.0f;
|
|
float y = 0.0f;
|
|
float width = 0.0f;
|
|
float height = 0.0f;
|
|
float scale = 1.0f;
|
|
int offsetX = 0;
|
|
int offsetY = 0;
|
|
int screenWidth = 0;
|
|
int screenHeight = 0;
|
|
|
|
ViewportResult() = default;
|
|
|
|
/**
|
|
* @brief 获取视口矩形
|
|
*/
|
|
Rect getRect() const { return Rect(x, y, width, height); }
|
|
|
|
/**
|
|
* @brief 获取缩放后的设计尺寸
|
|
*/
|
|
Size getScaledDesignSize() const { return Size(width / scale, height / scale); }
|
|
};
|
|
|
|
/**
|
|
* @brief 视口适配器
|
|
*
|
|
* 处理不同屏幕尺寸和宽高比的视口适配
|
|
*/
|
|
class ViewportAdapter {
|
|
public:
|
|
ViewportAdapter();
|
|
explicit ViewportAdapter(const ViewportConfig& config);
|
|
~ViewportAdapter() = default;
|
|
|
|
// ========================================================================
|
|
// 配置
|
|
// ========================================================================
|
|
|
|
/**
|
|
* @brief 设置配置
|
|
*/
|
|
void setConfig(const ViewportConfig& config);
|
|
|
|
/**
|
|
* @brief 获取配置
|
|
*/
|
|
const ViewportConfig& getConfig() const { return config_; }
|
|
|
|
/**
|
|
* @brief 设置设计尺寸
|
|
*/
|
|
void setDesignSize(float width, float height);
|
|
|
|
/**
|
|
* @brief 设置缩放模式
|
|
*/
|
|
void setScaleMode(ViewportScaleMode mode);
|
|
|
|
/**
|
|
* @brief 设置对齐方式
|
|
*/
|
|
void setAlign(ViewportAlign align);
|
|
|
|
// ========================================================================
|
|
// 更新
|
|
// ========================================================================
|
|
|
|
/**
|
|
* @brief 更新视口
|
|
*/
|
|
void update(int screenWidth, int screenHeight);
|
|
|
|
/**
|
|
* @brief 获取结果
|
|
*/
|
|
const ViewportResult& getResult() const { return result_; }
|
|
|
|
// ========================================================================
|
|
// 查询
|
|
// ========================================================================
|
|
|
|
/**
|
|
* @brief 获取设计宽度
|
|
*/
|
|
float getDesignWidth() const { return config_.designWidth; }
|
|
|
|
/**
|
|
* @brief 获取设计高度
|
|
*/
|
|
float getDesignHeight() const { return config_.designHeight; }
|
|
|
|
/**
|
|
* @brief 获取设计宽高比
|
|
*/
|
|
float getDesignAspectRatio() const;
|
|
|
|
/**
|
|
* @brief 获取屏幕宽度
|
|
*/
|
|
int getScreenWidth() const { return result_.screenWidth; }
|
|
|
|
/**
|
|
* @brief 获取屏幕高度
|
|
*/
|
|
int getScreenHeight() const { return result_.screenHeight; }
|
|
|
|
/**
|
|
* @brief 获取屏幕宽高比
|
|
*/
|
|
float getScreenAspectRatio() const;
|
|
|
|
/**
|
|
* @brief 获取当前缩放
|
|
*/
|
|
float getScale() const { return result_.scale; }
|
|
|
|
/**
|
|
* @brief 获取视口偏移 X
|
|
*/
|
|
int getOffsetX() const { return result_.offsetX; }
|
|
|
|
/**
|
|
* @brief 获取视口偏移 Y
|
|
*/
|
|
int getOffsetY() const { return result_.offsetY; }
|
|
|
|
// ========================================================================
|
|
// 坐标转换
|
|
// ========================================================================
|
|
|
|
/**
|
|
* @brief 屏幕坐标转设计坐标
|
|
*/
|
|
Vec2 screenToDesign(const Vec2& screenPos) const;
|
|
|
|
/**
|
|
* @brief 设计坐标转屏幕坐标
|
|
*/
|
|
Vec2 designToScreen(const Vec2& designPos) const;
|
|
|
|
// ========================================================================
|
|
// 调试
|
|
// ========================================================================
|
|
|
|
/**
|
|
* @brief 获取调试名称
|
|
*/
|
|
const std::string& getDebugName() const { return debugName_; }
|
|
|
|
/**
|
|
* @brief 设置调试名称
|
|
*/
|
|
void setDebugName(const std::string& name) { debugName_ = name; }
|
|
|
|
private:
|
|
/**
|
|
* @brief 计算视口
|
|
*/
|
|
void calculateViewport();
|
|
|
|
/**
|
|
* @brief 计算缩放
|
|
*/
|
|
float calculateScale() const;
|
|
|
|
/**
|
|
* @brief 计算偏移
|
|
*/
|
|
void calculateOffset();
|
|
|
|
ViewportConfig config_;
|
|
ViewportResult result_;
|
|
std::string debugName_;
|
|
};
|
|
|
|
} // namespace extra2d
|