/**
* Powder Toy - Main source
*
* Copyright (c) 2008 - 2011 Stanislaw Skowronek.
* Copyright (c) 2010 - 2011 Simon Robertshaw
* Copyright (c) 2010 - 2011 Skresanov Savely
* Copyright (c) 2010 - 2011 Bryan Hoyle
* Copyright (c) 2010 - 2011 Nathan Cousins
* Copyright (c) 2010 - 2011 cracker64
* Copyright (c) 2011 jacksonmj
*
* 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
#include
#include
#include
#include
#include
#include
#ifdef WIN32
#include
#else
#include
#include
#endif
#include
#include
#include
#include "gravity.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef LUACONSOLE
#include "luaconsole.h"
#endif
#include "save.h"
pixel *vid_buf;
#define NUM_SOUNDS 2
struct sample {
Uint8 *data;
Uint32 dpos;
Uint32 dlen;
} sounds[NUM_SOUNDS];
void mixaudio(void *unused, Uint8 *stream, int len)
{
int i;
Uint32 amount;
for ( i=0; i len ) {
amount = len;
}
SDL_MixAudio(stream, &sounds[i].data[sounds[i].dpos], amount, SDL_MIX_MAXVOLUME);
sounds[i].dpos += amount;
}
}
//plays a .wav file (sounds must be enabled)
void play_sound(char *file)
{
int index;
SDL_AudioSpec wave;
Uint8 *data;
Uint32 dlen;
SDL_AudioCVT cvt;
if (!sound_enable) return;
/* Look for an empty (or finished) sound slot */
for ( index=0; index1)
printf("Multithreading enabled\n");
else
printf("Multithreading disabled\n");
#endif
return numCPU;
}
int mousex = 0, mousey = 0; //They contain mouse position
int kiosk_enable = 0;
void sdl_seticon(void)
{
#ifdef WIN32
//SDL_Surface *icon = SDL_CreateRGBSurfaceFrom(app_icon_w32, 32, 32, 32, 128, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
//SDL_WM_SetIcon(icon, NULL/*app_icon_mask*/);
#else
#ifdef MACOSX
//SDL_Surface *icon = SDL_CreateRGBSurfaceFrom(app_icon_w32, 32, 32, 32, 128, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
//SDL_WM_SetIcon(icon, NULL/*app_icon_mask*/);
#else
SDL_Surface *icon = SDL_CreateRGBSurfaceFrom(app_icon, 16, 16, 32, 64, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
SDL_WM_SetIcon(icon, NULL/*app_icon_mask*/);
#endif
#endif
}
int frame_idx=0;
void dump_frame(pixel *src, int w, int h, int pitch)
{
char frame_name[32];
int j,i;
unsigned char c[3];
FILE *f;
sprintf(frame_name,"frame%04d.ppm",frame_idx);
f=fopen(frame_name,"wb");
fprintf(f,"P6\n%d %d\n255\n",w,h);
for (j=0; jXRES/GRID_S || stamps[i].thumb_h>YRES/GRID_S))
{
factor_x = ceil((float)stamps[i].thumb_w/(float)(XRES/GRID_S));
factor_y = ceil((float)stamps[i].thumb_h/(float)(YRES/GRID_S));
if (factor_y > factor_x)
factor_x = factor_y;
tmp = rescale_img(stamps[i].thumb, stamps[i].thumb_w, stamps[i].thumb_h, &(stamps[i].thumb_w), &(stamps[i].thumb_h), factor_x);
free(stamps[i].thumb);
stamps[i].thumb = tmp;
}
}
free(data);
}
int clipboard_ready = 0;
void *clipboard_data = 0;
int clipboard_length = 0;
void stamp_save(int x, int y, int w, int h)
{
FILE *f;
int n;
char fn[64], sn[16];
void *s=build_save(&n, x, y, w, h, bmap, vx, vy, pv, fvx, fvy, signs, parts);
if (!s)
return;
#ifdef WIN32
_mkdir("stamps");
#else
mkdir("stamps", 0755);
#endif
stamp_gen_name(sn);
sprintf(fn, "stamps" PATH_SEP "%s.stm", sn);
f = fopen(fn, "wb");
if (!f)
return;
fwrite(s, n, 1, f);
fclose(f);
free(s);
if (stamps[STAMP_MAX-1].thumb)
free(stamps[STAMP_MAX-1].thumb);
memmove(stamps+1, stamps, sizeof(struct stamp)*(STAMP_MAX-1));
memset(stamps, 0, sizeof(struct stamp));
if (stamp_count0)
{
memcpy(&tmp, stamps+i, sizeof(struct stamp));
memmove(stamps+1, stamps, sizeof(struct stamp)*i);
memcpy(stamps, &tmp, sizeof(struct stamp));
stamp_update();
}
return data;
}
void stamp_init(void)
{
int i;
FILE *f;
memset(stamps, 0, sizeof(stamps));
f=fopen("stamps" PATH_SEP "stamps.def", "rb");
if (!f)
return;
for (i=0; i= THUMB_CACHE_SIZE)
return;
free(thumb_cache_id[i]);
free(thumb_cache_data[i]);
thumb_cache_id[i] = NULL;
for (j=0; j thumb_cache_lru[i])
thumb_cache_lru[j]--;
}
void thumb_cache_add(char *id, void *thumb, int size)
{
int i,m=-1,j=-1;
thumb_cache_inval(id);
for (i=0; i m)
{
m = thumb_cache_lru[i];
j = i;
}
}
if (i >= THUMB_CACHE_SIZE)
{
thumb_cache_inval(thumb_cache_id[j]);
i = j;
}
for (j=0; j= THUMB_CACHE_SIZE)
return 0;
for (j=0; j0){
//return 0;
info_box(vid_buf, "Save file invalid or from newer version");
}
//Save PTi images
char * datares = NULL, *scaled_buf;
int res = 0, sw, sh;
datares = ptif_pack(vid_buf, XRES, YRES, &res);
if(datares!=NULL){
f=fopen(ptifilename, "wb");
fwrite(datares, res, 1, f);
fclose(f);
free(datares);
datares = NULL;
}
scaled_buf = resample_img(vid_buf, XRES, YRES, XRES/GRID_Z, YRES/GRID_Z);
datares = ptif_pack(scaled_buf, XRES/GRID_Z, YRES/GRID_Z, &res);
if(datares!=NULL){
f=fopen(ptismallfilename, "wb");
fwrite(datares, res, 1, f);
fclose(f);
free(datares);
datares = NULL;
}
free(scaled_buf);
//Save PPM image
f=fopen(ppmfilename, "wb");
fprintf(f,"P6\n%d %d\n255\n",XRES,YRES);
for (j=0; j=48 && tempString[ci]<=57)
{
tempNumberString[ns++] = tempString[ci];
tempNumberString[ns] = 0;
}
else if(tempString[ci]=='#')
{
okay = 1;
break;
}
else
{
puts("ptsave: invalid save ID");
break;
}
ci++;
}
if(!tempString[ci])
{
okay = 1;
}
if(okay)
{
tempSaveID = atoi(tempNumberString);
}
}
if(tempSaveID > 0)
{
puts("Got ptsave:id");
saveURIOpen = tempSaveID;
}
break;
}
}
make_kernel();
stamp_init();
if (!sdl_open())
{
sdl_scale = 1;
kiosk_enable = 0;
if (!sdl_open()) exit(1);
}
save_presets(0);
http_init(http_proxy_string[0] ? http_proxy_string : NULL);
prepare_alpha(CELL, 1.0f);
prepare_graphicscache();
flm_data = generate_gradient(flm_data_colours, flm_data_pos, flm_data_points, 200);
plasma_data = generate_gradient(plasma_data_colours, plasma_data_pos, plasma_data_points, 200);
if (cpu_check())
{
error_ui(vid_buf, 0, "Unsupported CPU. Try another version.");
return 1;
}
if(saveOpenError)
{
error_ui(vid_buf, 0, "Unable to open save file.");
}
http_ver_check = http_async_req_start(NULL, "http://" SERVER "/Update.api?Action=CheckVersion", NULL, 0, 0);
if (svf_login) {
http_auth_headers(http_ver_check, svf_user_id, NULL, svf_session_id); //Add authentication so beta checking can be done from user basis
http_session_check = http_async_req_start(NULL, "http://" SERVER "/Login.api?Action=CheckSession", NULL, 0, 0);
http_auth_headers(http_session_check, svf_user_id, NULL, svf_session_id);
}
#ifdef LUACONSOLE
luacon_eval("dofile(\"autorun.lua\")"); //Autorun lua script
#endif
while (!sdl_poll()) //the main loop
{
frameidx++;
frameidx %= 30;
if (!sys_pause||framerender) //only update air if not paused
{
update_air();
if(aheat_enable)
update_airh();
}
if(gravwl_timeout)
{
if(gravwl_timeout==1)
gravity_mask();
gravwl_timeout--;
}
//Can't be too sure (Limit the cursor size)
if (bsx>1180)
bsx = 1180;
if (bsx<0)
bsx = 0;
if (bsy>1180)
bsy = 1180;
if (bsy<0)
bsy = 0;
//Pretty powders, colour cycle
//sandcolour_r = 0;
//sandcolour_g = 0;
sandcolour_b = sandcolour_r = sandcolour_g = (int)(20.0f*sin((float)sandcolour_frame*(M_PI/180.0f)));
sandcolour_frame++;
sandcolour_frame%=360;
#ifdef OGLR
part_vbuf = vid_buf;
#else
if(ngrav_enable && (display_mode & DISPLAY_WARP))
{
part_vbuf = part_vbuf_store;
memset(vid_buf, 0, (XRES+BARSIZE)*YRES*PIXELSIZE);
} else {
part_vbuf = vid_buf;
}
#endif
render_before(part_vbuf);
if(debug_flags & (DEBUG_PERFORMANCE_CALC|DEBUG_PERFORMANCE_FRAME))
{
#ifdef WIN32
#elif defined(MACOSX)
#else
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
debug_perf_time = ts.tv_nsec;
#endif
}
update_particles(part_vbuf); //update everything
if(debug_flags & (DEBUG_PERFORMANCE_CALC|DEBUG_PERFORMANCE_FRAME))
{
#ifdef WIN32
#elif defined(MACOSX)
#else
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
debug_perf_partitime[debug_perf_iend] = ts.tv_nsec - debug_perf_time;
debug_perf_time = ts.tv_nsec;
#endif
}
render_after(part_vbuf, vid_buf);
if(su == WL_GRAV+100)
draw_grav_zones(part_vbuf);
if(debug_flags & (DEBUG_PERFORMANCE_CALC|DEBUG_PERFORMANCE_FRAME))
{
#ifdef WIN32
#elif defined(MACOSX)
#else
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
debug_perf_frametime[debug_perf_iend] = ts.tv_nsec - debug_perf_time;
#endif
debug_perf_iend++;
debug_perf_iend %= DEBUG_PERF_FRAMECOUNT;
debug_perf_istart++;
debug_perf_istart %= DEBUG_PERF_FRAMECOUNT;
}
gravity_update_async(); //Check for updated velocity maps from gravity thread
if (!sys_pause||framerender) //Only update if not paused
memset(gravmap, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); //Clear the old gravmap
if (framerender) {
framerender = 0;
sys_pause = 1;
}
memset(vid_buf+((XRES+BARSIZE)*YRES), 0, (PIXELSIZE*(XRES+BARSIZE))*MENUSIZE);//clear menu areas
clearrect(vid_buf, XRES-1, 0, BARSIZE+1, YRES);
draw_svf_ui(vid_buf, sdl_mod & (KMOD_LCTRL|KMOD_RCTRL));
if(debug_flags)
{
draw_debug_info(vid_buf, lm, lx, ly, x, y, line_x, line_y);
}
if (http_ver_check)
{
if (!do_check && http_async_req_status(http_ver_check))
{
ver_data = http_async_req_stop(http_ver_check, &http_ret, NULL);
if (http_ret==200 && ver_data)
{
if (sscanf(ver_data, "%d.%d.%d.%d", &major, &minor, &is_beta, &buildnum)==4)
if (buildnum>BUILD_NUM)
old_version = 1;
if (is_beta)
{
old_ver_len = textwidth((char*)old_ver_msg_beta);
}
else
{
old_ver_len = textwidth((char*)old_ver_msg);
}
free(ver_data);
}
http_ver_check = NULL;
}
do_check = (do_check+1) & 15;
}
if (http_session_check)
{
if (!do_s_check && http_async_req_status(http_session_check))
{
char saveURIOpenString[512];
check_data = http_async_req_stop(http_session_check, &http_s_ret, NULL);
if (http_ret==200 && check_data)
{
if (!strncmp(check_data, "EXPIRED", 7))
{
//Session expired
printf("EXPIRED");
strcpy(svf_user, "");
strcpy(svf_pass, "");
strcpy(svf_user_id, "");
strcpy(svf_session_id, "");
svf_login = 0;
svf_own = 0;
svf_admin = 0;
svf_mod = 0;
svf_messages = 0;
}
else if (!strncmp(check_data, "BANNED", 6))
{
//User banned
printf("BANNED");
strcpy(svf_user, "");
strcpy(svf_pass, "");
strcpy(svf_user_id, "");
strcpy(svf_session_id, "");
svf_login = 0;
svf_own = 0;
svf_admin = 0;
svf_mod = 0;
svf_messages = 0;
error_ui(vid_buf, 0, "Unable to log in\nYour account has been suspended, consider reading the rules.");
}
else if (!strncmp(check_data, "OK", 2))
{
//Session valid
if (strlen(check_data)>2) {
//User is elevated
if (!strncmp(check_data+3, "ADMIN", 5))
{
//Check for messages
svf_messages = atoi(check_data+9);
svf_admin = 1;
svf_mod = 0;
}
else if (!strncmp(check_data+3, "MOD", 3))
{
//Check for messages
svf_messages = atoi(check_data+7);
svf_admin = 0;
svf_mod = 1;
} else {
//Check for messages
svf_messages = atoi(check_data+3);
}
}
}
else
{
//No idea, but log the user out anyway
strcpy(svf_user, "");
strcpy(svf_pass, "");
strcpy(svf_user_id, "");
strcpy(svf_session_id, "");
svf_login = 0;
svf_own = 0;
svf_admin = 0;
svf_mod = 0;
svf_messages = 0;
}
save_presets(0);
free(check_data);
} else {
//Unable to check session, YOU WILL BE TERMINATED
strcpy(svf_user, "");
strcpy(svf_pass, "");
strcpy(svf_user_id, "");
strcpy(svf_session_id, "");
svf_login = 0;
svf_own = 0;
svf_admin = 0;
svf_mod = 0;
svf_messages = 0;
}
http_session_check = NULL;
if(saveURIOpen)
{
sprintf(saveURIOpenString, "%d", saveURIOpen);
open_ui(vid_buf, saveURIOpenString, NULL);
saveURIOpen = 0;
}
} else {
if(saveURIOpen)
info_box_overlay(vid_buf, "Waiting for login...");
clearrect(vid_buf, XRES-125+BARSIZE/*385*/, YRES+(MENUSIZE-16), 91, 14);
drawrect(vid_buf, XRES-125+BARSIZE/*385*/, YRES+(MENUSIZE-16), 91, 14, 255, 255, 255, 255);
drawtext(vid_buf, XRES-122+BARSIZE/*388*/, YRES+(MENUSIZE-13), "\x84", 255, 255, 255, 255);
if (username_flash>30) {
username_flash_t = -1;
username_flash = 30;
} else if (username_flash<0) {
username_flash_t = 1;
username_flash = 0;
}
username_flash += username_flash_t;
if (svf_login)
drawtext(vid_buf, XRES-104+BARSIZE/*406*/, YRES+(MENUSIZE-12), svf_user, 255, 255, 255, 175-(username_flash*5));
else
drawtext(vid_buf, XRES-104+BARSIZE/*406*/, YRES+(MENUSIZE-12), "[checking]", 255, 255, 255, 255);
}
do_s_check = (do_s_check+1) & 15;
}
else
{
char saveURIOpenString[512];
if(saveURIOpen)
{
sprintf(saveURIOpenString, "%d", saveURIOpen);
open_ui(vid_buf, saveURIOpenString, NULL);
saveURIOpen = 0;
}
}
#ifdef LUACONSOLE
if(sdl_key){
if(!luacon_keyevent(sdl_key, sdl_mod, LUACON_KDOWN))
sdl_key = 0;
}
if(sdl_rkey){
if(!luacon_keyevent(sdl_rkey, sdl_mod, LUACON_KUP))
sdl_rkey = 0;
}
#endif
if (sys_shortcuts==1)//all shortcuts can be disabled by python scripts
{
if (sdl_key=='q' || sdl_key==SDLK_ESCAPE)
{
if (confirm_ui(vid_buf, "You are about to quit", "Are you sure you want to quit?", "Quit"))
{
break;
}
}
if (sdl_key=='i' && (sdl_mod & KMOD_CTRL))
{
if(confirm_ui(vid_buf, "Install Powder Toy", "You are about to install The Powder Toy", "Install"))
{
if(register_extension())
{
info_ui(vid_buf, "Install success", "Powder Toy has been installed!");
}
else
{
error_ui(vid_buf, 0, "Install failed - You may not have permission or you may be on a platform that does not support installation");
}
}
}
if (sdl_key=='f')
{
framerender = 1;
}
if ((sdl_key=='l' || sdl_key=='k') && stamps[0].name[0])
{
if (load_mode)
{
free(load_img);
free(load_data);
load_mode = 0;
load_data = NULL;
load_img = NULL;
}
if (it > 50)
it = 50;
if (sdl_key=='k' && stamps[1].name[0])
{
j = stamp_ui(vid_buf);
if (j>=0)
load_data = stamp_load(j, &load_size);
else
load_data = NULL;
}
else
load_data = stamp_load(0, &load_size);
if (load_data)
{
load_img = prerender_save(load_data, load_size, &load_w, &load_h);
if (load_img)
load_mode = 1;
else
free(load_data);
}
}
if (sdl_key=='s' && ((sdl_mod & (KMOD_CTRL)) || !player2.spwn))
{
if (it > 50)
it = 50;
save_mode = 1;
}
if(sdl_key=='e')
{
element_search_ui(vid_buf, &sl, &sr);
}
//TODO: Superseded by new display mode switching, need some keyboard shortcuts
if (sdl_key=='1')
{
set_cmode(CM_VEL);
}
if (sdl_key=='2')
{
set_cmode(CM_PRESS);
}
if (sdl_key=='3')
{
set_cmode(CM_PERS);
}
if (sdl_key=='4')
{
set_cmode(CM_FIRE);
}
if (sdl_key=='5')
{
set_cmode(CM_BLOB);
}
if (sdl_key=='6')
{
set_cmode(CM_HEAT);
}
if (sdl_key=='7')
{
set_cmode(CM_FANCY);
}
if (sdl_key=='8')
{
set_cmode(CM_NOTHING);
}
if (sdl_key=='9')
{
set_cmode(CM_GRAD);
}
if (sdl_key=='0')
{
set_cmode(CM_CRACK);
}
if (sdl_key=='1'&& (sdl_mod & (KMOD_SHIFT)) && DEBUG_MODE)
{
set_cmode(CM_LIFE);
}
if (sdl_key==SDLK_TAB)
{
CURRENT_BRUSH =(CURRENT_BRUSH + 1)%BRUSH_NUM ;
}
if (sdl_key==SDLK_LEFTBRACKET) {
if (sdl_zoom_trig)
{
ZSIZE -= 1;
if (ZSIZE>60)
ZSIZE = 60;
if (ZSIZE<2)
ZSIZE = 2;
ZFACTOR = 256/ZSIZE;
}
else
{
if (sdl_mod & (KMOD_LALT|KMOD_RALT) && !(sdl_mod & (KMOD_SHIFT|KMOD_CTRL)))
{
bsx -= 1;
bsy -= 1;
}
else if (sdl_mod & (KMOD_SHIFT) && !(sdl_mod & (KMOD_CTRL)))
{
bsx -= 1;
}
else if (sdl_mod & (KMOD_CTRL) && !(sdl_mod & (KMOD_SHIFT)))
{
bsy -= 1;
}
else
{
bsx -= ceil((bsx/5)+0.5f);
bsy -= ceil((bsy/5)+0.5f);
}
if (bsx>1180)
bsx = 1180;
if (bsy>1180)
bsy = 1180;
if (bsx<0)
bsx = 0;
if (bsy<0)
bsy = 0;
}
}
if (sdl_key==SDLK_RIGHTBRACKET) {
if (sdl_zoom_trig)
{
ZSIZE += 1;
if (ZSIZE>60)
ZSIZE = 60;
if (ZSIZE<2)
ZSIZE = 2;
ZFACTOR = 256/ZSIZE;
}
else
{
if (sdl_mod & (KMOD_LALT|KMOD_RALT) && !(sdl_mod & (KMOD_SHIFT|KMOD_CTRL)))
{
bsx += 1;
bsy += 1;
}
else if (sdl_mod & (KMOD_SHIFT) && !(sdl_mod & (KMOD_CTRL)))
{
bsx += 1;
}
else if (sdl_mod & (KMOD_CTRL) && !(sdl_mod & (KMOD_SHIFT)))
{
bsy += 1;
}
else
{
bsx += ceil((bsx/5)+0.5f);
bsy += ceil((bsy/5)+0.5f);
}
if (bsx>1180)
bsx = 1180;
if (bsy>1180)
bsy = 1180;
if (bsx<0)
bsx = 0;
if (bsy<0)
bsy = 0;
}
}
if (sdl_key=='d' && ((sdl_mod & (KMOD_CTRL)) || !player2.spwn))
DEBUG_MODE = !DEBUG_MODE;
if (sdl_key=='i')
{
int nx, ny;
for (nx = 0; nx= 0 && parts[i].ctype < PT_NUM)
{
parts[i].type = parts[i].ctype;
parts[i].life = 0;
}
else
kill_part(i);
}
}
else
{
for (nx = 0; nx 50)
it = 50;
}*/
if (sdl_key=='z'&&(sdl_mod & (KMOD_LCTRL|KMOD_RCTRL))) // Undo
{
int cbx, cby, cbi;
for (cbi=0; cbi=1)
vs = 0;
else
vs = 3;//every other frame
}
else
{
if (vs>=1)
vs = 0;
else
vs = 1;
}
counterthing = 0;
}
if (vs)
{
if (counterthing+1>=vs)
{
dump_frame(vid_buf, XRES, YRES, XRES+BARSIZE);
counterthing = 0;
}
counterthing = (counterthing+1)%3;
}
#endif
if (sdl_wheel)
{
if (sdl_zoom_trig)//zoom window change
{
ZSIZE += sdl_wheel;
if (ZSIZE>60)
ZSIZE = 60;
if (ZSIZE<2)
ZSIZE = 2;
ZFACTOR = 256/ZSIZE;
sdl_wheel = 0;
}
else //change brush size
{
if (!(sdl_mod & (KMOD_SHIFT|KMOD_CTRL)))
{
bsx += sdl_wheel;
bsy += sdl_wheel;
}
else if (sdl_mod & (KMOD_SHIFT) && !(sdl_mod & (KMOD_CTRL)))
{
bsx += sdl_wheel;
}
else if (sdl_mod & (KMOD_CTRL) && !(sdl_mod & (KMOD_SHIFT)))
{
bsy += sdl_wheel;
}
if (bsx>1180)
bsx = 1180;
if (bsx<0)
bsx = 0;
if (bsy>1180)
bsy = 1180;
if (bsy<0)
bsy = 0;
sdl_wheel = 0;
/*if(su >= PT_NUM) {
if(sl < PT_NUM)
su = sl;
if(sr < PT_NUM)
su = sr;
}*/
}
}
bq = bc; // bq is previous mouse state
bc = b = mouse_get_state(&x, &y); // b is current mouse state
#ifdef LUACONSOLE
if(bc && bq){
if(!luacon_mouseevent(x, y, bc, LUACON_MPRESS)){
b = 0;
}
}
else if(bc && !bq){
if(!luacon_mouseevent(x, y, bc, LUACON_MDOWN)){
b = 0;
}
}
else if(!bc && bq){
if(!luacon_mouseevent(x, y, bq, LUACON_MUP)){
b = 0;
}
}
luacon_step(x, y,sl,sr);
#endif
quickoptions_menu(vid_buf, b, bq, x, y);
for (i=0; i=(XRES-2) && x<(XRES+BARSIZE-1) &&y>= ((i*16)+YRES+MENUSIZE-16-(SC_TOTAL*16)) && y<((i*16)+YRES+MENUSIZE-16-(SC_TOTAL*16)+15))
{
active_menu = i;
}
}
menu_ui_v3(vid_buf, active_menu, &sl, &sr, &su, &dae, b, bq, x, y); //draw the elements in the current menu
mouse_coords_window_to_sim(&x, &y, x, y);//change mouse position while it is in a zoom window
if (y>=0 && y=0 && x>8].ctype>=0 && parts[cr>>8].ctype>8].ctype].name);
}
else if ((cr&0xFF)==PT_LAVA && parts[cr>>8].ctype > 0 && parts[cr>>8].ctype < PT_NUM )
{
char lowername[6];
int ix;
strcpy(lowername, ptypes[parts[cr>>8].ctype].name);
for (ix = 0; lowername[ix]; ix++)
lowername[ix] = tolower(lowername[ix]);
sprintf(nametext, "Molten %s", lowername);
}
else if ((cr&0xFF)==PT_PIPE && (parts[cr>>8].tmp&0xFF) > 0 && (parts[cr>>8].tmp&0xFF) < PT_NUM )
{
char lowername[6];
int ix;
strcpy(lowername, ptypes[parts[cr>>8].tmp&0xFF].name);
for (ix = 0; lowername[ix]; ix++)
lowername[ix] = tolower(lowername[ix]);
sprintf(nametext, "Pipe with %s", lowername);
}
else if (DEBUG_MODE)
{
int tctype = parts[cr>>8].ctype;
if ((cr&0xFF)==PT_PIPE)
{
tctype = parts[cr>>8].tmp&0xFF;
}
if (tctype>=PT_NUM || tctype<0 || (cr&0xFF)==PT_PHOT)
tctype = 0;
sprintf(nametext, "%s (%s)", ptypes[cr&0xFF].name, ptypes[tctype].name);
}
else
{
strcpy(nametext, ptypes[cr&0xFF].name);
}
if (DEBUG_MODE)
{
sprintf(heattext, "%s, Pressure: %3.2f, Temp: %4.2f C, Life: %d, Tmp:%d", nametext, pv[y/CELL][x/CELL], parts[cr>>8].temp-273.15f, parts[cr>>8].life, parts[cr>>8].tmp);
sprintf(coordtext, "#%d, X:%d Y:%d", cr>>8, x, y);
}
else
{
#ifdef BETA
sprintf(heattext, "%s, Pressure: %3.2f, Temp: %4.2f C, Life: %d, Tmp:%d", nametext, pv[y/CELL][x/CELL], parts[cr>>8].temp-273.15f, parts[cr>>8].life, parts[cr>>8].tmp);
#else
sprintf(heattext, "%s, Pressure: %3.2f, Temp: %4.2f C", nametext, pv[y/CELL][x/CELL], parts[cr>>8].temp-273.15f);
#endif
}
if ((cr&0xFF)==PT_PHOT) wavelength_gfx = parts[cr>>8].ctype;
}
else
{
sprintf(heattext, "Empty, Pressure: %3.2f", pv[y/CELL][x/CELL]);
if (DEBUG_MODE)
{
if (ngrav_enable)
sprintf(coordtext, "X:%d Y:%d. GX: %.2f GY: %.2f", x, y, gravx[((y/CELL)*(XRES/CELL))+(x/CELL)], gravy[((y/CELL)*(XRES/CELL))+(x/CELL)]);
else
sprintf(coordtext, "X:%d Y:%d", x, y);
}
}
}
mx = x;
my = y;
if (b && !bq && x>=(XRES-19-new_message_len) &&
x<=(XRES-14) && y>=(YRES-37) && y<=(YRES-24) && svf_messages)
{
open_link("http://" SERVER "/Conversations.html");
}
if (update_flag)
{
info_box(vid_buf, "Finalizing update...");
if (last_build>BUILD_NUM)
{
update_cleanup();
error_ui(vid_buf, 0, "Update failed - try downloading a new version.");
}
else
{
if (update_finish())
error_ui(vid_buf, 0, "Update failed - try downloading a new version.");
else
info_ui(vid_buf, "Update success", "You have successfully updated the Powder Toy!");
}
update_flag = 0;
}
if (b && !bq && x>=(XRES-19-old_ver_len) &&
x<=(XRES-14) && y>=(YRES-22) && y<=(YRES-9) && old_version)
{
tmp = malloc(128);
#ifdef BETA
if (is_beta)
{
sprintf(tmp, "Your version: %d.%d Beta (%d)\nNew version: %d.%d Beta (%d)", SAVE_VERSION, MINOR_VERSION, BUILD_NUM, major, minor, buildnum);
}
else
{
sprintf(tmp, "Your version: %d.%d Beta (%d)\nNew version: %d.%d (%d)", SAVE_VERSION, MINOR_VERSION, BUILD_NUM, major, minor, buildnum);
}
#else
if (is_beta)
{
sprintf(tmp, "Your version: %d.%d (%d)\nNew version: %d.%d Beta (%d)", SAVE_VERSION, MINOR_VERSION, BUILD_NUM, major, minor, buildnum);
}
else
{
sprintf(tmp, "Your version: %d.%d (%d)\nNew version: %d.%d (%d)", SAVE_VERSION, MINOR_VERSION, BUILD_NUM, major, minor, buildnum);
}
#endif
if (confirm_ui(vid_buf, "Do you want to update The Powder Toy?", tmp, "Update"))
{
free(tmp);
tmp = download_ui(vid_buf, my_uri, &i);
if (tmp)
{
save_presets(1);
if (update_start(tmp, i))
{
update_cleanup();
save_presets(0);
error_ui(vid_buf, 0, "Update failed - try downloading a new version.");
}
else
return 0;
}
}
else
{
free(tmp);
old_version = 0;
}
}
if (y>=(YRES+(MENUSIZE-20))) //mouse checks for buttons at the bottom, to draw mouseover texts
{
if (x>=189 && x<=202 && svf_login && svf_open && svf_myvote==0)
{
db = svf_own ? 275 : 272;
if (da < 51)
da ++;
}
else if (x>=204 && x<=217 && svf_login && svf_open && svf_myvote==0)
{
db = svf_own ? 275 : 272;
if (da < 51)
da ++;
}
else if (x>=189 && x<=217 && svf_login && svf_open && svf_myvote!=0)
{
db = (svf_myvote==1) ? 273 : 274;
if (da < 51)
da ++;
}
else if (x>=219 && x<=((XRES+BARSIZE-(510-349))) && svf_login && svf_open)
{
db = svf_own ? 257 : 256;
if (da < 51)
da ++;
}
else if (x>=((XRES+BARSIZE-(510-351))) && x<((XRES+BARSIZE-(510-366))))
{
db = 270;
if (da < 51)
da ++;
}
else if (x>=((XRES+BARSIZE-(510-367))) && x<((XRES+BARSIZE-(510-383))))
{
db = 266;
if (da < 51)
da ++;
}
else if (x>=37 && x<=187)
{
if(sdl_mod & (KMOD_LCTRL|KMOD_RCTRL))
{
db = 277;
if (da < 51)
da ++;
}
else if(svf_login)
{
db = 259;
if (svf_open && svf_own && x<=55)
db = 258;
if (da < 51)
da ++;
}
}
else if (x>=((XRES+BARSIZE-(510-385))) && x<=((XRES+BARSIZE-(510-476))))
{
db = svf_login ? 261 : 260;
if (svf_admin)
{
db = 268;
}
else if (svf_mod)
{
db = 271;
}
if (da < 51)
da ++;
}
else if (x>=1 && x<=17)
{
if(sdl_mod & (KMOD_LCTRL|KMOD_RCTRL))
db = 276;
else
db = 262;
if (da < 51)
da ++;
}
else if (x>=((XRES+BARSIZE-(510-494))) && x<=((XRES+BARSIZE-(510-509))))
{
db = sys_pause ? 264 : 263;
if (da < 51)
da ++;
}
else if (x>=((XRES+BARSIZE-(510-476))) && x<=((XRES+BARSIZE-(510-491))))
{
db = 267;
if (da < 51)
da ++;
}
else if (x>=19 && x<=35 && svf_open)
{
db = 265;
if (da < 51)
da ++;
}
else if (da > 0)
da --;
}
else if (da > 0)//fade away mouseover text
da --;
if (dae > 0) //Fade away selected elements
dae --;
if (!sdl_zoom_trig && zoom_en==1)
zoom_en = 0;
if (sdl_key=='z' && zoom_en==2 && sys_shortcuts==1)
zoom_en = 1;
if (load_mode)
{
load_x = CELL*((mx-load_w/2+CELL/2)/CELL);
load_y = CELL*((my-load_h/2+CELL/2)/CELL);
if (load_x+load_w>XRES) load_x=XRES-load_w;
if (load_y+load_h>YRES) load_y=YRES-load_h;
if (load_x<0) load_x=0;
if (load_y<0) load_y=0;
if (bq==1 && !b)
{
parse_save(load_data, load_size, 0, load_x, load_y, bmap, vx, vy, pv, fvx, fvy, signs, parts, pmap);
free(load_data);
free(load_img);
load_mode = 0;
}
else if (bq==4 && !b)
{
free(load_data);
free(load_img);
load_mode = 0;
}
}
else if (save_mode==1)//getting the area you are selecting
{
save_x = mx;
save_y = my;
if (save_x >= XRES) save_x = XRES-1;
if (save_y >= YRES) save_y = YRES-1;
save_w = 1;
save_h = 1;
if (b==1)
{
save_mode = 2;
}
else if (b==4)
{
save_mode = 0;
copy_mode = 0;
}
}
else if (save_mode==2)
{
save_w = mx + 1 - save_x;
save_h = my + 1 - save_y;
if (save_w+save_x>XRES) save_w = XRES-save_x;
if (save_h+save_y>YRES) save_h = YRES-save_y;
if (save_w<1) save_w = 1;
if (save_h<1) save_h = 1;
if (!b)
{
if (copy_mode==1)//CTRL-C, copy
{
clipboard_data=build_save(&clipboard_length, save_x, save_y, save_w, save_h, bmap, vx, vy, pv, fvx, fvy, signs, parts);
clipboard_ready = 1;
save_mode = 0;
copy_mode = 0;
}
else if (copy_mode==2)//CTRL-X, cut
{
clipboard_data=build_save(&clipboard_length, save_x, save_y, save_w, save_h, bmap, vx, vy, pv, fvx, fvy, signs, parts);
clipboard_ready = 1;
save_mode = 0;
copy_mode = 0;
clear_area(save_x, save_y, save_w, save_h);
}
else//normal save
{
stamp_save(save_x, save_y, save_w, save_h);
save_mode = 0;
}
}
}
else if (sdl_zoom_trig && zoom_en<2)
{
x -= ZSIZE/2;
y -= ZSIZE/2;
if (x<0) x=0;
if (y<0) y=0;
if (x>XRES-ZSIZE) x=XRES-ZSIZE;
if (y>YRES-ZSIZE) y=YRES-ZSIZE;
zoom_x = x;
zoom_y = y;
zoom_wx = (x 50)
it = 50;
if (y>=YRES+(MENUSIZE-20))//check if mouse is on menu buttons
{
if (!lb)//mouse is NOT held down, so it is a first click
{
if (x>=189 && x<=202 && svf_login && svf_open && svf_myvote==0 && svf_own==0)
{
if (execute_vote(vid_buf, svf_id, "Up"))
{
svf_myvote = 1;
}
}
if (x>=204 && x<=217 && svf_login && svf_open && svf_myvote==0 && svf_own==0)
{
if (execute_vote(vid_buf, svf_id, "Down"))
{
svf_myvote = -1;
}
}
if (x>=219 && x<=(XRES+BARSIZE-(510-349)) && svf_login && svf_open)
tag_list_ui(vid_buf);
if (x>=(XRES+BARSIZE-(510-351)) && x<(XRES+BARSIZE-(510-366)) && !bq)
{
//legacy_enable = !legacy_enable;
simulation_ui(vid_buf);
}
if (x>=(XRES+BARSIZE-(510-367)) && x<=(XRES+BARSIZE-(510-383)) && !bq)
{
clear_sim();
for (i=0; i=(XRES+BARSIZE-(510-385)) && x<=(XRES+BARSIZE-(510-476)))
{
login_ui(vid_buf);
if (svf_login) {
save_presets(0);
http_session_check = NULL;
}
}
if(sdl_mod & (KMOD_LCTRL|KMOD_RCTRL))
{
if (x>=37 && x<=187)
{
save_filename_ui(vid_buf);
}
if (x>=1 && x<=17)
{
catalogue_ui(vid_buf);
}
} else {
if (x>=37 && x<=187 && svf_login)
{
if (!svf_open || !svf_own || x>51)
{
if (save_name_ui(vid_buf)) {
execute_save(vid_buf);
if (svf_id[0]) {
copytext_ui(vid_buf, "Save ID", "Saved successfully!", svf_id);
}
}
}
else
execute_save(vid_buf);
while (!sdl_poll())
if (!mouse_get_state(&x, &y))
break;
b = bq = 0;
}
if (x>=1 && x<=17)
{
search_ui(vid_buf);
memset(pers_bg, 0, (XRES+BARSIZE)*YRES*PIXELSIZE);
memset(fire_r, 0, sizeof(fire_r));
memset(fire_g, 0, sizeof(fire_g));
memset(fire_b, 0, sizeof(fire_b));
}
}
if (x>=19 && x<=35 && svf_last && (svf_open || svf_fileopen) && !bq) {
//int tpval = sys_pause;
parse_save(svf_last, svf_lsize, 1, 0, 0, bmap, vx, vy, pv, fvx, fvy, signs, parts, pmap);
//sys_pause = tpval;
}
if (x>=(XRES+BARSIZE-(510-476)) && x<=(XRES+BARSIZE-(510-491)) && !bq)
{
render_ui(vid_buf, XRES+BARSIZE-(510-491)+1, YRES+22, 3);
}
if (x>=(XRES+BARSIZE-(510-494)) && x<=(XRES+BARSIZE-(510-509)) && !bq)
sys_pause = !sys_pause;
lb = 0;
}
}
else if (y=signx && x<=signx+signw && y>=signy && y<=signy+signh)
{
char buff[256];
int sldr;
memset(buff, 0, sizeof(buff));
for (sldr=3; signs[signi].text[sldr] != '|'; sldr++)
buff[sldr-3] = signs[signi].text[sldr];
buff[sldr-3] = '\0';
open_ui(vid_buf, buff, 0);
}
}
}
if (c==WL_SIGN+100 || MSIGN!=-1) // if sign tool is selected or a sign is being moved
{
if (!bq)
add_sign_ui(vid_buf, x, y);
}
else if (c==PT_FIGH)
{
if (!bq)
create_part(-1, x, y, PT_FIGH);
}
//for the click functions, lx and ly, are the positions of where the FIRST click happened. x,y are current mouse position.
else if (lb)//lb means you are holding mouse down
{
if (lm == 1)//line tool
{
if (sdl_mod & KMOD_ALT)
{
float snap_angle = floor(atan2(y-ly, x-lx)/(M_PI*0.25)+0.5)*M_PI*0.25;
float line_mag = sqrtf(pow(x-lx,2)+pow(y-ly,2));
line_x = (int)(line_mag*cos(snap_angle)+lx+0.5f);
line_y = (int)(line_mag*sin(snap_angle)+ly+0.5f);
}
else
{
line_x = x;
line_y = y;
}
xor_line(lx, ly, line_x, line_y, vid_buf);
if (c==WL_FAN+100 && lx>=0 && ly>=0 && lx0 && ly+j>0 && lx+i0 && y+j>0 && x+i=0 && y=0 && x>8].ctype << 8) | c;
}
else
{
//Something
}
}
lx = x;
ly = y;
lb = 0;
lm = 0;
}
else //normal click, spawn element
{
//Copy state before drawing any particles (for undo)7
int cbx, cby, cbi;
for (cbi=0; cbi=XRES || ly>=YRES || bmap[ly/CELL][lx/CELL]!=WL_FAN)
create_line(lx, ly, line_x, line_y, bsx, bsy, c, get_brush_flags());
}
else//box
create_box(lx, ly, x, y, c, get_brush_flags());
lm = 0;
}
lb = 0;
}
if (load_mode)//draw preview of stamp
{
draw_image(vid_buf, load_img, load_x, load_y, load_w, load_h, 128);
xor_rect(vid_buf, load_x, load_y, load_w, load_h);
}
if (save_mode)//draw dotted lines for selection
{
xor_rect(vid_buf, save_x, save_y, save_w, save_h);
da = 51;//draws mouseover text for the message
db = 269;//the save message
}
if (zoom_en!=1 && !load_mode && !save_mode)//draw normal cursor
{
render_cursor(vid_buf, mx, my, su, bsx, bsy);
mousex = mx;
mousey = my;
}
#ifdef OGLR
draw_parts_fbo();
#endif
if (zoom_en)
render_zoom(vid_buf);
if (da)
switch (db)//various mouseover messages, da is the alpha
{
case 256:
drawtext(vid_buf, 16, YRES-24, "Add simulation tags.", 255, 255, 255, da*5);
break;
case 257:
drawtext(vid_buf, 16, YRES-24, "Add and remove simulation tags.", 255, 255, 255, da*5);
break;
case 258:
drawtext(vid_buf, 16, YRES-24, "Save the simulation under the current name.", 255, 255, 255, da*5);
break;
case 259:
drawtext(vid_buf, 16, YRES-24, "Save the simulation under a new name.", 255, 255, 255, da*5);
break;
case 260:
drawtext(vid_buf, 16, YRES-24, "Sign into the Simulation Server.", 255, 255, 255, da*5);
break;
case 261:
drawtext(vid_buf, 16, YRES-24, "Sign into the Simulation Server under a new name.", 255, 255, 255, da*5);
break;
case 262:
drawtext(vid_buf, 16, YRES-24, "Find & open a simulation", 255, 255, 255, da*5);
break;
case 263:
drawtext(vid_buf, 16, YRES-24, "Pause the simulation", 255, 255, 255, da*5);
break;
case 264:
drawtext(vid_buf, 16, YRES-24, "Resume the simulation", 255, 255, 255, da*5);
break;
case 265:
drawtext(vid_buf, 16, YRES-24, "Reload the simulation", 255, 255, 255, da*5);
break;
case 266:
drawtext(vid_buf, 16, YRES-24, "Erase all particles and walls", 255, 255, 255, da*5);
break;
case 267:
drawtext(vid_buf, 16, YRES-24, "Change display mode", 255, 255, 255, da*5);
break;
case 268:
drawtext(vid_buf, 16, YRES-24, "Annuit C\245ptis", 255, 255, 255, da*5);
break;
case 269:
drawtext(vid_buf, 16, YRES-24, "Click-and-drag to specify a rectangle to copy (right click = cancel).", 255, 216, 32, da*5);
break;
case 270:
drawtext(vid_buf, 16, YRES-24, "Simulation options", 255, 255, 255, da*5);
break;
case 271:
drawtext(vid_buf, 16, YRES-24, "You're a moderator", 255, 255, 255, da*5);
break;
case 272:
drawtext(vid_buf, 16, YRES-24, "Like/Dislike this save.", 255, 255, 255, da*5);
break;
case 273:
drawtext(vid_buf, 16, YRES-24, "You like this.", 255, 255, 255, da*5);
break;
case 274:
drawtext(vid_buf, 16, YRES-24, "You dislike this.", 255, 255, 255, da*5);
break;
case 275:
drawtext(vid_buf, 16, YRES-24, "You cannot vote on your own save.", 255, 255, 255, da*5);
break;
case 276:
drawtext(vid_buf, 16, YRES-24, "Open a simulation from your hard drive.", 255, 255, 255, da*5);
break;
case 277:
drawtext(vid_buf, 16, YRES-24, "Save the simulation to your hard drive.", 255, 255, 255, da*5);
break;
default:
drawtext(vid_buf, 16, YRES-24, (char *)ptypes[db].descs, 255, 255, 255, da*5);
}
if (itc)//message in the middle of the screen, such as view mode changes
{
itc--;
drawtext_outline(vid_buf, (XRES-textwidth(itc_msg))/2, ((YRES/2)-10), itc_msg, 255, 255, 255, itc>51?255:itc*5, 0, 0, 0, itc>51?255:itc*5);
}
if (it)//intro message
{
it--;
drawtext(vid_buf, 16, 20, it_msg, 255, 255, 255, it>51?255:it*5);
}
if (old_version)
{
clearrect(vid_buf, XRES-21-old_ver_len, YRES-24, old_ver_len+9, 17);
if (is_beta)
{
drawtext(vid_buf, XRES-16-old_ver_len, YRES-19, old_ver_msg_beta, 255, 216, 32, 255);
}
else
{
drawtext(vid_buf, XRES-16-old_ver_len, YRES-19, old_ver_msg, 255, 216, 32, 255);
}
drawrect(vid_buf, XRES-19-old_ver_len, YRES-22, old_ver_len+5, 13, 255, 216, 32, 255);
}
if (svf_messages)
{
sprintf(new_message_msg, "You have %d new message%s, Click to view", svf_messages, (svf_messages>1)?"s":"");
new_message_len = textwidth(new_message_msg);
clearrect(vid_buf, XRES-21-new_message_len, YRES-39, new_message_len+9, 17);
drawtext(vid_buf, XRES-16-new_message_len, YRES-34, new_message_msg, 255, 186, 32, 255);
drawrect(vid_buf, XRES-19-new_message_len, YRES-37, new_message_len+5, 13, 255, 186, 32, 255);
}
FPS++;
currentTime = SDL_GetTicks();
elapsedTime = currentTime-pastFPS;
if ((FPS>2 || elapsedTime>1000*2/limitFPS) && elapsedTime && FPS*1000/elapsedTime>limitFPS)
{
while (FPS*1000/elapsedTime>limitFPS)
{
SDL_Delay(1);
currentTime = SDL_GetTicks();
elapsedTime = currentTime-pastFPS;
}
}
if (elapsedTime>=1000)
{
FPSB = FPS;
FPS = 0;
pastFPS = currentTime;
}
if (hud_enable)
{
#ifdef BETA
sprintf(uitext, "Beta Build %d FPS:%d Parts:%d Gravity:%d Air:%d", BUILD_NUM, FPSB, NUM_PARTS, gravityMode, airMode);
#else
if (DEBUG_MODE)
sprintf(uitext, "Build %d FPS:%d Parts:%d Gravity:%d Air:%d", BUILD_NUM, FPSB, NUM_PARTS, gravityMode, airMode);
else
sprintf(uitext, "FPS:%d", FPSB);
#endif
if (REPLACE_MODE)
strappend(uitext, " [REPLACE MODE]");
if (sdl_mod&(KMOD_CAPS))
strappend(uitext, " [CAPS LOCK]");
if (GRID_MODE)
{
char gridtext[15];
sprintf(gridtext, " [GRID: %d]", GRID_MODE);
strappend(uitext, gridtext);
}
#ifdef INTERNAL
if (vs)
strappend(uitext, " [FRAME CAPTURE]");
#endif
quickoptions_tooltip_fade_invert = 255 - (quickoptions_tooltip_fade*20);
it_invert = 50 - it;
if(it_invert < 0)
it_invert = 0;
if(it_invert > 50)
it_invert = 50;
if (sdl_zoom_trig||zoom_en)
{
if (zoom_x0) || sr==SPC_AIR || sr == PT_NEUT || sr == PT_PHOT || sr == PT_LIGH)
player.elem = sr;
else
player.elem = PT_DUST;
}
if (player2.spwn==0)
{
if ((sr0) || sr==SPC_AIR || sr == PT_NEUT || sr == PT_PHOT || sr == PT_LIGH)
player2.elem = sr;
else
player2.elem = PT_DUST;
}
}
save_presets(0);
SDL_CloseAudio();
http_done();
gravity_cleanup();
#ifdef LUACONSOLE
luacon_close();
#endif
#ifdef PTW32_STATIC_LIB
pthread_win32_thread_detach_np();
pthread_win32_process_detach_np();
#endif
return 0;
}
#endif