/* -copyright-
#-#
#-# xsnow: let it snow on your desktop
#-# Copyright (C) 1984,1988,1990,1993-1995,2000-2001 Rick Jansen
#-# 2019,2020,2021 Willem Vermin
#-#
#-# This program is free software: you can redistribute it and/or modify
#-# it under the terms of the GNU General Public License as published by
#-# the Free Software Foundation, either version 3 of the License, or
#-# (at your option) any later version.
#-#
#-# This program is distributed in the hope that it will be useful,
#-# but WITHOUT ANY WARRANTY; without even the implied warranty of
#-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#-# GNU General Public License for more details.
#-#
#-# You should have received a copy of the GNU General Public License
#-# along with this program. If not, see .
#-#
*/
#include
#include
#include
#include "wind.h"
#include "utils.h"
#include "debug.h"
#include "flags.h"
#include "windows.h"
#include "clocks.h"
#include "xsnow.h"
#define NOTACTIVE \
(Flags.BirdsOnly || !WorkspaceActive())
static void SetWhirl(void);
static void SetWindTimer(void);
static int do_wind(void *);
static int do_newwind(void *);
void wind_init()
{
SetWhirl();
SetWindTimer();
add_to_mainloop(PRIORITY_DEFAULT, time_newwind, do_newwind );
add_to_mainloop(PRIORITY_DEFAULT, time_wind, do_wind );
}
void wind_ui()
{
UIDO(NoWind, global.Wind = 0; global.NewWind = 0;);
UIDO(WhirlFactor, SetWhirl(););
UIDO(WindTimer, SetWindTimer(););
if(Flags.WindNow)
{
Flags.WindNow = 0;
global.Wind = 2;
P("Gust: %d\n",Flags.Changes);
}
}
void draw_wind()
{
// Nothing to draw
}
int do_newwind(void *d)
{
P("newwind\n");
if (Flags.Done)
return FALSE;
if (NOTACTIVE)
return TRUE;
//
// the speed of newwind is pixels/second
// at steady Wind, eventually all flakes get this speed.
//
if(Flags.NoWind) return TRUE;
static double t0 = -1;
if (t0<0)
{
t0 = wallclock();
return TRUE;
}
float r;
switch (global.Wind)
{
case(0):
default:
r = drand48()*global.Whirl;
global.NewWind += r - global.Whirl/2;
if(global.NewWind > global.WindMax) global.NewWind = global.WindMax;
if(global.NewWind < -global.WindMax) global.NewWind = -global.WindMax;
break;
case(1):
global.NewWind = global.Direction*0.6*global.Whirl;
break;
case(2):
global.NewWind = global.Direction*1.2*global.Whirl;
break;
}
return TRUE;
(void)d;
}
int do_wind(void *d)
{
P("wind\n");
if (Flags.Done)
return FALSE;
if (NOTACTIVE)
return TRUE;
if(Flags.NoWind) return TRUE;
static int first = 1;
static double prevtime;
double TNow = wallclock();
if (first)
{
prevtime = TNow;;
first = 0;
}
// on the average, this function will do something
// after WindTimer secs
if ((TNow - prevtime) < 2*global.WindTimer*drand48()) return TRUE;
prevtime = TNow;
if(drand48() > 0.65) // Now for some of Rick's magic:
{
if(drand48() > 0.4)
global.Direction = 1;
else
global.Direction = -1;
global.Wind = 2;
global.WindTimer = 5;
// next time, this function will be active
// after on average 5 secs
}
else
{
if(global.Wind == 2)
{
global.Wind = 1;
global.WindTimer = 3;
// next time, this function will be active
// after on average 3 secs
}
else
{
global.Wind = 0;
global.WindTimer = global.WindTimerStart;
// next time, this function will be active
// after on average WindTimerStart secs
}
}
return TRUE;
(void)d;
}
void SetWhirl()
{
global.Whirl = 0.01*Flags.WhirlFactor*WHIRL;
}
void SetWindTimer()
{
global.WindTimerStart = Flags.WindTimer;
if (global.WindTimerStart < 3)
global.WindTimerStart = 3;
global.WindTimer = global.WindTimerStart;
}