Browse Source

Revise debug log format. Fix calculation of font linegap and linespace. Tweak state transitions

master
C. J. Howard 2 years ago
parent
commit
b5739f14c3
14 changed files with 230 additions and 56 deletions
  1. +0
    -1
      CMakeLists.txt
  2. +19
    -1
      src/animation/screen-transition.cpp
  3. +3
    -1
      src/animation/screen-transition.hpp
  4. +8
    -6
      src/debug/logger.cpp
  5. +1
    -1
      src/debug/logger.hpp
  6. +5
    -0
      src/game/context.hpp
  7. +9
    -20
      src/game/states/boot.cpp
  8. +4
    -4
      src/game/states/loading.cpp
  9. +166
    -2
      src/game/states/main-menu.cpp
  10. +1
    -17
      src/game/states/nuptial-flight.cpp
  11. +5
    -0
      src/game/states/splash.cpp
  12. +6
    -0
      src/game/states/title.cpp
  13. +1
    -1
      src/type/font-metrics.hpp
  14. +2
    -2
      src/type/freetype/typeface.cpp

+ 0
- 1
CMakeLists.txt View File

@ -123,4 +123,3 @@ elseif(PACKAGE_PLATFORM MATCHES "win")
#endif() #endif()
#install(FILES ${OPENAL_DLL} DESTINATION .) #install(FILES ${OPENAL_DLL} DESTINATION .)
endif() endif()

+ 19
- 1
src/animation/screen-transition.cpp View File

