ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
(Generate patch)

Comparing deliantra/Deliantra-Client/Client.xs (file contents):
Revision 1.216 by root, Tue Jul 31 00:56:02 2007 UTC vs.
Revision 1.225 by root, Sat Aug 11 12:07:54 2007 UTC

17#include "perl.h" 17#include "perl.h"
18#include "XSUB.h" 18#include "XSUB.h"
19 19
20#ifdef _WIN32 20#ifdef _WIN32
21# undef pipe 21# undef pipe
22// microsoft vs. C
23# define sqrtf(x) sqrt(x)
24# define roundf(x) (int)(x)
25# define atan2f(x,y) atan2(x,y)
26# define M_PI 3.14159265f
22#endif 27#endif
23 28
24#include <assert.h> 29#include <assert.h>
25#include <math.h> 30#include <math.h>
26#include <string.h> 31#include <string.h>
109 av_push (texture_av, (SV *)(size_t)name); 114 av_push (texture_av, (SV *)(size_t)name);
110 glDeleteTextures (1, &name); 115 glDeleteTextures (1, &name);
111} 116}
112 117
113#include "texcache.c" 118#include "texcache.c"
119#include "rendercache.c"
114 120
115#include "pango-font.c" 121#include "pango-font.c"
116#include "pango-fontmap.c" 122#include "pango-fontmap.c"
117#include "pango-render.c" 123#include "pango-render.c"
118 124
144typedef struct cf_layout { 150typedef struct cf_layout {
145 PangoLayout *pl; 151 PangoLayout *pl;
146 float r, g, b, a; // default color for rgba mode 152 float r, g, b, a; // default color for rgba mode
147 int base_height; 153 int base_height;
148 CFPlus__Font font; 154 CFPlus__Font font;
155 rc_t *rc;
149} *CFPlus__Layout; 156} *CFPlus__Layout;
150 157
151static CFPlus__Font default_font; 158static CFPlus__Font default_font;
152static PangoContext *opengl_context; 159static PangoContext *opengl_context;
153static PangoFontMap *opengl_fontmap; 160static PangoFontMap *opengl_fontmap;
804 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("CFPlus::UI::Event", 1)))); 811 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("CFPlus::UI::Event", 1))));
805 } 812 }
806} 813}
807 814
808int 815int
809Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096) 816Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 1024)
810 POSTCALL: 817 POSTCALL:
811 Mix_HookMusicFinished (music_finished); 818 Mix_HookMusicFinished (music_finished);
812 Mix_ChannelFinished (channel_finished); 819 Mix_ChannelFinished (channel_finished);
813 820
814void 821void
1030 RETVAL->g = 1.; 1037 RETVAL->g = 1.;
1031 RETVAL->b = 1.; 1038 RETVAL->b = 1.;
1032 RETVAL->a = 1.; 1039 RETVAL->a = 1.;
1033 RETVAL->base_height = MIN_FONT_HEIGHT; 1040 RETVAL->base_height = MIN_FONT_HEIGHT;
1034 RETVAL->font = 0; 1041 RETVAL->font = 0;
1042 RETVAL->rc = rc_alloc ();
1035 1043
1036 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR); 1044 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
1037 layout_update_font (RETVAL); 1045 layout_update_font (RETVAL);
1038 OUTPUT: 1046 OUTPUT:
1039 RETVAL 1047 RETVAL
1040 1048
1041void 1049void
1042DESTROY (CFPlus::Layout self) 1050DESTROY (CFPlus::Layout self)
1043 CODE: 1051 CODE:
1044 g_object_unref (self->pl); 1052 g_object_unref (self->pl);
1053 rc_free (self->rc);
1045 Safefree (self); 1054 Safefree (self);
1046 1055
1047void 1056void
1048set_text (CFPlus::Layout self, SV *text_) 1057set_text (CFPlus::Layout self, SV *text_)
1049 CODE: 1058 CODE:
1301 } 1310 }
1302} 1311}
1303 1312
1304void 1313void
1305render (CFPlus::Layout self, float x, float y, int flags = 0) 1314render (CFPlus::Layout self, float x, float y, int flags = 0)
1306 PPCODE: 1315 CODE:
1316 rc_clear (self->rc);
1307 pango_opengl_render_layout_subpixel ( 1317 pango_opengl_render_layout_subpixel (
1308 self->pl, 1318 self->pl,
1319 self->rc,
1309 x * PANGO_SCALE, y * PANGO_SCALE, 1320 x * PANGO_SCALE, y * PANGO_SCALE,
1310 self->r, self->g, self->b, self->a, 1321 self->r, self->g, self->b, self->a,
1311 flags 1322 flags
1312 ); 1323 );
1324 // we assume that context_change actually clears/frees stuff
1325 // and does not do any recomputation...
1326 pango_layout_context_changed (self->pl);
1327
1328void
1329draw (CFPlus::Layout self)
1330 CODE:
1331{
1332 glEnable (GL_TEXTURE_2D);
1333 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1334 glEnable (GL_BLEND);
1335 gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1336 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1337 glEnable (GL_ALPHA_TEST);
1338 glAlphaFunc (GL_GREATER, 7.f / 255.f);
1339
1340 rc_draw (self->rc);
1341
1342 glDisable (GL_ALPHA_TEST);
1343 glDisable (GL_BLEND);
1344 glDisable (GL_TEXTURE_2D);
1345}
1313 1346
1314MODULE = CFPlus PACKAGE = CFPlus::Texture 1347MODULE = CFPlus PACKAGE = CFPlus::Texture
1315 1348
1316PROTOTYPES: ENABLE 1349PROTOTYPES: ENABLE
1317 1350
1349{ 1382{
1350 HV *hv = (HV *)SvRV (self); 1383 HV *hv = (HV *)SvRV (self);
1351 float s = SvNV (*hv_fetch (hv, "s", 1, 1)); 1384 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
1352 float t = SvNV (*hv_fetch (hv, "t", 1, 1)); 1385 float t = SvNV (*hv_fetch (hv, "t", 1, 1));
1353 int name = SvIV (*hv_fetch (hv, "name", 4, 1)); 1386 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
1387
1388 if (name <= 0)
1389 XSRETURN_EMPTY;
1354 1390
1355 if (items < 5) 1391 if (items < 5)
1356 { 1392 {
1357 w = SvNV (*hv_fetch (hv, "w", 1, 1)); 1393 w = SvNV (*hv_fetch (hv, "w", 1, 1));
1358 h = SvNV (*hv_fetch (hv, "h", 1, 1)); 1394 h = SvNV (*hv_fetch (hv, "h", 1, 1));
1547 self->rows += MAP_EXTEND_Y; 1583 self->rows += MAP_EXTEND_Y;
1548 self->y += MAP_EXTEND_Y; 1584 self->y += MAP_EXTEND_Y;
1549 } 1585 }
1550} 1586}
1551 1587
1552void 1588SV *
1553map1a_update (CFPlus::Map self, SV *data_, int extmap) 1589map1a_update (CFPlus::Map self, SV *data_, int extmap)
1554 CODE: 1590 CODE:
1555{ 1591{
1556 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_); 1592 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1557 uint8_t *data_end = (uint8_t *)SvEND (data_); 1593 uint8_t *data_end = (uint8_t *)SvEND (data_);
1558 mapcell *cell; 1594 mapcell *cell;
1559 int x, y, flags; 1595 int x, y, z, flags;
1596 AV *missing = newAV ();
1597 RETVAL = newRV_noinc ((SV *)missing);
1560 1598
1561 while (data < data_end - 1) 1599 while (data < data_end - 1)
1562 { 1600 {
1563 flags = (data [0] << 8) + data [1]; data += 2; 1601 flags = (data [0] << 8) + data [1]; data += 2;
1564 1602
1615 } 1653 }
1616 else 1654 else
1617 cell->darkness = *data++ + 1; 1655 cell->darkness = *data++ + 1;
1618 } 1656 }
1619 1657
1658 for (z = 0; z <= 2; ++z)
1620 if (flags & 4) 1659 if (flags & (4 >> z))
1621 { 1660 {
1622 faceid face = (data [0] << 8) + data [1]; data += 2; 1661 faceid face = (data [0] << 8) + data [1]; data += 2;
1623 need_facenum (self, face); 1662 need_facenum (self, face);
1624 cell->tile [0] = self->face2tile [face]; 1663 cell->tile [z] = self->face2tile [face];
1664
1665 if (cell->tile [z])
1666 {
1667 maptex *tex = self->tex + cell->tile [z];
1668 if (!tex->name)
1669 av_push (missing, newSViv (cell->tile [z]));
1670
1671 if (tex->smoothtile)
1672 {
1673 maptex *smooth = self->tex + tex->smoothtile;
1674 if (!smooth->name)
1675 av_push (missing, newSViv (tex->smoothtile));
1676 }
1677 }
1625 } 1678 }
1626
1627 if (flags & 2)
1628 {
1629 faceid face = (data [0] << 8) + data [1]; data += 2;
1630 need_facenum (self, face);
1631 cell->tile [1] = self->face2tile [face];
1632 }
1633
1634 if (flags & 1)
1635 {
1636 faceid face = (data [0] << 8) + data [1]; data += 2;
1637 need_facenum (self, face);
1638 cell->tile [2] = self->face2tile [face];
1639 }
1640 } 1679 }
1641 else 1680 else
1642 cell->darkness = 0; 1681 cell->darkness = 0;
1643 } 1682 }
1644} 1683}
1684 OUTPUT:
1685 RETVAL
1645 1686
1646SV * 1687SV *
1647mapmap (CFPlus::Map self, int x0, int y0, int w, int h) 1688mapmap (CFPlus::Map self, int x0, int y0, int w, int h)
1648 CODE: 1689 CODE:
1649{ 1690{
1700 1741
1701void 1742void
1702draw (CFPlus::Map self, int mx, int my, int sw, int sh, int T) 1743draw (CFPlus::Map self, int mx, int my, int sw, int sh, int T)
1703 CODE: 1744 CODE:
1704{ 1745{
1746 int x, y, z;
1747
1705 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ()); 1748 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ());
1706 uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level 1749 uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level
1707 static uint8_t smooth_max[256][256]; // egad, fats and wasteful on memory (64k) 1750 static uint8_t smooth_max[256][256]; // egad, fats and wasteful on memory (64k)
1708 smooth_key skey; 1751 smooth_key skey;
1709 int x, y, z; 1752
1710 int last_name; 1753 rc_t *rc = rc_alloc ();
1754 rc_key_t key;
1755 rc_array_t *arr;
1711 1756
1712 // thats current max. sorry. 1757 // thats current max. sorry.
1713 if (sw > 255) sw = 255; 1758 if (sw > 255) sw = 255;
1714 if (sh > 255) sh = 255; 1759 if (sh > 255) sh = 255;
1715 1760
1716 // clear key, in case of extra padding 1761 // clear key, in case of extra padding
1717 memset (&skey, 0, sizeof (skey)); 1762 memset (&skey, 0, sizeof (skey));
1718 1763
1719 glColor4ub (255, 255, 255, 255); 1764 memset (&key, 0, sizeof (key));
1720 1765 key.r = 255;
1721 glEnable (GL_BLEND); 1766 key.g = 255;
1722 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 1767 key.b = 255;
1723 glEnable (GL_TEXTURE_2D); 1768 key.a = 255;
1724 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 1769 key.mode = GL_QUADS;
1725 1770 key.format = GL_T2F_V3F;
1726 glBegin (GL_QUADS); 1771 key.texname = -1;
1727
1728 last_name = 0;
1729 1772
1730 mx += self->x; 1773 mx += self->x;
1731 my += self->y; 1774 my += self->y;
1732 1775
1733 // first pass: determine smooth_max 1776 // first pass: determine smooth_max
1749 MAX (self->tex [cell->tile [0]].smoothlevel, 1792 MAX (self->tex [cell->tile [0]].smoothlevel,
1750 MAX (self->tex [cell->tile [1]].smoothlevel, 1793 MAX (self->tex [cell->tile [1]].smoothlevel,
1751 self->tex [cell->tile [2]].smoothlevel)); 1794 self->tex [cell->tile [2]].smoothlevel));
1752 } 1795 }
1753 } 1796 }
1797
1798 glEnable (GL_BLEND);
1799 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1800 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1754 1801
1755 for (z = 0; z <= 2; z++) 1802 for (z = 0; z <= 2; z++)
1756 { 1803 {
1757 memset (smooth_level, 0, sizeof (smooth_level)); 1804 memset (smooth_level, 0, sizeof (smooth_level));
1758 1805
1768 tileid tile = cell->tile [z]; 1815 tileid tile = cell->tile [z];
1769 1816
1770 if (tile) 1817 if (tile)
1771 { 1818 {
1772 maptex tex = self->tex [tile]; 1819 maptex tex = self->tex [tile];
1773 int px = (x + 1) * T - tex.w; 1820 int px, py;
1774 int py = (y + 1) * T - tex.h;
1775 1821
1776 // suppressing texture state switches here 1822 // suppressing texture state switches here
1777 // is only moderately effective, but worth the extra effort 1823 // is only moderately effective, but worth the extra effort
1778 if (last_name != tex.name) 1824 if (key.texname != tex.name)
1779 { 1825 {
1780 if (!tex.name) 1826 if (!tex.name)
1781 tex = self->tex [2]; /* missing, replace by noface */ 1827 tex = self->tex [2]; /* missing, replace by noface */
1782 1828
1783 glEnd (); 1829 key.texname = tex.name;
1784 glBindTexture (GL_TEXTURE_2D, last_name = tex.name); 1830 arr = rc_array (rc, &key);
1785 glBegin (GL_QUADS);
1786 } 1831 }
1787 1832
1788 glTexCoord2f (0 , 0 ); glVertex2f (px , py ); 1833 px = (x + 1) * T - tex.w;
1834 py = (y + 1) * T - tex.h;
1835
1836 rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
1789 glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h); 1837 rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0);
1790 glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h); 1838 rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0);
1791 glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py ); 1839 rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0);
1792 1840
1793 if (cell->flags && z == 2) 1841 if (cell->flags && z == 2)
1794 { 1842 {
1843 // overlays such as the speech bubble, probably more to come
1795 if (cell->flags & 1) 1844 if (cell->flags & 1)
1796 { 1845 {
1797 maptex tex = self->tex [1]; 1846 maptex tex = self->tex [1];
1798 int px = x * T + T * 2 / 32; 1847 int px = x * T + T * 2 / 32;
1799 int py = y * T - T * 6 / 32; 1848 int py = y * T - T * 6 / 32;
1800 1849
1850 if (tex.name)
1801 glEnd (); 1851 {
1802 glBindTexture (GL_TEXTURE_2D, last_name = tex.name); 1852 if (key.texname != tex.name)
1853 {
1854 key.texname = tex.name;
1855 arr = rc_array (rc, &key);
1856 }
1857
1858 rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
1859 rc_t2f_v3f (arr, 0 , tex.t, px , py + T, 0);
1860 rc_t2f_v3f (arr, tex.s, tex.t, px + T, py + T, 0);
1861 rc_t2f_v3f (arr, tex.s, 0 , px + T, py , 0);
1803 glBegin (GL_QUADS); 1862 }
1804
1805 glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1806 glTexCoord2f (0 , tex.t); glVertex2f (px , py + T);
1807 glTexCoord2f (tex.s, tex.t); glVertex2f (px + T, py + T);
1808 glTexCoord2f (tex.s, 0 ); glVertex2f (px + T, py );
1809 } 1863 }
1810 } 1864 }
1811 1865
1812 // update smooth hash 1866 // update smooth hash
1813 if (tex.smoothtile) 1867 if (tex.smoothtile)
1848 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0800); 1902 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0800);
1849 } 1903 }
1850 } 1904 }
1851 } 1905 }
1852 } 1906 }
1907
1908 rc_draw (rc);
1909 rc_clear (rc);
1853 1910
1854 // go through all smoothlevels, lowest to highest, then draw. 1911 // go through all smoothlevels, lowest to highest, then draw.
1855 // this is basically counting sort 1912 // this is basically counting sort
1856 { 1913 {
1857 int w, b; 1914 int w, b;
1882 int border = bits & 15; 1939 int border = bits & 15;
1883 int corner = (bits >> 8) & ~(bits >> 4) & 15; 1940 int corner = (bits >> 8) & ~(bits >> 4) & 15;
1884 float dx = tex.s * .0625f; // 16 images/row 1941 float dx = tex.s * .0625f; // 16 images/row
1885 float dy = tex.t * .5f ; // 2 images/column 1942 float dy = tex.t * .5f ; // 2 images/column
1886 1943
1887 // this time naively avoiding texture state changes
1888 // save gobs of state changes.
1889 if (last_name != tex.name) 1944 if (tex.name)
1890 { 1945 {
1946 // this time avoiding texture state changes
1947 // save gobs of state changes.
1891 if (!tex.name) 1948 if (key.texname != tex.name)
1892 continue; // smoothing not yet available
1893
1894 glEnd (); 1949 {
1895 glBindTexture (GL_TEXTURE_2D, last_name = tex.name); 1950 key.texname = tex.name;
1896 glBegin (GL_QUADS); 1951 arr = rc_array (rc, &key);
1897 } 1952 }
1898 1953
1899 if (border) 1954 if (border)
1900 { 1955 {
1901 float ox = border * dx; 1956 float ox = border * dx;
1902 1957
1903 glTexCoord2f (ox , 0.f ); glVertex2f (px , py ); 1958 rc_t2f_v3f (arr, ox , 0.f , px , py , 0);
1904 glTexCoord2f (ox , dy ); glVertex2f (px , py + T); 1959 rc_t2f_v3f (arr, ox , dy , px , py + T, 0);
1905 glTexCoord2f (ox + dx, dy ); glVertex2f (px + T, py + T); 1960 rc_t2f_v3f (arr, ox + dx, dy , px + T, py + T, 0);
1906 glTexCoord2f (ox + dx, 0.f ); glVertex2f (px + T, py ); 1961 rc_t2f_v3f (arr, ox + dx, 0.f , px + T, py , 0);
1907 } 1962 }
1908 1963
1909 if (corner) 1964 if (corner)
1910 { 1965 {
1911 float ox = corner * dx; 1966 float ox = corner * dx;
1912 1967
1913 glTexCoord2f (ox , dy ); glVertex2f (px , py ); 1968 rc_t2f_v3f (arr, ox , dy , px , py , 0);
1914 glTexCoord2f (ox , dy * 2.f); glVertex2f (px , py + T); 1969 rc_t2f_v3f (arr, ox , dy * 2.f, px , py + T, 0);
1915 glTexCoord2f (ox + dx, dy * 2.f); glVertex2f (px + T, py + T); 1970 rc_t2f_v3f (arr, ox + dx, dy * 2.f, px + T, py + T, 0);
1916 glTexCoord2f (ox + dx, dy ); glVertex2f (px + T, py ); 1971 rc_t2f_v3f (arr, ox + dx, dy , px + T, py , 0);
1972 }
1917 } 1973 }
1918 } 1974 }
1919 } 1975 }
1920 } 1976 }
1921 } 1977 }
1922 } 1978 }
1923 1979
1924 hv_clear (smooth); 1980 hv_clear (smooth);
1981 rc_draw (rc);
1982 rc_clear (rc);
1925 } 1983 }
1926 1984
1927 glEnd ();
1928
1929 glDisable (GL_TEXTURE_2D);
1930 glDisable (GL_BLEND); 1985 glDisable (GL_BLEND);
1986 rc_free (rc);
1931 1987
1932 // top layer: overlays such as the health bar 1988 // top layer: overlays such as the health bar
1933 for (y = 0; y < sh; y++) 1989 for (y = 0; y < sh; y++)
1934 if (0 <= y + my && y + my < self->rows) 1990 if (0 <= y + my && y + my < self->rows)
1935 { 1991 {
2260 CODE: 2316 CODE:
2261 RETVAL = SDL_RWFromFile (path, mode); 2317 RETVAL = SDL_RWFromFile (path, mode);
2262 OUTPUT: 2318 OUTPUT:
2263 RETVAL 2319 RETVAL
2264 2320
2321# fails on win32:
2322# CFPlus.xs(2268) : error C2059: syntax error : '('
2265void 2323#void
2266close (CFPlus::RW self) 2324#close (CFPlus::RW self)
2267 CODE: 2325# CODE:
2268 SDL_RWclose (self); 2326# (self->(close)) (self);
2269 2327
2270MODULE = CFPlus PACKAGE = CFPlus::Channel 2328MODULE = CFPlus PACKAGE = CFPlus::Channel
2271 2329
2272PROTOTYPES: DISABLE 2330PROTOTYPES: DISABLE
2273 2331
2333 Mix_SetDistance (self, CLAMP (distance, 0, 255)); 2391 Mix_SetDistance (self, CLAMP (distance, 0, 255));
2334 2392
2335void 2393void
2336set_position (CFPlus::Channel self, int angle, int distance) 2394set_position (CFPlus::Channel self, int angle, int distance)
2337 CODE: 2395 CODE:
2396
2397void
2398set_position_r (CFPlus::Channel self, int dx, int dy, int maxdistance)
2399 CODE:
2400{
2401 int distance = sqrtf (dx * dx + dy * dy) * (255.f / sqrtf (maxdistance * maxdistance));
2402 int angle = 360 + (int)roundf (atan2f (dx, -dy) * 180.f / (float)M_PI);
2338 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255)); 2403 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255));
2404}
2339 2405
2340void 2406void
2341set_reverse_stereo (CFPlus::Channel self, int flip) 2407set_reverse_stereo (CFPlus::Channel self, int flip)
2342 CODE: 2408 CODE:
2343 Mix_SetReverseStereo (self, flip); 2409 Mix_SetReverseStereo (self, flip);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines