MethaneKit

Форк
0
/
TypographyApp.cpp 
580 строк · 22.8 Кб
1
/******************************************************************************
2

3
Copyright 2020 Evgeny Gorodetskiy
4

5
Licensed under the Apache License, Version 2.0 (the "License"),
6
you may not use this file except in compliance with the License.
7
You may obtain a copy of the License at
8

9
    http://www.apache.org/licenses/LICENSE-2.0
10

11
Unless required by applicable law or agreed to in writing, software
12
distributed under the License is distributed on an "AS IS" BASIS,
13
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
See the License for the specific language governing permissions and
15
limitations under the License.
16

17
*******************************************************************************
18

19
FILE: TypographyApp.cpp
20
Tutorial demonstrating dynamic text rendering and fonts management with Methane Kit.
21

22
******************************************************************************/
23

24
#include "TypographyApp.h"
25
#include "TypographyAppController.h"
26

27
#include <Methane/Tutorials/AppSettings.h>
28
#include <Methane/Data/TimeAnimation.h>
29

30
#include <magic_enum.hpp>
31
#include <array>
32

33
namespace Methane::Tutorials
34
{
35

36
struct FontSettings
37
{
38
    gui::Font::Description desc;
39
    gfx::Color3F           color;
40
};
41

42
constexpr int32_t g_margin_size_in_dots  = 32;
43
constexpr int32_t g_top_text_pos_in_dots = 110;
44
constexpr size_t  g_text_blocks_count    = 3;
45

46
static const std::array<FontSettings, g_text_blocks_count> g_font_settings { {
47
    { { "European",     "Fonts/Roboto/Roboto-Regular.ttf",                 20U }, { 1.F,  1.F,  0.5F } },
48
    { { "Japanese",     "Fonts/SawarabiMincho/SawarabiMincho-Regular.ttf", 20U }, { 1.F,  0.3F, 0.1F } },
49
    { { "Calligraphic", "Fonts/Playball/Playball-Regular.ttf",             20U }, { 0.5F, 1.F,  0.5F } }
50
} };
51

52
static const gfx::Color3F g_misc_font_color { 1.F, 1.F, 1.F };
53
static const std::map<std::string, gfx::Color3F, std::less<>> g_font_color_by_name   {
54
    { g_font_settings[0].desc.name, g_font_settings[0].color },
55
    { g_font_settings[1].desc.name, g_font_settings[1].color },
56
    { g_font_settings[2].desc.name, g_font_settings[2].color },
57
};
58

59
// Pangrams from http://clagnut.com/blog/2380/
60
static const std::array<std::u32string, g_text_blocks_count> g_text_blocks = { {
61
    // 0: european pangrams
62
    gui::Font::ConvertUtf8To32(
63
        "The quick brown fox jumps over the lazy dog!\n" \
64
         "Съешь ещё этих мягких французских булок, да выпей чаю.\n" \
65
         "Ο καλύμνιος σφουγγαράς ψιθύρισε πως θα βουτήξει χωρίς να διστάζει.\n" \
66
         "Pijamalı hasta, yağız şoföre çabucak güvendi."),
67

68
    // 1: japanese pangram
69
    gui::Font::ConvertUtf8To32(
70
        "いろはにほへと ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさきゆめみし ゑひもせす"),
71

72
    // 2: hitchhiker's guide quote
73
    gui::Font::ConvertUtf8To32(
74
        "A towel is about the most massively useful thing an interstellar hitchhiker can have. " \
75
        "Partly it has great practical value. You can wrap it around you for warmth as you bound across the cold moons of Jaglan Beta; " \
76
        "you can lie on it on the brilliant marble-sanded beaches of Santraginus V, inhaling the heady sea vapors; " \
77
        "you can sleep under it beneath the stars which shine so redly on the desert world of Kakrafoon; " \
78
        "use it to sail a miniraft down the slow heavy River Moth; " \
79
        "wet it for use in hand-to-hand-combat; " \
80
        "wrap it round your head to ward off noxious fumes or avoid the gaze of the Ravenous Bugblatter Beast of Traal " \
81
        "(such a mind-boggingly stupid animal, it assumes that if you can't see it, it can't see you); " \
82
        "you can wave your towel in emergencies as a distress signal, and of course dry yourself off with it if it still seems to be clean enough.")
83
}};
84

85
static const std::map<pin::Keyboard::State, TypographyAppAction> g_typography_action_by_keyboard_state{
86
    { { pin::Keyboard::Key::W       }, TypographyAppAction::SwitchTextWrapMode            },
87
    { { pin::Keyboard::Key::H       }, TypographyAppAction::SwitchTextHorizontalAlignment },
88
    { { pin::Keyboard::Key::V       }, TypographyAppAction::SwitchTextVerticalAlignment   },
89
    { { pin::Keyboard::Key::U       }, TypographyAppAction::SwitchIncrementalTextUpdate   },
90
    { { pin::Keyboard::Key::D       }, TypographyAppAction::SwitchTypingDirection         },
91
    { { pin::Keyboard::Key::Equal   }, TypographyAppAction::SpeedupTyping                 },
92
    { { pin::Keyboard::Key::Minus   }, TypographyAppAction::SlowdownTyping                },
93
};
94

95
[[nodiscard]]
96
static gui::UnitRect GetTextBlockRectInDots(size_t block_index, int32_t vertical_pos_in_dots, const gfx::FrameSize& frame_size_in_dots)
97
{
98
    return gui::UnitRect(
99
        gui::Units::Dots,
100
        gfx::Point2I
101
        {
102
            g_margin_size_in_dots,
103
            vertical_pos_in_dots
104
        },
105
        gfx::FrameSize
106
        {
107
            frame_size_in_dots.GetWidth() - 2 * g_margin_size_in_dots,
108
            block_index == g_text_blocks_count - 1
109
                ? frame_size_in_dots.GetHeight() - vertical_pos_in_dots - g_margin_size_in_dots  // last text block fills all available space
110
                : 0U                                                                        // other text blocks have calculated height
111
        }
112
    );
113
}
114

115
inline Timer::TimeDuration UpdateTextRect(gui::TextItem& text, const gui::UnitRect& text_block_rect)
116
{
117
    Methane::ScopeTimer scope_timer("Text update");
118
    text.SetRect(text_block_rect);
119
    return scope_timer.GetElapsedDuration();
120
}
121

122
inline Timer::TimeDuration UpdateText(const gui::Text& text, const std::u32string& displayed_text, const gui::UnitRect& text_block_rect)
123
{
124
    Methane::ScopeTimer scope_timer("Text update");
125
    text.SetTextInScreenRect(displayed_text, text_block_rect);
126
    return scope_timer.GetElapsedDuration();
127
}
128

129
TypographyApp::TypographyApp()
130
    : UserInterfaceApp(
131
        GetGraphicsTutorialAppSettings("Methane Typography", AppOptions::GetDefaultWithColorOnlyAndAnim()),
132
        { gui::HeadsUpDisplayMode::UserInterface },
133
        "Dynamic text rendering and fonts management tutorial.")
134
    , m_font_context(UserInterfaceApp::GetFontContext().GetFontLibrary(), Data::FontProvider::Get())
135
{
136
    m_displayed_text_lengths.resize(g_text_blocks_count, 0);
137
    m_displayed_text_lengths[0] = 1;
138

139
    GetHeadsUpDisplaySettings().position = gui::UnitPoint(gui::Units::Dots, g_margin_size_in_dots, g_margin_size_in_dots);
140

141
    m_font_context.GetFontLibrary().Connect(*this);
142
    AddInputControllers({
143
        std::make_shared<TypographyAppController>(*this, g_typography_action_by_keyboard_state)
144
    });
145

146
    // Setup animations
147
    GetAnimations().push_back(
148
        std::make_shared<Data::TimeAnimation>(std::bind(&TypographyApp::Animate, this, std::placeholders::_1, std::placeholders::_2))
149
    );
150

151
    ShowParameters();
152
}
153

154
TypographyApp::~TypographyApp()
155
{
156
    // Wait for GPU rendering is completed to release resources
157
    WaitForRenderComplete();
158

159
    // Clear the font library to release all atlas textures
160
    m_font_context.GetFontLibrary().Clear();
161
    m_font_atlas_badges.clear();
162
}
163

164
void TypographyApp::Init()
165
{
166
    UserInterfaceApp::Init();
167

168
    const gfx::FrameSize frame_size_in_dots = GetFrameSizeInDots();
169
    const uint32_t frame_width_without_margins = frame_size_in_dots.GetWidth() - 2 * g_margin_size_in_dots;
170
    int32_t vertical_text_pos_in_dots = g_top_text_pos_in_dots;
171

172
    for(size_t block_index = 0; block_index < g_text_blocks_count; ++block_index)
173
    {
174
        const FontSettings& font_settings = g_font_settings[block_index];
175
        const size_t displayed_text_length = m_displayed_text_lengths[block_index];
176
        const std::u32string displayed_text_block = g_text_blocks[block_index].substr(0, displayed_text_length);
177

178
        // Add font to library
179
        m_fonts.push_back(
180
            m_font_context.GetFont(
181
                gui::Font::Settings
182
                {
183
                    font_settings.desc,
184
                    GetUIContext().GetFontResolutionDpi(),
185
                    gui::Font::GetAlphabetFromText(displayed_text_block)
186
                }
187
            )
188
        );
189

190
        // Add text element
191
        m_texts.push_back(
192
            std::make_shared<gui::TextItem>(GetUIContext(), m_fonts.back(),
193
                gui::Text::SettingsUtf32
194
                {
195
                    font_settings.desc.name,
196
                    displayed_text_block,
197
                    gui::UnitRect
198
                    {
199
                        gui::Units::Dots,
200
                        gfx::Point2I { g_margin_size_in_dots, vertical_text_pos_in_dots },
201
                        gfx::FrameSize { frame_width_without_margins, 0U /* calculated height */ }
202
                    },
203
                    m_settings.text_layout,
204
                    gfx::Color4F(font_settings.color, 1.F),
205
                    m_settings.is_incremental_text_update
206
                }
207
            )
208
        );
209

210
        vertical_text_pos_in_dots = m_texts.back()->GetRectInDots().GetBottom() + g_margin_size_in_dots;
211
    }
212

213
    UpdateFontAtlasBadges();
214

215
    // Create per-frame command lists
216
    for(TypographyFrame& frame : GetFrames())
217
    {
218
        frame.render_cmd_list = GetRenderContext().GetRenderCommandKit().GetQueue().CreateRenderCommandList(frame.screen_pass);
219
        frame.render_cmd_list.SetName(fmt::format("Text Rendering {}", frame.index));
220
        frame.execute_cmd_list_set = rhi::CommandListSet({ frame.render_cmd_list.GetInterface() }, frame.index);
221
    }
222

223
    CompleteInitialization();
224
}
225

226
Ptr<gui::Badge> TypographyApp::CreateFontAtlasBadge(const gui::Font& font, const rhi::Texture& atlas_texture)
227
{
228
    const auto font_color_by_name_it = g_font_color_by_name.find(font.GetSettings().description.name);
229
    const gui::Color3F& font_color = font_color_by_name_it != g_font_color_by_name.end()
230
                                   ? font_color_by_name_it->second : g_misc_font_color;
231

232
    return std::make_shared<gui::Badge>(
233
        GetUIContext(), atlas_texture,
234
        gui::Badge::Settings
235
        {
236
            font.GetSettings().description.name + " Font Atlas",
237
            gui::Badge::FrameCorner::BottomLeft,
238
            gui::UnitSize(gui::Units::Pixels, static_cast<const gfx::FrameSize&>(atlas_texture.GetSettings().dimensions)),
239
            gui::UnitSize(gui::Units::Dots, 16U, 16U),
240
            gui::Color4F(font_color, 0.5F),
241
            gui::Badge::TextureMode::RFloatToAlpha,
242
        }
243
    );
244
}
245

246
void TypographyApp::UpdateFontAtlasBadges()
247
{
248
    const std::vector<gui::Font> fonts = m_font_context.GetFontLibrary().GetFonts();
249
    const rhi::RenderContext&  context = GetRenderContext();
250

251
    // Remove obsolete font atlas badges
252
    for(auto badge_it = m_font_atlas_badges.begin(); badge_it != m_font_atlas_badges.end();)
253
    {
254
        META_CHECK_ARG_NOT_NULL(*badge_it);
255
        if (const gui::Badge& badge = **badge_it;
256
            std::any_of(fonts.begin(), fonts.end(),
257
                [&badge, &context](const gui::Font& font)
258
                { return badge.GetTexture() == font.GetAtlasTexture(context); }))
259
        {
260
            ++badge_it;
261
            continue;
262
        }
263

264
        badge_it = m_font_atlas_badges.erase(badge_it);
265
    }
266

267
    // Add new font atlas badges
268
    for(const gui::Font& font : fonts)
269
    {
270
        const rhi::Texture& font_atlas_texture = font.GetAtlasTexture(context);
271
        if (!font_atlas_texture.IsInitialized() ||
272
            std::any_of(m_font_atlas_badges.begin(), m_font_atlas_badges.end(),
273
                        [&font_atlas_texture](const Ptr<gui::Badge>& font_atlas_badge_ptr)
274
                        {
275
                            return font_atlas_badge_ptr->GetTexture() == font_atlas_texture;
276
                        }))
277
            continue;
278

279
        m_font_atlas_badges.emplace_back(CreateFontAtlasBadge(font, font_atlas_texture));
280
    }
281

282
    LayoutFontAtlasBadges(GetRenderContext().GetSettings().frame_size);
283
}
284

285
void TypographyApp::LayoutFontAtlasBadges(const gfx::FrameSize& frame_size)
286
{
287
    // Sort atlas badges by size so that largest are displayed first
288
    std::sort(m_font_atlas_badges.begin(), m_font_atlas_badges.end(),
289
              [](const Ptr<gui::Badge>& left_ptr, const Ptr<gui::Badge>& right_ptr)
290
              {
291
                  return left_ptr->GetQuadSettings().screen_rect.size.GetPixelsCount() >
292
                         right_ptr->GetQuadSettings().screen_rect.size.GetPixelsCount();
293
              }
294
    );
295

296
    // Layout badges in a row one after another with a margin spacing
297
    gui::UnitSize badge_margins(gui::Units::Dots, g_margin_size_in_dots, g_margin_size_in_dots);
298
    for(const Ptr<gui::Badge>& badge_atlas_ptr : m_font_atlas_badges)
299
    {
300
        META_CHECK_ARG_NOT_NULL(badge_atlas_ptr);
301
        const gui::UnitSize atlas_size = GetUIContext().ConvertTo<gui::Units::Dots>(badge_atlas_ptr->GetTexture().GetSettings().dimensions.AsRectSize());
302
        badge_atlas_ptr->FrameResize(gui::UnitSize(gui::Units::Pixels, frame_size), atlas_size, badge_margins);
303
        badge_margins += gui::UnitSize(gui::Units::Dots, atlas_size.GetWidth() + g_margin_size_in_dots, 0U);
304
    }
305
}
306

307
bool TypographyApp::Resize(const gfx::FrameSize& frame_size, bool is_minimized)
308
{
309
    // Resize screen color and depth textures
310
    if (!UserInterfaceApp::Resize(frame_size, is_minimized))
311
        return false;
312

313
    const gfx::FrameSize frame_size_in_dots = GetFrameSizeInDots();
314
    int32_t       vertical_text_pos_in_dots = g_top_text_pos_in_dots;
315

316
    for (size_t block_index = 0; block_index < g_text_blocks_count; ++block_index)
317
    {
318
        const Ptr<gui::TextItem>& text_ptr = m_texts[block_index];
319
        const gui::UnitRect text_block_rect = GetTextBlockRectInDots(block_index, vertical_text_pos_in_dots, frame_size_in_dots);
320
        m_text_update_duration = UpdateTextRect(*text_ptr, text_block_rect);
321
        vertical_text_pos_in_dots += text_ptr->GetRectInDots().size.GetHeight() + g_margin_size_in_dots;
322
    }
323

324
    LayoutFontAtlasBadges(frame_size);
325
    UpdateParametersText(); // show text update timing
326
    return true;
327
}
328

329
bool TypographyApp::Animate(double elapsed_seconds, double)
330
{
331
    if (elapsed_seconds - m_text_update_elapsed_sec < m_settings.typing_update_interval_sec)
332
        return true;
333

334
    m_text_update_elapsed_sec = elapsed_seconds;
335

336
    int32_t vertical_text_pos_in_dots = g_top_text_pos_in_dots;
337
    for(size_t block_index = 0; block_index < g_text_blocks_count; ++block_index)
338
    {
339
        AnimateTextBlock(block_index, vertical_text_pos_in_dots);
340
    }
341

342
    UpdateParametersText();
343
    return true;
344
}
345

346
void TypographyApp::AnimateTextBlock(size_t block_index, int32_t& vertical_text_pos_in_dots)
347
{
348
    const gui::TextItem& text       = *m_texts[block_index];
349
    const std::u32string& full_text = g_text_blocks[block_index];
350
    const size_t text_block_length  = full_text.length();
351
    size_t& displayed_text_length   = m_displayed_text_lengths[block_index];
352

353
    if (displayed_text_length == (m_settings.is_forward_typing_direction ? 0 : text_block_length))
354
    {
355
        text.SetText(m_settings.is_forward_typing_direction ? std::u32string() : full_text);
356
        if (!m_settings.is_forward_typing_direction)
357
            vertical_text_pos_in_dots = text.GetRectInDots().GetBottom() + g_margin_size_in_dots;
358
        return;
359
    }
360

361
    if (displayed_text_length == (m_settings.is_forward_typing_direction ? text_block_length : 0))
362
    {
363
        if (block_index == (m_settings.is_forward_typing_direction ? g_text_blocks_count - 1 : 0))
364
        {
365
            ResetAnimation();
366
            return;
367
        }
368

369
        vertical_text_pos_in_dots = text.GetRectInDots().GetBottom() + g_margin_size_in_dots;
370
        size_t next_block_index = block_index + (m_settings.is_forward_typing_direction ? 1 : -1);
371
        size_t& next_displayed_text_length = m_displayed_text_lengths[next_block_index];
372

373
        if (m_settings.is_forward_typing_direction && next_displayed_text_length == 0)
374
            next_displayed_text_length = 1;
375

376
        if (!m_settings.is_forward_typing_direction && next_displayed_text_length == g_text_blocks[next_block_index].length())
377
            next_displayed_text_length = g_text_blocks[next_block_index].length() - 1;
378

379
        return;
380
    }
381

382
    if (m_settings.is_forward_typing_direction)
383
        displayed_text_length++;
384
    else
385
        displayed_text_length--;
386

387
    const std::u32string displayed_text = full_text.substr(0, displayed_text_length);
388
    const gui::UnitRect  text_block_rect = GetTextBlockRectInDots(block_index, vertical_text_pos_in_dots, GetFrameSizeInDots());
389

390
    m_text_update_duration = UpdateText(text, displayed_text, text_block_rect);
391

392
    vertical_text_pos_in_dots = text.GetRectInDots().GetBottom() + g_margin_size_in_dots;
393
}
394

395
void TypographyApp::ResetAnimation()
396
{
397
    for(size_t block_index = 0; block_index < g_text_blocks_count; ++block_index)
398
    {
399
        const std::u32string& full_text = g_text_blocks[block_index];
400

401
        size_t displayed_text_length = block_index ? 0 : 1;
402
        if (!m_settings.is_forward_typing_direction)
403
        {
404
            displayed_text_length = full_text.length();
405
            if (block_index == g_text_blocks_count - 1)
406
                displayed_text_length--;
407
        }
408

409
        const std::u32string displayed_text = full_text.substr(0, displayed_text_length);
410
        m_displayed_text_lengths[block_index] = displayed_text_length;
411
        m_texts[block_index]->SetText(displayed_text);
412
        m_fonts[block_index].ResetChars(displayed_text);
413
    }
414
    
415
    LayoutFontAtlasBadges(GetRenderContext().GetSettings().frame_size);
416
}
417

418
bool TypographyApp::Update()
419
{
420
    if (!UserInterfaceApp::Update())
421
        return false;
422

423
    // Update text block resources
424
    for(const Ptr<gui::TextItem>& text_ptr : m_texts)
425
    {
426
        text_ptr->Update(GetFrameSize());
427
    }
428

429
    return true;
430
}
431

432
bool TypographyApp::Render()
433
{
434
    if (!UserInterfaceApp::Render())
435
        return false;
436

437
    const TypographyFrame& frame = GetCurrentFrame();
438

439
    // Draw text blocks
440
    META_DEBUG_GROUP_VAR(s_text_debug_group, "Text Blocks Rendering");
441
    for(const Ptr<gui::TextItem>& text_ptr : m_texts)
442
    {
443
        text_ptr->Draw(frame.render_cmd_list, &s_text_debug_group);
444
    }
445

446
    // Draw font atlas badges
447
    META_DEBUG_GROUP_VAR(s_atlas_debug_group, "Font Atlases Rendering");
448
    for(const Ptr<gui::Badge>& badge_atlas_ptr : m_font_atlas_badges)
449
    {
450
        badge_atlas_ptr->Draw(frame.render_cmd_list, &s_atlas_debug_group);
451
    }
452

453
    RenderOverlay(frame.render_cmd_list);
454
    frame.render_cmd_list.Commit();
455

456
    // Execute command list on render queue and present frame to screen
457
    GetRenderContext().GetRenderCommandKit().GetQueue().Execute(frame.execute_cmd_list_set);
458
    GetRenderContext().Present();
459

460
    return true;
461
}
462

463
std::string TypographyApp::GetParametersString()
464
{
465
    std::stringstream ss;
466
    ss << "Typography parameters:"
467
       << std::endl << "  - text wrap mode:            " << magic_enum::enum_name(m_settings.text_layout.wrap)
468
       << std::endl << "  - horizontal text alignment: " << magic_enum::enum_name(m_settings.text_layout.horizontal_alignment)
469
       << std::endl << "  - vertical text alignment:   " << magic_enum::enum_name(m_settings.text_layout.vertical_alignment)
470
       << std::endl << "  - text typing mode:          " << (m_settings.is_forward_typing_direction ? "Appending" : "Backspace")
471
       << std::endl << "  - text typing interval (ms): " << static_cast<uint32_t>(m_settings.typing_update_interval_sec * 1000)
472
       << std::endl << "  - text typing animation:     " << (!GetAnimations().IsPaused() ? "ON" : "OFF")
473
       << std::endl << "  - incremental text updates:  " << (m_settings.is_incremental_text_update ? "ON" : "OFF")
474
       << std::endl << "  - text update duration (us): " << static_cast<double>(m_text_update_duration.count()) / 1000;
475

476
    return ss.str();
477
}
478

479
void TypographyApp::SetTextLayout(const gui::Text::Layout& text_layout)
480
{
481
    if (m_settings.text_layout == text_layout)
482
        return;
483

484
    m_settings.text_layout = text_layout;
485
    for (const Ptr<gui::TextItem>& text_ptr : m_texts)
486
    {
487
        text_ptr->SetLayout(text_layout);
488
    }
489

490
    UpdateParametersText();
491
}
492

493
void TypographyApp::SetForwardTypingDirection(bool is_forward_typing_direction)
494
{
495
    if (m_settings.is_forward_typing_direction == is_forward_typing_direction)
496
        return;
497

498
    m_settings.is_forward_typing_direction = is_forward_typing_direction;
499
    UpdateParametersText();
500
}
501

502
void TypographyApp::SetTextUpdateInterval(double text_update_interval_sec)
503
{
504
    if (std::abs(m_settings.typing_update_interval_sec - text_update_interval_sec) < 0.000001)
505
        return;
506

507
    m_settings.typing_update_interval_sec = text_update_interval_sec;
508
    UpdateParametersText();
509
}
510

511
void TypographyApp::SetIncrementalTextUpdate(bool is_incremental_text_update)
512
{
513
    if (m_settings.is_incremental_text_update == is_incremental_text_update)
514
        return;
515

516
    m_settings.is_incremental_text_update = is_incremental_text_update;
517
    for(const Ptr<gui::TextItem>& text_ptr : m_texts)
518
    {
519
        text_ptr->SetIncrementalUpdate(is_incremental_text_update);
520
    }
521

522
    UpdateParametersText();
523
}
524

525
void TypographyApp::OnContextReleased(rhi::IContext& context)
526
{
527
    m_font_context.GetFontLibrary().Clear();
528

529
    m_fonts.clear();
530
    m_texts.clear();
531
    m_font_atlas_badges.clear();
532

533
    UserInterfaceApp::OnContextReleased(context);
534
}
535

536
void TypographyApp::OnFontAdded(gui::Font& font)
537
{
538
    font.Connect(*this);
539
}
540

541
void TypographyApp::OnFontAtlasTextureReset(gui::Font& font, const rhi::Texture* old_atlas_texture_ptr, const rhi::Texture* new_atlas_texture_ptr)
542
{
543
    const auto font_atlas_badge_ptr_it = old_atlas_texture_ptr
544
        ? std::find_if(m_font_atlas_badges.begin(), m_font_atlas_badges.end(),
545
                       [&old_atlas_texture_ptr](const Ptr<gui::Badge>& font_atlas_badge_ptr)
546
                       { return font_atlas_badge_ptr->GetTexture() == *old_atlas_texture_ptr; })
547
        : m_font_atlas_badges.end();
548

549
    if (new_atlas_texture_ptr)
550
    {
551
        if (font_atlas_badge_ptr_it == m_font_atlas_badges.end())
552
        {
553
            m_font_atlas_badges.emplace_back(CreateFontAtlasBadge(font, *new_atlas_texture_ptr));
554
            LayoutFontAtlasBadges(GetRenderContext().GetSettings().frame_size);
555
        }
556
        else
557
        {
558
            const Ptr<gui::Badge>& badge_ptr = *font_atlas_badge_ptr_it;
559
            badge_ptr->SetTexture(*new_atlas_texture_ptr);
560
            badge_ptr->SetSize(gui::UnitSize(gui::Units::Pixels, static_cast<const gfx::FrameSize&>(new_atlas_texture_ptr->GetSettings().dimensions)));
561
        }
562
    }
563
    else if (font_atlas_badge_ptr_it != m_font_atlas_badges.end())
564
    {
565
        m_font_atlas_badges.erase(font_atlas_badge_ptr_it);
566
        LayoutFontAtlasBadges(GetRenderContext().GetSettings().frame_size);
567
    }
568
}
569

570
void TypographyApp::OnFontAtlasUpdated(gui::Font&)
571
{
572
    LayoutFontAtlasBadges(GetRenderContext().GetSettings().frame_size);
573
}
574

575
} // namespace Methane::Tutorials
576

577
int main(int argc, const char* argv[])
578
{
579
    return Methane::Tutorials::TypographyApp().Run({ argc, argv });
580
}
581

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.