@ -65,7 +65,12 @@ screen_transition::screen_transition()
); );
} }
void screen_transition::transition(float duration, bool reverse, ::animation<float>::interpolator_type interpolator)
void screen_transition::set_visible(bool visible)
{
billboard.set_active(visible);
}
void screen_transition::transition(float duration, bool reverse, ::animation<float>::interpolator_type interpolator, bool hide)
{ {
float initial_state = (reverse) ? 1.0f : 0.0f; float initial_state = (reverse) ? 1.0f : 0.0f;
float final_state = (reverse) ? 0.0f : 1.0f; float final_state = (reverse) ? 0.0f : 1.0f;
@ -78,6 +83,19 @@ void screen_transition::transition(float duration, bool reverse, ::animation
// Set transition animation interpolator // Set transition animation interpolator
animation.set_interpolator(interpolator); animation.set_interpolator(interpolator);
if (hide)
{
// Setup animation end callback to hide transition billboard
animation.set_end_callback
(
std::bind(&scene::object_base::set_active, &billboard, false)
);
}
else
{
animation.set_end_callback(nullptr);
}
// Update tweens // Update tweens
progress->set_value(initial_state); progress->set_value(initial_state);
material.update_tweens(); material.update_tweens();

+ 3
- 1
src/animation/screen-transition.hpp View File

@ -33,7 +33,9 @@ class screen_transition
public: public:
screen_transition(); screen_transition();
void transition(float duration, bool reverse, animation<float>::interpolator_type interpolator);
void set_visible(bool visible);
void transition(float duration, bool reverse, animation<float>::interpolator_type interpolator, bool hide = true);
scene::billboard* get_billboard(); scene::billboard* get_billboard();
render::material* get_material(); render::material* get_material();

+ 8
- 6
src/debug/logger.cpp View File

@ -154,7 +154,7 @@ void logger::set_success_postfix(const std::string& postfix)
void logger::push_task(const std::string& description) void logger::push_task(const std::string& description)
{ {
std::string message = description + "...";
std::string message = description + " {";
if (!auto_newline) if (!auto_newline)
message += "\n"; message += "\n";
@ -163,20 +163,20 @@ void logger::push_task(const std::string& description)
tasks.push(description); tasks.push(description);
} }
void logger::pop_task(int status)
void logger::pop_task(int status, std::string error)
{ {
if (tasks.empty()) if (tasks.empty())
{ {
return; return;
} }
std::string message = tasks.top() + "... ";
std::string message = "} ";
tasks.pop(); tasks.pop();
if (status == EXIT_SUCCESS) if (status == EXIT_SUCCESS)
{ {
message += "success";
message += "=> success";
if (!auto_newline) if (!auto_newline)
message += "\n"; message += "\n";
@ -184,11 +184,13 @@ void logger::pop_task(int status)
} }
else else
{ {
message += "failed (" + std::to_string(status) + ")";
message += "failed";
if (!error.empty())
message += " (" + error + ")";
if (!auto_newline) if (!auto_newline)
message += "\n"; message += "\n";
error(message);
this->error(message);
} }
} }

+ 1
- 1
src/debug/logger.hpp View File

@ -97,7 +97,7 @@ public:
* *
* @param status Exit status of the task. A value of `0` or `EXIT_SUCCESS` indicates the task exited successfully. A non-zero exit status indicates the task failed. * @param status Exit status of the task. A value of `0` or `EXIT_SUCCESS` indicates the task exited successfully. A non-zero exit status indicates the task failed.
*/ */
void pop_task(int status);
void pop_task(int status, std::string error = std::string());
const std::string& get_history() const; const std::string& get_history() const;

+ 5
- 0
src/game/context.hpp View File

@ -201,6 +201,11 @@ struct context
scene::billboard* camera_flash_billboard; scene::billboard* camera_flash_billboard;
scene::text* title_text; scene::text* title_text;
scene::text* title_version_text; scene::text* title_version_text;
scene::text* main_menu_start_text;
scene::text* main_menu_options_text;
scene::text* main_menu_credits_text;
scene::text* main_menu_quit_text;
scene::model_instance* ui_pointer;
// Surface scene // Surface scene
scene::collection* surface_scene; scene::collection* surface_scene;

+ 9
- 20
src/game/states/boot.cpp View File

@ -119,8 +119,6 @@ void enter(application* app, int argc, char** argv)
// Get application logger // Get application logger
debug::logger* logger = app->get_logger(); debug::logger* logger = app->get_logger();
logger->push_task("Running application bootloader");
// Allocate game context // Allocate game context
game::context* ctx = new game::context(); game::context* ctx = new game::context();
ctx->app = app; ctx->app = app;
@ -150,31 +148,22 @@ void enter(application* app, int argc, char** argv)
return; return;
} }
logger->pop_task(EXIT_SUCCESS);
// Set update rate // Set update rate
if (ctx->config->contains("update_rate")) if (ctx->config->contains("update_rate"))
{ {
app->set_update_rate((*ctx->config)["update_rate"].get<double>()); app->set_update_rate((*ctx->config)["update_rate"].get<double>());
} }
// Setup initial application state
application::state initial_state;
initial_state.name = "loading";
initial_state.enter = std::bind(game::state::loading::enter, ctx);
initial_state.exit = std::bind(game::state::loading::exit, ctx);
// Enter initial application state
app->change_state(initial_state);
return;
// Queue next application state
application::state next_state;
next_state.name = "loading";
next_state.enter = std::bind(game::state::loading::enter, ctx);
next_state.exit = std::bind(game::state::loading::exit, ctx);
app->queue_state(next_state);
} }
void exit(application* app) void exit(application* app)
{
}
{}
void parse_options(game::context* ctx, int argc, char** argv) void parse_options(game::context* ctx, int argc, char** argv)
{ {
@ -289,10 +278,10 @@ void setup_resources(game::context* ctx)
// Redirect logger output to log file on non-debug builds // Redirect logger output to log file on non-debug builds
#if defined(NDEBUG) #if defined(NDEBUG)
std::string log_filename = config_path + "log.txt";
std::string log_filename = ctx->config_path + "log.txt";
ctx->log_filestream.open(log_filename.c_str()); ctx->log_filestream.open(log_filename.c_str());
ctx->log_filestream << logger->get_history(); ctx->log_filestream << logger->get_history();
logger->redirect(&log_filestream);
logger->redirect(&ctx->log_filestream);
#endif #endif
// Scan for mods // Scan for mods

+ 4
- 4
src/game/states/loading.cpp View File

@ -33,7 +33,7 @@
#include "entity/archetype.hpp" #include "entity/archetype.hpp"
#include "game/states/nuptial-flight.hpp" #include "game/states/nuptial-flight.hpp"
#include "game/states/splash.hpp" #include "game/states/splash.hpp"
#include "game/states/forage.hpp"
#include "game/states/main-menu.hpp"
#include "game/controls.hpp" #include "game/controls.hpp"
#include "geom/spherical.hpp" #include "geom/spherical.hpp"
#include "gl/drawing-mode.hpp" #include "gl/drawing-mode.hpp"
@ -132,9 +132,9 @@ void enter(game::context* ctx)
application::state next_state; application::state next_state;
if (ctx->option_quick_start.has_value()) if (ctx->option_quick_start.has_value())
{ {
next_state.name = "forage";
next_state.enter = std::bind(game::state::forage::enter, ctx);
next_state.exit = std::bind(game::state::forage::exit, ctx);
next_state.name = "main_menu";
next_state.enter = std::bind(game::state::main_menu::enter, ctx);
next_state.exit = std::bind(game::state::main_menu::exit, ctx);
} }
else else
{ {

+ 166
- 2
src/game/states/main-menu.cpp View File

@ -18,6 +18,16 @@
*/ */
#include "game/states/main-menu.hpp" #include "game/states/main-menu.hpp"
#include "game/states/forage.hpp"
#include "game/states/nuptial-flight.hpp"
#include "render/passes/clear-pass.hpp"
#include "resources/resource-manager.hpp"
#include "render/model.hpp"
#include "animation/screen-transition.hpp"
#include "animation/ease.hpp"
#include "animation/timeline.hpp"
#include "application.hpp"
#include <limits>
namespace game { namespace game {
namespace state { namespace state {
@ -25,12 +35,166 @@ namespace main_menu {
void enter(game::context* ctx) void enter(game::context* ctx)
{ {
ctx->ui_clear_pass->set_cleared_buffers(true, true, false);
// Construct main menu texts
ctx->main_menu_start_text = new scene::text();
ctx->main_menu_options_text = new scene::text();
ctx->main_menu_credits_text = new scene::text();
ctx->main_menu_quit_text = new scene::text();
// Set content of texts
ctx->main_menu_start_text->set_content((*ctx->strings)["main_menu_start"]);
ctx->main_menu_options_text->set_content((*ctx->strings)["main_menu_options"]);
ctx->main_menu_credits_text->set_content((*ctx->strings)["main_menu_credits"]);
ctx->main_menu_quit_text->set_content((*ctx->strings)["main_menu_quit"]);
std::vector<scene::text*> texts;
texts.push_back(ctx->main_menu_start_text);
texts.push_back(ctx->main_menu_options_text);
texts.push_back(ctx->main_menu_credits_text);
texts.push_back(ctx->main_menu_quit_text);
float offset_y = 0.0f;
for (scene::text* text: texts)
{
text->set_material(&ctx->menu_font_material);
text->set_font(&ctx->menu_font);
text->set_color({1.0f, 1.0f, 1.0f, 0.5f});
ctx->ui_scene->add_object(text);
// Align text
const auto& text_aabb = static_cast<const geom::aabb<float>&>(text->get_local_bounds());
float title_w = text_aabb.max_point.x - text_aabb.min_point.x;
float title_h = text_aabb.max_point.y - text_aabb.min_point.y;
text->set_translation({std::round(-title_w * 0.5f), std::round(-title_h * 0.5f) + offset_y, 0.0f});
offset_y -= ctx->menu_font.get_font_metrics().linespace * 1.5f;
// Update menu AABB
}
// Load pointer
ctx->ui_pointer = new scene::model_instance();
ctx->ui_pointer->set_model(ctx->resource_manager->load<render::model>("pointer.mdl"));
ctx->ui_scene->add_object(ctx->ui_pointer);
// Scale and position pointer
float pointer_scale = (ctx->menu_font.get_font_metrics().ascent - ctx->menu_font.get_font_metrics().descent) * (1.0f/3.0f);
ctx->ui_pointer->set_scale({pointer_scale, pointer_scale, pointer_scale});
float advance_x = ctx->menu_font.get_glyph_metrics(U' ').horizontal_advance * 2.0f;
const auto& text_aabb = static_cast<const geom::aabb<float>&>(ctx->main_menu_start_text->get_local_bounds());
const auto& text_translation = ctx->main_menu_start_text->get_translation();
ctx->ui_pointer->set_translation(text_translation + float3{-advance_x, (text_aabb.max_point.y - text_aabb.min_point.y) * 0.5f, 0.0f});
ctx->main_menu_start_text->set_color({1.0f, 1.0f, 1.0f, 1.0f});
ctx->controls["menu_down"]->set_activated_callback
(
[ctx]()
{
ctx->ui_pointer->set_translation(ctx->ui_pointer->get_translation() - float3{0.0f, ctx->menu_font.get_font_metrics().linespace * 1.5f, 0.0f});
}
);
ctx->controls["menu_up"]->set_activated_callback
(
[ctx]()
{
ctx->ui_pointer->set_translation(ctx->ui_pointer->get_translation() + float3{0.0f, ctx->menu_font.get_font_metrics().linespace * 1.5f, 0.0f});
}
);
ctx->controls["menu_select"]->set_activated_callback
(
[ctx]()
{
// Disable menu controls
ctx->controls["menu_down"]->set_activated_callback(nullptr);
ctx->controls["menu_up"]->set_activated_callback(nullptr);
ctx->controls["menu_select"]->set_activated_callback(nullptr);
// Create change state functions
auto change_state_nuptial_flight = [ctx]()
{
application::state next_state;
next_state.name = "nuptial_flight";
next_state.enter = std::bind(game::state::nuptial_flight::enter, ctx);
next_state.exit = std::bind(game::state::nuptial_flight::exit, ctx);
ctx->app->change_state(next_state);
};
// Set up timing
const float fade_out_duration = 1.0f;
// Schedule state change
timeline* timeline = ctx->timeline;
float t = timeline->get_position();
timeline::sequence sequence =
{
{t + fade_out_duration, change_state_nuptial_flight}
};
timeline->add_sequence(sequence);
// Start fade out to white
ctx->fade_transition_color->set_value({1, 1, 1});
ctx->fade_transition->transition(fade_out_duration, false, ease<float>::out_quad, false);
}
);
// Disable control callbacks
ctx->controls["menu_down"]->set_callbacks_enabled(false);
ctx->controls["menu_up"]->set_callbacks_enabled(false);
ctx->controls["menu_select"]->set_callbacks_enabled(false);
// Start fade in from black
const float fade_in_duration = 0.5f;
ctx->fade_transition_color->set_value({0, 0, 0});
ctx->fade_transition->transition(fade_in_duration, true, ease<float>::in_quad);
// Schedule enabling of control callbacks
auto enable_control_callbacks = [ctx]()
{
ctx->controls["menu_down"]->set_callbacks_enabled(true);
ctx->controls["menu_up"]->set_callbacks_enabled(true);
ctx->controls["menu_select"]->set_callbacks_enabled(true);
};
timeline* timeline = ctx->timeline;
float t = timeline->get_position();
timeline::sequence sequence =
{
{t + fade_in_duration, enable_control_callbacks}
};
timeline->add_sequence(sequence);
} }
void exit(game::context* ctx) void exit(game::context* ctx)
{ {
// Remove control callbacks
ctx->controls["menu_down"]->set_activated_callback(nullptr);
ctx->controls["menu_up"]->set_activated_callback(nullptr);
ctx->controls["menu_select"]->set_activated_callback(nullptr);
// Remove text objects from UI
std::vector<scene::text*> texts;
texts.push_back(ctx->main_menu_start_text);
texts.push_back(ctx->main_menu_options_text);
texts.push_back(ctx->main_menu_credits_text);
texts.push_back(ctx->main_menu_quit_text);
for (scene::text* text: texts)
{
ctx->ui_scene->remove_object(text);
delete text;
text = nullptr;
}
// Remove pointer from UI
ctx->ui_scene->remove_object(ctx->ui_pointer);
delete ctx->ui_pointer;
ctx->ui_pointer = nullptr;
ctx->ui_clear_pass->set_cleared_buffers(false, true, false);
} }
} // namespace main_menu } // namespace main_menu

+ 1
- 17
src/game/states/nuptial-flight.cpp View File

@ -66,22 +66,6 @@ void enter(game::context* ctx)
ctx->astronomy_system->set_observer_location(double3{observer.elevation, observer.latitude, observer.longitude}); ctx->astronomy_system->set_observer_location(double3{observer.elevation, observer.latitude, observer.longitude});
} }
// Create wing
entity::archetype* ant_forewing_archetype = ctx->resource_manager->load<entity::archetype>("ant-forewing.ent");
auto forewing_eid = ctx->entity_registry->create();
//ant_forewing_archetype->assign(*ctx->entity_registry, forewing_eid);
// Create eye
entity::archetype* ant_round_eye_archetype = ctx->resource_manager->load<entity::archetype>("ant-round-eye.ent");
auto ant_round_eye_eid = ctx->entity_registry->create();
ant_round_eye_archetype->assign(*ctx->entity_registry, ant_round_eye_eid);
entity::command::assign_render_layers(*ctx->entity_registry, ant_round_eye_eid, 0b10);
// Create green orb ring
entity::archetype* orb_ring_archetype = ctx->resource_manager->load<entity::archetype>("orb-ring.ent");
auto orb_ring_eid = ctx->entity_registry->create();
//orb_ring_archetype->assign(*ctx->entity_registry, orb_ring_eid);
// Setup camera // Setup camera
ctx->surface_camera->look_at({0, 0, 1}, {0, 0, 0}, {0, 1, 0}); ctx->surface_camera->look_at({0, 0, 1}, {0, 0, 0}, {0, 1, 0});
ctx->surface_camera->set_exposure(-14.5f); ctx->surface_camera->set_exposure(-14.5f);
@ -94,7 +78,7 @@ void enter(game::context* ctx)
// Start fade in from white // Start fade in from white
ctx->fade_transition_color->set_value({1, 1, 1}); ctx->fade_transition_color->set_value({1, 1, 1});
ctx->fade_transition->transition(2.0f, true, ease<float>::in_quad);
ctx->fade_transition->transition(5.0f, true, math::lerp<float, float>);
} }
void exit(game::context* ctx) void exit(game::context* ctx)

+ 5
- 0
src/game/states/splash.cpp View File

@ -23,6 +23,7 @@
#include "animation/ease.hpp" #include "animation/ease.hpp"
#include "animation/timeline.hpp" #include "animation/timeline.hpp"
#include "application.hpp" #include "application.hpp"
#include "render/passes/clear-pass.hpp"
namespace game { namespace game {
namespace state { namespace state {
@ -30,6 +31,8 @@ namespace splash {
void enter(game::context* ctx) void enter(game::context* ctx)
{ {
ctx->ui_clear_pass->set_cleared_buffers(true, true, false);
// Add splash billboard to UI scene // Add splash billboard to UI scene
ctx->ui_scene->add_object(ctx->splash_billboard); ctx->ui_scene->add_object(ctx->splash_billboard);
@ -102,6 +105,8 @@ void exit(game::context* ctx)
// Remove splash billboard from UI scene // Remove splash billboard from UI scene
ctx->ui_scene->remove_object(ctx->splash_billboard); ctx->ui_scene->remove_object(ctx->splash_billboard);
ctx->ui_clear_pass->set_cleared_buffers(false, true, false);
} }
} // namespace splash } // namespace splash

+ 6
- 0
src/game/states/title.cpp View File

@ -25,6 +25,7 @@
#include "application.hpp" #include "application.hpp"
#include "scene/text.hpp" #include "scene/text.hpp"
#include "configuration.hpp" #include "configuration.hpp"
#include "render/passes/clear-pass.hpp"
namespace game { namespace game {
namespace state { namespace state {
@ -32,6 +33,8 @@ namespace title {
void enter(game::context* ctx) void enter(game::context* ctx)
{ {
ctx->ui_clear_pass->set_cleared_buffers(true, true, false);
// Setup timing // Setup timing
const float title_fade_in_duration = 0.5f; const float title_fade_in_duration = 0.5f;
const float title_fade_out_duration = 0.5f; const float title_fade_out_duration = 0.5f;
@ -66,6 +69,7 @@ void enter(game::context* ctx)
{ {
ctx->timeline->clear(); ctx->timeline->clear();
ctx->fade_transition->get_animation()->stop(); ctx->fade_transition->get_animation()->stop();
ctx->fade_transition->get_billboard()->set_active(false);
ctx->rasterizer->set_clear_color(0.0f, 0.0f, 0.0f, 1.0f); ctx->rasterizer->set_clear_color(0.0f, 0.0f, 0.0f, 1.0f);
ctx->rasterizer->clear_framebuffer(true, false, false); ctx->rasterizer->clear_framebuffer(true, false, false);
ctx->app->swap_buffers(); ctx->app->swap_buffers();
@ -125,6 +129,8 @@ void exit(game::context* ctx)
// Disable title skipper // Disable title skipper
ctx->input_listener->set_enabled(false); ctx->input_listener->set_enabled(false);
ctx->input_listener->set_callback(nullptr); ctx->input_listener->set_callback(nullptr);
ctx->ui_clear_pass->set_cleared_buffers(false, true, false);
} }
} // namespace title } // namespace title

+ 1
- 1
src/type/font-metrics.hpp View File

@ -36,7 +36,7 @@ struct font_metrics
/// Distance that must be placed between two lines of text. /// Distance that must be placed between two lines of text.
float linegap; float linegap;
/// Baseline-to-baseline distance, computed as ascent - descent + linegap`.
/// Baseline-to-baseline distance, computed as `ascent - descent + linegap`.
float linespace; float linespace;
/// Vertical position of an underline. /// Vertical position of an underline.

+ 2
- 2
src/type/freetype/typeface.cpp View File

@ -56,8 +56,8 @@ bool typeface::get_metrics(float height, font_metrics& metrics) const
// Get font metrics // Get font metrics
metrics.ascent = face->size->metrics.ascender / 64.0f; metrics.ascent = face->size->metrics.ascender / 64.0f;
metrics.descent = face->size->metrics.descender / 64.0f; metrics.descent = face->size->metrics.descender / 64.0f;
metrics.linegap = face->size->metrics.height / 64.0f;
metrics.linespace = metrics.ascent - metrics.descent + metrics.linegap;
metrics.linespace = face->size->metrics.height / 64.0f;
metrics.linegap = metrics.linespace - (metrics.ascent - metrics.descent);
metrics.underline_position = FT_MulFix(face->underline_position, face->size->metrics.y_scale) / 64.0f; metrics.underline_position = FT_MulFix(face->underline_position, face->size->metrics.y_scale) / 64.0f;
metrics.underline_thickness = FT_MulFix(face->underline_thickness, face->size->metrics.y_scale) / 64.0f; metrics.underline_thickness = FT_MulFix(face->underline_thickness, face->size->metrics.y_scale) / 64.0f;
metrics.max_horizontal_advance = face->size->metrics.max_advance / 64.0f; metrics.max_horizontal_advance = face->size->metrics.max_advance / 64.0f;

Loading…
Cancel
Save