[add] Added Text.

This commit is contained in:
falsycat 2019-10-13 00:00:00 +00:00
parent 54355fccd0
commit 93f6844a2b
5 changed files with 148 additions and 7 deletions

View File

@ -31,7 +31,7 @@ class Game : AbstractGame {
lobby_ = new LobbyWorld(programs_);
title_ = new TitleScene(lobby_, programs_);
select_ = new SelectScene(lobby_, programs_, songs_);
select_ = new SelectScene(lobby_, programs_, fonts_, songs_);
title_.SetupSceneDependency(select_);
select_.SetupSceneDependency(title_);

View File

@ -1,18 +1,22 @@
/// License: MIT
module sj.SelectScene;
import std.math,
import std.conv,
std.math,
std.variant;
import derelict.sfml2.audio;
import gl4d;
import sj.KeyInput,
import sj.FontSet,
sj.KeyInput,
sj.LobbyWorld,
sj.ProgramSet,
sj.SceneInterface,
sj.Song,
sj.Text,
sj.TextProgram,
sj.TitleScene,
sj.util.Animation,
sj.util.Easing,
@ -21,12 +25,14 @@ import sj.KeyInput,
///
class SelectScene : SceneInterface {
public:
///
this(LobbyWorld lobby, ProgramSet program, Song[] songs) {
this(LobbyWorld lobby, ProgramSet program, FontSet fonts, Song[] songs) {
lobby_ = lobby;
songs_ = songs.dup;
text_ = new Text(program.Get!TextProgram);
fonts_ = fonts;
sound_ = sfSound_create();
soundres_.Load();
@ -34,6 +40,8 @@ class SelectScene : SceneInterface {
status_ = first_state_;
}
~this() {
text_.destroy();
sfSound_destroy(sound_);
soundres_.Unload();
}
@ -61,6 +69,7 @@ class SelectScene : SceneInterface {
}
override void Draw() {
lobby_.Draw();
text_.Draw(lobby_.Projection, lobby_.view.Create());
}
private:
@ -82,6 +91,9 @@ class SelectScene : SceneInterface {
LobbyWorld lobby_;
Text text_;
FontSet fonts_;
Song[] songs_;
sfSound* sound_;
@ -195,6 +207,15 @@ private class SongAppearState : AbstractSceneState {
sfSound_setBuffer(owner.sound_, owner.soundres_.spotlight);
sfSound_play(owner.sound_);
// TODO:
const song = owner.songs_[song_index_];
with (owner.text_) {
matrix.scale = vec3(0.2, 0.05, 0.05);
matrix.translation = vec3(0, -0.3, 0);
LoadGlyphs(vec2i(256, 64),
song.name.to!dstring, vec2i(32, 0), owner.fonts_.gothic);
}
}
override UpdateResult Update(KeyInput input) {
const ratio = anime_.Update();

View File

@ -84,6 +84,10 @@ class Song {
assert(false); // TODO:
}
///
@property string name() const {
return name_;
}
///
@property ref const(PreviewConfig) preview() const {
return preview_;

113
src/sj/Text.d Normal file
View File

@ -0,0 +1,113 @@
/// License: MIT
module sj.Text;
import std.exception;
import gl4d, ft4d;
import sj.TextProgram;
///
class Text {
public:
///
this(TextProgram program) {
program_ = program;
texture_ = Texture2D.Create();
vao_ = VertexArray.Create();
vertices_ = ArrayBuffer.Create();
program_.SetupVertexArray(vao_, vertices_);
vertices_.Bind();
ArrayBufferAllocator allocator;
with (allocator) {
const v = [
-1f, 1f, 0f, 1f, 0f,
-1f, -1f, 0f, 1f, 1f,
1f, -1f, 0f, 0f, 1f,
1f, 1f, 0f, 0f, 0f,
];
data = v.ptr;
size = v.length * v[0].sizeof;
usage = GL_STATIC_DRAW;
Allocate(vertices_);
}
}
///
void LoadGlyphs(vec2i texsz, dstring text, vec2i charsz, FaceRef face)
in (texsz.x > 0 && texsz.y > 0) {
auto pixels = new ubyte[texsz.x * texsz.y];
GlyphLoader gloader;
gloader.pxWidth = charsz.x;
gloader.pxHeight = charsz.y;
gloader.flags = FT_LOAD_DEFAULT | FT_LOAD_RENDER;
int x;
foreach (c; text) {
with (gloader) {
character = c;
Load(face).enforce;
}
const bitmap = face.EnforceGlyphBitmap();
const srcsz = vec2i(bitmap.width, bitmap.rows);
CopyRawPixels(bitmap.buffer, srcsz, pixels.ptr, texsz, vec2i(x, 0));
x += srcsz.x;
}
texture_.Bind();
Texture2DAllocator allocator;
with (allocator) {
level = 0;
internalFormat = GL_RGBA8;
data = pixels.ptr;
size = texsz;
format = GL_RED;
type = GL_UNSIGNED_BYTE;
Allocate(texture_);
}
glyph_loaded_ = true;
}
///
void Draw(mat4 proj, mat4 view) {
if (!glyph_loaded_) return;
program_.Use(proj, view, matrix.Create(), texture_, color);
vao_.Bind();
gl.DrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
///
ModelMatrixFactory!4 matrix;
///
vec4 color = vec4(0, 0, 0, 1);
private:
static void CopyRawPixels(in ubyte* src, vec2i srcsz, ubyte* dst, vec2i dstsz, vec2i offset) {
auto srcy = 0, dsty = offset.y;
for (; srcy < srcsz.y && dsty < dstsz.y; ++srcy, ++dsty) {
auto srcx = 0, dstx = offset.x;
for (; srcx < srcsz.x && dstx < dstsz.x; ++srcx, ++dstx) {
dst[dstx + dsty * dstsz.x] = src[srcx + srcy * srcsz.x];
}
}
}
TextProgram program_;
Texture2DRef texture_;
VertexArrayRef vao_;
ArrayBufferRef vertices_;
bool glyph_loaded_ = false;
}

View File

@ -38,13 +38,15 @@ class TextProgram {
///
enum FragmentShaderSrc = ShaderHeader ~ q{
layout(location = 3) uniform sampler2D tex;
layout(location = 4) uniform vec4 color;
in vec2 uv_;
out vec4 pixel_;
void main() {
pixel_ = texture(tex, uv_);
pixel_ = color;
pixel_.a *= texture(tex, uv_).r;
}
};
@ -87,7 +89,7 @@ class TextProgram {
}
///
void Use(mat4 proj, mat4 view, mat4 model, ref Texture2DRef tex) {
void Use(mat4 proj, mat4 view, mat4 model, ref Texture2DRef tex, vec4 color) {
tex.BindToUnit(GL_TEXTURE0);
sampler_.Bind(0);
@ -96,6 +98,7 @@ class TextProgram {
program_.uniform!1 = view;
program_.uniform!2 = model;
program_.uniform!3 = 0;
program_.uniform!4 = color;
}
private: