Deliantra-Client
view release on metacpan or search on metacpan
sv_rvweaken (rv);
int
in_destruct ()
CODE:
RETVAL = PL_main_cv == Nullcv;
OUTPUT:
RETVAL
NV floor (NV x)
NV ceil (NV x)
IV minpot (UV n)
IV popcount (UV n)
NV distance (NV dx, NV dy)
CODE:
RETVAL = pow (dx * dx + dy * dy, 0.5);
OUTPUT:
RETVAL
void
pango_init ()
CODE:
{
opengl_fontmap = pango_opengl_font_map_new ();
pango_opengl_font_map_set_default_substitute ((PangoOpenGLFontMap *)opengl_fontmap, substitute_func, 0, 0);
opengl_context = pango_opengl_font_map_create_context ((PangoOpenGLFontMap *)opengl_fontmap);
/*pango_context_set_font_description (opengl_context, default_font);*/
#if PANGO_VERSION_CHECK (1, 15, 2)
pango_context_set_language (opengl_context, pango_language_from_string ("en"));
/*pango_context_set_base_dir (opengl_context, PANGO_DIRECTION_WEAK_LTR);*/
#endif
}
char *SDL_GetError ()
void SDL_braino ()
int SDL_Init (U32 flags)
int SDL_InitSubSystem (U32 flags)
void SDL_QuitSubSystem (U32 flags)
void SDL_Quit ()
int SDL_GL_SetAttribute (int attr, int value)
int SDL_GL_GetAttribute (int attr)
CODE:
if (SDL_GL_GetAttribute (attr, &RETVAL))
XSRETURN_UNDEF;
OUTPUT:
RETVAL
void
SDL_ListModes (int rgb, int alpha)
PPCODE:
{
SDL_Rect **m;
SDL_GL_SetAttribute (SDL_GL_RED_SIZE , rgb);
SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, rgb);
SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE , rgb);
SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, alpha);
SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15);
SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE , 0);
SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE , 0);
SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE , 0);
SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
if (m && m != (SDL_Rect **)-1)
while (*m)
{
if ((*m)->w >= 400 && (*m)->h >= 300)
{
AV *av = newAV ();
av_push (av, newSViv ((*m)->w));
av_push (av, newSViv ((*m)->h));
av_push (av, newSViv (rgb));
av_push (av, newSViv (alpha));
XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
}
++m;
}
}
int
SDL_SetVideoMode (int w, int h, int rgb, int alpha, int fullscreen)
CODE:
{
SDL_EnableUNICODE (1);
SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
SDL_GL_SetAttribute (SDL_GL_RED_SIZE , rgb);
SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, rgb);
SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE , rgb);
SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, alpha);
RETVAL = !!SDL_SetVideoMode (
w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)
);
if (RETVAL)
{
av_clear (texture_av);
SDL_WM_SetCaption ("Deliantra MORPG Client " VERSION, "Deliantra");
#define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
#include "glfunc.h"
#undef GL_FUNC
if (!gl.ActiveTexture ) gl.ActiveTexture = gl.ActiveTextureARB;
if (!gl.MultiTexCoord2f) gl.MultiTexCoord2f = gl.MultiTexCoord2fARB;
}
}
OUTPUT:
RETVAL
void
SDL_GL_SwapBuffers ()
char *
SDL_GetKeyName (int sym)
int
SDL_GetAppState ()
int
SDL_GetModState ()
void
poll_events ()
PPCODE:
{
SDL_Event ev;
SDL_PumpEvents ();
while (SDL_PeepEvents (&ev, 1, SDL_GETEVENT, SDL_ALLEVENTS) > 0)
{
HV *hv = newHV ();
hv_store (hv, "type", 4, newSViv (ev.type), 0);
switch (ev.type)
{
case SDL_KEYDOWN:
case SDL_KEYUP:
hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
hv_store (hv, "mod", 3, newSViv (mod_munge (ev.key.keysym.mod)), 0);
hv_store (hv, "cmod", 4, newSViv (mod_munge (SDL_GetModState ())), 0); /* current mode */
hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
break;
case SDL_ACTIVEEVENT:
hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
break;
case SDL_MOUSEMOTION:
{
int state = ev.motion.state;
int x = ev.motion.x;
int y = ev.motion.y;
int xrel = ev.motion.xrel;
int yrel = ev.motion.yrel;
/* do simplistic event compression */
while (SDL_PeepEvents (&ev, 1, SDL_PEEKEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION)) > 0
&& state == ev.motion.state)
{
xrel += ev.motion.xrel;
yrel += ev.motion.yrel;
x = ev.motion.x;
y = ev.motion.y;
SDL_PeepEvents (&ev, 1, SDL_GETEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION));
}
hv_store (hv, "mod", 3, newSViv (mod_munge (SDL_GetModState ())), 0);
hv_store (hv, "state", 5, newSViv (state), 0);
hv_store (hv, "x", 1, newSViv (x), 0);
hv_store (hv, "y", 1, newSViv (y), 0);
hv_store (hv, "xrel", 4, newSViv (xrel), 0);
hv_store (hv, "yrel", 4, newSViv (yrel), 0);
}
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
hv_store (hv, "mod", 3, newSViv (SDL_GetModState () & MOD_MASK), 0);
hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
break;
case SDL_USEREVENT:
hv_store (hv, "code", 4, newSViv (ev.user.code), 0);
hv_store (hv, "data1", 5, newSViv ((IV)ev.user.data1), 0);
hv_store (hv, "data2", 5, newSViv ((IV)ev.user.data2), 0);
break;
}
XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("DC::UI::Event", 1))));
}
}
char *
SDL_AudioDriverName ()
CODE:
{
char buf [256];
if (!SDL_AudioDriverName (buf, sizeof (buf)))
XSRETURN_UNDEF;
RETVAL = buf;
}
OUTPUT:
RETVAL
int
Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096)
POSTCALL:
Mix_HookMusicFinished (music_finished);
Mix_ChannelFinished (channel_finished);
void
Mix_QuerySpec ()
PPCODE:
{
int freq, channels;
Uint16 format;
if (Mix_QuerySpec (&freq, &format, &channels))
{
EXTEND (SP, 3);
PUSHs (sv_2mortal (newSViv (freq)));
PUSHs (sv_2mortal (newSViv (format)));
PUSHs (sv_2mortal (newSViv (channels)));
}
}
void
Mix_CloseAudio ()
int
Mix_AllocateChannels (int numchans = -1)
const char *
Mix_GetError ()
void
lowdelay (int fd, int val = 1)
CODE:
setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&val, sizeof (val));
void
win32_proxy_info ()
PPCODE:
{
#ifdef _WIN32
char buffer[2048];
DWORD buflen;
EXTEND (SP, 3);
buflen = sizeof (buffer);
if (InternetQueryOption (0, INTERNET_OPTION_PROXY, (void *)buffer, &buflen))
if (((INTERNET_PROXY_INFO *)buffer)->dwAccessType == INTERNET_OPEN_TYPE_PROXY)
{
PUSHs (newSVpv (((INTERNET_PROXY_INFO *)buffer)->lpszProxy, 0));
buflen = sizeof (buffer);
if (InternetQueryOption (0, INTERNET_OPTION_PROXY_USERNAME, (void *)buffer, &buflen))
{
PUSHs (newSVpv (buffer, 0));
buflen = sizeof (buffer);
if (InternetQueryOption (0, INTERNET_OPTION_PROXY_PASSWORD, (void *)buffer, &buflen))
PUSHs (newSVpv (buffer, 0));
}
}
#endif
}
int
add_font (char *file)
CODE:
RETVAL = FcConfigAppFontAddFile (0, (const FcChar8 *)file);
OUTPUT:
RETVAL
void
load_image_inline (SV *image_)
ALIAS:
load_image_file = 1
PPCODE:
{
STRLEN image_len;
char *image = (char *)SvPVbyte (image_, image_len);
SDL_Surface *surface, *surface2;
SDL_PixelFormat fmt;
SDL_RWops *rw = ix
? SDL_RWFromFile (image, "rb")
: SDL_RWFromConstMem (image, image_len);
if (!rw)
croak ("load_image: %s", SDL_GetError ());
surface = IMG_Load_RW (rw, 1);
if (!surface)
croak ("load_image: %s", SDL_GetError ());
fmt.palette = NULL;
fmt.BitsPerPixel = 32;
fmt.BytesPerPixel = 4;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
fmt.Rmask = 0x000000ff;
fmt.Gmask = 0x0000ff00;
fmt.Bmask = 0x00ff0000;
fmt.Amask = 0xff000000;
#else
fmt.Rmask = 0xff000000;
fmt.Gmask = 0x00ff0000;
fmt.Bmask = 0x0000ff00;
fmt.Amask = 0x000000ff;
#endif
fmt.Rloss = 0;
fmt.Gloss = 0;
fmt.Bloss = 0;
fmt.Aloss = 0;
fmt.Rshift = 0;
fmt.Gshift = 8;
fmt.Bshift = 16;
fmt.Ashift = 24;
fmt.colorkey = 0;
fmt.alpha = 0;
surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
assert (surface2->pitch == surface2->w * 4);
SDL_LockSurface (surface2);
EXTEND (SP, 6);
PUSHs (sv_2mortal (newSViv (surface2->w)));
PUSHs (sv_2mortal (newSViv (surface2->h)));
PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
PUSHs (sv_2mortal (newSViv (GL_RGBA)));
PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
SDL_UnlockSurface (surface2);
SDL_FreeSurface (surface);
SDL_FreeSurface (surface2);
}
void
average (int x, int y, uint32_t *data)
PPCODE:
{
uint32_t r = 0, g = 0, b = 0, a = 0;
x = y = x * y;
while (x--)
{
uint32_t p = *data++;
r += (p ) & 255;
g += (p >> 8) & 255;
b += (p >> 16) & 255;
a += (p >> 24) & 255;
}
EXTEND (SP, 4);
PUSHs (sv_2mortal (newSViv (r / y)));
PUSHs (sv_2mortal (newSViv (g / y)));
PUSHs (sv_2mortal (newSViv (b / y)));
PUSHs (sv_2mortal (newSViv (a / y)));
}
void
error (char *message)
CODE:
fprintf (stderr, "ERROR: %s\n", message);
#ifdef _WIN32
MessageBox (0, message, "Deliantra Client Error", MB_OK | MB_ICONERROR);
#endif
void
fatal (char *message)
CODE:
fprintf (stderr, "FATAL: %s\n", message);
#ifdef _WIN32
MessageBox (0, message, "Deliantra Client Fatal Error", MB_OK | MB_ICONERROR);
#endif
_exit (1);
void
_exit (int retval = 0)
CODE:
#ifdef WIN32
ExitThread (retval); // unclean, please beam me up
#else
_exit (retval);
#endif
void
debug ()
CODE:
{
#if DEBUG
VALGRIND_DO_LEAK_CHECK;
#endif
}
int
SvREFCNT (SV *sv)
CODE:
pango_layout_set_text (self->pl, text, textlen);
}
void
set_markup (DC::Layout self, SV *text_)
CODE:
{
STRLEN textlen;
char *text = SvPVutf8 (text_, textlen);
pango_layout_set_markup (self->pl, text, textlen);
}
void
set_shapes (DC::Layout self, ...)
CODE:
{
PangoAttrList *attrs = 0;
const char *text = pango_layout_get_text (self->pl);
const char *pos = text;
int arg = 4;
while (arg < items && (pos = strstr (pos, OBJ_STR)))
{
PangoRectangle inkrect, rect;
PangoAttribute *attr;
int x = SvIV (ST (arg - 3));
int y = SvIV (ST (arg - 2));
int w = SvIV (ST (arg - 1));
int h = SvIV (ST (arg ));
inkrect.x = 0;
inkrect.y = 0;
inkrect.width = 0;
inkrect.height = 0;
rect.x = x * PANGO_SCALE;
rect.y = y * PANGO_SCALE;
rect.width = w * PANGO_SCALE;
rect.height = h * PANGO_SCALE;
if (!attrs)
attrs = pango_layout_get_attributes (self->pl);
attr = pango_attr_shape_new (&inkrect, &rect);
attr->start_index = pos - text;
attr->end_index = attr->start_index + sizeof (OBJ_STR) - 1;
pango_attr_list_insert (attrs, attr);
arg += 4;
pos += sizeof (OBJ_STR) - 1;
}
if (attrs)
pango_layout_set_attributes (self->pl, attrs);
}
void
get_shapes (DC::Layout self)
PPCODE:
{
PangoLayoutIter *iter = pango_layout_get_iter (self->pl);
do
{
PangoLayoutRun *run = pango_layout_iter_get_run_readonly (iter);
if (run && shape_attr_p (run))
{
PangoRectangle extents;
pango_layout_iter_get_run_extents (iter, 0, &extents);
EXTEND (SP, 2);
PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.x))));
PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.y))));
}
}
while (pango_layout_iter_next_run (iter));
pango_layout_iter_free (iter);
}
int
has_wrapped (DC::Layout self)
CODE:
{
int lines = 1;
const char *text = pango_layout_get_text (self->pl);
while (*text)
lines += *text++ == '\n';
RETVAL = lines < pango_layout_get_line_count (self->pl);
}
OUTPUT:
RETVAL
SV *
get_text (DC::Layout self)
CODE:
RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
sv_utf8_decode (RETVAL);
OUTPUT:
RETVAL
void
set_foreground (DC::Layout self, float r, float g, float b, float a = 1.)
CODE:
self->r = r;
self->g = g;
self->b = b;
self->a = a;
void
set_font (DC::Layout self, DC::Font font = 0)
CODE:
if (self->font != font)
{
self->font = font;
layout_update_font (self);
}
void
set_height (DC::Layout self, int base_height)
CODE:
if (self->base_height != base_height)
{
self->base_height = base_height;
layout_update_font (self);
}
void
set_width (DC::Layout self, int max_width = -1)
CODE:
pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
void
set_indent (DC::Layout self, int indent)
CODE:
pango_layout_set_indent (self->pl, indent * PANGO_SCALE);
void
set_spacing (DC::Layout self, int spacing)
CODE:
pango_layout_set_spacing (self->pl, spacing * PANGO_SCALE);
void
set_ellipsise (DC::Layout self, int ellipsise)
CODE:
pango_layout_set_ellipsize (self->pl,
ellipsise == 1 ? PANGO_ELLIPSIZE_START
: ellipsise == 2 ? PANGO_ELLIPSIZE_MIDDLE
: ellipsise == 3 ? PANGO_ELLIPSIZE_END
: PANGO_ELLIPSIZE_NONE
);
void
set_single_paragraph_mode (DC::Layout self, int spm)
CODE:
pango_layout_set_single_paragraph_mode (self->pl, !!spm);
void
size (DC::Layout self)
PPCODE:
{
int w, h;
layout_get_pixel_size (self, &w, &h);
EXTEND (SP, 2);
PUSHs (sv_2mortal (newSViv (w)));
PUSHs (sv_2mortal (newSViv (h)));
}
int
descent (DC::Layout self)
CODE:
{
PangoRectangle rect;
PangoLayoutLine *line = pango_layout_get_line_readonly (self->pl, 0);
pango_layout_line_get_pixel_extents (line, 0, &rect);
RETVAL = PANGO_DESCENT (rect);
}
OUTPUT:
RETVAL
int
xy_to_index (DC::Layout self, int x, int y)
CODE:
{
int index, trailing;
pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
RETVAL = index + trailing;
}
OUTPUT:
RETVAL
void
cursor_pos (DC::Layout self, int index)
PPCODE:
{
PangoRectangle pos;
pango_layout_get_cursor_pos (self->pl, index, &pos, 0);
EXTEND (SP, 3);
PUSHs (sv_2mortal (newSViv (pos.x / PANGO_SCALE)));
PUSHs (sv_2mortal (newSViv (pos.y / PANGO_SCALE)));
PUSHs (sv_2mortal (newSViv (pos.height / PANGO_SCALE)));
}
void
index_to_line_x (DC::Layout self, int index, int trailing = 0)
PPCODE:
{
int line, x;
pango_layout_index_to_line_x (self->pl, index, trailing, &line, &x);
#if !PANGO_VERSION_CHECK (1, 17, 3)
/* pango bug: line is between 1..numlines, not 0..numlines-1 */
--line;
#endif
EXTEND (SP, 2);
PUSHs (sv_2mortal (newSViv (line)));
PUSHs (sv_2mortal (newSViv (x / PANGO_SCALE)));
}
void
line_x_to_index (DC::Layout self, int line, int x)
PPCODE:
{
PangoLayoutLine *lp;
int index, trailing;
if (line < 0)
XSRETURN_EMPTY;
if (!(lp = pango_layout_get_line_readonly (self->pl, line)))
XSRETURN_EMPTY; /* do better */
pango_layout_line_x_to_index (lp, x * PANGO_SCALE, &index, &trailing);
EXTEND (SP, 2);
if (GIMME_V == G_SCALAR)
PUSHs (sv_2mortal (newSViv (index + trailing)));
else
{
PUSHs (sv_2mortal (newSViv (index)));
PUSHs (sv_2mortal (newSViv (trailing)));
}
}
void
render (DC::Layout self, float x, float y, int flags = 0)
CODE:
rc_clear (self->rc);
pango_opengl_render_layout_subpixel (
self->pl,
self->rc,
x * PANGO_SCALE, y * PANGO_SCALE,
self->r, self->g, self->b, self->a,
flags
);
// we assume that context_change actually clears/frees stuff
// and does not do any recomputation...
pango_layout_context_changed (self->pl);
void
draw (DC::Layout self)
CODE:
{
glEnable (GL_TEXTURE_2D);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable (GL_BLEND);
gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
glEnable (GL_ALPHA_TEST);
glAlphaFunc (GL_GREATER, 7.f / 255.f);
rc_draw (self->rc);
glDisable (GL_ALPHA_TEST);
glDisable (GL_BLEND);
glDisable (GL_TEXTURE_2D);
}
MODULE = Deliantra::Client PACKAGE = DC::Texture
PROTOTYPES: ENABLE
{
need_facenum (self, face); self->face2tile [face] = tile;
need_texid (self, tile);
}
void
set_smooth (DC::Map self, int face, int smooth, int level)
CODE:
{
tileid texid;
maptex *tex;
if (face < 0 || face >= self->faces)
return;
if (smooth < 0 || smooth >= self->faces)
return;
texid = self->face2tile [face];
if (!texid)
return;
tex = self->tex + texid;
tex->smoothtile = self->face2tile [smooth];
tex->smoothlevel = level;
}
void
set_texture (DC::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
CODE:
{
need_texid (self, texid);
{
maptex *tex = self->tex + texid;
tex->name = name;
tex->w = w;
tex->h = h;
tex->s = s;
tex->t = t;
tex->r = r;
tex->g = g;
tex->b = b;
tex->a = a;
}
// somewhat hackish, but for textures that require it, it really
// improves the look, and most others don't suffer.
glBindTexture (GL_TEXTURE_2D, name);
//glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// use uglier nearest interpolation because linear suffers
// from transparent color bleeding and ugly wrapping effects.
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
void
expire_textures (DC::Map self, int texid, int count)
PPCODE:
for (; texid < self->texs && count; ++texid, --count)
{
maptex *tex = self->tex + texid;
if (tex->name)
{
if (tex->unused)
{
tex->name = 0;
tex->unused = 0;
XPUSHs (sv_2mortal (newSViv (texid)));
}
else
tex->unused = 1;
}
}
int
ox (DC::Map self)
ALIAS:
oy = 1
x = 2
y = 3
w = 4
h = 5
CODE:
switch (ix)
{
case 0: RETVAL = self->ox; break;
case 1: RETVAL = self->oy; break;
case 2: RETVAL = self->x; break;
case 3: RETVAL = self->y; break;
case 4: RETVAL = self->w; break;
case 5: RETVAL = self->h; break;
}
OUTPUT:
RETVAL
void
scroll (DC::Map self, int dx, int dy)
CODE:
{
if (dx > 0)
map_blank (self, self->x, self->y, dx, self->h);
else if (dx < 0)
map_blank (self, self->x + self->w + dx, self->y, -dx, self->h);
if (dy > 0)
map_blank (self, self->x, self->y, self->w, dy);
else if (dy < 0)
map_blank (self, self->x, self->y + self->h + dy, self->w, -dy);
self->ox += dx; self->x += dx;
self->oy += dy; self->y += dy;
while (self->y < 0)
{
Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
self->rows += MAP_EXTEND_Y;
{ 1.00f, 0.00f, 0.00f },
{ 1.00f, 0.54f, 0.00f },
{ 0.11f, 0.56f, 1.00f },
{ 0.93f, 0.46f, 0.00f },
{ 0.18f, 0.54f, 0.34f },
{ 0.56f, 0.73f, 0.56f },
{ 0.80f, 0.80f, 0.80f },
{ 0.55f, 0.41f, 0.13f },
{ 0.99f, 0.77f, 0.26f },
{ 0.74f, 0.65f, 0.41f },
{ 0.00f, 1.00f, 1.00f },
{ 1.00f, 0.00f, 1.00f },
{ 1.00f, 1.00f, 0.00f },
};
int x, y;
glEnable (GL_TEXTURE_2D);
/* GL_REPLACE would be correct, as we don't need to modulate alpha,
* but the nvidia driver (185.18.14) mishandles alpha textures
* and takes the colour from god knows where instead of using
* Cp. MODULATE results in the same colour, but slightly different
* alpha, but atcually gives us the correct colour with nvidia.
*/
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBegin (GL_QUADS);
for (y = 0; y < h; y++)
for (x = 0; x < w; x++)
{
unsigned char m = data [x + y * w];
if (m)
{
float *c = color [m & 15];
float tx1 = m & 0x40 ? 0.5f : 0.f;
float tx2 = tx1 + 0.5f;
glColor4f (c[0], c[1], c[2], 1);
glTexCoord2f (tx1, 0.); glVertex2i (x , y );
glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
}
}
glEnd ();
glDisable (GL_BLEND);
glDisable (GL_TEXTURE_2D);
}
void
fow_texture (DC::Map self, int mx, int my, int sw, int sh)
PPCODE:
{
int x, y;
int sw1 = sw + 2;
int sh1 = sh + 2;
int sh3 = sh * 3;
int sw3 = sw * 3;
uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1);
SV *darkness3_sv = sv_2mortal (newSV (sw3 * sh3));
uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
SvPOK_only (darkness3_sv);
SvCUR_set (darkness3_sv, sw3 * sh3);
mx += self->x - 1;
my += self->y - 1;
for (y = 0; y < sh1; y++)
if (0 <= y + my && y + my < self->rows)
{
maprow *row = self->row + (y + my);
for (x = 0; x < sw1; x++)
if (row->c0 <= x + mx && x + mx < row->c1)
{
mapcell *cell = row->col + (x + mx - row->c0);
darkness1 [y * sw1 + x] = cell->darkness
? DARKNESS_ADJUST (255 - (cell->darkness - 1))
: DARKNESS_ADJUST (255 - FOW_DARKNESS);
}
}
for (y = 0; y < sh; ++y)
for (x = 0; x < sw; ++x)
{
uint8_t d11 = darkness1 [(y ) * sw1 + x ];
uint8_t d21 = darkness1 [(y ) * sw1 + x + 1];
uint8_t d31 = darkness1 [(y ) * sw1 + x + 2];
uint8_t d12 = darkness1 [(y + 1) * sw1 + x ];
uint8_t d22 = darkness1 [(y + 1) * sw1 + x + 1];
uint8_t d32 = darkness1 [(y + 1) * sw1 + x + 2];
uint8_t d13 = darkness1 [(y + 2) * sw1 + x ];
uint8_t d23 = darkness1 [(y + 2) * sw1 + x + 1];
uint8_t d33 = darkness1 [(y + 2) * sw1 + x + 2];
uint8_t r11 = (d11 + d21 + d12) / 3;
uint8_t r21 = d21;
uint8_t r31 = (d21 + d31 + d32) / 3;
uint8_t r12 = d12;
uint8_t r22 = d22;
uint8_t r32 = d32;
uint8_t r13 = (d13 + d23 + d12) / 3;
uint8_t r23 = d23;
uint8_t r33 = (d23 + d33 + d32) / 3;
darkness3 [(y * 3 ) * sw3 + (x * 3 )] = MAX (d22, r11);
darkness3 [(y * 3 ) * sw3 + (x * 3 + 1)] = MAX (d22, r21);
darkness3 [(y * 3 ) * sw3 + (x * 3 + 2)] = MAX (d22, r31);
for (y = y0; y < y1; y++)
{
maprow *row = 0 <= y && y < self->rows
? self->row + y
: 0;
for (x = x0; x < x1; x++)
{
if (row && row->c0 <= x && x < row->c1)
{
mapcell *cell = row->col + (x - row->c0);
uint8_t flags = 0;
if (cell->tile [0]) flags |= 1;
if (cell->tile [1]) flags |= 2;
if (cell->tile [2]) flags |= 4;
*data++ = flags;
if (flags & 1)
{
tileid tile = cell->tile [0];
*data++ = tile >> 8;
*data++ = tile;
}
if (flags & 2)
{
tileid tile = cell->tile [1];
*data++ = tile >> 8;
*data++ = tile;
}
if (flags & 4)
{
tileid tile = cell->tile [2];
*data++ = tile >> 8;
*data++ = tile;
}
}
else
*data++ = 0;
}
}
/* if size is w*h + 5 then no data has been found */
if (data - (uint8_t *)SvPVX (data_sv) != w * h + 5)
{
SvPOK_only (data_sv);
SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
}
RETVAL = data_sv;
}
OUTPUT:
RETVAL
void
set_rect (DC::Map self, int x0, int y0, SV *data_sv)
PPCODE:
{
int x, y, z;
int w, h;
int x1, y1;
STRLEN len;
uint8_t *data, *end;
len = SvLEN (data_sv);
SvGROW (data_sv, len + 8); // reserve at least 7+ bytes more
data = SvPVbyte_nolen (data_sv);
end = data + len + 8;
if (len < 5)
XSRETURN_EMPTY;
if (*data++ != 0)
XSRETURN_EMPTY; /* version mismatch */
w = *data++ << 8; w |= *data++;
h = *data++ << 8; h |= *data++;
// we need to do this 'cause we don't keep an absolute coord system for rows
// TODO: treat rows as we treat columns
map_get_row (self, y0 + self->y - self->oy);//D
map_get_row (self, y0 + self->y - self->oy + h - 1);//D
x0 += self->x - self->ox;
y0 += self->y - self->oy;
x1 = x0 + w;
y1 = y0 + h;
for (y = y0; y < y1; y++)
{
maprow *row = map_get_row (self, y);
for (x = x0; x < x1; x++)
{
uint8_t flags;
if (data + 7 >= end)
XSRETURN_EMPTY;
flags = *data++;
if (flags)
{
mapcell *cell = row_get_cell (row, x);
tileid tile[3] = { 0, 0, 0 };
if (flags & 1) { tile[0] = *data++ << 8; tile[0] |= *data++; }
if (flags & 2) { tile[1] = *data++ << 8; tile[1] |= *data++; }
if (flags & 4) { tile[2] = *data++ << 8; tile[2] |= *data++; }
if (cell->darkness == 0)
{
/*cell->darkness = 0;*/
EXTEND (SP, 3);
for (z = 0; z <= 2; z++)
Mix_HaltChannel (self);
void
expire (DC::Channel self, int ticks = -1)
CODE:
Mix_ExpireChannel (self, ticks);
void
fade_out (DC::Channel self, int ticks = -1)
CODE:
Mix_FadeOutChannel (self, ticks);
int
volume (DC::Channel self, int volume)
CODE:
RETVAL = Mix_Volume (self, CLAMP (volume, 0, 128));
OUTPUT:
RETVAL
void
unregister_all_effects (DC::Channel self)
CODE:
Mix_UnregisterAllEffects (self);
void
set_panning (DC::Channel self, int left, int right)
CODE:
left = CLAMP (left , 0, 255);
right = CLAMP (right, 0, 255);
Mix_SetPanning (self, left, right);
void
set_distance (DC::Channel self, int distance)
CODE:
Mix_SetDistance (self, CLAMP (distance, 0, 255));
void
set_position (DC::Channel self, int angle, int distance)
CODE:
void
set_position_r (DC::Channel self, int dx, int dy, int maxdistance)
CODE:
{
int distance = sqrtf (dx * dx + dy * dy) * (255.f / sqrtf (maxdistance * maxdistance));
int angle = atan2f (dx, -dy) * 180.f / (float)M_PI + 360.f;
Mix_SetPosition (self, angle, CLAMP (distance, 0, 255));
}
void
set_reverse_stereo (DC::Channel self, int flip)
CODE:
Mix_SetReverseStereo (self, flip);
MODULE = Deliantra::Client PACKAGE = DC::MixChunk
PROTOTYPES: DISABLE
void
decoders ()
PPCODE:
#if SDL_MIXER_MAJOR_VERSION > 1 || SDL_MIXER_MINOR_VERSION > 2 || SDL_MIXER_PATCHLEVEL >= 10
int i, num = Mix_GetNumChunkDecoders ();
EXTEND (SP, num);
for (i = 0; i < num; ++i)
PUSHs (sv_2mortal (newSVpv (Mix_GetChunkDecoder (i), 0)));
#else
XPUSHs (sv_2mortal (newSVpv ("(sdl mixer too old)", 0)));
#endif
DC::MixChunk
new (SV *class, DC::RW rwops)
CODE:
RETVAL = Mix_LoadWAV_RW (rwops, 1);
OUTPUT:
RETVAL
void
DESTROY (DC::MixChunk self)
CODE:
Mix_FreeChunk (self);
int
volume (DC::MixChunk self, int volume = -1)
CODE:
if (items > 1)
volume = CLAMP (volume, 0, 128);
RETVAL = Mix_VolumeChunk (self, volume);
OUTPUT:
RETVAL
DC::Channel
play (DC::MixChunk self, DC::Channel channel = -1, int loops = 0, int ticks = -1)
CODE:
{
RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
if (RETVAL < 0)
XSRETURN_UNDEF;
if (channel < 0)
{
Mix_UnregisterAllEffects (RETVAL);
Mix_Volume (RETVAL, 128);
}
}
OUTPUT:
RETVAL
MODULE = Deliantra::Client PACKAGE = DC::MixMusic
void
decoders ()
PPCODE:
#if SDL_MIXER_MAJOR_VERSION > 1 || SDL_MIXER_MINOR_VERSION > 2 || SDL_MIXER_PATCHLEVEL >= 10
int i, num = Mix_GetNumMusicDecoders ();
EXTEND (SP, num);
for (i = 0; i < num; ++i)
PUSHs (sv_2mortal (newSVpv (Mix_GetMusicDecoder (i), 0)));
#else
XPUSHs (sv_2mortal (newSVpv ("(sdl mixer too old)", 0)));
#endif
int
volume (int volume = -1)
PROTOTYPE: ;$
CODE:
if (items > 0)
volume = CLAMP (volume, 0, 128);
RETVAL = Mix_VolumeMusic (volume);
OUTPUT:
RETVAL
void
fade_out (int ms)
CODE:
Mix_FadeOutMusic (ms);
void
halt ()
CODE:
Mix_HaltMusic ();
int
playing ()
CODE:
RETVAL = Mix_PlayingMusic ();
OUTPUT:
RETVAL
DC::MixMusic
new (SV *class, DC::RW rwops)
CODE:
RETVAL = Mix_LoadMUS_RW (rwops);
OUTPUT:
RETVAL
void
DESTROY (DC::MixMusic self)
CODE:
Mix_FreeMusic (self);
int
play (DC::MixMusic self, int loops = -1)
CODE:
RETVAL = Mix_PlayMusic (self, loops);
OUTPUT:
RETVAL
void
fade_in_pos (DC::MixMusic self, int loops, int ms, double position)
CODE:
Mix_FadeInMusicPos (self, loops, ms, position);
if (gl.ConvolutionParameterf)
gl.ConvolutionParameterf (target, pname, params);
void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
CODE:
if (gl.ConvolutionFilter2D)
gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
CODE:
if (gl.SeparableFilter2D)
gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data = 0)
void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
void glDrawPixels (int width, int height, int format, int type, char *pixels)
void glPixelZoom (float x, float y)
void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
int glGenTexture ()
CODE:
RETVAL = gen_texture ();
OUTPUT:
RETVAL
void glDeleteTexture (int name)
CODE:
del_texture (name);
int glGenList ()
CODE:
RETVAL = glGenLists (1);
OUTPUT:
RETVAL
void glDeleteList (int list)
CODE:
glDeleteLists (list, 1);
void glNewList (int list, int mode = GL_COMPILE)
void glEndList ()
void glCallList (int list)
void c_init ()
CODE:
glPixelStorei (GL_PACK_ALIGNMENT , 1);
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
MODULE = Deliantra::Client PACKAGE = DC::UI::Base
PROTOTYPES: DISABLE
void
find_widget (SV *self, NV x, NV y)
PPCODE:
{
if (within_widget (self, x, y))
XPUSHs (self);
}
BOOT:
{
hover_gv = gv_fetchpv ("DC::UI::HOVER", 1, SVt_NV);
draw_x_gv = gv_fetchpv ("DC::UI::Base::draw_x", 1, SVt_NV);
draw_y_gv = gv_fetchpv ("DC::UI::Base::draw_y", 1, SVt_NV);
draw_w_gv = gv_fetchpv ("DC::UI::Base::draw_w", 1, SVt_NV);
draw_h_gv = gv_fetchpv ("DC::UI::Base::draw_h", 1, SVt_NV);
}
void
draw (SV *self)
CODE:
{
HV *hv;
SV **svp;
NV x, y, w, h;
SV *draw_x_sv = GvSV (draw_x_gv);
SV *draw_y_sv = GvSV (draw_y_gv);
SV *draw_w_sv = GvSV (draw_w_gv);
SV *draw_h_sv = GvSV (draw_h_gv);
double draw_x, draw_y;
if (!SvROK (self))
croak ("DC::Base::draw: %s not a reference", SvPV_nolen (self));
hv = (HV *)SvRV (self);
if (SvTYPE (hv) != SVt_PVHV)
croak ("DC::Base::draw: %s not a hashref", SvPV_nolen (self));
svp = hv_fetch (hv, "w", 1, 0); w = svp ? SvNV (*svp) : 0.;
svp = hv_fetch (hv, "h", 1, 0); h = svp ? SvNV (*svp) : 0.;
if (!h || !w)
XSRETURN_EMPTY;
svp = hv_fetch (hv, "x", 1, 0); x = svp ? SvNV (*svp) : 0.;
svp = hv_fetch (hv, "y", 1, 0); y = svp ? SvNV (*svp) : 0.;
draw_x = SvNV (draw_x_sv) + x;
draw_y = SvNV (draw_y_sv) + y;
if (draw_x + w < 0 || draw_x >= SvNV (draw_w_sv)
|| draw_y + h < 0 || draw_y >= SvNV (draw_h_sv))
XSRETURN_EMPTY;
sv_setnv (draw_x_sv, draw_x);
sv_setnv (draw_y_sv, draw_y);
glPushMatrix ();
glTranslated (x, y, 0);
if (SvROK (GvSV (hover_gv)) && SvRV (GvSV (hover_gv)) == (SV *)hv)
{
( run in 0.981 second using v1.01-cache-2.11-cpan-71847e10f99 )