[add] Added Text.
This commit is contained in:
parent
54355fccd0
commit
93f6844a2b
@ -31,7 +31,7 @@ class Game : AbstractGame {
|
|||||||
lobby_ = new LobbyWorld(programs_);
|
lobby_ = new LobbyWorld(programs_);
|
||||||
|
|
||||||
title_ = new TitleScene(lobby_, programs_);
|
title_ = new TitleScene(lobby_, programs_);
|
||||||
select_ = new SelectScene(lobby_, programs_, songs_);
|
select_ = new SelectScene(lobby_, programs_, fonts_, songs_);
|
||||||
|
|
||||||
title_.SetupSceneDependency(select_);
|
title_.SetupSceneDependency(select_);
|
||||||
select_.SetupSceneDependency(title_);
|
select_.SetupSceneDependency(title_);
|
||||||
|
@ -1,18 +1,22 @@
|
|||||||
/// License: MIT
|
/// License: MIT
|
||||||
module sj.SelectScene;
|
module sj.SelectScene;
|
||||||
|
|
||||||
import std.math,
|
import std.conv,
|
||||||
|
std.math,
|
||||||
std.variant;
|
std.variant;
|
||||||
|
|
||||||
import derelict.sfml2.audio;
|
import derelict.sfml2.audio;
|
||||||
|
|
||||||
import gl4d;
|
import gl4d;
|
||||||
|
|
||||||
import sj.KeyInput,
|
import sj.FontSet,
|
||||||
|
sj.KeyInput,
|
||||||
sj.LobbyWorld,
|
sj.LobbyWorld,
|
||||||
sj.ProgramSet,
|
sj.ProgramSet,
|
||||||
sj.SceneInterface,
|
sj.SceneInterface,
|
||||||
sj.Song,
|
sj.Song,
|
||||||
|
sj.Text,
|
||||||
|
sj.TextProgram,
|
||||||
sj.TitleScene,
|
sj.TitleScene,
|
||||||
sj.util.Animation,
|
sj.util.Animation,
|
||||||
sj.util.Easing,
|
sj.util.Easing,
|
||||||
@ -21,12 +25,14 @@ import sj.KeyInput,
|
|||||||
///
|
///
|
||||||
class SelectScene : SceneInterface {
|
class SelectScene : SceneInterface {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
///
|
///
|
||||||
this(LobbyWorld lobby, ProgramSet program, Song[] songs) {
|
this(LobbyWorld lobby, ProgramSet program, FontSet fonts, Song[] songs) {
|
||||||
lobby_ = lobby;
|
lobby_ = lobby;
|
||||||
songs_ = songs.dup;
|
songs_ = songs.dup;
|
||||||
|
|
||||||
|
text_ = new Text(program.Get!TextProgram);
|
||||||
|
fonts_ = fonts;
|
||||||
|
|
||||||
sound_ = sfSound_create();
|
sound_ = sfSound_create();
|
||||||
soundres_.Load();
|
soundres_.Load();
|
||||||
|
|
||||||
@ -34,6 +40,8 @@ class SelectScene : SceneInterface {
|
|||||||
status_ = first_state_;
|
status_ = first_state_;
|
||||||
}
|
}
|
||||||
~this() {
|
~this() {
|
||||||
|
text_.destroy();
|
||||||
|
|
||||||
sfSound_destroy(sound_);
|
sfSound_destroy(sound_);
|
||||||
soundres_.Unload();
|
soundres_.Unload();
|
||||||
}
|
}
|
||||||
@ -61,6 +69,7 @@ class SelectScene : SceneInterface {
|
|||||||
}
|
}
|
||||||
override void Draw() {
|
override void Draw() {
|
||||||
lobby_.Draw();
|
lobby_.Draw();
|
||||||
|
text_.Draw(lobby_.Projection, lobby_.view.Create());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -82,6 +91,9 @@ class SelectScene : SceneInterface {
|
|||||||
|
|
||||||
LobbyWorld lobby_;
|
LobbyWorld lobby_;
|
||||||
|
|
||||||
|
Text text_;
|
||||||
|
FontSet fonts_;
|
||||||
|
|
||||||
Song[] songs_;
|
Song[] songs_;
|
||||||
|
|
||||||
sfSound* sound_;
|
sfSound* sound_;
|
||||||
@ -195,6 +207,15 @@ private class SongAppearState : AbstractSceneState {
|
|||||||
|
|
||||||
sfSound_setBuffer(owner.sound_, owner.soundres_.spotlight);
|
sfSound_setBuffer(owner.sound_, owner.soundres_.spotlight);
|
||||||
sfSound_play(owner.sound_);
|
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) {
|
override UpdateResult Update(KeyInput input) {
|
||||||
const ratio = anime_.Update();
|
const ratio = anime_.Update();
|
||||||
|
@ -84,6 +84,10 @@ class Song {
|
|||||||
assert(false); // TODO:
|
assert(false); // TODO:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@property string name() const {
|
||||||
|
return name_;
|
||||||
|
}
|
||||||
///
|
///
|
||||||
@property ref const(PreviewConfig) preview() const {
|
@property ref const(PreviewConfig) preview() const {
|
||||||
return preview_;
|
return preview_;
|
||||||
|
113
src/sj/Text.d
Normal file
113
src/sj/Text.d
Normal 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;
|
||||||
|
}
|
@ -38,13 +38,15 @@ class TextProgram {
|
|||||||
///
|
///
|
||||||
enum FragmentShaderSrc = ShaderHeader ~ q{
|
enum FragmentShaderSrc = ShaderHeader ~ q{
|
||||||
layout(location = 3) uniform sampler2D tex;
|
layout(location = 3) uniform sampler2D tex;
|
||||||
|
layout(location = 4) uniform vec4 color;
|
||||||
|
|
||||||
in vec2 uv_;
|
in vec2 uv_;
|
||||||
|
|
||||||
out vec4 pixel_;
|
out vec4 pixel_;
|
||||||
|
|
||||||
void main() {
|
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);
|
tex.BindToUnit(GL_TEXTURE0);
|
||||||
sampler_.Bind(0);
|
sampler_.Bind(0);
|
||||||
|
|
||||||
@ -96,6 +98,7 @@ class TextProgram {
|
|||||||
program_.uniform!1 = view;
|
program_.uniform!1 = view;
|
||||||
program_.uniform!2 = model;
|
program_.uniform!2 = model;
|
||||||
program_.uniform!3 = 0;
|
program_.uniform!3 = 0;
|
||||||
|
program_.uniform!4 = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Reference in New Issue
Block a user