mirror of
https://github.com/CTCaer/RetroArch.git
synced 2024-11-27 04:00:56 +00:00
show challenge indicators
This commit is contained in:
parent
ec7e528094
commit
7919a87b97
@ -1180,6 +1180,21 @@ static void rcheevos_lboard_updated(rcheevos_ralboard_t* lboard, int value,
|
|||||||
gfx_widgets_set_leaderboard_display(lboard->id, buffer);
|
gfx_widgets_set_leaderboard_display(lboard->id, buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rcheevos_challenge_started(rcheevos_racheevo_t* cheevo, int value,
|
||||||
|
bool widgets_ready)
|
||||||
|
{
|
||||||
|
if (cheevo && widgets_ready && rcheevos_locals.leaderboard_trackers)
|
||||||
|
gfx_widgets_set_challenge_display(cheevo->id, cheevo->badge);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rcheevos_challenge_ended(rcheevos_racheevo_t* cheevo, int value,
|
||||||
|
bool widgets_ready)
|
||||||
|
{
|
||||||
|
if (cheevo && widgets_ready && rcheevos_locals.leaderboard_trackers)
|
||||||
|
gfx_widgets_set_challenge_display(cheevo->id, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int rcheevos_get_richpresence(char buffer[], int buffer_size)
|
int rcheevos_get_richpresence(char buffer[], int buffer_size)
|
||||||
@ -1704,6 +1719,20 @@ static void rcheevos_runtime_event_handler(const rc_runtime_event_t* runtime_eve
|
|||||||
|
|
||||||
switch (runtime_event->type)
|
switch (runtime_event->type)
|
||||||
{
|
{
|
||||||
|
#if defined(HAVE_GFX_WIDGETS)
|
||||||
|
case RC_RUNTIME_EVENT_LBOARD_UPDATED:
|
||||||
|
rcheevos_lboard_updated(rcheevos_find_lboard(runtime_event->id), runtime_event->value, widgets_ready);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RC_RUNTIME_EVENT_ACHIEVEMENT_PRIMED:
|
||||||
|
rcheevos_challenge_started(rcheevos_find_cheevo(runtime_event->id), runtime_event->value, widgets_ready);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RC_RUNTIME_EVENT_ACHIEVEMENT_UNPRIMED:
|
||||||
|
rcheevos_challenge_ended(rcheevos_find_cheevo(runtime_event->id), runtime_event->value, widgets_ready);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case RC_RUNTIME_EVENT_ACHIEVEMENT_TRIGGERED:
|
case RC_RUNTIME_EVENT_ACHIEVEMENT_TRIGGERED:
|
||||||
rcheevos_award_achievement(&rcheevos_locals, rcheevos_find_cheevo(runtime_event->id), widgets_ready);
|
rcheevos_award_achievement(&rcheevos_locals, rcheevos_find_cheevo(runtime_event->id), widgets_ready);
|
||||||
break;
|
break;
|
||||||
@ -1712,12 +1741,6 @@ static void rcheevos_runtime_event_handler(const rc_runtime_event_t* runtime_eve
|
|||||||
rcheevos_lboard_started(rcheevos_find_lboard(runtime_event->id), runtime_event->value, widgets_ready);
|
rcheevos_lboard_started(rcheevos_find_lboard(runtime_event->id), runtime_event->value, widgets_ready);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if defined(HAVE_GFX_WIDGETS)
|
|
||||||
case RC_RUNTIME_EVENT_LBOARD_UPDATED:
|
|
||||||
rcheevos_lboard_updated(rcheevos_find_lboard(runtime_event->id), runtime_event->value, widgets_ready);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case RC_RUNTIME_EVENT_LBOARD_CANCELED:
|
case RC_RUNTIME_EVENT_LBOARD_CANCELED:
|
||||||
rcheevos_lboard_canceled(rcheevos_find_lboard(runtime_event->id),
|
rcheevos_lboard_canceled(rcheevos_find_lboard(runtime_event->id),
|
||||||
widgets_ready);
|
widgets_ready);
|
||||||
|
5
deps/rcheevos/include/rc_runtime.h
vendored
5
deps/rcheevos/include/rc_runtime.h
vendored
@ -102,7 +102,7 @@ int rc_runtime_format_lboard_value(char* buffer, int size, int value, int format
|
|||||||
|
|
||||||
|
|
||||||
int rc_runtime_activate_richpresence(rc_runtime_t* runtime, const char* script, lua_State* L, int funcs_idx);
|
int rc_runtime_activate_richpresence(rc_runtime_t* runtime, const char* script, lua_State* L, int funcs_idx);
|
||||||
int rc_runtime_get_richpresence(const rc_runtime_t* self, char* buffer, unsigned buffersize, rc_runtime_peek_t peek, void* peek_ud, lua_State* L);
|
int rc_runtime_get_richpresence(const rc_runtime_t* runtime, char* buffer, unsigned buffersize, rc_runtime_peek_t peek, void* peek_ud, lua_State* L);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
RC_RUNTIME_EVENT_ACHIEVEMENT_ACTIVATED, /* from WAITING, PAUSED, or PRIMED to ACTIVE */
|
RC_RUNTIME_EVENT_ACHIEVEMENT_ACTIVATED, /* from WAITING, PAUSED, or PRIMED to ACTIVE */
|
||||||
@ -115,7 +115,8 @@ enum {
|
|||||||
RC_RUNTIME_EVENT_LBOARD_UPDATED,
|
RC_RUNTIME_EVENT_LBOARD_UPDATED,
|
||||||
RC_RUNTIME_EVENT_LBOARD_TRIGGERED,
|
RC_RUNTIME_EVENT_LBOARD_TRIGGERED,
|
||||||
RC_RUNTIME_EVENT_ACHIEVEMENT_DISABLED,
|
RC_RUNTIME_EVENT_ACHIEVEMENT_DISABLED,
|
||||||
RC_RUNTIME_EVENT_LBOARD_DISABLED
|
RC_RUNTIME_EVENT_LBOARD_DISABLED,
|
||||||
|
RC_RUNTIME_EVENT_ACHIEVEMENT_UNPRIMED
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct rc_runtime_event_t {
|
typedef struct rc_runtime_event_t {
|
||||||
|
1
deps/rcheevos/src/rcheevos/rc_internal.h
vendored
1
deps/rcheevos/src/rcheevos/rc_internal.h
vendored
@ -119,6 +119,7 @@ unsigned rc_get_memref_value(rc_memref_t* memref, int operand_type, rc_eval_stat
|
|||||||
unsigned rc_get_memref_value_value(rc_memref_value_t* memref, int operand_type);
|
unsigned rc_get_memref_value_value(rc_memref_value_t* memref, int operand_type);
|
||||||
|
|
||||||
void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_parse_state_t* parse);
|
void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_parse_state_t* parse);
|
||||||
|
int rc_trigger_state_active(int state);
|
||||||
|
|
||||||
rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse, int is_value);
|
rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse, int is_value);
|
||||||
int rc_test_condset(rc_condset_t* self, rc_eval_state_t* eval_state);
|
int rc_test_condset(rc_condset_t* self, rc_eval_state_t* eval_state);
|
||||||
|
58
deps/rcheevos/src/rcheevos/runtime.c
vendored
58
deps/rcheevos/src/rcheevos/runtime.c
vendored
@ -229,19 +229,13 @@ int rc_runtime_get_achievement_measured(const rc_runtime_t* runtime, unsigned id
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (trigger->state)
|
if (rc_trigger_state_active(trigger->state)) {
|
||||||
{
|
*measured_value = trigger->measured_value;
|
||||||
case RC_TRIGGER_STATE_DISABLED:
|
*measured_target = trigger->measured_target;
|
||||||
case RC_TRIGGER_STATE_INACTIVE:
|
}
|
||||||
case RC_TRIGGER_STATE_TRIGGERED:
|
else {
|
||||||
/* don't report measured information for inactive triggers */
|
/* don't report measured information for inactive triggers */
|
||||||
*measured_value = *measured_target = 0;
|
*measured_value = *measured_target = 0;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
*measured_value = trigger->measured_value;
|
|
||||||
*measured_target = trigger->measured_target;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -457,7 +451,7 @@ int rc_runtime_activate_richpresence(rc_runtime_t* self, const char* script, lua
|
|||||||
return RC_OK;
|
return RC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc_runtime_get_richpresence(const rc_runtime_t* self, char* buffer, unsigned buffersize, rc_peek_t peek, void* peek_ud, lua_State* L) {
|
int rc_runtime_get_richpresence(const rc_runtime_t* self, char* buffer, unsigned buffersize, rc_runtime_peek_t peek, void* peek_ud, lua_State* L) {
|
||||||
if (self->richpresence && self->richpresence->richpresence)
|
if (self->richpresence && self->richpresence->richpresence)
|
||||||
return rc_get_richpresence_display_string(self->richpresence->richpresence, buffer, buffersize, peek, peek_ud, L);
|
return rc_get_richpresence_display_string(self->richpresence->richpresence, buffer, buffersize, peek, peek_ud, L);
|
||||||
|
|
||||||
@ -465,7 +459,7 @@ int rc_runtime_get_richpresence(const rc_runtime_t* self, char* buffer, unsigned
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rc_runtime_do_frame(rc_runtime_t* self, rc_runtime_event_handler_t event_handler, rc_peek_t peek, void* ud, lua_State* L) {
|
void rc_runtime_do_frame(rc_runtime_t* self, rc_runtime_event_handler_t event_handler, rc_runtime_peek_t peek, void* ud, lua_State* L) {
|
||||||
rc_runtime_event_t runtime_event;
|
rc_runtime_event_t runtime_event;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -476,7 +470,7 @@ void rc_runtime_do_frame(rc_runtime_t* self, rc_runtime_event_handler_t event_ha
|
|||||||
|
|
||||||
for (i = self->trigger_count - 1; i >= 0; --i) {
|
for (i = self->trigger_count - 1; i >= 0; --i) {
|
||||||
rc_trigger_t* trigger = self->triggers[i].trigger;
|
rc_trigger_t* trigger = self->triggers[i].trigger;
|
||||||
int trigger_state;
|
int old_state, new_state;
|
||||||
|
|
||||||
if (!trigger)
|
if (!trigger)
|
||||||
continue;
|
continue;
|
||||||
@ -495,8 +489,18 @@ void rc_runtime_do_frame(rc_runtime_t* self, rc_runtime_event_handler_t event_ha
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
trigger_state = trigger->state;
|
old_state = trigger->state;
|
||||||
switch (rc_evaluate_trigger(trigger, peek, ud, L))
|
new_state = rc_evaluate_trigger(trigger, peek, ud, L);
|
||||||
|
if (new_state == old_state)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (old_state == RC_TRIGGER_STATE_PRIMED) {
|
||||||
|
runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_UNPRIMED;
|
||||||
|
runtime_event.id = self->triggers[i].id;
|
||||||
|
event_handler(&runtime_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (new_state)
|
||||||
{
|
{
|
||||||
case RC_TRIGGER_STATE_RESET:
|
case RC_TRIGGER_STATE_RESET:
|
||||||
runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_RESET;
|
runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_RESET;
|
||||||
@ -511,23 +515,19 @@ void rc_runtime_do_frame(rc_runtime_t* self, rc_runtime_event_handler_t event_ha
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RC_TRIGGER_STATE_PAUSED:
|
case RC_TRIGGER_STATE_PAUSED:
|
||||||
if (trigger_state != RC_TRIGGER_STATE_PAUSED) {
|
runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_PAUSED;
|
||||||
runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_PAUSED;
|
runtime_event.id = self->triggers[i].id;
|
||||||
runtime_event.id = self->triggers[i].id;
|
event_handler(&runtime_event);
|
||||||
event_handler(&runtime_event);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RC_TRIGGER_STATE_PRIMED:
|
case RC_TRIGGER_STATE_PRIMED:
|
||||||
if (trigger_state != RC_TRIGGER_STATE_PRIMED) {
|
runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_PRIMED;
|
||||||
runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_PRIMED;
|
runtime_event.id = self->triggers[i].id;
|
||||||
runtime_event.id = self->triggers[i].id;
|
event_handler(&runtime_event);
|
||||||
event_handler(&runtime_event);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RC_TRIGGER_STATE_ACTIVE:
|
case RC_TRIGGER_STATE_ACTIVE:
|
||||||
if (trigger_state != RC_TRIGGER_STATE_ACTIVE) {
|
if (old_state == RC_TRIGGER_STATE_WAITING || old_state == RC_TRIGGER_STATE_PAUSED) {
|
||||||
runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_ACTIVATED;
|
runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_ACTIVATED;
|
||||||
runtime_event.id = self->triggers[i].id;
|
runtime_event.id = self->triggers[i].id;
|
||||||
event_handler(&runtime_event);
|
event_handler(&runtime_event);
|
||||||
|
31
deps/rcheevos/src/rcheevos/runtime_progress.c
vendored
31
deps/rcheevos/src/rcheevos/runtime_progress.c
vendored
@ -337,17 +337,9 @@ static int rc_runtime_progress_write_achievements(rc_runtime_progress_t* progres
|
|||||||
if (!runtime_trigger->trigger)
|
if (!runtime_trigger->trigger)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (runtime_trigger->trigger->state)
|
/* don't store state for inactive or triggered achievements */
|
||||||
{
|
if (!rc_trigger_state_active(runtime_trigger->trigger->state))
|
||||||
case RC_TRIGGER_STATE_DISABLED:
|
continue;
|
||||||
case RC_TRIGGER_STATE_INACTIVE:
|
|
||||||
case RC_TRIGGER_STATE_TRIGGERED:
|
|
||||||
/* don't store state for inactive or triggered achievements */
|
|
||||||
continue;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!progress->buffer) {
|
if (!progress->buffer) {
|
||||||
if (runtime_trigger->serialized_size) {
|
if (runtime_trigger->serialized_size) {
|
||||||
@ -470,19 +462,12 @@ int rc_runtime_deserialize_progress(rc_runtime_t* runtime, const unsigned char*
|
|||||||
for (i = 0; i < runtime->trigger_count; ++i) {
|
for (i = 0; i < runtime->trigger_count; ++i) {
|
||||||
rc_runtime_trigger_t* runtime_trigger = &runtime->triggers[i];
|
rc_runtime_trigger_t* runtime_trigger = &runtime->triggers[i];
|
||||||
if (runtime_trigger->trigger) {
|
if (runtime_trigger->trigger) {
|
||||||
switch (runtime_trigger->trigger->state)
|
/* don't update state for inactive or triggered achievements */
|
||||||
|
if (rc_trigger_state_active(runtime_trigger->trigger->state))
|
||||||
{
|
{
|
||||||
case RC_TRIGGER_STATE_DISABLED:
|
/* mark active achievements as unupdated. anything that's still unupdated
|
||||||
case RC_TRIGGER_STATE_INACTIVE:
|
* after deserializing the progress will be reset to waiting */
|
||||||
case RC_TRIGGER_STATE_TRIGGERED:
|
runtime_trigger->trigger->state = RC_TRIGGER_STATE_UNUPDATED;
|
||||||
/* don't update state for inactive or triggered achievements */
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
/* mark active achievements as unupdated. anything that's still unupdated
|
|
||||||
* after deserializing the progress will be reset to waiting */
|
|
||||||
runtime_trigger->trigger->state = RC_TRIGGER_STATE_UNUPDATED;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
46
deps/rcheevos/src/rcheevos/trigger.c
vendored
46
deps/rcheevos/src/rcheevos/trigger.c
vendored
@ -80,6 +80,20 @@ rc_trigger_t* rc_parse_trigger(void* buffer, const char* memaddr, lua_State* L,
|
|||||||
return (parse.offset >= 0) ? self : NULL;
|
return (parse.offset >= 0) ? self : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rc_trigger_state_active(int state)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case RC_TRIGGER_STATE_DISABLED:
|
||||||
|
case RC_TRIGGER_STATE_INACTIVE:
|
||||||
|
case RC_TRIGGER_STATE_TRIGGERED:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void rc_reset_trigger_hitcounts(rc_trigger_t* self) {
|
static void rc_reset_trigger_hitcounts(rc_trigger_t* self) {
|
||||||
rc_condset_t* condset;
|
rc_condset_t* condset;
|
||||||
|
|
||||||
@ -102,21 +116,28 @@ int rc_evaluate_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, lua_State*
|
|||||||
char is_paused;
|
char is_paused;
|
||||||
char is_primed;
|
char is_primed;
|
||||||
|
|
||||||
/* previously triggered, do nothing - return INACTIVE so caller doesn't think it triggered again */
|
switch (self->state)
|
||||||
if (self->state == RC_TRIGGER_STATE_TRIGGERED)
|
{
|
||||||
return RC_TRIGGER_STATE_INACTIVE;
|
case RC_TRIGGER_STATE_TRIGGERED:
|
||||||
|
/* previously triggered. do nothing - return INACTIVE so caller doesn't think it triggered again */
|
||||||
|
return RC_TRIGGER_STATE_INACTIVE;
|
||||||
|
|
||||||
/* unsupported, do nothing - return INACTIVE */
|
case RC_TRIGGER_STATE_DISABLED:
|
||||||
if (self->state == RC_TRIGGER_STATE_DISABLED)
|
/* unsupported. do nothing - return INACTIVE */
|
||||||
return RC_TRIGGER_STATE_INACTIVE;
|
return RC_TRIGGER_STATE_INACTIVE;
|
||||||
|
|
||||||
|
case RC_TRIGGER_STATE_INACTIVE:
|
||||||
|
/* not yet active. update the memrefs so deltas are correct when it becomes active, then return INACTIVE */
|
||||||
|
rc_update_memref_values(self->memrefs, peek, ud);
|
||||||
|
return RC_TRIGGER_STATE_INACTIVE;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* update the memory references */
|
/* update the memory references */
|
||||||
rc_update_memref_values(self->memrefs, peek, ud);
|
rc_update_memref_values(self->memrefs, peek, ud);
|
||||||
|
|
||||||
/* not yet active, only update the memrefs so deltas are correct when it becomes active */
|
|
||||||
if (self->state == RC_TRIGGER_STATE_INACTIVE)
|
|
||||||
return RC_TRIGGER_STATE_INACTIVE;
|
|
||||||
|
|
||||||
/* process the trigger */
|
/* process the trigger */
|
||||||
memset(&eval_state, 0, sizeof(eval_state));
|
memset(&eval_state, 0, sizeof(eval_state));
|
||||||
eval_state.peek = peek;
|
eval_state.peek = peek;
|
||||||
@ -178,6 +199,11 @@ int rc_evaluate_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, lua_State*
|
|||||||
/* if there were hit counts to clear, return RESET, but don't change the state */
|
/* if there were hit counts to clear, return RESET, but don't change the state */
|
||||||
if (self->has_hits) {
|
if (self->has_hits) {
|
||||||
self->has_hits = 0;
|
self->has_hits = 0;
|
||||||
|
|
||||||
|
/* cannot be PRIMED while ResetIf is true */
|
||||||
|
if (self->state == RC_TRIGGER_STATE_PRIMED)
|
||||||
|
self->state = RC_TRIGGER_STATE_ACTIVE;
|
||||||
|
|
||||||
return RC_TRIGGER_STATE_RESET;
|
return RC_TRIGGER_STATE_RESET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,6 +354,7 @@ void gfx_widgets_ai_service_overlay_unload(dispgfx_widget_t *p_dispwidget);
|
|||||||
#ifdef HAVE_CHEEVOS
|
#ifdef HAVE_CHEEVOS
|
||||||
void gfx_widgets_push_achievement(const char *title, const char *badge);
|
void gfx_widgets_push_achievement(const char *title, const char *badge);
|
||||||
void gfx_widgets_set_leaderboard_display(unsigned id, const char* value);
|
void gfx_widgets_set_leaderboard_display(unsigned id, const char* value);
|
||||||
|
void gfx_widgets_set_challenge_display(unsigned id, const char* badge);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Warning: not thread safe! */
|
/* Warning: not thread safe! */
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CHEEVO_LBOARD_ARRAY_SIZE 4
|
#define CHEEVO_LBOARD_ARRAY_SIZE 4
|
||||||
|
#define CHEEVO_CHALLENGE_ARRAY_SIZE 8
|
||||||
|
|
||||||
#define CHEEVO_LBOARD_DISPLAY_PADDING 3
|
#define CHEEVO_LBOARD_DISPLAY_PADDING 3
|
||||||
|
|
||||||
@ -37,13 +38,21 @@ struct leaderboard_display_info
|
|||||||
char display[24]; /* should never exceed 12 bytes, but aligns the structure at 32 bytes */
|
char display[24]; /* should never exceed 12 bytes, but aligns the structure at 32 bytes */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct challenge_display_info
|
||||||
|
{
|
||||||
|
unsigned id;
|
||||||
|
uintptr_t image;
|
||||||
|
};
|
||||||
|
|
||||||
struct gfx_widget_leaderboard_display_state
|
struct gfx_widget_leaderboard_display_state
|
||||||
{
|
{
|
||||||
#ifdef HAVE_THREADS
|
#ifdef HAVE_THREADS
|
||||||
slock_t* array_lock;
|
slock_t* array_lock;
|
||||||
#endif
|
#endif
|
||||||
struct leaderboard_display_info info[CHEEVO_LBOARD_ARRAY_SIZE];
|
struct leaderboard_display_info tracker_info[CHEEVO_LBOARD_ARRAY_SIZE];
|
||||||
int count;
|
unsigned tracker_count;
|
||||||
|
struct challenge_display_info challenge_info[CHEEVO_CHALLENGE_ARRAY_SIZE];
|
||||||
|
unsigned challenge_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct gfx_widget_leaderboard_display_state gfx_widget_leaderboard_display_state_t;
|
typedef struct gfx_widget_leaderboard_display_state gfx_widget_leaderboard_display_state_t;
|
||||||
@ -66,7 +75,8 @@ static void gfx_widget_leaderboard_display_free(void)
|
|||||||
{
|
{
|
||||||
gfx_widget_leaderboard_display_state_t *state = &p_w_leaderboard_display_st;
|
gfx_widget_leaderboard_display_state_t *state = &p_w_leaderboard_display_st;
|
||||||
|
|
||||||
state->count = 0;
|
state->tracker_count = 0;
|
||||||
|
state->challenge_count = 0;
|
||||||
#ifdef HAVE_THREADS
|
#ifdef HAVE_THREADS
|
||||||
slock_free(state->array_lock);
|
slock_free(state->array_lock);
|
||||||
state->array_lock = NULL;
|
state->array_lock = NULL;
|
||||||
@ -76,7 +86,8 @@ static void gfx_widget_leaderboard_display_free(void)
|
|||||||
static void gfx_widget_leaderboard_display_context_destroy(void)
|
static void gfx_widget_leaderboard_display_context_destroy(void)
|
||||||
{
|
{
|
||||||
gfx_widget_leaderboard_display_state_t *state = &p_w_leaderboard_display_st;
|
gfx_widget_leaderboard_display_state_t *state = &p_w_leaderboard_display_st;
|
||||||
state->count = 0;
|
state->tracker_count = 0;
|
||||||
|
state->challenge_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gfx_widget_leaderboard_display_frame(void* data, void* userdata)
|
static void gfx_widget_leaderboard_display_frame(void* data, void* userdata)
|
||||||
@ -84,7 +95,7 @@ static void gfx_widget_leaderboard_display_frame(void* data, void* userdata)
|
|||||||
gfx_widget_leaderboard_display_state_t *state = &p_w_leaderboard_display_st;
|
gfx_widget_leaderboard_display_state_t *state = &p_w_leaderboard_display_st;
|
||||||
|
|
||||||
/* if there's nothing to display, just bail */
|
/* if there's nothing to display, just bail */
|
||||||
if (state->count == 0)
|
if (state->tracker_count == 0 && state->challenge_count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SLOCK_LOCK(state->array_lock);
|
SLOCK_LOCK(state->array_lock);
|
||||||
@ -108,9 +119,53 @@ static void gfx_widget_leaderboard_display_frame(void* data, void* userdata)
|
|||||||
gfx_display_set_alpha(p_dispwidget->backdrop_orig, DEFAULT_BACKDROP);
|
gfx_display_set_alpha(p_dispwidget->backdrop_orig, DEFAULT_BACKDROP);
|
||||||
gfx_display_set_alpha(pure_white, 1.0f);
|
gfx_display_set_alpha(pure_white, 1.0f);
|
||||||
|
|
||||||
for (i = 0; i < (unsigned)state->count; ++i)
|
if (state->challenge_count)
|
||||||
{
|
{
|
||||||
const unsigned widget_width = state->info[i].width;
|
const unsigned widget_size = video_width / 32;
|
||||||
|
|
||||||
|
x = video_width;
|
||||||
|
y -= (widget_size + spacing);
|
||||||
|
|
||||||
|
for (i = 0; i < state->challenge_count; ++i)
|
||||||
|
{
|
||||||
|
x -= (widget_size + spacing);
|
||||||
|
|
||||||
|
if (!state->challenge_info[i].image)
|
||||||
|
{
|
||||||
|
/* default icon */
|
||||||
|
if (p_dispwidget->gfx_widgets_icons_textures[
|
||||||
|
MENU_WIDGETS_ICON_ACHIEVEMENT])
|
||||||
|
{
|
||||||
|
gfx_display_ctx_driver_t* dispctx = p_disp->dispctx;
|
||||||
|
if (dispctx && dispctx->blend_begin)
|
||||||
|
dispctx->blend_begin(video_info->userdata);
|
||||||
|
|
||||||
|
gfx_widgets_draw_icon(video_info->userdata,
|
||||||
|
p_disp, video_width, video_height,
|
||||||
|
widget_size, widget_size,
|
||||||
|
p_dispwidget->gfx_widgets_icons_textures[
|
||||||
|
MENU_WIDGETS_ICON_ACHIEVEMENT],
|
||||||
|
x, y, 0, 1, pure_white);
|
||||||
|
|
||||||
|
if (dispctx && dispctx->blend_end)
|
||||||
|
dispctx->blend_end(video_info->userdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* achievement badge */
|
||||||
|
gfx_widgets_draw_icon(video_info->userdata,
|
||||||
|
p_disp, video_width, video_height,
|
||||||
|
widget_size, widget_size,
|
||||||
|
state->challenge_info[i].image,
|
||||||
|
x, y, 0, 1, pure_white);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < state->tracker_count; ++i)
|
||||||
|
{
|
||||||
|
const unsigned widget_width = state->tracker_info[i].width;
|
||||||
x = video_width - widget_width - spacing;
|
x = video_width - widget_width - spacing;
|
||||||
y -= (widget_height + spacing);
|
y -= (widget_height + spacing);
|
||||||
|
|
||||||
@ -125,7 +180,7 @@ static void gfx_widget_leaderboard_display_frame(void* data, void* userdata)
|
|||||||
|
|
||||||
/* Text */
|
/* Text */
|
||||||
gfx_widgets_draw_text(&p_dispwidget->gfx_widget_fonts.regular,
|
gfx_widgets_draw_text(&p_dispwidget->gfx_widget_fonts.regular,
|
||||||
state->info[i].display,
|
state->tracker_info[i].display,
|
||||||
(float)(x + CHEEVO_LBOARD_DISPLAY_PADDING),
|
(float)(x + CHEEVO_LBOARD_DISPLAY_PADDING),
|
||||||
(float)(y + widget_height - (CHEEVO_LBOARD_DISPLAY_PADDING - 1)
|
(float)(y + widget_height - (CHEEVO_LBOARD_DISPLAY_PADDING - 1)
|
||||||
- p_dispwidget->gfx_widget_fonts.regular.line_descender),
|
- p_dispwidget->gfx_widget_fonts.regular.line_descender),
|
||||||
@ -146,9 +201,9 @@ void gfx_widgets_set_leaderboard_display(unsigned id, const char* value)
|
|||||||
|
|
||||||
SLOCK_LOCK(state->array_lock);
|
SLOCK_LOCK(state->array_lock);
|
||||||
|
|
||||||
for (i = 0; i < state->count; ++i)
|
for (i = 0; i < state->tracker_count; ++i)
|
||||||
{
|
{
|
||||||
if (state->info[i].id == id)
|
if (state->tracker_info[i].id == id)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,13 +212,13 @@ void gfx_widgets_set_leaderboard_display(unsigned id, const char* value)
|
|||||||
if (value == NULL)
|
if (value == NULL)
|
||||||
{
|
{
|
||||||
/* hide display */
|
/* hide display */
|
||||||
if (i < state->count)
|
if (i < state->tracker_count)
|
||||||
{
|
{
|
||||||
--state->count;
|
--state->tracker_count;
|
||||||
if (i < state->count)
|
if (i < state->tracker_count)
|
||||||
{
|
{
|
||||||
memcpy(&state->info[i], &state->info[i + 1],
|
memcpy(&state->tracker_info[i], &state->tracker_info[i + 1],
|
||||||
(state->count - i) * sizeof(state->info[i]));
|
(state->tracker_count - i) * sizeof(state->tracker_info[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -172,20 +227,81 @@ void gfx_widgets_set_leaderboard_display(unsigned id, const char* value)
|
|||||||
/* show or update display */
|
/* show or update display */
|
||||||
const dispgfx_widget_t* p_dispwidget = (const dispgfx_widget_t*)dispwidget_get_ptr();
|
const dispgfx_widget_t* p_dispwidget = (const dispgfx_widget_t*)dispwidget_get_ptr();
|
||||||
|
|
||||||
if (i == state->count)
|
if (i == state->tracker_count)
|
||||||
state->info[state->count++].id = id;
|
state->tracker_info[state->tracker_count++].id = id;
|
||||||
|
|
||||||
strncpy(state->info[i].display, value, sizeof(state->info[i].display));
|
strncpy(state->tracker_info[i].display, value, sizeof(state->tracker_info[i].display));
|
||||||
state->info[i].width = font_driver_get_message_width(
|
state->tracker_info[i].width = font_driver_get_message_width(
|
||||||
p_dispwidget->gfx_widget_fonts.regular.font,
|
p_dispwidget->gfx_widget_fonts.regular.font,
|
||||||
state->info[i].display, 0, 1);
|
state->tracker_info[i].display, 0, 1);
|
||||||
state->info[i].width += CHEEVO_LBOARD_DISPLAY_PADDING * 2;
|
state->tracker_info[i].width += CHEEVO_LBOARD_DISPLAY_PADDING * 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SLOCK_UNLOCK(state->array_lock);
|
SLOCK_UNLOCK(state->array_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gfx_widgets_set_challenge_display(unsigned id, const char* badge)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
gfx_widget_leaderboard_display_state_t* state = &p_w_leaderboard_display_st;
|
||||||
|
|
||||||
|
/* important - this must be done outside the lock because it has the potential to need to
|
||||||
|
* lock the video thread, which may be waiting for the popup queue lock to render popups */
|
||||||
|
uintptr_t badge_id = badge ? rcheevos_get_badge_texture(badge, 0) : NULL;
|
||||||
|
uintptr_t old_badge_id = NULL;
|
||||||
|
|
||||||
|
SLOCK_LOCK(state->array_lock);
|
||||||
|
|
||||||
|
for (i = 0; i < state->challenge_count; ++i)
|
||||||
|
{
|
||||||
|
if (state->challenge_info[i].id == id)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < CHEEVO_CHALLENGE_ARRAY_SIZE)
|
||||||
|
{
|
||||||
|
if (badge == NULL)
|
||||||
|
{
|
||||||
|
/* hide indicator */
|
||||||
|
if (i < state->challenge_count)
|
||||||
|
{
|
||||||
|
old_badge_id = state->challenge_info[i].image;
|
||||||
|
|
||||||
|
--state->challenge_count;
|
||||||
|
if (i < state->challenge_count)
|
||||||
|
{
|
||||||
|
memcpy(&state->challenge_info[i], &state->challenge_info[i + 1],
|
||||||
|
(state->challenge_count - i) * sizeof(state->challenge_info[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
state->challenge_info[state->challenge_count].image = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* show indicator */
|
||||||
|
if (i == state->challenge_count)
|
||||||
|
{
|
||||||
|
/* new indicator, assign id */
|
||||||
|
state->challenge_info[state->challenge_count++].id = id;
|
||||||
|
}
|
||||||
|
else if (state->challenge_info[i].image)
|
||||||
|
{
|
||||||
|
/* existing indicator, free old image */
|
||||||
|
old_badge_id = state->challenge_info[i].image;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->challenge_info[i].image = badge_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SLOCK_UNLOCK(state->array_lock);
|
||||||
|
|
||||||
|
if (old_badge_id)
|
||||||
|
video_driver_texture_unload(&old_badge_id);
|
||||||
|
}
|
||||||
|
|
||||||
const gfx_widget_t gfx_widget_leaderboard_display = {
|
const gfx_widget_t gfx_widget_leaderboard_display = {
|
||||||
&gfx_widget_leaderboard_display_init,
|
&gfx_widget_leaderboard_display_init,
|
||||||
&gfx_widget_leaderboard_display_free,
|
&gfx_widget_leaderboard_display_free,
|
||||||
|
Loading…
Reference in New Issue
Block a user