mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-26 21:10:42 +00:00
ui: Improve logo animation
This commit is contained in:
parent
3a6907b0ea
commit
f672185b1c
@ -2,30 +2,30 @@
|
||||
#define msdf tex
|
||||
uniform sampler2D tex;
|
||||
uniform vec4 in_ColorPrimary;
|
||||
uniform vec4 in_ColorSecondary;
|
||||
uniform vec4 in_ColorFill;
|
||||
uniform float scale;
|
||||
uniform float iTime;
|
||||
in vec2 Texcoord;
|
||||
out vec4 out_Color;
|
||||
|
||||
float pxRange = 6.0;
|
||||
vec4 bgColor = in_ColorFill;
|
||||
vec4 fgColor = in_ColorPrimary;
|
||||
vec4 particleColor = in_ColorSecondary;
|
||||
const int numParticles = 40;
|
||||
const float duration = 1.1;
|
||||
const float pause = 5.0;
|
||||
const vec4 textPos = vec4(0.01, 0, 0.98, 0.125);
|
||||
const float lineWidth = 0.15;
|
||||
float pxRange = 6.0;
|
||||
vec4 fgColor = in_ColorPrimary;
|
||||
vec4 bgColor = in_ColorFill;
|
||||
const vec4 textPos = vec4(0.01, 0, 0.98, 0.125);
|
||||
const float pi = 3.14159265359;
|
||||
const float lineWidth = 0.175;
|
||||
const float duration = 1.25;
|
||||
const float pause = 6.;
|
||||
const int numParticles = 35;
|
||||
const int numSpotlights = 5;
|
||||
|
||||
// Thanks to: https://www.shadertoy.com/view/Xl2SRR
|
||||
float random(float co)
|
||||
{
|
||||
return fract(sin(co*12.989) * 43758.545);
|
||||
return fract(abs(sin(co*12.989)) * 43758.545);
|
||||
}
|
||||
|
||||
float median(float r, float g, float b) {
|
||||
float median(float r, float g, float b)
|
||||
{
|
||||
return max(min(r, g), min(max(r, g), b));
|
||||
}
|
||||
|
||||
@ -42,9 +42,9 @@ float getCurrentTime()
|
||||
|
||||
float getBox(vec2 uv, float x, float width)
|
||||
{
|
||||
float rhs = sign(clamp(x-uv.x+width, 0., 1.));
|
||||
float lhs = sign(clamp(x-uv.x, 0., 1.));
|
||||
return rhs-lhs;
|
||||
float lhs = sign(clamp(x - uv.x, 0., 1.));
|
||||
float rhs = sign(clamp(x - uv.x + width, 0., 1.));
|
||||
return rhs-lhs;
|
||||
}
|
||||
|
||||
float getSweepingLinePos()
|
||||
@ -60,51 +60,88 @@ float getSweepingLine(vec2 uv)
|
||||
float getGradients(vec2 uv)
|
||||
{
|
||||
float t = getCurrentTime();
|
||||
float gw = lineWidth/2.;
|
||||
float left = getBox(uv, getSweepingLinePos() - gw, gw)*smoothstep(0., 1., (gw + lineWidth - (t - uv.x + textPos.x))/lineWidth);
|
||||
float right = getBox(uv, getSweepingLinePos() + lineWidth, gw)*smoothstep(0., 1., (gw + (t - uv.x + textPos.x))/lineWidth);
|
||||
float gradient_y = smoothstep(0.8, 1., 1.-abs(0.5-uv.y));
|
||||
float l_s = abs(cos(t*pi*2.));
|
||||
float pos = t - uv.x + textPos.x;
|
||||
float left = l_s*smoothstep(0., 1., 0.5-abs(pos - lineWidth)*(20.+80.*(1.-l_s)));
|
||||
float r_s = abs(sin(t*pi*2.));
|
||||
float right = r_s*smoothstep(0., 1., 0.5-abs(pos)*(20.+80.*(1.-r_s)));
|
||||
float gradient_y = smoothstep(0.55, 1., 1.-abs(0.5-uv.y));
|
||||
return (left + right) * gradient_y;
|
||||
}
|
||||
|
||||
vec2 getSpotlightPos(int i)
|
||||
{
|
||||
float t = getCurrentTime();
|
||||
vec2 initialPos = textPos.zw*vec2(
|
||||
float(i)/float(numSpotlights-1), // Even
|
||||
sign(random(float(i+62)) - 0.6)*2.); // Top biased
|
||||
|
||||
vec2 velocity;
|
||||
velocity.x = sign(random(float(i+63)) - 0.5)*0.7*(0.3+0.6*random(float(i+100)));
|
||||
velocity.y = -sign(initialPos.y)*0.8*(0.1+0.9*random(float(i+62)));
|
||||
return initialPos + velocity * t + vec2(textPos.x, 0.5); // Offset to center
|
||||
}
|
||||
|
||||
float getSpotlights(vec2 uv)
|
||||
{
|
||||
float t = getCurrentTime();
|
||||
float right = smoothstep(0.3, 0.7, 0.8-8.*abs(t - uv.x + textPos.x + 0.05));
|
||||
|
||||
// Compute contribution from all spotlights to this frag
|
||||
float c = 0.;
|
||||
for (int j = 0; j < numSpotlights; j++) {
|
||||
vec2 pos = getSpotlightPos(j);
|
||||
float d = distance(uv, pos);
|
||||
c += (1.-smoothstep(0.04, 0.07835, d));
|
||||
}
|
||||
|
||||
return 0.6*right + 0.4*c;
|
||||
}
|
||||
|
||||
// Note: Does not include offset, added in getParticlePosition
|
||||
vec2 getParticleInitialPosition(int i)
|
||||
{
|
||||
vec2 pos;
|
||||
pos.x = float(i)/float(numParticles-1); // Even
|
||||
pos.y = sign(random(float(i)) - 0.1); // Top biased
|
||||
return pos*textPos.zw;
|
||||
return textPos.zw*vec2(
|
||||
float(i)/float(numParticles-1), // Even
|
||||
sign(random(float(i)) - 0.2)); // Top biased
|
||||
}
|
||||
|
||||
float prob(float p, int i)
|
||||
{
|
||||
return sign(clamp(random(float(i*30))-(1.-p), 0., 1.));
|
||||
}
|
||||
|
||||
float getParticleLifespan(int i)
|
||||
{
|
||||
return 1. + 1.25*exp(-10.*random(float(i*30))) + 0.5*prob(0.3, i);
|
||||
}
|
||||
|
||||
float getParticleTime(int i)
|
||||
{
|
||||
// Compute based on initial x due to sweeping reveal
|
||||
return getCurrentTime()-getParticleInitialPosition(i).x;
|
||||
}
|
||||
|
||||
float getParticleAlive(int i)
|
||||
{
|
||||
return clamp(sign(getParticleTime(i)), 0., 1.);
|
||||
}
|
||||
|
||||
float getParticleIntensity(int i)
|
||||
{
|
||||
float lifespan = 1.0 + 0.4*(random(float(i*44))-0.5);
|
||||
float alive = clamp(sign(getParticleTime(i)), 0., 1.);
|
||||
return alive*clamp(lifespan-getParticleTime(i), 0., 1.);
|
||||
return getParticleAlive(i)*clamp(getParticleLifespan(i)-getParticleTime(i), 0., 1.);
|
||||
}
|
||||
|
||||
vec2 getParticlePosition(int i)
|
||||
{
|
||||
float pt = getParticleTime(i);
|
||||
float alive = clamp(sign(pt), 0., 1.);
|
||||
float falloff = 10.;
|
||||
float impulse = quaImpulse(falloff, pt+0.8)+0.2;
|
||||
vec2 pos = getParticleInitialPosition(i);
|
||||
|
||||
float impulse = quaImpulse(20., pt*0.25+0.05+0.4*random(float(i+30)));
|
||||
vec2 initialPos = getParticleInitialPosition(i);
|
||||
vec2 velocity;
|
||||
// Move mostly right, but sometimes left
|
||||
velocity.x = sign(random(float(i+32*3030))-0.2);
|
||||
velocity.x *= impulse*1.25*(0.00 + random(float(i+62)));
|
||||
// Move vertically in whatever direction we spawned in
|
||||
velocity.y = sign(pos.y);
|
||||
velocity.y *= impulse*1.40*(0.05 + random(float(i+62)));
|
||||
return pos + alive * velocity * pt + vec2(textPos.x, 0.5); // Offset to center
|
||||
// Move mostly right, sometimes left
|
||||
velocity.x = 0.4*impulse*sign(random(float(i+66)) - 0.1)*(0.3 + 0.6*random(float(i + 100)));
|
||||
// Move vertically in whatever direction particle spawned in
|
||||
velocity.y = 0.8*impulse*sign(initialPos.y)*(0.1 + 0.9*random(float(i + 62)));
|
||||
return initialPos + getParticleAlive(i) * velocity * pt + vec2(textPos.x, 0.5); // Offset to center
|
||||
}
|
||||
|
||||
float getParticles(vec2 uv)
|
||||
@ -114,7 +151,7 @@ float getParticles(vec2 uv)
|
||||
for (int j = 0; j < numParticles; j++) {
|
||||
vec2 pos = getParticlePosition(j);
|
||||
float d = distance(uv, pos);
|
||||
c += (1.-smoothstep(0.01, 0.01035,d))*getParticleIntensity(j);
|
||||
c += (1.-smoothstep(0.004, 0.00835,d))*getParticleIntensity(j);
|
||||
}
|
||||
|
||||
return c;
|
||||
@ -122,32 +159,25 @@ float getParticles(vec2 uv)
|
||||
|
||||
void main()
|
||||
{
|
||||
// Normalized pixel coordinates (from 0 to 1)
|
||||
vec2 uv = gl_FragCoord.xy/vec2(512);
|
||||
float scale = 1.4;
|
||||
|
||||
// Center when scaling
|
||||
uv -= 0.5 * (1.-1./scale);
|
||||
uv *= scale;
|
||||
vec2 pos = uv;
|
||||
|
||||
// Get signed distance from the input texture
|
||||
// Thanks to https://github.com/Chlumsky/msdfgen
|
||||
vec2 msdfUnit = pxRange/vec2(textureSize(msdf, 0));
|
||||
vec3 s = texture(msdf, pos).rgb;
|
||||
vec3 msd = texture2D(tex, vec2(pos.x, pos.y)).rgb;
|
||||
float sd = median(msd.r, msd.g, msd.b);
|
||||
float screenPxDistance = pxRange*(sd - 0.5);
|
||||
float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0);
|
||||
vec4 fill_color = mix(bgColor, fgColor, opacity);
|
||||
float outline = clamp(screenPxDistance + 1.6, 0., 1.);
|
||||
outline -= clamp(screenPxDistance - 1.6, 0., 1.);
|
||||
outline = smoothstep(0.5, 1., outline);
|
||||
|
||||
// Create an alpha mask for the text
|
||||
float sigDist = median(s.r, s.g, s.b) - 0.5;
|
||||
sigDist *= dot(msdfUnit, 0.5/fwidth(pos));
|
||||
|
||||
float smoothing = 4.-scale;
|
||||
float fill = smoothstep(0.5 - smoothing, 0.5 + smoothing, sigDist);
|
||||
vec4 fill_color = mix(bgColor, fgColor, fill);
|
||||
|
||||
float outline = smoothstep(0.65, 0.80, 1.0-abs(sigDist/15.0-(-0.3333*scale+0.6667)+0.05));
|
||||
vec4 line_color = mix(bgColor, fgColor, outline);
|
||||
|
||||
out_Color = mix(fill_color, line_color, getSweepingLine(uv));
|
||||
out_Color += mix(bgColor, particleColor, getParticles(uv));
|
||||
out_Color += 2.*vec4(1.)*getBox(uv, textPos.x, textPos.z)*getGradients(uv);
|
||||
float mask_rhs = clamp(sign(uv.x-lineWidth-getSweepingLinePos()),0.,1.);
|
||||
out_Color += fill_color*mask_rhs*getSpotlights(uv);
|
||||
out_Color += mix(vec4(0), fgColor, getParticles(uv));
|
||||
out_Color += 2.*fgColor*getBox(uv, textPos.x, textPos.z)*getGradients(uv);
|
||||
}
|
||||
|
@ -368,20 +368,38 @@ void RenderDecal(DecalShader *s, float x, float y, float w, float h,
|
||||
float tw = tw_i, th = th_i;
|
||||
|
||||
#define COL(color, c) (float)(((color)>>((c)*8)) & 0xff)/255.0
|
||||
glUniform1i(s->flipy_loc, s->flip);
|
||||
glUniform4f(s->scale_offset_loc, w / ww, h / wh, -1 + ((2 * x + w) / ww),
|
||||
-1 + ((2 * y + h) / wh));
|
||||
glUniform4f(s->tex_scale_offset_loc, tex_w / tw, tex_h / th, tex_x / tw,
|
||||
tex_y / th);
|
||||
glUniform1i(s->tex_loc, 0);
|
||||
glUniform4f(s->color_primary_loc, COL(primary, 3), COL(primary, 2),
|
||||
COL(primary, 1), COL(primary, 0));
|
||||
glUniform4f(s->color_secondary_loc, COL(secondary, 3), COL(secondary, 2),
|
||||
COL(secondary, 1), COL(secondary, 0));
|
||||
glUniform4f(s->color_fill_loc, COL(fill, 3), COL(fill, 2), COL(fill, 1),
|
||||
COL(fill, 0));
|
||||
if (s->time_loc >= 0) glUniform1f(s->time_loc, s->time/1000.0f);
|
||||
if (s->scale_loc >= 0) glUniform1f(s->scale_loc, s->scale);
|
||||
if (s->flipy_loc >= 0) {
|
||||
glUniform1i(s->flipy_loc, s->flip);
|
||||
}
|
||||
if (s->scale_offset_loc >= 0) {
|
||||
glUniform4f(s->scale_offset_loc, w / ww, h / wh, -1 + ((2 * x + w) / ww),
|
||||
-1 + ((2 * y + h) / wh));
|
||||
}
|
||||
if (s->tex_scale_offset_loc >= 0) {
|
||||
glUniform4f(s->tex_scale_offset_loc, tex_w / tw, tex_h / th, tex_x / tw,
|
||||
tex_y / th);
|
||||
}
|
||||
if (s->tex_loc >= 0) {
|
||||
glUniform1i(s->tex_loc, 0);
|
||||
}
|
||||
if (s->color_primary_loc >= 0) {
|
||||
glUniform4f(s->color_primary_loc, COL(primary, 3), COL(primary, 2),
|
||||
COL(primary, 1), COL(primary, 0));
|
||||
}
|
||||
if (s->color_secondary_loc >= 0) {
|
||||
glUniform4f(s->color_secondary_loc, COL(secondary, 3), COL(secondary, 2),
|
||||
COL(secondary, 1), COL(secondary, 0));
|
||||
}
|
||||
if (s->color_fill_loc >= 0) {
|
||||
glUniform4f(s->color_fill_loc, COL(fill, 3), COL(fill, 2), COL(fill, 1),
|
||||
COL(fill, 0));
|
||||
}
|
||||
if (s->time_loc >= 0) {
|
||||
glUniform1f(s->time_loc, s->time/1000.0f);
|
||||
}
|
||||
if (s->scale_loc >= 0) {
|
||||
glUniform1f(s->scale_loc, s->scale);
|
||||
}
|
||||
#undef COL
|
||||
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, NULL);
|
||||
}
|
||||
@ -623,17 +641,18 @@ void RenderControllerPort(float frame_x, float frame_y, int i,
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
void RenderLogo(uint32_t time, uint32_t primary_color, uint32_t secondary_color,
|
||||
uint32_t fill_color)
|
||||
void RenderLogo(uint32_t time)
|
||||
{
|
||||
uint32_t color = 0x62ca13ff;
|
||||
|
||||
g_logo_shader->time = time;
|
||||
glUseProgram(g_logo_shader->prog);
|
||||
glBindVertexArray(g_decal_shader->vao);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, g_logo_tex);
|
||||
RenderDecal(g_logo_shader, 0, 0, 512, 512, 0, 0, 128, 128, primary_color,
|
||||
secondary_color, fill_color);
|
||||
RenderDecal(g_logo_shader, 0, 0, 512, 512, 0, 0, 128, 128, color,
|
||||
color, 0x00000000);
|
||||
glBindVertexArray(0);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
@ -40,8 +40,7 @@ public:
|
||||
extern Fbo *controller_fbo, *logo_fbo;
|
||||
|
||||
void InitCustomRendering(void);
|
||||
void RenderLogo(uint32_t time, uint32_t primary_color, uint32_t secondary_color,
|
||||
uint32_t fill_color);
|
||||
void RenderLogo(uint32_t time);
|
||||
void RenderController(float frame_x, float frame_y, uint32_t primary_color,
|
||||
uint32_t secondary_color, ControllerState *state);
|
||||
void RenderControllerPort(float frame_x, float frame_y, int i,
|
||||
|
@ -819,31 +819,7 @@ void MainMenuAboutView::Draw()
|
||||
gl_renderer, gl_version, gl_shader_version);
|
||||
}
|
||||
|
||||
static uint32_t time_start = 0;
|
||||
if (ImGui::IsWindowAppearing()) {
|
||||
time_start = SDL_GetTicks();
|
||||
}
|
||||
uint32_t now = SDL_GetTicks() - time_start;
|
||||
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY()-50*g_viewport_mgr.m_scale);
|
||||
ImGui::SetCursorPosX((ImGui::GetWindowWidth()-256*g_viewport_mgr.m_scale)/2);
|
||||
|
||||
logo_fbo->Target();
|
||||
ImTextureID id = (ImTextureID)(intptr_t)logo_fbo->Texture();
|
||||
float t_w = 256.0;
|
||||
float t_h = 256.0;
|
||||
float x_off = 0;
|
||||
ImGui::Image(id,
|
||||
ImVec2((t_w-x_off)*g_viewport_mgr.m_scale, t_h*g_viewport_mgr.m_scale),
|
||||
ImVec2(x_off/t_w, t_h/t_h),
|
||||
ImVec2(t_w/t_w, 0));
|
||||
if (ImGui::IsItemClicked()) {
|
||||
time_start = SDL_GetTicks();
|
||||
}
|
||||
RenderLogo(now, 0x42e335ff, 0x42e335ff, 0x00000000);
|
||||
logo_fbo->Restore();
|
||||
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY()-75*g_viewport_mgr.m_scale);
|
||||
Logo();
|
||||
|
||||
SectionTitle("Build Information");
|
||||
ImGui::PushFont(g_font_mgr.m_fixed_width_font);
|
||||
|
@ -43,56 +43,33 @@ void FirstBootWindow::Draw()
|
||||
ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always);
|
||||
|
||||
ImGui::SetNextWindowSize(size, ImGuiCond_Appearing);
|
||||
if (!ImGui::Begin("First Boot", &is_open, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoDecoration)) {
|
||||
if (!ImGui::Begin("First Boot", &is_open, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
static uint32_t time_start = 0;
|
||||
if (ImGui::IsWindowAppearing()) {
|
||||
time_start = SDL_GetTicks();
|
||||
}
|
||||
uint32_t now = SDL_GetTicks() - time_start;
|
||||
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY()-50*g_viewport_mgr.m_scale);
|
||||
ImGui::SetCursorPosX((ImGui::GetWindowWidth()-256*g_viewport_mgr.m_scale)/2);
|
||||
|
||||
logo_fbo->Target();
|
||||
ImTextureID id = (ImTextureID)(intptr_t)logo_fbo->Texture();
|
||||
float t_w = 256.0;
|
||||
float t_h = 256.0;
|
||||
float x_off = 0;
|
||||
ImGui::Image(id,
|
||||
ImVec2((t_w-x_off)*g_viewport_mgr.m_scale, t_h*g_viewport_mgr.m_scale),
|
||||
ImVec2(x_off/t_w, t_h/t_h),
|
||||
ImVec2(t_w/t_w, 0));
|
||||
if (ImGui::IsItemClicked()) {
|
||||
time_start = SDL_GetTicks();
|
||||
}
|
||||
RenderLogo(now, 0x42e335ff, 0x42e335ff, 0x00000000);
|
||||
logo_fbo->Restore();
|
||||
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY()-100*g_viewport_mgr.m_scale);
|
||||
ImGui::SetCursorPosX(10*g_viewport_mgr.m_scale);
|
||||
ImGui::Dummy(ImVec2(0,20*g_viewport_mgr.m_scale));
|
||||
Logo();
|
||||
|
||||
const char *msg = "Configure machine settings to get started";
|
||||
ImGui::SetCursorPosX((ImGui::GetWindowWidth()-ImGui::CalcTextSize(msg).x)/2);
|
||||
ImGui::Text("%s", msg);
|
||||
|
||||
ImGui::Dummy(ImVec2(0,20*g_viewport_mgr.m_scale));
|
||||
|
||||
ImGui::SetCursorPosX((ImGui::GetWindowWidth()-120*g_viewport_mgr.m_scale)/2);
|
||||
ImGui::SetItemDefaultFocus();
|
||||
if (ImGui::Button("Settings", ImVec2(120*g_viewport_mgr.m_scale, 0))) {
|
||||
g_main_menu.ShowSystem();
|
||||
g_config.general.show_welcome = false;
|
||||
}
|
||||
ImGui::Dummy(ImVec2(0,20*g_viewport_mgr.m_scale));
|
||||
|
||||
ImGui::Dummy(ImVec2(0,50*g_viewport_mgr.m_scale));
|
||||
|
||||
msg = "Visit https://xemu.app for more information";
|
||||
ImGui::SetCursorPosX((ImGui::GetWindowWidth()-ImGui::CalcTextSize(msg).x)/2);
|
||||
Hyperlink(msg, "https://xemu.app");
|
||||
|
||||
ImGui::Dummy(ImVec2(400*g_viewport_mgr.m_scale,20*g_viewport_mgr.m_scale));
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "font-manager.hh"
|
||||
#include "viewport-manager.hh"
|
||||
#include "ui/xemu-os-utils.h"
|
||||
#include "gl-helpers.hh"
|
||||
|
||||
void Separator()
|
||||
{
|
||||
@ -505,3 +506,44 @@ void HelpMarker(const char* desc)
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
void Logo()
|
||||
{
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY()-25*g_viewport_mgr.m_scale);
|
||||
ImGui::SetCursorPosX((ImGui::GetWindowWidth()-256*g_viewport_mgr.m_scale)/2);
|
||||
|
||||
static uint32_t time_start = 0;
|
||||
static uint32_t offset = 0;
|
||||
uint32_t now = SDL_GetTicks();
|
||||
|
||||
if (ImGui::IsWindowAppearing()) {
|
||||
time_start = now;
|
||||
}
|
||||
|
||||
logo_fbo->Target();
|
||||
ImTextureID id = (ImTextureID)(intptr_t)logo_fbo->Texture();
|
||||
float t_w = 256.0;
|
||||
float t_h = 256.0;
|
||||
float x_off = 0;
|
||||
ImVec2 pos = ImGui::GetCursorPos();
|
||||
ImGui::Image(id,
|
||||
ImVec2((t_w-x_off)*g_viewport_mgr.m_scale, t_h*g_viewport_mgr.m_scale),
|
||||
ImVec2(x_off/t_w, t_h/t_h),
|
||||
ImVec2(t_w/t_w, 0));
|
||||
ImVec2 size = ImGui::GetItemRectSize();
|
||||
ImGui::SetCursorPos(pos);
|
||||
ImGui::InvisibleButton("###empty", ImVec2(size.x, size.y*0.8));
|
||||
if (ImGui::IsItemClicked()) {
|
||||
time_start = now;
|
||||
offset = 0;
|
||||
}
|
||||
if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
|
||||
ImVec2 item_min = ImGui::GetItemRectMin();
|
||||
ImVec2 mouse = ImGui::GetMousePos();
|
||||
time_start = now;
|
||||
offset = 1500 * fmin(fmax(0, (mouse.x - item_min.x) / (size.x)), 1);
|
||||
}
|
||||
|
||||
RenderLogo(now - time_start + offset);
|
||||
logo_fbo->Restore();
|
||||
}
|
||||
|
@ -46,3 +46,4 @@ bool ChevronCombo(const char *label, int *current_item,
|
||||
bool ChevronCombo(const char* label, int* current_item, const char* items_separated_by_zeros, const char *description = NULL);
|
||||
void Hyperlink(const char *text, const char *url);
|
||||
void HelpMarker(const char* desc);
|
||||
void Logo();
|
||||
|
Loading…
Reference in New Issue
Block a user