Deliantra-Client

 view release on metacpan or  search on metacpan

Client.xs  view on Meta::CPAN

        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:

Client.xs  view on Meta::CPAN

        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

Client.xs  view on Meta::CPAN

{
	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;

Client.xs  view on Meta::CPAN

           { 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);

Client.xs  view on Meta::CPAN


        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++)

Client.xs  view on Meta::CPAN

        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);

Client.xs  view on Meta::CPAN

        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 )