Implements element handling.
This commit is contained in:
parent
213902021c
commit
e74a599ac1
@ -156,8 +156,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="src\common.h" />
|
<ClInclude Include="src\common.h" />
|
||||||
|
<ClInclude Include="src\ElementStore.h" />
|
||||||
<ClInclude Include="src\Font.h" />
|
<ClInclude Include="src\Font.h" />
|
||||||
<ClInclude Include="src\Game.h" />
|
<ClInclude Include="src\Game.h" />
|
||||||
|
<ClInclude Include="src\GlyphElementFactory.h" />
|
||||||
<ClInclude Include="src\iDrawable.h" />
|
<ClInclude Include="src\iDrawable.h" />
|
||||||
<ClInclude Include="src\iElement.h" />
|
<ClInclude Include="src\iElement.h" />
|
||||||
<ClInclude Include="src\iElementDriver.h" />
|
<ClInclude Include="src\iElementDriver.h" />
|
||||||
@ -180,6 +182,7 @@
|
|||||||
<ClInclude Include="src\SystemClock.h" />
|
<ClInclude Include="src\SystemClock.h" />
|
||||||
<ClInclude Include="src\Text.h" />
|
<ClInclude Include="src\Text.h" />
|
||||||
<ClInclude Include="src\Texture.h" />
|
<ClInclude Include="src\Texture.h" />
|
||||||
|
<ClInclude Include="src\TextureElement.h" />
|
||||||
<ClInclude Include="src\TickingClock.h" />
|
<ClInclude Include="src\TickingClock.h" />
|
||||||
<ClInclude Include="thirdparty\lauxlib.h" />
|
<ClInclude Include="thirdparty\lauxlib.h" />
|
||||||
<ClInclude Include="thirdparty\linalg.h" />
|
<ClInclude Include="thirdparty\linalg.h" />
|
||||||
@ -189,6 +192,7 @@
|
|||||||
<ClInclude Include="thirdparty\lualib.h" />
|
<ClInclude Include="thirdparty\lualib.h" />
|
||||||
<ClInclude Include="thirdparty\stb_truetype.h" />
|
<ClInclude Include="thirdparty\stb_truetype.h" />
|
||||||
<ClInclude Include="src\Win32Console.h" />
|
<ClInclude Include="src\Win32Console.h" />
|
||||||
|
<ClInclude Include="thirdparty\utf8.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<CopyFileToFolders Include="thirdparty\lua5.1.dll">
|
<CopyFileToFolders Include="thirdparty\lua5.1.dll">
|
||||||
|
@ -33,10 +33,10 @@
|
|||||||
<ClCompile Include="src\Game.cc">
|
<ClCompile Include="src\Game.cc">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="src\PlayScene.cc">
|
<ClCompile Include="src\Lua.cc">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="src\Lua.cc">
|
<ClCompile Include="src\PlayScene.cc">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@ -143,6 +143,18 @@
|
|||||||
<ClInclude Include="src\iElementDriver.h">
|
<ClInclude Include="src\iElementDriver.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\TextureElement.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\GlyphElementFactory.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\ElementStore.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="thirdparty\utf8.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Library Include="thirdparty\lua5.1.lib" />
|
<Library Include="thirdparty\lua5.1.lib" />
|
||||||
|
81
src/ElementStore.h
Normal file
81
src/ElementStore.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "iAllocator.h"
|
||||||
|
#include "iClock.h"
|
||||||
|
#include "iElement.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace gj {
|
||||||
|
|
||||||
|
|
||||||
|
class ElementStore {
|
||||||
|
public:
|
||||||
|
ElementStore() = delete;
|
||||||
|
|
||||||
|
ElementStore(ElementStore&&) = delete;
|
||||||
|
ElementStore(const ElementStore&) = delete;
|
||||||
|
|
||||||
|
ElementStore& operator=(ElementStore&&) = delete;
|
||||||
|
ElementStore& operator=(const ElementStore&) = delete;
|
||||||
|
|
||||||
|
ElementStore(iClock* clock, size_t reserve) : clock_(clock) {
|
||||||
|
pending_.reserve(reserve);
|
||||||
|
performing_.reserve(reserve);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Schedule(UniqPtr<iElement>&& e) {
|
||||||
|
const uint64_t st = e->period.start;
|
||||||
|
|
||||||
|
auto insert_pos = std::find_if(pending_.begin(), pending_.end(),
|
||||||
|
[st](auto& x) { return x->period.start > st; });
|
||||||
|
|
||||||
|
pending_.insert(insert_pos, std::move(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update(Frame& frame) {
|
||||||
|
const uint64_t now = clock_->now();
|
||||||
|
|
||||||
|
auto pending_beg = pending_.begin();
|
||||||
|
auto pending_end = pending_.end();
|
||||||
|
auto pending_itr = pending_beg;
|
||||||
|
for (; pending_itr < pending_end; ++pending_itr) {
|
||||||
|
iElement* e = pending_itr->get();
|
||||||
|
if (e->period.start > now) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
performing_.push_back(std::move(*pending_itr));
|
||||||
|
}
|
||||||
|
pending_.erase(pending_beg, pending_itr);
|
||||||
|
|
||||||
|
for (auto& eptr : performing_) {
|
||||||
|
iElement* e = eptr.get();
|
||||||
|
if (e->period.end <= now) {
|
||||||
|
eptr = nullptr;
|
||||||
|
} else {
|
||||||
|
e->Update(frame, e->period.Normalize(now));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* erase nullptr */
|
||||||
|
performing_.erase(
|
||||||
|
std::remove_if(
|
||||||
|
performing_.begin(), performing_.end(), [](auto& x) {return !x; }),
|
||||||
|
performing_.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEmpty() {
|
||||||
|
return pending_.empty() && performing_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const iClock* clock_;
|
||||||
|
|
||||||
|
std::vector<UniqPtr<iElement>> pending_;
|
||||||
|
std::vector<UniqPtr<iElement>> performing_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
56
src/Font.h
56
src/Font.h
@ -42,7 +42,7 @@ namespace gj {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Colorbuffer&& RenderGlyph(char16_t c, uint32_t fontsize = 32) {
|
Colorbuffer RenderGlyph(char16_t c, uint32_t fontsize = 32) {
|
||||||
int w, h;
|
int w, h;
|
||||||
|
|
||||||
const float s = stbtt_ScaleForPixelHeight(&stb_, fontsize*1.f);
|
const float s = stbtt_ScaleForPixelHeight(&stb_, fontsize*1.f);
|
||||||
@ -60,6 +60,60 @@ namespace gj {
|
|||||||
}
|
}
|
||||||
return std::move(ret);
|
return std::move(ret);
|
||||||
}
|
}
|
||||||
|
Colorbuffer RenderGlyphs(const std::wstring& str, uint32_t fontsize = 32) {
|
||||||
|
const float s = stbtt_ScaleForPixelHeight(&stb_, fontsize * 1.f);
|
||||||
|
|
||||||
|
int ascent;
|
||||||
|
stbtt_GetFontVMetrics(&stb_, &ascent, 0, 0);
|
||||||
|
|
||||||
|
const int baseline = static_cast<int>(ascent * s);
|
||||||
|
|
||||||
|
/* calculate bitmap size */
|
||||||
|
float h = 0, w = 2;
|
||||||
|
for (auto c : str) {
|
||||||
|
int advance, lsb;
|
||||||
|
stbtt_GetCodepointHMetrics(&stb_, c, &advance, &lsb);
|
||||||
|
|
||||||
|
int x0, y0, x1, y1;
|
||||||
|
const float x_shift = w - (int) w;
|
||||||
|
stbtt_GetCodepointBitmapBoxSubpixel(&stb_, c, s, s, x_shift, 0, &x0, &y0, &x1, &y1);
|
||||||
|
|
||||||
|
const int ch = y1 - y0;
|
||||||
|
if (h < ch) h = static_cast<float>(ch);
|
||||||
|
|
||||||
|
w += advance * s;
|
||||||
|
}
|
||||||
|
|
||||||
|
Colorbuffer buf(alloc_, static_cast<uint32_t>(w), static_cast<uint32_t>(h));
|
||||||
|
buf.Clear();
|
||||||
|
|
||||||
|
float* dst = buf.ptr();
|
||||||
|
|
||||||
|
float x = 2;
|
||||||
|
for (auto c : str) {
|
||||||
|
int advance, lsb;
|
||||||
|
stbtt_GetCodepointHMetrics(&stb_, c, &advance, &lsb);
|
||||||
|
|
||||||
|
int x0, y0, x1, y1;
|
||||||
|
const float x_shift = x - (int)x;
|
||||||
|
stbtt_GetCodepointBitmapBoxSubpixel(&stb_, c, s, s, x_shift, 0, &x0, &y0, &x1, &y1);
|
||||||
|
|
||||||
|
uint8_t ptr[64][64] = {0};
|
||||||
|
stbtt_MakeCodepointBitmapSubpixel(&stb_, &ptr[0][0], x1-x0, y1-y0, 64, s, s, x_shift, 0, c);
|
||||||
|
|
||||||
|
const int l = static_cast<int>(x) + x0;
|
||||||
|
const int r = static_cast<int>(x) + x1;
|
||||||
|
const int u = baseline + y0;
|
||||||
|
const int b = baseline + y1;
|
||||||
|
for (int y = 0; y < b-u; ++y) {
|
||||||
|
for (int x = 0; x < r-l; ++x) {
|
||||||
|
dst[y*static_cast<int>(w) + l+x] = static_cast<float>(ptr[y][x]*1. / UINT8_MAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x += advance * s;
|
||||||
|
}
|
||||||
|
return std::move(buf);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
iAllocator* alloc_;
|
iAllocator* alloc_;
|
||||||
|
57
src/GlyphElementFactory.h
Normal file
57
src/GlyphElementFactory.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "Font.h"
|
||||||
|
#include "iAllocator.h"
|
||||||
|
#include "iClock.h"
|
||||||
|
#include "iElementFactory.h"
|
||||||
|
#include "Texture.h"
|
||||||
|
#include "TextureElement.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace gj {
|
||||||
|
|
||||||
|
class GlyphElementFactory : public iElementFactory {
|
||||||
|
public:
|
||||||
|
GlyphElementFactory(GlyphElementFactory&&) = delete;
|
||||||
|
GlyphElementFactory(const GlyphElementFactory&) = delete;
|
||||||
|
|
||||||
|
GlyphElementFactory& operator=(GlyphElementFactory&&) = delete;
|
||||||
|
GlyphElementFactory& operator=(const GlyphElementFactory&) = delete;
|
||||||
|
|
||||||
|
GlyphElementFactory(iAllocator* alloc) : alloc_(alloc) {
|
||||||
|
}
|
||||||
|
|
||||||
|
UniqPtr<iElement> Create(Param&& param) override {
|
||||||
|
if (param.custom.size() != 3) return nullptr;
|
||||||
|
|
||||||
|
const std::string text = std::get<std::string>(param.custom[0]);
|
||||||
|
const std::string name = std::get<std::string>(param.custom[1]);
|
||||||
|
const intmax_t size = std::get<double>(param.custom[2]);
|
||||||
|
|
||||||
|
auto& font = FindOrCreateFont(name);
|
||||||
|
auto tex = std::move(font.RenderGlyphs(ConvertUtf8ToUtf16(text), size)); /* TODO */
|
||||||
|
|
||||||
|
return alloc_->MakeUniq<iElement, TextureElement>(
|
||||||
|
param.period, std::move(tex), std::move(param.driver));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Font& FindOrCreateFont(const std::string& name) {
|
||||||
|
auto found = fonts_.find(name);
|
||||||
|
if (found != fonts_.end()) {
|
||||||
|
return *found->second;
|
||||||
|
}
|
||||||
|
auto f = alloc_->MakeUniq<Font>(alloc_, "res/font/"+name);
|
||||||
|
auto ptr = f.get();
|
||||||
|
fonts_[name] = std::move(f);
|
||||||
|
return *ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
iAllocator* alloc_;
|
||||||
|
|
||||||
|
std::map<std::string, UniqPtr<Font>> fonts_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -76,6 +76,9 @@ public:
|
|||||||
|
|
||||||
hprev->next += h->next;
|
hprev->next += h->next;
|
||||||
hnext->prev += h->prev;
|
hnext->prev += h->prev;
|
||||||
|
|
||||||
|
// chaos test
|
||||||
|
// std::memset(h, 0xFF, h->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
104
src/Lua.cc
104
src/Lua.cc
@ -1,6 +1,45 @@
|
|||||||
#include "Lua.h"
|
#include "Lua.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct LuaPusher {
|
||||||
|
LuaPusher() = delete;
|
||||||
|
LuaPusher(lua_State* L) : L(L) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(int64_t v) {
|
||||||
|
lua_pushinteger(L, v);
|
||||||
|
}
|
||||||
|
void operator()(double v) {
|
||||||
|
lua_pushnumber(L, v);
|
||||||
|
}
|
||||||
|
void operator()(const std::string& v) {
|
||||||
|
lua_pushstring(L, v.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
lua_State* L;
|
||||||
|
};
|
||||||
|
struct LuaTaker {
|
||||||
|
LuaTaker() = delete;
|
||||||
|
LuaTaker(lua_State* L, int index) : L(L), index_(index) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(int64_t& v) {
|
||||||
|
v = luaL_checkinteger(L, index_);
|
||||||
|
}
|
||||||
|
void operator()(double& v) {
|
||||||
|
v = luaL_checknumber(L, index_);
|
||||||
|
}
|
||||||
|
void operator()(std::string& v) {
|
||||||
|
v = luaL_checkstring(L, index_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
lua_State* L;
|
||||||
|
int index_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class LuaFunc : public gj::iElementDriver {
|
class LuaFunc : public gj::iElementDriver {
|
||||||
public:
|
public:
|
||||||
LuaFunc() = delete;
|
LuaFunc() = delete;
|
||||||
@ -10,7 +49,8 @@ class LuaFunc : public gj::iElementDriver {
|
|||||||
LuaFunc& operator=(LuaFunc&&) = delete;
|
LuaFunc& operator=(LuaFunc&&) = delete;
|
||||||
LuaFunc& operator=(const LuaFunc&) = delete;
|
LuaFunc& operator=(const LuaFunc&) = delete;
|
||||||
|
|
||||||
LuaFunc(lua_State* L) : L(L) {
|
LuaFunc(lua_State* L, int index) : L(L) {
|
||||||
|
lua_pushvalue(L, index);
|
||||||
func_ = luaL_ref(L, LUA_REGISTRYINDEX);
|
func_ = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
|
|
||||||
lua_createtable(L, 0, 0);
|
lua_createtable(L, 0, 0);
|
||||||
@ -20,26 +60,19 @@ class LuaFunc : public gj::iElementDriver {
|
|||||||
luaL_unref(L, LUA_REGISTRYINDEX, func_);
|
luaL_unref(L, LUA_REGISTRYINDEX, func_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update(Param& param) override {
|
void Update(Param& param, double t) override {
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, func_);
|
lua_rawgeti(L, LUA_REGISTRYINDEX, func_);
|
||||||
|
|
||||||
|
lua_pushnumber(L, t);
|
||||||
|
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, table_);
|
lua_rawgeti(L, LUA_REGISTRYINDEX, table_);
|
||||||
for (const auto& p : param) {
|
for (const auto& p : param) {
|
||||||
lua_pushstring(L, p.first.c_str());
|
lua_pushstring(L, p.first.c_str());
|
||||||
if (std::holds_alternative<int64_t>(p.second)) {
|
std::visit(LuaPusher(L), p.second);
|
||||||
lua_pushinteger(L, std::get<int64_t>(p.second));
|
|
||||||
} else if (std::holds_alternative<double>(p.second)) {
|
|
||||||
lua_pushnumber(L, std::get<double>(p.second));
|
|
||||||
} else if (std::holds_alternative<std::string>(p.second)) {
|
|
||||||
const std::string str = std::get<std::string>(p.second);
|
|
||||||
lua_pushstring(L, str.c_str());
|
|
||||||
} else {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
lua_rawset(L, -3);
|
lua_rawset(L, -3);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int ret = lua_pcall(L, 1, 0, 0);
|
const int ret = lua_pcall(L, 2, 0, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
gj::Abort(std::string("Lua error: ")+lua_tostring(L, -1));
|
gj::Abort(std::string("Lua error: ")+lua_tostring(L, -1));
|
||||||
}
|
}
|
||||||
@ -48,16 +81,7 @@ class LuaFunc : public gj::iElementDriver {
|
|||||||
for (auto& p : param) {
|
for (auto& p : param) {
|
||||||
lua_pushstring(L, p.first.c_str());
|
lua_pushstring(L, p.first.c_str());
|
||||||
lua_rawget(L, -2);
|
lua_rawget(L, -2);
|
||||||
|
std::visit(LuaTaker(L, -1), p.second);
|
||||||
if (std::holds_alternative<int64_t>(p.second)) {
|
|
||||||
p.second = luaL_checkinteger(L, -1);
|
|
||||||
} else if (std::holds_alternative<double>(p.second)) {
|
|
||||||
p.second = luaL_checknumber(L, -1);
|
|
||||||
} else if (std::holds_alternative<std::string>(p.second)) {
|
|
||||||
p.second = luaL_checkstring(L, -1);
|
|
||||||
} else {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
@ -74,25 +98,46 @@ class LuaFunc : public gj::iElementDriver {
|
|||||||
static int CallFactory_(lua_State* L) {
|
static int CallFactory_(lua_State* L) {
|
||||||
gj::iAllocator* alloc =
|
gj::iAllocator* alloc =
|
||||||
reinterpret_cast<gj::iAllocator*>(lua_touserdata(L, lua_upvalueindex(1)));
|
reinterpret_cast<gj::iAllocator*>(lua_touserdata(L, lua_upvalueindex(1)));
|
||||||
|
gj::ElementStore* store =
|
||||||
|
reinterpret_cast<gj::ElementStore*>(lua_touserdata(L, lua_upvalueindex(2)));
|
||||||
gj::iElementFactory* factory =
|
gj::iElementFactory* factory =
|
||||||
reinterpret_cast<gj::iElementFactory*>(lua_touserdata(L, lua_upvalueindex(2)));
|
reinterpret_cast<gj::iElementFactory*>(lua_touserdata(L, lua_upvalueindex(3)));
|
||||||
|
|
||||||
|
const int n = lua_gettop(L);
|
||||||
|
|
||||||
const lua_Integer st = luaL_checkinteger(L, 1);
|
const lua_Integer st = luaL_checkinteger(L, 1);
|
||||||
const lua_Integer ed = luaL_checkinteger(L, 2);
|
const lua_Integer ed = luaL_checkinteger(L, 2);
|
||||||
if (st >= ed) {
|
if (st >= ed) {
|
||||||
return luaL_error(L, "invalid period");
|
return luaL_error(L, "invalid period");
|
||||||
}
|
}
|
||||||
if (!lua_isfunction(L, 3)) {
|
if (!lua_isfunction(L, n)) {
|
||||||
return luaL_error(L, "no driver specified");
|
return luaL_error(L, "no driver specified");
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_pushvalue(L, 3);
|
gj::iElementFactory::Param param;
|
||||||
factory->Create(gj::Period(st, ed), alloc->MakeUniq<gj::iElementDriver, LuaFunc>(L));
|
param.period = gj::Period(st, ed);
|
||||||
|
param.driver = alloc->MakeUniq<gj::iElementDriver, LuaFunc>(L, n);
|
||||||
|
|
||||||
|
for (int i = 3; i < n; ++i) {
|
||||||
|
gj::iElementFactory::Param::CustomValue v;
|
||||||
|
if (lua_isnumber(L, i)) {
|
||||||
|
v = lua_tonumber(L, i);
|
||||||
|
} else if (lua_isstring(L, i)) {
|
||||||
|
v = lua_tostring(L, i);
|
||||||
|
} else {
|
||||||
|
return luaL_error(L, "invalid args");
|
||||||
|
}
|
||||||
|
param.custom.push_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto e = factory->Create(std::move(param));
|
||||||
|
if (!e) return luaL_error(L, "factory returned nullptr");
|
||||||
|
store->Schedule(std::move(e));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gj::Lua::Lua(iAllocator* alloc, const FactoryMap& factory, const std::string& path) {
|
gj::Lua::Lua(iAllocator* alloc, ElementStore* store, const FactoryMap& factory, const std::string& path) {
|
||||||
L = luaL_newstate();
|
L = luaL_newstate();
|
||||||
if (L == nullptr) {
|
if (L == nullptr) {
|
||||||
Abort("lua_newstate failure");
|
Abort("lua_newstate failure");
|
||||||
@ -102,8 +147,9 @@ gj::Lua::Lua(iAllocator* alloc, const FactoryMap& factory, const std::string& pa
|
|||||||
lua_pushstring(L, f.first.c_str());
|
lua_pushstring(L, f.first.c_str());
|
||||||
|
|
||||||
lua_pushlightuserdata(L, alloc);
|
lua_pushlightuserdata(L, alloc);
|
||||||
|
lua_pushlightuserdata(L, store);
|
||||||
lua_pushlightuserdata(L, f.second);
|
lua_pushlightuserdata(L, f.second);
|
||||||
lua_pushcclosure(L, CallFactory_, 2);
|
lua_pushcclosure(L, CallFactory_, 3);
|
||||||
|
|
||||||
lua_rawset(L, LUA_GLOBALSINDEX);
|
lua_rawset(L, LUA_GLOBALSINDEX);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "iAllocator.h"
|
#include "iAllocator.h"
|
||||||
#include "iElementFactory.h"
|
#include "iElementFactory.h"
|
||||||
|
#include "ElementStore.h"
|
||||||
|
|
||||||
|
|
||||||
namespace gj {
|
namespace gj {
|
||||||
@ -24,7 +25,7 @@ class Lua {
|
|||||||
Lua& operator=(Lua&&) = delete;
|
Lua& operator=(Lua&&) = delete;
|
||||||
Lua& operator=(const Lua&) = delete;
|
Lua& operator=(const Lua&) = delete;
|
||||||
|
|
||||||
Lua(iAllocator* alloc, const FactoryMap& factory, const std::string& path);
|
Lua(iAllocator* alloc, ElementStore* store, const FactoryMap& factory, const std::string& path);
|
||||||
|
|
||||||
~Lua() {
|
~Lua() {
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
|
10
src/Period.h
10
src/Period.h
@ -7,13 +7,17 @@ namespace gj {
|
|||||||
|
|
||||||
struct Period {
|
struct Period {
|
||||||
public:
|
public:
|
||||||
Period() = delete;
|
Period() : Period(0, 0) {
|
||||||
|
}
|
||||||
Period(uint64_t st, uint64_t ed) : start(st), end(ed) {
|
Period(uint64_t st, uint64_t ed) : start(st), end(ed) {
|
||||||
assert(st <= ed);
|
assert(st <= ed);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isHit(uint64_t now) const {
|
double Normalize(uint64_t now) const {
|
||||||
|
return (static_cast<int64_t>(now) - start)*1./duration();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsHit(uint64_t now) const {
|
||||||
return start <= now && now < end;
|
return start <= now && now < end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,18 @@
|
|||||||
#include "PlayScene.h"
|
#include "PlayScene.h"
|
||||||
|
|
||||||
|
#include "GlyphElementFactory.h"
|
||||||
|
|
||||||
gj::PlayScene::PlayScene(gj::PlayScene::Param&& p) :
|
|
||||||
|
gj::PlayScene::PlayScene(Param&& p) :
|
||||||
alloc_(p.alloc), logger_(p.logger), w_(p.w), h_(p.h),
|
alloc_(p.alloc), logger_(p.logger), w_(p.w), h_(p.h),
|
||||||
clock_(p.clock) {
|
clock_(p.clock), store_(&clock_, 256) {
|
||||||
lua_ = alloc_->MakeUniq<Lua>(alloc_, Lua::FactoryMap(), "res/score/"+p.score+".lua");
|
GlyphElementFactory glyph(alloc_);
|
||||||
|
|
||||||
|
Lua::FactoryMap map;
|
||||||
|
map["Glyph"] = &glyph;
|
||||||
|
|
||||||
|
lua_ = alloc_->MakeUniq<Lua>(
|
||||||
|
alloc_, &store_, map, "res/score/" + p.score + ".lua");
|
||||||
|
|
||||||
logger_->Print(L"PlayScene init");
|
logger_->Print(L"PlayScene init");
|
||||||
}
|
}
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "ElementStore.h"
|
||||||
#include "Frame.h"
|
#include "Frame.h"
|
||||||
#include "iAllocator.h"
|
#include "iAllocator.h"
|
||||||
#include "iLogger.h"
|
#include "iLogger.h"
|
||||||
@ -33,6 +35,10 @@ class PlayScene : public iScene {
|
|||||||
PlayScene(Param&& p);
|
PlayScene(Param&& p);
|
||||||
|
|
||||||
UniqPtr<iScene> Update(Frame& f) override {
|
UniqPtr<iScene> Update(Frame& f) override {
|
||||||
|
if (store_.IsEmpty()) {
|
||||||
|
/* TODO create and return next scene */
|
||||||
|
}
|
||||||
|
store_.Update(f);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +50,7 @@ class PlayScene : public iScene {
|
|||||||
|
|
||||||
OffsetClock clock_;
|
OffsetClock clock_;
|
||||||
|
|
||||||
|
ElementStore store_;
|
||||||
UniqPtr<Lua> lua_;
|
UniqPtr<Lua> lua_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "iAllocator.h"
|
#include "iAllocator.h"
|
||||||
|
|
||||||
@ -15,36 +16,18 @@ class Rasterbuffer {
|
|||||||
Rasterbuffer(const Rasterbuffer&) = delete;
|
Rasterbuffer(const Rasterbuffer&) = delete;
|
||||||
Rasterbuffer& operator=(const Rasterbuffer&) = delete;
|
Rasterbuffer& operator=(const Rasterbuffer&) = delete;
|
||||||
|
|
||||||
|
Rasterbuffer(Rasterbuffer&& src) = default;
|
||||||
|
Rasterbuffer& operator=(Rasterbuffer&& src) = default;
|
||||||
|
|
||||||
Rasterbuffer(iAllocator* alloc, uint32_t w, uint32_t h) :
|
Rasterbuffer(iAllocator* alloc, uint32_t w, uint32_t h) :
|
||||||
alloc_(alloc), w_(w), h_(h),
|
alloc_(alloc), w_(w), h_(h),
|
||||||
buf_(alloc->Alloc<T>(static_cast<uint64_t>(w_)*h_)) {
|
buf_(alloc->MakeUniqArray<T>(static_cast<uint64_t>(w_)*h_)) {
|
||||||
_ASSERT(buf_ != nullptr);
|
|
||||||
}
|
}
|
||||||
~Rasterbuffer() {
|
|
||||||
alloc_->Free(buf_);
|
|
||||||
}
|
|
||||||
|
|
||||||
Rasterbuffer(Rasterbuffer&& src) noexcept :
|
|
||||||
alloc_(src.alloc_), w_(src.w_), h_(src.h_), buf_(src.buf_) {
|
|
||||||
src.buf_ = nullptr;
|
|
||||||
}
|
|
||||||
Rasterbuffer& operator=(Rasterbuffer&& src) noexcept {
|
|
||||||
if (this != &src) {
|
|
||||||
alloc_ = src.alloc_;
|
|
||||||
w_ = src.w_;
|
|
||||||
h_ = src.h_;
|
|
||||||
buf_ = src.buf_;
|
|
||||||
src.buf_ = nullptr;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Clear() {
|
void Clear() {
|
||||||
memset(buf_, 0, static_cast<uint64_t>(w_) * h_ * sizeof(T));
|
std::memset(buf_.get(), 0, static_cast<uint64_t>(w_) * h_ * sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t width() const {
|
uint32_t width() const {
|
||||||
return w_;
|
return w_;
|
||||||
}
|
}
|
||||||
@ -52,17 +35,17 @@ class Rasterbuffer {
|
|||||||
return h_;
|
return h_;
|
||||||
}
|
}
|
||||||
T* ptr() {
|
T* ptr() {
|
||||||
return buf_;
|
return buf_.get();
|
||||||
}
|
}
|
||||||
const T* ptr() const {
|
const T* ptr() const {
|
||||||
return buf_;
|
return buf_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
iAllocator* alloc_;
|
iAllocator* alloc_;
|
||||||
|
|
||||||
uint32_t w_, h_;
|
uint32_t w_, h_;
|
||||||
T* buf_;
|
UniqPtr<T> buf_;
|
||||||
};
|
};
|
||||||
|
|
||||||
using Colorbuffer = Rasterbuffer<float>;
|
using Colorbuffer = Rasterbuffer<float>;
|
||||||
|
@ -72,7 +72,7 @@ void gj::Texture::Draw(Colorbuffer& fb) const {
|
|||||||
if (std::abs(xf) > 1 || std::abs(yf) > 1) continue;
|
if (std::abs(xf) > 1 || std::abs(yf) > 1) continue;
|
||||||
|
|
||||||
int32_t srcx = static_cast<int32_t>((xf+1)/2 * srcw);
|
int32_t srcx = static_cast<int32_t>((xf+1)/2 * srcw);
|
||||||
int32_t srcy = srch - 1 - static_cast<int32_t>((yf+1)/2 * srch);
|
int32_t srcy = static_cast<int32_t>((yf+1)/2 * srch);
|
||||||
if (srcx >= srcw) srcx = srcw - 1;
|
if (srcx >= srcw) srcx = srcw - 1;
|
||||||
if (srcy >= srch) srcy = srch - 1;
|
if (srcy >= srch) srcy = srch - 1;
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ void gj::Texture::Draw(Colorbuffer& fb) const {
|
|||||||
if (dstx < 0 || w <= dstx) continue;
|
if (dstx < 0 || w <= dstx) continue;
|
||||||
if (dsty < 0 || h <= dsty) continue;
|
if (dsty < 0 || h <= dsty) continue;
|
||||||
|
|
||||||
dst[dstx + w*dsty] = src[srcx + srcw*srcy];
|
dst[dstx + w*dsty] = src[srcx + srcw*srcy] * alpha_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
55
src/TextureElement.h
Normal file
55
src/TextureElement.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "iElement.h"
|
||||||
|
#include "iElementDriver.h"
|
||||||
|
#include "Texture.h"
|
||||||
|
|
||||||
|
namespace gj {
|
||||||
|
|
||||||
|
|
||||||
|
class TextureElement : public iElement {
|
||||||
|
public:
|
||||||
|
TextureElement() = delete;
|
||||||
|
TextureElement(TextureElement&&) = delete;
|
||||||
|
TextureElement(const TextureElement&) = delete;
|
||||||
|
|
||||||
|
TextureElement& operator=(TextureElement&&) = delete;
|
||||||
|
TextureElement& operator=(const TextureElement&) = delete;
|
||||||
|
|
||||||
|
TextureElement(const Period& p, Texture&& tex, UniqPtr<iElementDriver>&& drv) :
|
||||||
|
iElement(p), tex_(std::move(tex)), drv_(std::move(drv)) {
|
||||||
|
param_["posX"] = 0.;
|
||||||
|
param_["posY"] = 0.;
|
||||||
|
param_["scaleX"] = 1.;
|
||||||
|
param_["scaleY"] = 1.;
|
||||||
|
param_["alpha"] = 1.;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update(Frame& frame, double t) override {
|
||||||
|
drv_->Update(param_, t);
|
||||||
|
|
||||||
|
const double posX = std::get<double>(param_["posX"]);
|
||||||
|
const double posY = std::get<double>(param_["posY"]);
|
||||||
|
const double scaleX = std::get<double>(param_["scaleX"]);
|
||||||
|
const double scaleY = std::get<double>(param_["scaleY"]);
|
||||||
|
const double alpha = std::get<double>(param_["alpha"]);
|
||||||
|
|
||||||
|
tex_.SetMatrix(mat3{
|
||||||
|
{ scaleX, 0, 0 },
|
||||||
|
{ 0, scaleY, 0 },
|
||||||
|
{ posX, posY, 1},
|
||||||
|
});
|
||||||
|
tex_.SetAlpha(static_cast<float>(alpha));
|
||||||
|
|
||||||
|
frame.Add(&tex_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Texture tex_;
|
||||||
|
UniqPtr<iElementDriver> drv_;
|
||||||
|
|
||||||
|
iElementDriver::Param param_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
16
src/common.h
16
src/common.h
@ -1,8 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <codecvt>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
@ -10,6 +9,7 @@
|
|||||||
#undef NOMINMAX
|
#undef NOMINMAX
|
||||||
|
|
||||||
#include "thirdparty/linalg.h"
|
#include "thirdparty/linalg.h"
|
||||||
|
#include "thirdparty/utf8.h"
|
||||||
|
|
||||||
namespace gj {
|
namespace gj {
|
||||||
|
|
||||||
@ -19,9 +19,15 @@ using vec3 = ::linalg::vec<double, 3>;
|
|||||||
|
|
||||||
|
|
||||||
static inline std::wstring ConvertUtf8ToUtf16(const std::string& str) {
|
static inline std::wstring ConvertUtf8ToUtf16(const std::string& str) {
|
||||||
std::wostringstream conv;
|
std::wstring ret;
|
||||||
conv << str.c_str();
|
|
||||||
return conv.str();
|
const void* c = str.c_str();
|
||||||
|
for (;;) {
|
||||||
|
int32_t code;
|
||||||
|
c = utf8codepoint(c, &code);
|
||||||
|
if (!code) return ret;
|
||||||
|
ret += static_cast<wchar_t>(code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,9 +40,15 @@ class DrawableBase : public iDrawable {
|
|||||||
invmat_ = ::linalg::inverse(mat_);
|
invmat_ = ::linalg::inverse(mat_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetAlpha(float a) {
|
||||||
|
alpha_ = a;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
mat3 mat_ = ::linalg::identity;
|
mat3 mat_ = ::linalg::identity;
|
||||||
mat3 invmat_ = ::linalg::identity;
|
mat3 invmat_ = ::linalg::identity;
|
||||||
|
|
||||||
|
float alpha_ = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,16 +9,19 @@ namespace gj {
|
|||||||
|
|
||||||
class iElement {
|
class iElement {
|
||||||
public:
|
public:
|
||||||
|
iElement() = delete;
|
||||||
iElement(iElement&&) = default;
|
iElement(iElement&&) = default;
|
||||||
iElement(const iElement&) = default;
|
iElement(const iElement&) = default;
|
||||||
|
|
||||||
iElement& operator=(iElement&&) = default;
|
iElement& operator=(iElement&&) = default;
|
||||||
iElement& operator=(const iElement&) = default;
|
iElement& operator=(const iElement&) = default;
|
||||||
|
|
||||||
iElement() = default;
|
|
||||||
virtual ~iElement() = default;
|
virtual ~iElement() = default;
|
||||||
|
|
||||||
virtual void Update(Frame& f) = 0;
|
iElement(const Period& p) : period(p) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Update(Frame& frame, double t) = 0;
|
||||||
|
|
||||||
/* Interfaces had better not have a variable but this is for optimization. */
|
/* Interfaces had better not have a variable but this is for optimization. */
|
||||||
const Period period;
|
const Period period;
|
||||||
|
@ -22,7 +22,7 @@ class iElementDriver {
|
|||||||
iElementDriver() = default;
|
iElementDriver() = default;
|
||||||
virtual ~iElementDriver() = default;
|
virtual ~iElementDriver() = default;
|
||||||
|
|
||||||
virtual void Update(Param&) = 0;
|
virtual void Update(Param&, double t) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <variant>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "iAllocator.h"
|
#include "iAllocator.h"
|
||||||
#include "iElement.h"
|
#include "iElement.h"
|
||||||
#include "iElementDriver.h"
|
#include "iElementDriver.h"
|
||||||
@ -11,6 +16,14 @@ namespace gj {
|
|||||||
|
|
||||||
class iElementFactory {
|
class iElementFactory {
|
||||||
public:
|
public:
|
||||||
|
struct Param {
|
||||||
|
using CustomValue = std::variant<int64_t, double, std::string>;
|
||||||
|
|
||||||
|
Period period;
|
||||||
|
std::vector<CustomValue> custom;
|
||||||
|
UniqPtr<iElementDriver> driver;
|
||||||
|
};
|
||||||
|
|
||||||
iElementFactory(iElementFactory&&) = default;
|
iElementFactory(iElementFactory&&) = default;
|
||||||
iElementFactory(const iElementFactory&) = default;
|
iElementFactory(const iElementFactory&) = default;
|
||||||
|
|
||||||
@ -20,7 +33,7 @@ class iElementFactory {
|
|||||||
iElementFactory() = default;
|
iElementFactory() = default;
|
||||||
virtual ~iElementFactory() = default;
|
virtual ~iElementFactory() = default;
|
||||||
|
|
||||||
virtual UniqPtr<iElement> Create(const Period& p, UniqPtr<iElementDriver>&& drv) = 0;
|
virtual UniqPtr<iElement> Create(Param&& p) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
1662
thirdparty/utf8.h
vendored
Normal file
1662
thirdparty/utf8.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user