Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,29 @@ options:
--user-scale SCALE
Change scale of user avatars.

--user-scale-by-commits
Scale user avatar size based on their commit count.

--persist-user-scale
Remember user scale when they disappear and reappear.

--commit-scale-factor FLOAT
Controls the intensity of commit-based scaling (default: 0.5).

--commit-scale-type TYPE
Algorithm for commit-based scaling (default: log).

log - Logarithmic scaling, tapers off for high values.
linear - Grows proportionally with commit count.
sqrt - Middle ground between log and linear.
exp - Aggressive growth

--user-min-scale FLOAT
Minimum scale for commit-based user scaling (default: 1.0).

--user-max-scale FLOAT
Maximum scale for commit-based user scaling (default: 3.0).

--camera-mode MODE
Camera mode (overview,track).

Expand Down
13 changes: 13 additions & 0 deletions src/gource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,14 @@ RUser* Gource::addUser(const std::string& username) {

RUser* user = new RUser(username, pos, tagid);

// Restore persisted commit count
if(gGourceSettings.persist_user_scale && gGourceSettings.user_scale_by_commits) {
std::map<std::string, size_t>::iterator it = user_commit_counts.find(username);
if(it != user_commit_counts.end()) {
user->setTotalCommitCount(it->second);
}
}

users[username] = user;
tagusermap[tagid] = user;

Expand All @@ -1050,6 +1058,11 @@ void Gource::deleteUser(RUser* user) {
selectUser(0);
}

// Save commit count for persistence
if(gGourceSettings.persist_user_scale && gGourceSettings.user_scale_by_commits) {
user_commit_counts[user->getName()] = user->getTotalCommitCount();
}

users.erase(user->getName());
tagusermap.erase(user->getTagID());

Expand Down
1 change: 1 addition & 0 deletions src/gource.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ class Gource : public SDLApp {
std::map<std::string, RUser*> users;
std::map<std::string, RFile*> files;
std::map<int, RUser*> tagusermap;
std::map<std::string, size_t> user_commit_counts;

std::list<RCaption*> captions;
std::list<RCaption*> active_captions;
Expand Down
86 changes: 85 additions & 1 deletion src/gource_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,13 @@ if(extended_help) {

printf(" --user-friction SECONDS Change the rate users slow down (default: 0.67)\n");
printf(" --user-scale SCALE Change scale of users (default: 1.0)\n");
printf(" --max-user-speed UNITS Speed users can travel per second (default: 500)\n\n");
printf(" --max-user-speed UNITS Speed users can travel per second (default: 500)\n");
printf(" --user-scale-by-commits Scale user size based on commit count\n");
printf(" --persist-user-scale Remember user scale when they reappear\n");
printf(" --commit-scale-factor F Commit scaling intensity (default: 0.5)\n");
printf(" --commit-scale-type TYPE Scaling algorithm: log, linear, sqrt, exp (default: log)\n");
printf(" --user-min-scale SCALE Minimum user scale (default: 1.0)\n");
printf(" --user-max-scale SCALE Maximum user scale (default: 3.0)\n\n");

printf(" --follow-user USER Camera will automatically follow this user\n");
printf(" --highlight-dirs Highlight the names of all directories\n");
Expand Down Expand Up @@ -319,6 +325,13 @@ GourceSettings::GourceSettings() {
arg_types["follow-user"] = "multi-value";
arg_types["highlight-user"] = "multi-value";

arg_types["user-scale-by-commits"] = "bool";
arg_types["persist-user-scale"] = "bool";
arg_types["commit-scale-factor"] = "float";
arg_types["commit-scale-type"] = "string";
arg_types["user-min-scale"] = "float";
arg_types["user-max-scale"] = "float";

arg_types["log-level"] = "string";
arg_types["background-image"] = "string";
arg_types["logo"] = "string";
Expand Down Expand Up @@ -472,6 +485,13 @@ void GourceSettings::setGourceDefaults() {
user_friction = 1.0f;
user_scale = 1.0f;

user_scale_by_commits = false;
commit_scale_factor = 0.5f;
user_min_scale = 1.0f;
user_max_scale = 3.0f;
persist_user_scale = false;
commit_scale_type = COMMIT_SCALE_LOG;

follow_users.clear();
highlight_users.clear();
highlight_all_users = false;
Expand Down Expand Up @@ -1432,6 +1452,70 @@ void GourceSettings::importGourceSettings(ConfFile& conffile, ConfSection* gourc
}
}

if(gource_settings->getBool("user-scale-by-commits")) {
user_scale_by_commits = true;
}

if(gource_settings->getBool("persist-user-scale")) {
persist_user_scale = true;
}

if((entry = gource_settings->getEntry("commit-scale-factor")) != 0) {

if(!entry->hasValue()) conffile.entryException(entry, "specify commit-scale-factor (float)");

commit_scale_factor = entry->getFloat();

if(commit_scale_factor<=0.0 || commit_scale_factor>10.0) {
conffile.invalidValueException(entry);
}
}

if((entry = gource_settings->getEntry("commit-scale-type")) != 0) {

if(!entry->hasValue()) conffile.entryException(entry, "specify commit-scale-type (log,linear,sqrt,exp)");

std::string scale_type_str = entry->getString();

if(scale_type_str == "log") {
commit_scale_type = COMMIT_SCALE_LOG;
} else if(scale_type_str == "linear") {
commit_scale_type = COMMIT_SCALE_LINEAR;
} else if(scale_type_str == "sqrt") {
commit_scale_type = COMMIT_SCALE_SQRT;
} else if(scale_type_str == "exp") {
commit_scale_type = COMMIT_SCALE_EXP;
} else {
conffile.invalidValueException(entry);
}
}

if((entry = gource_settings->getEntry("user-min-scale")) != 0) {

if(!entry->hasValue()) conffile.entryException(entry, "specify user-min-scale (float)");

user_min_scale = entry->getFloat();

if(user_min_scale<=0.0 || user_min_scale>100.0) {
conffile.invalidValueException(entry);
}
}

if((entry = gource_settings->getEntry("user-max-scale")) != 0) {

if(!entry->hasValue()) conffile.entryException(entry, "specify user-max-scale (float)");

user_max_scale = entry->getFloat();

if(user_max_scale<=0.0 || user_max_scale>1000.0) {
conffile.invalidValueException(entry);
}
}

if(user_min_scale > user_max_scale) {
throw ConfFileException("user-min-scale cannot be greater than user-max-scale", "", 0);
}

if((entry = gource_settings->getEntry("max-user-speed")) != 0) {

if(!entry->hasValue()) conffile.entryException(entry, "specify max-user-speed (units)");
Expand Down
15 changes: 15 additions & 0 deletions src/gource_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@
#include "core/settings.h"
#include "core/regex.h"

// Commit-based user scaling algorithms
enum CommitScaleType {
COMMIT_SCALE_LOG,
COMMIT_SCALE_LINEAR,
COMMIT_SCALE_SQRT,
COMMIT_SCALE_EXP
};

class GourceSettings : public SDLAppSettings {
protected:
void commandLineOption(const std::string& name, const std::string& value);
Expand Down Expand Up @@ -136,6 +144,13 @@ class GourceSettings : public SDLAppSettings {
float user_scale;
float time_scale;

bool user_scale_by_commits;
float commit_scale_factor;
float user_min_scale;
float user_max_scale;
bool persist_user_scale;
CommitScaleType commit_scale_type;

bool highlight_dirs;
bool highlight_all_users;

Expand Down
50 changes: 50 additions & 0 deletions src/user.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ RUser::RUser(const std::string& name, vec2 pos, int tagid) : Pawn(name,pos,tagid
min_units_ps = 100.0;

actionCount = activeCount = 0;
totalCommitCount = 0;
}

void RUser::addAction(RAction* action) {
Expand All @@ -56,6 +57,9 @@ void RUser::addAction(RAction* action) {

actions.push_back(action);
actionCount++;
totalCommitCount++;

updateSizeByCommits();
}

// remove references to this file
Expand Down Expand Up @@ -228,6 +232,52 @@ int RUser::getPendingActionCount() {
return actionCount;
}

size_t RUser::getTotalCommitCount() const {
return totalCommitCount;
}

void RUser::setTotalCommitCount(size_t count) {
totalCommitCount = count;
updateSizeByCommits();
}

void RUser::updateSizeByCommits() {
if(!gGourceSettings.user_scale_by_commits) return;

float commitScale = 1.0f;
float commits = (float)totalCommitCount;
float factor = gGourceSettings.commit_scale_factor;

// tuned so factor=1 gives roughly 2x scale at 100 commits
const float LINEAR_COEFF = 0.01f;
const float SQRT_COEFF = 0.1f;
const float EXP_BASE_COEFF = 0.1f;
const float EXP_POWER_MULT = 3.0f;

switch(gGourceSettings.commit_scale_type) {
case COMMIT_SCALE_LINEAR:
commitScale = 1.0f + commits * factor * LINEAR_COEFF;
break;
case COMMIT_SCALE_SQRT:
commitScale = 1.0f + sqrtf(commits) * factor * SQRT_COEFF;
break;
case COMMIT_SCALE_EXP:
commitScale = powf(1.0f + factor * EXP_BASE_COEFF, log10f(1.0f + commits) * EXP_POWER_MULT);
break;
case COMMIT_SCALE_LOG:
default:
commitScale = 1.0f + log10f(1.0f + commits) * factor;
break;
}

commitScale = glm::clamp(commitScale, gGourceSettings.user_min_scale, gGourceSettings.user_max_scale);

size = 20.0f * gGourceSettings.user_scale * commitScale;
shadowOffset = vec2(2.0, 2.0) * gGourceSettings.user_scale * commitScale;

dims = vec2(size, size * graphic_ratio);
}

void RUser::logic(float t, float dt) {
Pawn::logic(dt);

Expand Down
5 changes: 5 additions & 0 deletions src/user.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class RUser : public Pawn {
std::list<RAction*> activeActions;
size_t actionCount;
size_t activeCount;
size_t totalCommitCount;

float action_interval;
float action_dist;
Expand Down Expand Up @@ -77,6 +78,10 @@ class RUser : public Pawn {

int getActionCount();
int getPendingActionCount();
size_t getTotalCommitCount() const;
void setTotalCommitCount(size_t count);

void updateSizeByCommits();

float getAlpha() const;

Expand Down