mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-07 23:53:58 +02:00
Add green outline to speaking video tiles.
This commit is contained in:
parent
b906b2f625
commit
ddf81c949b
5 changed files with 74 additions and 42 deletions
|
@ -1212,7 +1212,7 @@ groupCallNarrowIconSkip: 15px;
|
||||||
// fg: groupCallVideoTextFg;
|
// fg: groupCallVideoTextFg;
|
||||||
// icon: icon {{ "calls/voice_mute_mini", groupCallVideoTextFg }};
|
// icon: icon {{ "calls/voice_mute_mini", groupCallVideoTextFg }};
|
||||||
//}
|
//}
|
||||||
|
groupCallOutline: 2px;
|
||||||
groupCallLargeVideoCrossLine: CrossLineAnimation(groupCallMemberColoredCrossLine) {
|
groupCallLargeVideoCrossLine: CrossLineAnimation(groupCallMemberColoredCrossLine) {
|
||||||
fg: groupCallVideoTextFg;
|
fg: groupCallVideoTextFg;
|
||||||
icon: icon {{ "calls/video_over_mute", groupCallVideoTextFg }};
|
icon: icon {{ "calls/video_over_mute", groupCallVideoTextFg }};
|
||||||
|
|
|
@ -241,11 +241,13 @@ void Viewport::RendererGL::paint(
|
||||||
not_null<QOpenGLWidget*> widget,
|
not_null<QOpenGLWidget*> widget,
|
||||||
QOpenGLFunctions &f) {
|
QOpenGLFunctions &f) {
|
||||||
_factor = widget->devicePixelRatio();
|
_factor = widget->devicePixelRatio();
|
||||||
validateNames();
|
validateDatas();
|
||||||
fillBackground(f);
|
fillBackground(f);
|
||||||
auto index = 0;
|
auto index = 0;
|
||||||
for (const auto &tile : _owner->_tiles) {
|
for (const auto &tile : _owner->_tiles) {
|
||||||
paintTile(f, tile.get(), _nameData[_nameDataIndices[index++]]);
|
auto &data = _tileData[_tileDataIndices[index++]];
|
||||||
|
validateOutlineAnimation(tile.get(), data);
|
||||||
|
paintTile(f, tile.get(), data);
|
||||||
}
|
}
|
||||||
freeTextures(f);
|
freeTextures(f);
|
||||||
}
|
}
|
||||||
|
@ -278,7 +280,7 @@ void Viewport::RendererGL::fillBackground(QOpenGLFunctions &f) {
|
||||||
void Viewport::RendererGL::paintTile(
|
void Viewport::RendererGL::paintTile(
|
||||||
QOpenGLFunctions &f,
|
QOpenGLFunctions &f,
|
||||||
not_null<VideoTile*> tile,
|
not_null<VideoTile*> tile,
|
||||||
const NameData &nameData) {
|
const TileData &tileData) {
|
||||||
const auto track = tile->track();
|
const auto track = tile->track();
|
||||||
const auto data = track->frameWithInfo(false);
|
const auto data = track->frameWithInfo(false);
|
||||||
if (data.format == Webrtc::FrameFormat::None) {
|
if (data.format == Webrtc::FrameFormat::None) {
|
||||||
|
@ -369,8 +371,8 @@ void Viewport::RendererGL::paintTile(
|
||||||
- st::semiboldFont->height
|
- st::semiboldFont->height
|
||||||
+ nameShift));
|
+ nameShift));
|
||||||
const auto name = _names.texturedRect(
|
const auto name = _names.texturedRect(
|
||||||
QRect(namePosition, nameData.rect.size() / cIntRetinaFactor()),
|
QRect(namePosition, tileData.nameRect.size() / cIntRetinaFactor()),
|
||||||
nameData.rect,
|
tileData.nameRect,
|
||||||
geometry);
|
geometry);
|
||||||
const auto nameRect = transformRect(name.geometry);
|
const auto nameRect = transformRect(name.geometry);
|
||||||
|
|
||||||
|
@ -499,9 +501,17 @@ void Viewport::RendererGL::paintTile(
|
||||||
program->setUniformValue(
|
program->setUniformValue(
|
||||||
"frameBg",
|
"frameBg",
|
||||||
Uniform(st::groupCallMembersBg->c));
|
Uniform(st::groupCallMembersBg->c));
|
||||||
program->setUniformValue("roundRadius", radius * _factor);
|
const auto outline = tileData.outlined.value(tileData.outline ? 1. : 0.);
|
||||||
|
program->setUniformValue("radiusOutline", QVector2D(
|
||||||
|
radius * _factor,
|
||||||
|
(outline > 0) ? (st::groupCallOutline * _factor) : 0.f));
|
||||||
program->setUniformValue("roundRect", Uniform(rect));
|
program->setUniformValue("roundRect", Uniform(rect));
|
||||||
program->setUniformValue("roundBg", Uniform(st::groupCallBg->c));
|
program->setUniformValue("roundBg", Uniform(st::groupCallBg->c));
|
||||||
|
program->setUniformValue("outlineFg", QVector4D(
|
||||||
|
st::groupCallMemberActiveIcon->c.redF(),
|
||||||
|
st::groupCallMemberActiveIcon->c.greenF(),
|
||||||
|
st::groupCallMemberActiveIcon->c.blueF(),
|
||||||
|
st::groupCallMemberActiveIcon->c.alphaF() * outline));
|
||||||
|
|
||||||
const auto shadowHeight = st.shadowHeight * _factor;
|
const auto shadowHeight = st.shadowHeight * _factor;
|
||||||
const auto shadowAlpha = kShadowMaxAlpha / 255.f;
|
const auto shadowAlpha = kShadowMaxAlpha / 255.f;
|
||||||
|
@ -635,7 +645,7 @@ void Viewport::RendererGL::ensureButtonsImage() {
|
||||||
_buttons.setImage(std::move(image));
|
_buttons.setImage(std::move(image));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Viewport::RendererGL::validateNames() {
|
void Viewport::RendererGL::validateDatas() {
|
||||||
const auto &tiles = _owner->_tiles;
|
const auto &tiles = _owner->_tiles;
|
||||||
const auto &st = st::groupCallLargeVideo;
|
const auto &st = st::groupCallLargeVideo;
|
||||||
const auto count = int(tiles.size());
|
const auto count = int(tiles.size());
|
||||||
|
@ -647,10 +657,10 @@ void Viewport::RendererGL::validateNames() {
|
||||||
};
|
};
|
||||||
auto requests = std::vector<Request>();
|
auto requests = std::vector<Request>();
|
||||||
auto available = _names.image().width();
|
auto available = _names.image().width();
|
||||||
for (auto &data : _nameData) {
|
for (auto &data : _tileData) {
|
||||||
data.stale = true;
|
data.stale = true;
|
||||||
}
|
}
|
||||||
_nameDataIndices.resize(count);
|
_tileDataIndices.resize(count);
|
||||||
const auto nameWidth = [&](int i) {
|
const auto nameWidth = [&](int i) {
|
||||||
const auto row = tiles[i]->row();
|
const auto row = tiles[i]->row();
|
||||||
const auto hasWidth = tiles[i]->geometry().width()
|
const auto hasWidth = tiles[i]->geometry().width()
|
||||||
|
@ -669,60 +679,60 @@ void Viewport::RendererGL::validateNames() {
|
||||||
available = width;
|
available = width;
|
||||||
}
|
}
|
||||||
const auto peer = tiles[i]->row()->peer();
|
const auto peer = tiles[i]->row()->peer();
|
||||||
const auto j = ranges::find(_nameData, peer, &NameData::peer);
|
const auto j = ranges::find(_tileData, peer, &TileData::peer);
|
||||||
if (j != end(_nameData)) {
|
if (j != end(_tileData)) {
|
||||||
j->stale = false;
|
j->stale = false;
|
||||||
const auto index = (j - begin(_nameData));
|
const auto index = (j - begin(_tileData));
|
||||||
_nameDataIndices[i] = index;
|
_tileDataIndices[i] = index;
|
||||||
if (peer->nameVersion != j->nameVersion
|
if (peer->nameVersion != j->nameVersion
|
||||||
|| width != j->rect.width()) {
|
|| width != j->nameRect.width()) {
|
||||||
const auto nameTop = index * nameHeight;
|
const auto nameTop = index * nameHeight;
|
||||||
j->rect = QRect(0, nameTop, width, nameHeight);
|
j->nameRect = QRect(0, nameTop, width, nameHeight);
|
||||||
requests.push_back({ .index = i, .updating = true });
|
requests.push_back({ .index = i, .updating = true });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_nameDataIndices[i] = -1;
|
_tileDataIndices[i] = -1;
|
||||||
requests.push_back({ .index = i, .updating = false });
|
requests.push_back({ .index = i, .updating = false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (requests.empty()) {
|
if (requests.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto maybeStaleAfter = begin(_nameData);
|
auto maybeStaleAfter = begin(_tileData);
|
||||||
auto maybeStaleEnd = end(_nameData);
|
auto maybeStaleEnd = end(_tileData);
|
||||||
for (auto &request : requests) {
|
for (auto &request : requests) {
|
||||||
const auto i = request.index;
|
const auto i = request.index;
|
||||||
if (_nameDataIndices[i] >= 0) {
|
if (_tileDataIndices[i] >= 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto peer = tiles[i]->row()->peer();
|
const auto peer = tiles[i]->row()->peer();
|
||||||
auto index = int(_nameData.size());
|
auto index = int(_tileData.size());
|
||||||
maybeStaleAfter = ranges::find(
|
maybeStaleAfter = ranges::find(
|
||||||
maybeStaleAfter,
|
maybeStaleAfter,
|
||||||
maybeStaleEnd,
|
maybeStaleEnd,
|
||||||
true,
|
true,
|
||||||
&NameData::stale);
|
&TileData::stale);
|
||||||
if (maybeStaleAfter != maybeStaleEnd) {
|
if (maybeStaleAfter != maybeStaleEnd) {
|
||||||
index = (maybeStaleAfter - begin(_nameData));
|
index = (maybeStaleAfter - begin(_tileData));
|
||||||
maybeStaleAfter->peer = peer;
|
maybeStaleAfter->peer = peer;
|
||||||
maybeStaleAfter->stale = false;
|
maybeStaleAfter->stale = false;
|
||||||
request.updating = true;
|
request.updating = true;
|
||||||
} else {
|
} else {
|
||||||
// This invalidates maybeStale*, but they're already equal.
|
// This invalidates maybeStale*, but they're already equal.
|
||||||
_nameData.push_back({ .peer = peer });
|
_tileData.push_back({ .peer = peer });
|
||||||
}
|
}
|
||||||
_nameData[index].nameVersion = peer->nameVersion;
|
_tileData[index].nameVersion = peer->nameVersion;
|
||||||
_nameData[index].rect = QRect(
|
_tileData[index].nameRect = QRect(
|
||||||
0,
|
0,
|
||||||
index * nameHeight,
|
index * nameHeight,
|
||||||
nameWidth(i),
|
nameWidth(i),
|
||||||
nameHeight);
|
nameHeight);
|
||||||
_nameDataIndices[i] = index;
|
_tileDataIndices[i] = index;
|
||||||
}
|
}
|
||||||
auto image = _names.takeImage();
|
auto image = _names.takeImage();
|
||||||
const auto imageSize = QSize(
|
const auto imageSize = QSize(
|
||||||
available * factor,
|
available * factor,
|
||||||
_nameData.size() * nameHeight);
|
_tileData.size() * nameHeight);
|
||||||
const auto allocate = (image.size() != imageSize);
|
const auto allocate = (image.size() != imageSize);
|
||||||
auto paintToImage = allocate
|
auto paintToImage = allocate
|
||||||
? QImage(imageSize, QImage::Format_ARGB32_Premultiplied)
|
? QImage(imageSize, QImage::Format_ARGB32_Premultiplied)
|
||||||
|
@ -757,14 +767,14 @@ void Viewport::RendererGL::validateNames() {
|
||||||
p.setPen(st::groupCallVideoTextFg);
|
p.setPen(st::groupCallVideoTextFg);
|
||||||
for (const auto &request : requests) {
|
for (const auto &request : requests) {
|
||||||
const auto i = request.index;
|
const auto i = request.index;
|
||||||
const auto index = _nameDataIndices[i];
|
const auto index = _tileDataIndices[i];
|
||||||
const auto &data = _nameData[_nameDataIndices[i]];
|
const auto &data = _tileData[_tileDataIndices[i]];
|
||||||
const auto row = tiles[i]->row();
|
const auto row = tiles[i]->row();
|
||||||
if (request.updating) {
|
if (request.updating) {
|
||||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||||
p.fillRect(
|
p.fillRect(
|
||||||
0,
|
0,
|
||||||
data.rect.y() / factor,
|
data.nameRect.y() / factor,
|
||||||
paintToImage.width() / factor,
|
paintToImage.width() / factor,
|
||||||
nameHeight / factor,
|
nameHeight / factor,
|
||||||
Qt::transparent);
|
Qt::transparent);
|
||||||
|
@ -773,12 +783,27 @@ void Viewport::RendererGL::validateNames() {
|
||||||
row->name().drawLeftElided(
|
row->name().drawLeftElided(
|
||||||
p,
|
p,
|
||||||
0,
|
0,
|
||||||
data.rect.y() / factor,
|
data.nameRect.y() / factor,
|
||||||
data.rect.width() / factor,
|
data.nameRect.width() / factor,
|
||||||
paintToImage.width() / factor);
|
paintToImage.width() / factor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_names.setImage(std::move(paintToImage));
|
_names.setImage(std::move(paintToImage));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Viewport::RendererGL::validateOutlineAnimation(
|
||||||
|
not_null<VideoTile*> tile,
|
||||||
|
TileData &data) {
|
||||||
|
const auto outline = tile->row()->speaking();
|
||||||
|
if (data.outline == outline) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data.outline = outline;
|
||||||
|
data.outlined.start(
|
||||||
|
[=] { _owner->widget()->update(); },
|
||||||
|
outline ? 0. : 1.,
|
||||||
|
outline ? 1. : 0.,
|
||||||
|
st::fadeWrapDuration);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Calls::Group
|
} // namespace Calls::Group
|
||||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "calls/group/calls_group_viewport.h"
|
#include "calls/group/calls_group_viewport.h"
|
||||||
#include "ui/round_rect.h"
|
#include "ui/round_rect.h"
|
||||||
|
#include "ui/effects/animations.h"
|
||||||
#include "ui/effects/cross_line.h"
|
#include "ui/effects/cross_line.h"
|
||||||
#include "ui/gl/gl_surface.h"
|
#include "ui/gl/gl_surface.h"
|
||||||
#include "ui/gl/gl_image.h"
|
#include "ui/gl/gl_image.h"
|
||||||
|
@ -43,24 +44,30 @@ public:
|
||||||
QOpenGLFunctions &f) override;
|
QOpenGLFunctions &f) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct NameData {
|
struct TileData {
|
||||||
not_null<PeerData*> peer;
|
not_null<PeerData*> peer;
|
||||||
|
Ui::Animations::Simple outlined;
|
||||||
|
QRect nameRect;
|
||||||
int nameVersion = 0;
|
int nameVersion = 0;
|
||||||
QRect rect;
|
|
||||||
bool stale = false;
|
bool stale = false;
|
||||||
|
bool outline = false;
|
||||||
};
|
};
|
||||||
void fillBackground(QOpenGLFunctions &f);
|
void fillBackground(QOpenGLFunctions &f);
|
||||||
void paintTile(
|
void paintTile(
|
||||||
QOpenGLFunctions &f,
|
QOpenGLFunctions &f,
|
||||||
not_null<VideoTile*> tile,
|
not_null<VideoTile*> tile,
|
||||||
const NameData &nameData);
|
const TileData &nameData);
|
||||||
void freeTextures(QOpenGLFunctions &f);
|
void freeTextures(QOpenGLFunctions &f);
|
||||||
[[nodiscard]] Ui::GL::Rect transformRect(const QRect &raster) const;
|
[[nodiscard]] Ui::GL::Rect transformRect(const QRect &raster) const;
|
||||||
[[nodiscard]] Ui::GL::Rect transformRect(const Ui::GL::Rect &raster) const;
|
[[nodiscard]] Ui::GL::Rect transformRect(
|
||||||
|
const Ui::GL::Rect &raster) const;
|
||||||
|
|
||||||
void ensureARGB32Program();
|
void ensureARGB32Program();
|
||||||
void ensureButtonsImage();
|
void ensureButtonsImage();
|
||||||
void validateNames();
|
void validateDatas();
|
||||||
|
void validateOutlineAnimation(
|
||||||
|
not_null<VideoTile*> tile,
|
||||||
|
TileData &data);
|
||||||
|
|
||||||
const not_null<Viewport*> _owner;
|
const not_null<Viewport*> _owner;
|
||||||
|
|
||||||
|
@ -81,8 +88,8 @@ private:
|
||||||
QRect _muteOff;
|
QRect _muteOff;
|
||||||
|
|
||||||
Ui::GL::Image _names;
|
Ui::GL::Image _names;
|
||||||
std::vector<NameData> _nameData;
|
std::vector<TileData> _tileData;
|
||||||
std::vector<int> _nameDataIndices;
|
std::vector<int> _tileDataIndices;
|
||||||
|
|
||||||
std::vector<GLfloat> _bgTriangles;
|
std::vector<GLfloat> _bgTriangles;
|
||||||
std::vector<Textures> _texturesToFree;
|
std::vector<Textures> _texturesToFree;
|
||||||
|
|
|
@ -105,7 +105,7 @@ public:
|
||||||
std::optional<Participant> now;
|
std::optional<Participant> now;
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr auto kSoundStatusKeptFor = crl::time(350);
|
static constexpr auto kSoundStatusKeptFor = crl::time(1350);
|
||||||
|
|
||||||
[[nodiscard]] auto participants() const
|
[[nodiscard]] auto participants() const
|
||||||
-> const std::vector<Participant> &;
|
-> const std::vector<Participant> &;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit f475fe28e47af4408bc96ba63e63f599c02538ca
|
Subproject commit 5389de6b96f241d992eb93e515e4aefaaf4d86f9
|
Loading…
Add table
Reference in a new issue