Add Discord.user_avatar

This commit is contained in:
Inori 2019-09-05 02:13:43 -04:00
parent fa130126ba
commit 3fd0604f9f
5 changed files with 124 additions and 8 deletions

View file

@ -3,6 +3,7 @@
#include "discordstate.h"
#include "sharedstate.h"
#include "binding-util.h"
#include "binding-types.h"
//NYI
void discordResultCb(void *callback_data, enum EDiscordResult result)
@ -44,6 +45,22 @@ RB_METHOD(DiscordGetUserId)
return LL2NUM(shState->discord().userId());
}
void bitmapInitProps(Bitmap *b, VALUE self);
RB_METHOD(DiscordGetUserAvatar)
{
RB_UNUSED_PARAM;
Bitmap *result = shState->discord().userAvatar();
if (!result) return RUBY_Qnil;
VALUE ret = wrapObject(result, BitmapType);
bitmapInitProps(result, ret);
return ret;
}
RB_METHOD(DiscordActivitySend)
{
RB_UNUSED_PARAM;
@ -236,6 +253,7 @@ void DiscordBindingInit()
_rb_define_module_function(mod, "user_name", DiscordGetUsername);
_rb_define_module_function(mod, "user_discriminator", DiscordGetDiscriminator);
_rb_define_module_function(mod, "user_id", DiscordGetUserId);
_rb_define_module_function(mod, "user_avatar", DiscordGetUserAvatar);
VALUE activityClass = rb_define_class_under(mod, "Activity", rb_cObject);
#ifndef OLD_RUBY

View file

@ -307,6 +307,52 @@ Bitmap::Bitmap(int width, int height)
clear();
}
Bitmap::Bitmap(void *pixeldata, int width, int height)
{
SDL_Surface *surface = SDL_CreateRGBSurface(0, width, height, p->format->BitsPerPixel,
p->format->Rmask,
p->format->Gmask,
p->format->Bmask,
p->format->Amask);
if (!surface)
throw Exception(Exception::SDLError, "Error creating Bitmap: %s",
SDL_GetError());
memcpy(surface->pixels, pixeldata, width*height*(p->format->BitsPerPixel/8));
if (surface->w > glState.caps.maxTexSize || surface->h > glState.caps.maxTexSize)
{
p = new BitmapPrivate(this);
p->megaSurface = surface;
SDL_SetSurfaceBlendMode(p->megaSurface, SDL_BLENDMODE_NONE);
}
else
{
TEXFBO tex;
try
{
tex = shState->texPool().request(surface->w, surface->h);
}
catch (const Exception &e)
{
SDL_FreeSurface(surface);
throw e;
}
p = new BitmapPrivate(this);
p->gl = tex;
TEX::bind(p->gl.tex);
TEX::uploadImage(p->gl.width, p->gl.height, surface->pixels, GL_RGBA);
SDL_FreeSurface(surface);
}
p->addTaintedArea(rect());
}
Bitmap::Bitmap(const Bitmap &other)
{
other.ensureNonMega();
@ -837,6 +883,26 @@ void Bitmap::setPixel(int x, int y, const Color &color)
p->onModified(false);
}
void Bitmap::replaceRaw(void *pixel_data, int w, int h)
{
guardDisposed();
if (w != width() || h != height()) return;
GUARD_MEGA;
TEXFBO buf = shState->texPool().request(w, h);
TEX::bind(buf.tex);
TEX::uploadImage(w, h, pixel_data, GL_RGBA);
GLMeta::blitBegin(p->gl);
GLMeta::blitSource(buf);
GLMeta::blitRectangle(IntRect(0,0,w,h), Vec2i());
GLMeta::blitEnd();
taintArea(IntRect(0,0,w,h));
}
void Bitmap::hueChange(int hue)
{
guardDisposed();

View file

@ -40,6 +40,7 @@ class Bitmap : public Disposable
public:
Bitmap(const char *filename);
Bitmap(int width, int height);
Bitmap(void *pixeldata, int width, int height);
/* Clone constructor */
Bitmap(const Bitmap &other);
~Bitmap();
@ -81,6 +82,8 @@ public:
Color getPixel(int x, int y) const;
void setPixel(int x, int y, const Color &color);
void replaceRaw(void *pixel_data, int width, int height);
void hueChange(int hue);
enum TextAlign

View file

@ -15,12 +15,9 @@ void defaultActivityCb(void *callback_data, enum EDiscordResult result)
struct Application {
struct IDiscordCore* core;
struct IDiscordImageManager* images;
struct IDiscordUserManager* users;
struct IDiscordAchievementManager* achievements;
struct IDiscordActivityManager* activities;
struct IDiscordRelationshipManager* relationships;
struct IDiscordApplicationManager* application;
struct IDiscordLobbyManager* lobbies;
DiscordUserId user_id;
};
@ -118,6 +115,7 @@ int discordTryConnect(DiscordStatePrivate *p)
p->app.activities = p->core->get_activity_manager(p->core);
p->app.users = p->core->get_user_manager(p->core);
p->app.images = p->core->get_image_manager(p->core);
p->connected = true;
@ -160,6 +158,11 @@ IDiscordUserManager *DiscordState::userManager()
return p->app.users;
}
IDiscordImageManager *DiscordState::imageManager()
{
return p->app.images;
}
int DiscordState::update()
{
if (!p->discordInstalled) return DiscordResult_NotInstalled;
@ -205,10 +208,33 @@ DiscordUserId DiscordState::userId()
return (p->userPresent) ? p->currentUser.id : 0;
}
// NYI
Bitmap *userAvatar()
typedef struct { DiscordStatePrivate *pri; Bitmap *bmp; } AvatarCbData;
Bitmap *DiscordState::getAvatar(DiscordUserId userId, int size)
{
Bitmap *ret = new Bitmap(256, 256);
if (!isConnected()) return 0;
AvatarCbData cbData{};
cbData.bmp = new Bitmap(size, size);
cbData.pri = p;
DiscordImageHandle handle{};
handle.id = userId;
handle.size = size;
return ret;
p->app.images->fetch(p->app.images, handle, true, &cbData,
[](void *callback_data, enum EDiscordResult result, struct DiscordImageHandle handle_result){
if (result == DiscordResult_Ok)
{
AvatarCbData *data = (AvatarCbData*)callback_data;
int sz = data->bmp->width()*data->bmp->height()*4;
uint8_t *buf = new uint8_t[sz];
data->pri->app.images->get_data(data->pri->app.images, handle_result, buf, sz);
data->bmp->replaceRaw(buf, data->bmp->width(), data->bmp->height());
delete[] buf;
}
});
return cbData.bmp;
}
Bitmap *DiscordState::userAvatar()
{
return (p->userPresent) ? getAvatar(p->currentUser.id, 256) : 0;
}

View file

@ -17,6 +17,7 @@ public:
IDiscordActivityManager *activityManager();
IDiscordUserManager *userManager();
IDiscordImageManager *imageManager();
int update();
bool isConnected();
@ -24,6 +25,8 @@ public:
std::string userName();
std::string userDiscrim();
DiscordUserId userId();
Bitmap *getAvatar(DiscordUserId userId, int size);
Bitmap *userAvatar();
private: