From: xolatile Date: Wed, 6 Aug 2025 20:54:55 +0000 (+0200) Subject: Please do not hate me, it makes sense... X-Git-Url: https://git.xolatile.top/?a=commitdiff_plain;h=0a1172b75f571685c264a8b9d8ee224bbf11381f;p=xolatile-badassbug.git Please do not hate me, it makes sense... --- diff --git a/TODO.md b/TODO.md index 0f657ed..6080bee 100644 --- a/TODO.md +++ b/TODO.md @@ -3,7 +3,7 @@ 1) Remove unused functions. 2) Remove dumb global variables. 3) Reformat to Chad coding style. - 4) Remove MD3 and IQM models. + 4) Remove MD5 models. 5) Use TGA instead of PNG? 6) Optimize for speed instead of size? - Frag messages: diff --git a/data/glsl.cfg b/data/glsl.cfg index e058ddd..38b19b5 100644 --- a/data/glsl.cfg +++ b/data/glsl.cfg @@ -11,12 +11,12 @@ lmcoordscale = (divf 1 32767) shader 0 "null" [ attribute vec4 vvertex; void main(void) - { + { gl_Position = vvertex; } ] [ void main(void) - { + { gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0); } ] @@ -41,7 +41,7 @@ shader 0 "hud" [ varying vec2 texcoord0; varying vec4 color; void main(void) - { + { gl_Position = hudmatrix * vvertex; texcoord0 = vtexcoord0; color = vcolor; @@ -51,7 +51,7 @@ shader 0 "hud" [ varying vec4 color; uniform sampler2D tex0; void main(void) - { + { gl_FragColor = color * texture2D(tex0, texcoord0); } ] @@ -61,14 +61,14 @@ shader 0 "hudnotexture" [ uniform mat4 hudmatrix; varying vec4 color; void main(void) - { + { gl_Position = hudmatrix * vvertex; color = vcolor; } ] [ varying vec4 color; void main(void) - { + { gl_FragColor = color; } ] @@ -80,7 +80,7 @@ shader 0 "hudrgb" [ varying vec2 texcoord0; varying vec4 color; void main(void) - { + { gl_Position = hudmatrix * vvertex; texcoord0 = vtexcoord0; color = vcolor; @@ -90,7 +90,7 @@ shader 0 "hudrgb" [ varying vec4 color; uniform sampler2D tex0; void main(void) - { + { gl_FragColor.rgb = color.rgb * texture2D(tex0, texcoord0).rgb; gl_FragColor.a = color.a; } @@ -109,7 +109,7 @@ shader 0 "texture" [ varying vec2 texcoord0; varying vec4 color; void main(void) - { + { gl_Position = camprojmatrix * vvertex; texcoord0 = vtexcoord0; color = vcolor; @@ -119,7 +119,7 @@ shader 0 "texture" [ varying vec4 color; uniform sampler2D tex0; void main(void) - { + { gl_FragColor = color * texture2D(tex0, texcoord0); } ] @@ -129,14 +129,14 @@ shader 0 "notexture" [ uniform mat4 camprojmatrix; varying vec4 color; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vcolor; } ] [ varying vec4 color; void main(void) - { + { gl_FragColor = color; } ] @@ -147,7 +147,7 @@ shader 0 "cubemap" [ varying vec3 texcoord0; varying vec4 color; void main(void) - { + { gl_Position = vvertex; texcoord0 = vtexcoord0; color = vcolor; @@ -157,7 +157,7 @@ shader 0 "cubemap" [ varying vec4 color; uniform samplerCube tex0; void main(void) - { + { gl_FragColor = color * textureCube(tex0, texcoord0); } ] @@ -176,7 +176,7 @@ shader 0 "fogged" [ varying vec2 texcoord0; varying vec4 color; void main(void) - { + { gl_Position = camprojmatrix * vvertex; texcoord0 = vtexcoord0; color = vcolor; @@ -186,7 +186,7 @@ shader 0 "fogged" [ varying vec4 color; uniform sampler2D tex0; void main(void) - { + { gl_FragColor = color * texture2D(tex0, texcoord0); } ] @@ -197,14 +197,14 @@ shader 0 "foggednotexture" [ uniform mat4 camprojmatrix; varying vec4 color; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vcolor; } ] [ varying vec4 color; void main(void) - { + { gl_FragColor = color; } ] @@ -213,14 +213,14 @@ shader 0 "fogoverlay" [ attribute vec4 vvertex, vcolor; varying vec4 color; void main(void) - { + { gl_Position = vvertex; color = vcolor; } ] [ varying vec4 color; void main(void) - { + { gl_FragColor = color; } ] @@ -268,7 +268,7 @@ worldshader = [ uniform vec2 texgenscroll; varying vec2 texcoord0, texcoord1; void main(void) - { + { gl_Position = camprojmatrix * vvertex; texcoord0 = vtexcoord0 + texgenscroll; texcoord1 = vtexcoord1 * @lmcoordscale; @@ -285,7 +285,7 @@ worldshader = [ varying vec2 texcoord0, texcoord1; uniform sampler2D diffusemap, lightmap; void main(void) - { + { @(? (>= (strstr $arg1 "alpha") 0) [ vec4 diffuse = texture2D(diffusemap, texcoord0); diffuse.rgb *= diffuse.a; @@ -317,7 +317,7 @@ glareworldshader = [ uniform vec2 texgenscroll; varying vec2 texcoord0, texcoord1; void main(void) - { + { gl_Position = camprojmatrix * vvertex; texcoord0 = vtexcoord0 + texgenscroll; texcoord1 = vtexcoord1 * @lmcoordscale; @@ -330,7 +330,7 @@ glareworldshader = [ uniform vec4 colorparams; varying vec2 texcoord0, texcoord1; void main(void) - { + { @arg3 } ] @@ -418,13 +418,13 @@ shader 0 "fogworld" [ attribute vec4 vvertex; uniform mat4 camprojmatrix; void main(void) - { + { gl_Position = camprojmatrix * vvertex; } ] [ uniform vec3 fogcolor; void main(void) - { + { gl_FragColor = vec4(fogcolor, 1.0); } ] @@ -433,12 +433,12 @@ shader 0 "noglareworld" [ attribute vec4 vvertex; uniform mat4 camprojmatrix; void main(void) - { + { gl_Position = camprojmatrix * vvertex; } ] [ void main(void) - { + { gl_FragColor = vec4(0.0); } ] @@ -449,7 +449,7 @@ shader 0 "noglareblendworld" [ uniform mat4 camprojmatrix; varying vec2 texcoord0; void main(void) - { + { gl_Position = camprojmatrix * vvertex; texcoord0 = vtexcoord1 * @lmcoordscale; } @@ -457,7 +457,7 @@ shader 0 "noglareblendworld" [ varying vec2 texcoord0; uniform sampler2D lightmap; void main(void) - { + { gl_FragColor.rgb = vec3(0.0); gl_FragColor.a = texture2D(lightmap, texcoord0).a; } @@ -467,14 +467,14 @@ shader 0 "noglarealphaworld" [ attribute vec4 vvertex; uniform mat4 camprojmatrix; void main(void) - { + { gl_Position = camprojmatrix * vvertex; } ] [ uniform vec4 colorparams; uniform sampler2D lightmap; void main(void) - { + { gl_FragColor.rgb = vec3(0.0); gl_FragColor.a = colorparams.a; } @@ -519,14 +519,14 @@ shader 0 "depthfxworld" [ uniform vec4 depthscale, depthoffsets; varying vec4 depthranges; void main(void) - { + { gl_Position = camprojmatrix * vvertex; depthranges = depthoffsets + gl_Position.w*depthscale; } ] [ varying vec4 depthranges; void main(void) - { + { gl_FragColor = depthranges; } ] @@ -537,14 +537,14 @@ shader 0 depthfxsplitworld [ uniform vec4 depthscale, depthoffsets; varying vec4 depthranges; void main(void) - { + { gl_Position = camprojmatrix * vvertex; depthranges = depthoffsets + gl_Position.w*depthscale; } ] [ varying vec4 depthranges; void main(void) - { + { vec4 ranges = vec4(depthranges.x, fract(depthranges.yzw)); ranges.xy -= ranges.yz*vec2(0.00390625, 0.00390625); gl_FragColor = ranges; @@ -608,7 +608,7 @@ bumpvariantshader = [ @(if (btopt "G") [result [uniform float millis; varying float pulse;]]) @(if (btopt "r") [result [varying mat3 world;]]) void main(void) - { + { gl_Position = camprojmatrix * vvertex; texcoord0 = vtexcoord0 + texgenscroll; texcoord1 = vtexcoord1 * @lmcoordscale; @@ -652,7 +652,7 @@ bumpvariantshader = [ @(if (btopt "r") [result [uniform samplerCube envmap; varying mat3 world;]]) @(if (|| (! (btopt "i")) (btopt "s")) [result [uniform vec4 ambient;]]) void main(void) - { + { @(if (|| (! (btopt "i")) (btopt "s")) [result [ vec4 lmc = texture2D(lmcolor, texcoord1); gl_FragColor.a = colorparams.a * lmc.a; @@ -1011,7 +1011,7 @@ shadowmapcastervertexshader = [ uniform vec4 shadowintensity; varying vec4 shadowmapvals; void main(void) - { + { @(if (>= $numargs 2) [result $arg2] [result [ #define mpos vvertex ]]) @@ -1024,7 +1024,7 @@ shadowmapcastervertexshader = [ shader 0 shadowmapcaster (shadowmapcastervertexshader) [ varying vec4 shadowmapvals; void main(void) - { + { gl_FragColor = shadowmapvals; } ] @@ -1038,14 +1038,14 @@ shader 0 "shadowmapreceiver" [ uniform vec2 shadowmapbias; varying vec4 shadowmapvals; void main(void) - { + { gl_Position = shadowmatrix * vvertex; shadowmapvals = vec4(0.0, 0.0, shadowmapbias.y - gl_Position.z, 0.0); } ] [ varying vec4 shadowmapvals; void main(void) - { + { gl_FragColor = shadowmapvals; } ] @@ -1060,7 +1060,7 @@ notexturemodelvertexshader = [ @(if (>= $numargs 2) [result $arg1]) //:fog void main(void) - { + { @(if (>= $numargs 2) [result $arg2] [result [ #define mpos vvertex ]]) @@ -1073,7 +1073,7 @@ notexturemodelvertexshader = [ shader 0 notexturemodel (notexturemodelvertexshader) [ varying vec4 color; void main(void) - { + { gl_FragColor = color; } ] @@ -1130,7 +1130,7 @@ modelvertexshader = [ ]]) ]]) void main(void) - { + { @(if (mdlopt "b") [result [ @(skelanim $arg2 (mdlopt "q") (mdlopt "n")) ]] [result [ @@ -1223,7 +1223,7 @@ modelfragmentshader = [ @(if (mdlopt "n") [result [uniform sampler2D tex3;]]) @(? (mdlopt "a") [uniform float alphatest;]) void main(void) - { + { vec4 light = texture2D(tex0, texcoord0); @(? (mdlopt "a") [ @@ -1352,7 +1352,7 @@ blurshader = [ varying vec2 texcoordp@(+ $i 2), texcoordn@(+ $i 2); ]]) void main(void) - { + { gl_Position = vvertex; texcoord0 = vtexcoord0; vec2 tcp = vtexcoord0, tcn = vtexcoord0; @@ -1376,7 +1376,7 @@ blurshader = [ ]]) uniform sampler2D tex0; void main(void) - { + { #define texval(coords) texture2D(tex0, (coords)) vec4 val = texval(texcoord0) * weights[0]; @(loopconcat i $arg2 [ @@ -1420,7 +1420,7 @@ fsvs = [result [ varying vec2 texcoord0; @arg2 void main(void) - { + { gl_Position = vvertex; // woohoo, no mvp :) texcoord0 = vtexcoord0; @arg1 @@ -1432,7 +1432,7 @@ fsps = [result [ varying vec2 texcoord0; @arg2 void main(void) - { + { vec4 color = texture2D(tex0, texcoord0); @arg1 } @@ -1485,7 +1485,7 @@ lazyshader 0 "rotoscope" [ uniform vec4 params; varying vec2 t11, t00, t12, t01, t20, t02, t21, t10, t22; void main(void) - { + { gl_Position = vvertex; t11 = vtexcoord0; vec2 scale = postfxscale*params.x; @@ -1502,7 +1502,7 @@ lazyshader 0 "rotoscope" [ uniform sampler2D tex0; varying vec2 t11, t00, t12, t01, t20, t02, t21, t10, t22; void main(void) - { + { vec4 c00 = texture2D(tex0, t00); vec4 c01 = texture2D(tex0, t01); vec4 c02 = texture2D(tex0, t02); @@ -1539,7 +1539,7 @@ blur3shader = [ uniform vec2 postfxscale; varying vec2 texcoord0, texcoord1; void main(void) - { + { gl_Position = vvertex; texcoord0 = vtexcoord0 + vec2(@(if $arg2 -0.5 0.0), @(if $arg3 -0.5 0.0))*postfxscale; texcoord1 = vtexcoord0 + vec2(@(if $arg2 0.5 0.0), @(if $arg3 0.5 0.0))*postfxscale; @@ -1548,7 +1548,7 @@ blur3shader = [ varying vec2 texcoord0, texcoord1; uniform sampler2D tex0; void main(void) - { + { gl_FragColor = 0.5*(texture2D(tex0, texcoord0) + texture2D(tex0, texcoord1)); } ] @@ -1563,7 +1563,7 @@ blur5shader = [ uniform vec2 postfxscale; varying vec2 texcoord0, texcoord1, texcoord2; void main(void) - { + { gl_Position = vvertex; texcoord0 = vtexcoord0; texcoord1 = vtexcoord0 + vec2(@(? $arg2 -1.333 0.0), @(? $arg3 -1.333 0.0))*postfxscale; @@ -1573,7 +1573,7 @@ blur5shader = [ uniform sampler2D tex0; varying vec2 texcoord0, texcoord1, texcoord2; void main(void) - { + { gl_FragColor = 0.4*texture2D(tex0, texcoord0) + 0.3*(texture2D(tex0, texcoord1) + texture2D(tex0, texcoord2)); } ] @@ -1596,7 +1596,7 @@ shader 0 "screenrect" [ varying vec2 texcoord0; varying vec4 color; void main(void) - { + { gl_Position = vvertex; texcoord0 = vtexcoord0; color = vcolor; @@ -1606,7 +1606,7 @@ shader 0 "screenrect" [ varying vec4 color; uniform sampler2D tex0; void main(void) - { + { gl_FragColor = color * texture2D(tex0, texcoord0); } ] @@ -1631,7 +1631,7 @@ bloomshader = [ @(screentexcoord 0) varying vec2 texcoord0; void main(void) - { + { gl_Position = vvertex; texcoord0 = vtexcoord0; } @@ -1640,7 +1640,7 @@ bloomshader = [ varying vec2 texcoord0; uniform sampler2D tex0 @@(loopconcat i $arg2 [result [, tex@(+ $i 1)]]); void main(void) - { + { vec4 sample = texture2D(tex0, texcoord0); @@(loopconcat i $arg2 [result [ @(? $i "bloom +=" "vec4 bloom =") texture2D(tex@(+ $i 1), texcoord0); @@ -1694,7 +1694,7 @@ explosionshader = [ varying vec2 texcoord0, texcoord1, texcoord2; @(if (>= (strstr $arg1 "soft") 0) [result [uniform vec4 depthfxparams; varying vec4 texcoord3; ]]) void main(void) - { + { vec4 wobble = vec4(vvertex.xyz*(1.0 + 0.5*abs(fract(dot(vvertex.xyz, center) + millis*2.0) - 0.5)), vvertex.w); @(if (>= (strstr $arg1 "soft") 0) [result [ gl_Position = explosionmatrix * wobble; @@ -1722,7 +1722,7 @@ explosionshader = [ @(if (>= (strstr $arg1 "soft") 0) [result [uniform vec4 depthfxparams; varying vec4 texcoord3; ]]) @(if (>= (strstr $arg1 "soft8") 0) [result [uniform vec4 depthfxselect;]]) void main(void) - { + { vec2 dtc = texcoord0 + texture2D(tex0, texcoord2).xy*0.1; // use color texture as noise to distort texcoords vec4 diffuse = texture2D(tex0, dtc); float blend = max(pow(clamp(1.0 - dot(texcoord1, texcoord1), 0.0, 1.0), blendparams.x), blendparams.y); @@ -1764,14 +1764,14 @@ shader 0 "particlenotexture" [ uniform vec4 colorscale; varying vec4 color; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vcolor * colorscale; } ] [ varying vec4 color; void main(void) - { + { gl_FragColor = color; } ] @@ -1787,7 +1787,7 @@ particleshader = [ varying vec4 color; @(if (>= (strstr $arg1 "soft") 0) [result [uniform vec4 depthfxparams; varying vec3 texcoord1, surface; ]]) void main(void) - { + { gl_Position = camprojmatrix * vvertex; texcoord0 = vtexcoord0; color = vcolor * colorscale; @@ -1809,7 +1809,7 @@ particleshader = [ @(if (>= (strstr $arg1 "soft") 0) [result [uniform vec4 depthfxparams; varying vec3 texcoord1, surface;]]) @(if (>= (strstr $arg1 "soft8") 0) [result [uniform vec4 depthfxselect;]]) void main(void) - { + { vec4 diffuse = texture2D(tex0, texcoord0); @(if (>= (strstr $arg1 "soft") 0) [result [ @@ -1838,7 +1838,7 @@ shader 0 "blendbrush" [ varying vec4 color; varying vec2 texcoord0; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vcolor; texcoord0 = vec2(dot(texgenS, vvertex), dot(texgenT, vvertex)); @@ -1848,7 +1848,7 @@ shader 0 "blendbrush" [ varying vec2 texcoord0; uniform sampler2D tex0; void main(void) - { + { gl_FragColor = texture2D(tex0, texcoord0).r * color; } ] @@ -1861,7 +1861,7 @@ lazyshader 0 "prefab" [ varying vec4 color; void main(void) - { + { gl_Position = prefabmatrix * vvertex; color = vcolor; color.rgb *= dot(prefabworld * vnormal, vec3(0.0, -0.447213595, 0.894427191)); @@ -1869,7 +1869,7 @@ lazyshader 0 "prefab" [ ] [ varying vec4 color; void main(void) - { + { gl_FragColor = color; } ] @@ -1879,7 +1879,7 @@ lazyshader 0 "moviergb" [ @(screentexcoord 0) varying vec2 texcoord0; void main(void) - { + { gl_Position = vvertex; texcoord0 = vtexcoord0; } @@ -1887,7 +1887,7 @@ lazyshader 0 "moviergb" [ varying vec2 texcoord0; uniform sampler2D tex0; void main(void) - { + { gl_FragColor = texture2D(tex0, texcoord0); } ] @@ -1897,7 +1897,7 @@ lazyshader 0 "movieyuv" [ @(screentexcoord 0) varying vec2 texcoord0; void main(void) - { + { gl_Position = vvertex; texcoord0 = vtexcoord0; } @@ -1905,7 +1905,7 @@ lazyshader 0 "movieyuv" [ varying vec2 texcoord0; uniform sampler2D tex0; void main(void) - { + { vec3 sample = texture2D(tex0, texcoord0).rgb; gl_FragColor = vec4(dot(sample, vec3(0.439216, -0.367788, -0.071427)) + 0.501961, dot(sample, vec3(-0.148224, -0.290992, 0.439216)) + 0.501961, @@ -1920,7 +1920,7 @@ lazyshader 0 "moviey" [ uniform vec2 moviescale; varying vec2 texcoord0, texcoord1, texcoord2, texcoord3; void main(void) - { + { gl_Position = vvertex; texcoord0 = vtexcoord0 + vec2(-1.5, 0.0)*moviescale; texcoord1 = vtexcoord0 + vec2(-0.5, 0.0)*moviescale; @@ -1931,7 +1931,7 @@ lazyshader 0 "moviey" [ varying vec2 texcoord0, texcoord1, texcoord2, texcoord3; uniform sampler2D tex0; void main(void) - { + { vec3 sample1 = texture2D(tex0, texcoord0).rgb; vec3 sample2 = texture2D(tex0, texcoord1).rgb; vec3 sample3 = texture2D(tex0, texcoord2).rgb; @@ -1949,7 +1949,7 @@ lazyshader 0 "movieu" [ uniform vec2 moviescale; varying vec2 texcoord0, texcoord1, texcoord2, texcoord3; void main(void) - { + { gl_Position = vvertex; texcoord0 = vtexcoord0 + vec2(-3.0, 0.0)*moviescale; texcoord1 = vtexcoord0 + vec2(-1.0, 0.0)*moviescale; @@ -1960,7 +1960,7 @@ lazyshader 0 "movieu" [ varying vec2 texcoord0, texcoord1, texcoord2, texcoord3; uniform sampler2D tex0; void main(void) - { + { vec3 sample1 = texture2D(tex0, texcoord0).rgb; vec3 sample2 = texture2D(tex0, texcoord1).rgb; vec3 sample3 = texture2D(tex0, texcoord2).rgb; @@ -1978,7 +1978,7 @@ lazyshader 0 "moviev" [ uniform vec2 moviescale; varying vec2 texcoord0, texcoord1, texcoord2, texcoord3; void main(void) - { + { gl_Position = vvertex; texcoord0 = vtexcoord0 + vec2(-3.0, 0.0)*moviescale; texcoord1 = vtexcoord0 + vec2(-1.0, 0.0)*moviescale; @@ -1989,7 +1989,7 @@ lazyshader 0 "moviev" [ varying vec2 texcoord0, texcoord1, texcoord2, texcoord3; uniform sampler2D tex0; void main(void) - { + { vec3 sample1 = texture2D(tex0, texcoord0).rgb; vec3 sample2 = texture2D(tex0, texcoord1).rgb; vec3 sample3 = texture2D(tex0, texcoord2).rgb; @@ -2025,7 +2025,7 @@ watershader = [ varying vec4 texcoord0; varying vec2 texcoord1, texcoord2; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vcolor; texcoord0 = watermatrix * vvertex; @@ -2060,7 +2060,7 @@ watershader = [ ]]) uniform sampler2D tex1, tex2, tex3; void main(void) - { + { vec3 camvec = normalize(camdir); @(if $specular [result [ vec3 lightvec = normalize(lightdir); @@ -2091,12 +2091,12 @@ lazyshader 0 "waterglarefast" [ attribute vec4 vvertex; uniform mat4 camprojmatrix; void main(void) - { + { gl_Position = camprojmatrix * vvertex; } ] [ void main(void) - { + { gl_FragColor = vec4(0.0); } ] @@ -2109,7 +2109,7 @@ lazyshader 0 "underwater" [ uniform mat4 camprojmatrix; varying vec3 color; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vcolor; } @@ -2118,7 +2118,7 @@ lazyshader 0 "underwater" [ uniform vec2 depth; varying vec3 color; void main(void) - { + { gl_FragColor.rgb = 0.8*depth.x*color; gl_FragColor.a = 0.5*depth.y; } @@ -2313,7 +2313,7 @@ causticshader = [ uniform vec3 texgenS, texgenT; varying vec2 texcoord0; void main(void) - { + { gl_Position = camprojmatrix * vvertex; texcoord0 = vec2(dot(texgenS, vvertex.xyz), dot(texgenT, vvertex.xyz)); } @@ -2323,7 +2323,7 @@ causticshader = [ varying vec2 texcoord0; uniform sampler2D tex0, tex1; void main(void) - { + { @arg2 } ] @@ -2341,7 +2341,7 @@ lazyshader 0 "lava" [ uniform vec4 lavatexgen; varying vec2 texcoord0; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vcolor; vec2 tc = mix(vvertex.xz, vvertex.yy, abs(vnormal.xz)); @@ -2352,7 +2352,7 @@ lazyshader 0 "lava" [ varying vec4 color; varying vec2 texcoord0; void main(void) - { + { gl_FragColor = color * texture2D(tex0, texcoord0) * 2.0; } ] @@ -2366,7 +2366,7 @@ lazyshader 0 "lavaglare" [ uniform vec4 lavatexgen; varying vec2 texcoord0; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vec4(vcolor.rgb*2.0 - 1.0, vcolor.a); vec2 tc = mix(vvertex.xz, vvertex.yy, abs(vnormal.xz)); @@ -2377,7 +2377,7 @@ lazyshader 0 "lavaglare" [ varying vec4 color; varying vec2 texcoord0; void main(void) - { + { vec4 glow = texture2D(tex0, texcoord0) * color; float k = max(glow.r, max(glow.g, glow.b)); gl_FragColor = glow*k*k*32.0; @@ -2393,7 +2393,7 @@ lazyshader 0 "waterfall" [ uniform vec4 waterfalltexgen; varying vec2 texcoord0; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vcolor; vec2 tc = mix(vvertex.xz, vvertex.yy, abs(vnormal.xz)); @@ -2404,7 +2404,7 @@ lazyshader 0 "waterfall" [ varying vec4 color; varying vec2 texcoord0; void main(void) - { + { gl_FragColor = color * texture2D(tex0, texcoord0); } ] @@ -2420,7 +2420,7 @@ lazyshader 0 "waterfallrefract" [ varying vec2 texcoord0; varying vec4 texcoord1; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vcolor; vec2 tc = mix(vvertex.xz, vvertex.yy, abs(vnormal.xz)); @@ -2434,7 +2434,7 @@ lazyshader 0 "waterfallrefract" [ varying vec2 texcoord0; varying vec4 texcoord1; void main(void) - { + { vec4 diffuse = texture2D(tex0, texcoord0); vec2 dudv = texture2D(tex2, texcoord0 + 0.2*diffuse.xy + dudvoffset).xy; vec4 refract = texture2DProj(tex4, texcoord1 + vec4(4.0*dudv, 0.0, 0.0)); @@ -2456,7 +2456,7 @@ lazyshader 0 "waterfallenvrefract" [ varying vec3 camdir; varying mat3 world; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vcolor; camdir = camera - vvertex.xyz; @@ -2476,7 +2476,7 @@ lazyshader 0 "waterfallenvrefract" [ varying vec3 camdir; varying mat3 world; void main(void) - { + { vec4 diffuse = texture2D(tex0, texcoord0); vec2 dudv = texture2D(tex2, texcoord0 + 0.2*diffuse.xy + dudvoffset).xy; vec3 normal = world * (texture2D(tex1, texcoord0 + 0.1*dudv).rgb*2.0 - 1.0); @@ -2500,7 +2500,7 @@ lazyshader 0 "waterfallenv" [ varying vec3 color, camdir; varying mat3 world; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vcolor; camdir = camera - vvertex.xyz; @@ -2517,7 +2517,7 @@ lazyshader 0 "waterfallenv" [ varying vec3 color, camdir; varying mat3 world; void main(void) - { + { vec4 diffuse = texture2D(tex0, texcoord0); vec2 dudv = texture2D(tex2, texcoord0 + 0.2*diffuse.xy + dudvoffset).xy; vec3 normal = world * (texture2D(tex1, texcoord0 + 0.1*dudv).rgb*2.0 - 1.0); @@ -2535,7 +2535,7 @@ lazyshader 0 "glass" [ uniform vec3 camera; varying vec3 color, rvec, camdir, normal; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vcolor; normal = vnormal; @@ -2547,7 +2547,7 @@ lazyshader 0 "glass" [ uniform samplerCube tex0; varying vec3 color, rvec, camdir, normal; void main(void) - { + { vec3 camvec = normalize(camdir); vec3 reflect = textureCube(tex0, rvec).rgb; @@ -2563,7 +2563,7 @@ lazyshader 0 "glassfast" [ uniform vec3 camera; varying vec3 color, rvec; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vcolor; vec3 camdir = camera - vvertex.xyz; @@ -2574,7 +2574,7 @@ lazyshader 0 "glassfast" [ uniform samplerCube tex0; varying vec3 color, rvec; void main(void) - { + { vec3 reflect = textureCube(tex0, rvec).rgb; const float invfresnel = 0.75; gl_FragColor.rgb = mix(reflect, color*0.05, invfresnel); @@ -2595,7 +2595,7 @@ lazyshader 0 "grass" [ varying vec2 texcoord0, texcoord1; varying vec2 bounds; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vcolor; texcoord0 = vtexcoord0; @@ -2610,7 +2610,7 @@ lazyshader 0 "grass" [ varying vec2 bounds; uniform sampler2D tex0, tex1; void main(void) - { + { vec4 diffuse = texture2D(tex0, texcoord0); diffuse.rgb *= 2.0; vec4 lm = texture2D(tex1, texcoord1) * color; @@ -2627,7 +2627,7 @@ shader 0 "overbrightdecal" [ varying vec4 color; varying vec2 texcoord0; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vcolor; texcoord0 = vtexcoord0; @@ -2638,7 +2638,7 @@ shader 0 "overbrightdecal" [ varying vec2 texcoord0; uniform sampler2D tex0; void main(void) - { + { vec4 diffuse = texture2D(tex0, texcoord0); gl_FragColor = mix(color, diffuse, color.a); } @@ -2652,7 +2652,7 @@ shader 0 "saturatedecal" [ varying vec4 color; varying vec2 texcoord0; void main(void) - { + { gl_Position = camprojmatrix * vvertex; color = vcolor; texcoord0 = vtexcoord0; @@ -2662,7 +2662,7 @@ shader 0 "saturatedecal" [ varying vec2 texcoord0; uniform sampler2D tex0; void main(void) - { + { vec4 diffuse = texture2D(tex0, texcoord0); diffuse.rgb *= 2.0; gl_FragColor = diffuse * color; @@ -2676,7 +2676,7 @@ shader 0 "skybox" [ varying vec2 texcoord0; varying vec4 color; void main(void) - { + { gl_Position = skymatrix * vvertex; texcoord0 = vtexcoord0; color = vcolor; @@ -2686,7 +2686,7 @@ shader 0 "skybox" [ varying vec4 color; uniform sampler2D tex0; void main(void) - { + { gl_FragColor = color * texture2D(tex0, texcoord0); } ] @@ -2698,7 +2698,7 @@ shader 0 "skyboxglare" [ varying vec4 color; varying vec2 texcoord0; void main(void) - { + { gl_Position = skymatrix * vvertex; color = vcolor; texcoord0 = vtexcoord0; @@ -2708,7 +2708,7 @@ shader 0 "skyboxglare" [ varying vec2 texcoord0; uniform sampler2D tex0; void main(void) - { + { vec4 glare = texture2D(tex0, texcoord0) * color; gl_FragColor.rgb = vec3(dot(glare.rgb, vec3(10.56, 10.88, 10.56)) - 30.4); gl_FragColor.a = glare.a; @@ -2720,14 +2720,14 @@ shader 0 "skyfog" [ uniform mat4 skymatrix; varying vec4 color; void main(void) - { + { gl_Position = skymatrix * vvertex; color = vcolor; } ] [ varying vec4 color; void main(void) - { + { gl_FragColor = color; } ] @@ -2738,7 +2738,7 @@ loop i 2 [ uniform mat4 skymatrix; varying vec3 camvec; void main(void) - { + { gl_Position = skymatrix * vvertex; camvec = vvertex.xyz; @@ -2755,7 +2755,7 @@ loop i 2 [ varying vec3 camvec; void main(void) - { + { vec3 camdir = normalize(camvec); float costheta = dot(camdir, sundir); diff --git a/src/Makefile b/src/Makefile index e258102..63e56f5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,5 @@ CXXFLAGS= -O3 -fomit-frame-pointer -ffast-math -override CXXFLAGS+= -Wall -Wextra -fsigned-char -fno-exceptions -fno-rtti -Wno-unused-parameter +override CXXFLAGS+= -Wall -Wextra -fsigned-char -fno-exceptions -fno-rtti PLATFORM= $(shell uname -s | tr '[:lower:]' '[:upper:]') PLATFORM_PREFIX= native @@ -335,15 +335,14 @@ engine/rendermodel.o: shared/glexts.h shared/glemu.h shared/iengine.h engine/rendermodel.o: shared/igame.h engine/world.h engine/octa.h engine/rendermodel.o: engine/lightmap.h engine/bih.h engine/texture.h engine/rendermodel.o: engine/model.h engine/ragdoll.h engine/animmodel.h -engine/rendermodel.o: engine/vertmodel.h engine/skelmodel.h -engine/rendermodel.o: engine/md3.h engine/md5.h engine/iqm.h +engine/rendermodel.o: engine/skelmodel.h +engine/rendermodel.o: engine/md5.h engine/iqm.h engine/renderparticles.o: engine/engine.h shared/cube.h shared/tools.h engine/renderparticles.o: shared/geom.h shared/ents.h shared/command.h engine/renderparticles.o: shared/glexts.h shared/glemu.h shared/iengine.h engine/renderparticles.o: shared/igame.h engine/world.h engine/octa.h engine/renderparticles.o: engine/lightmap.h engine/bih.h engine/texture.h engine/renderparticles.o: engine/model.h engine/rendertarget.h -engine/renderparticles.o: engine/explosion.h engine/lightning.h engine/rendertext.o: engine/engine.h shared/cube.h shared/tools.h engine/rendertext.o: shared/geom.h shared/ents.h shared/command.h engine/rendertext.o: shared/glexts.h shared/glemu.h shared/iengine.h diff --git a/src/engine/3dgui.cpp b/src/engine/3dgui.cpp index 1e17e78..201f9e3 100644 --- a/src/engine/3dgui.cpp +++ b/src/engine/3dgui.cpp @@ -36,75 +36,55 @@ VARP(guipreviewtime, 0, 15, 1000); static int lastpreview = 0; -static inline bool throttlepreview(bool loaded) -{ +static inline bool throttlepreview(bool loaded) { if(loaded) return true; if(totalmillis - lastpreview < guipreviewtime) return false; lastpreview = totalmillis; return true; } -struct gui : g3d_gui -{ - struct list - { +struct gui : g3d_gui { + struct list { int parent, w, h, springs, curspring, column; }; - int firstlist, nextlist; int columns[MAXCOLUMNS]; - static vector lists; static float hitx, hity; static int curdepth, curlist, xsize, ysize, curx, cury; static bool shouldmergehits, shouldautotab; - - static void reset() - { + static void reset() { lists.setsize(0); } - static int ty, tx, tpos, *tcurrent, tcolor; //tracking tab size and position since uses different layout method... - - bool allowautotab(bool on) - { + bool allowautotab(bool on) { bool oldval = shouldautotab; shouldautotab = on; return oldval; } - - void autotab() - { - if(tcurrent) - { + void autotab() { + if(tcurrent) { if(layoutpass && !tpos) tcurrent = NULL; //disable tabs because you didn't start with one if(shouldautotab && !curdepth && (layoutpass ? 0 : cury) + ysize > guiautotab*FONTH) tab(NULL, tcolor); } } - - bool shouldtab() - { - if(tcurrent && shouldautotab) - { - if(layoutpass) - { + bool shouldtab() { + if(tcurrent && shouldautotab) { + if(layoutpass) { int space = guiautotab*FONTH - ysize; if(space < 0) return true; int l = lists[curlist].parent; - while(l >= 0) - { + while(l >= 0) { space -= lists[l].h; if(space < 0) return true; l = lists[l].parent; } } - else - { + else { int space = guiautotab*FONTH - cury; if(ysize > space) return true; int l = lists[curlist].parent; - while(l >= 0) - { + while(l >= 0) { if(lists[l].h > space) return true; l = lists[l].parent; } @@ -112,24 +92,19 @@ struct gui : g3d_gui } return false; } - bool visible() { return (!tcurrent || tpos==*tcurrent) && !layoutpass; } - //tab is always at top of page - void tab(const char *name, int color) - { + void tab(const char *name, int color) { if(curdepth != 0) return; if(color) tcolor = color; tpos++; if(!name) name = intstr(tpos); int w = max(text_width(name) - 2*INSERT, 0); - if(layoutpass) - { + if(layoutpass) { ty = max(ty, ysize); ysize = 0; } - else - { + else { cury = -ysize; int h = FONTH-2*INSERT, x1 = curx + tx, @@ -139,22 +114,16 @@ struct gui : g3d_gui bool hit = tcurrent && windowhit==this && hitx>=x1 && hity>=y1 && hitx=0) - { + void pushlist() { + if(layoutpass) { + if(curlist>=0) { lists[curlist].w = xsize; lists[curlist].h = ysize; } @@ -165,11 +134,9 @@ struct gui : g3d_gui curlist = lists.length()-1; xsize = ysize = 0; } - else - { + else { curlist = nextlist++; - if(curlist >= lists.length()) // should never get here unless script code doesn't use same amount of lists in layout and render passes - { + if(curlist >= lists.length()) { // should never get here unless script code doesn't use same amount of lists in layout and render passes { list &l = lists.add(); l.parent = curlist; l.springs = 0; @@ -178,155 +145,121 @@ struct gui : g3d_gui } list &l = lists[curlist]; l.curspring = 0; - if(l.springs > 0) - { + if(l.springs > 0) { if(ishorizontal()) xsize = l.w; else ysize = l.h; } - else - { + else { xsize = l.w; ysize = l.h; } } curdepth++; } - - void poplist() - { + void poplist() { if(!lists.inrange(curlist)) return; list &l = lists[curlist]; - if(layoutpass) - { + if(layoutpass) { l.w = xsize; l.h = ysize; if(l.column >= 0) columns[l.column] = max(columns[l.column], ishorizontal() ? ysize : xsize); } curlist = l.parent; curdepth--; - if(lists.inrange(curlist)) - { + if(lists.inrange(curlist)) { int w = xsize, h = ysize; if(ishorizontal()) cury -= h; else curx -= w; list &p = lists[curlist]; xsize = p.w; ysize = p.h; - if(!layoutpass && p.springs > 0) - { + if(!layoutpass && p.springs > 0) { list &s = lists[p.parent]; if(ishorizontal()) xsize = s.w; else ysize = s.h; } layout(w, h); } } - int text (const char *text, int color, const char *icon) { autotab(); return button_(text, color, icon, false, false); } int button(const char *text, int color, const char *icon) { autotab(); return button_(text, color, icon, true, false); } int title (const char *text, int color, const char *icon) { autotab(); return button_(text, color, icon, false, true); } - void separator() { autotab(); line_(FONTH/3); } void progress(float percent) { autotab(); line_((FONTH*4)/5, percent); } - //use to set min size (useful when you have progress bars) void strut(float size) { layout(isvertical() ? int(size*FONTW) : 0, isvertical() ? 0 : int(size*FONTH)); } //add space between list items void space(float size) { layout(isvertical() ? 0 : int(size*FONTW), isvertical() ? int(size*FONTH) : 0); } - - void spring(int weight) - { + void spring(int weight) { if(curlist < 0) return; list &l = lists[curlist]; if(layoutpass) { if(l.parent >= 0) l.springs += weight; return; } int nextspring = min(l.curspring + weight, l.springs); if(nextspring <= l.curspring) return; - if(ishorizontal()) - { + if(ishorizontal()) { int w = xsize - l.w; layout((w*nextspring)/l.springs - (w*l.curspring)/l.springs, 0); } - else - { + else { int h = ysize - l.h; layout(0, (h*nextspring)/l.springs - (h*l.curspring)/l.springs); } l.curspring = nextspring; } - - void column(int col) - { + void column(int col) { if(curlist < 0 || !layoutpass || col < 0 || col >= MAXCOLUMNS) return; list &l = lists[curlist]; l.column = col; } - - int layout(int w, int h) - { - if(layoutpass) - { - if(ishorizontal()) - { + int layout(int w, int h) { + if(layoutpass) { + if(ishorizontal()) { xsize += w; ysize = max(ysize, h); } - else - { + else { xsize = max(xsize, w); ysize += h; } return 0; } - else - { + else { bool hit = ishit(w, h); if(ishorizontal()) curx += w; else cury += h; return (hit && visible()) ? mousebuttons|G3D_ROLLOVER : 0; } } - - bool mergehits(bool on) - { + bool mergehits(bool on) { bool oldval = shouldmergehits; shouldmergehits = on; return oldval; } - - bool ishit(int w, int h, int x = curx, int y = cury) - { + bool ishit(int w, int h, int x = curx, int y = cury) { if(shouldmergehits) return windowhit==this && (ishorizontal() ? hitx>=x && hitx=y && hity=x && hity>=y && hitx=0 && visible()) - { + if(model>=0 && visible()) { bool hit = ishit(size+SHADOW, size+SHADOW); float xs = size, ys = size, xi = curx, yi = cury; - if(overlaid && hit && actionon) - { + if(overlaid && hit && actionon) { hudnotextureshader->set(); gle::colorf(0, 0, 0, 0.75f); rect_(xi+SHADOW, yi+SHADOW, xs, ys); @@ -341,10 +274,8 @@ struct gui : g3d_gui hudshader->set(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - if(overlaid) - { - if(hit) - { + if(overlaid) { + if(hit) { hudnotextureshader->set(); glBlendFunc(GL_ZERO, GL_SRC_COLOR); gle::colorf(1, 0.5f, 0.5f); @@ -361,18 +292,14 @@ struct gui : g3d_gui } return layout(size+SHADOW, size+SHADOW); } - - int modelpreview(const char *name, int anim, float sizescale, const char *overlaid, bool throttle) - { + int modelpreview(const char *name, int anim, float sizescale, const char *overlaid, bool throttle) { autotab(); if(sizescale==0) sizescale = 1; int size = (int)(sizescale*2*FONTH)-SHADOW; - if(name[0] && visible() && (!throttle || throttlepreview(modelloaded(name)))) - { + if(name[0] && visible() && (!throttle || throttlepreview(modelloaded(name)))) { bool hit = ishit(size+SHADOW, size+SHADOW); float xs = size, ys = size, xi = curx, yi = cury; - if(overlaid && hit && actionon) - { + if(overlaid && hit && actionon) { hudnotextureshader->set(); gle::colorf(0, 0, 0, 0.75f); rect_(xi+SHADOW, yi+SHADOW, xs, ys); @@ -383,8 +310,7 @@ struct gui : g3d_gui glDisable(GL_BLEND); modelpreview::start(x1, y1, x2-x1, y2-y1, overlaid!=NULL); model *m = loadmodel(name); - if(m) - { + if(m) { entitylight light; light.color = vec(1, 1, 1); light.dir = vec(0, -1, 2).normalize(); @@ -398,10 +324,8 @@ struct gui : g3d_gui hudshader->set(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - if(overlaid) - { - if(hit) - { + if(overlaid) { + if(hit) { hudnotextureshader->set(); glBlendFunc(GL_ZERO, GL_SRC_COLOR); gle::colorf(1, 0.5f, 0.5f); @@ -418,18 +342,14 @@ struct gui : g3d_gui } return layout(size+SHADOW, size+SHADOW); } - - int prefabpreview(const char *prefab, const vec &color, float sizescale, const char *overlaid, bool throttle) - { + int prefabpreview(const char *prefab, const vec &color, float sizescale, const char *overlaid, bool throttle) { autotab(); if(sizescale==0) sizescale = 1; int size = (int)(sizescale*2*FONTH)-SHADOW; - if(prefab[0] && visible() && (!throttle || throttlepreview(prefabloaded(prefab)))) - { + if(prefab[0] && visible() && (!throttle || throttlepreview(prefabloaded(prefab)))) { bool hit = ishit(size+SHADOW, size+SHADOW); float xs = size, ys = size, xi = curx, yi = cury; - if(overlaid && hit && actionon) - { + if(overlaid && hit && actionon) { hudnotextureshader->set(); gle::colorf(0, 0, 0, 0.75f); rect_(xi+SHADOW, yi+SHADOW, xs, ys); @@ -444,10 +364,8 @@ struct gui : g3d_gui hudshader->set(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - if(overlaid) - { - if(hit) - { + if(overlaid) { + if(hit) { hudnotextureshader->set(); glBlendFunc(GL_ZERO, GL_SRC_COLOR); gle::colorf(1, 0.5f, 0.5f); @@ -464,37 +382,29 @@ struct gui : g3d_gui } return layout(size+SHADOW, size+SHADOW); } - - void slider(int &val, int vmin, int vmax, int color, const char *label) - { + void slider(int &val, int vmin, int vmax, int color, const char *label) { autotab(); int x = curx; int y = cury; line_((FONTH*2)/3); - if(visible()) - { + if(visible()) { if(!label) label = intstr(val); int w = text_width(label); - bool hit; int px, py, offset = vmin < vmax ? clamp(val, vmin, vmax) : clamp(val, vmax, vmin); - if(ishorizontal()) - { + if(ishorizontal()) { hit = ishit(FONTH, ysize, x, y); px = x + (FONTH-w)/2; py = y + (ysize-FONTH) - ((ysize-FONTH)*(offset-vmin))/((vmax==vmin) ? 1 : (vmax-vmin)); //vmin at bottom } - else - { + else { hit = ishit(xsize, FONTH, x, y); px = x + FONTH/2 - w/2 + ((xsize-w)*(offset-vmin))/((vmax==vmin) ? 1 : (vmax-vmin)); //vmin at left py = y; } - if(hit) color = 0xFF0000; text_(label, px, py, color, hit && actionon, hit); - if(hit && actionon) - { + if(hit && actionon) { int vnew = (vmin < vmax ? 1 : -1)+vmax-vmin; if(ishorizontal()) vnew = int((vnew*(y+ysize-FONTH/2-hity))/(ysize-FONTH)); else vnew = int((vnew*(hitx-x-FONTH/2))/(xsize-w)); @@ -504,32 +414,23 @@ struct gui : g3d_gui } } } - - char *field(const char *name, int color, int length, int height, const char *initval, int initmode) - { + char *field(const char *name, int color, int length, int height, const char *initval, int initmode) { return field_(name, color, length, height, initval, initmode, FIELDEDIT); } - - char *keyfield(const char *name, int color, int length, int height, const char *initval, int initmode) - { + char *keyfield(const char *name, int color, int length, int height, const char *initval, int initmode) { return field_(name, color, length, height, initval, initmode, FIELDKEY); } - - char *field_(const char *name, int color, int length, int height, const char *initval, int initmode, int fieldtype = FIELDEDIT) - { + char *field_(const char *name, int color, int length, int height, const char *initval, int initmode, int fieldtype = FIELDEDIT) { editor *e = useeditor(name, initmode, false, initval); // generate a new editor if necessary - if(layoutpass) - { - if(initval && e->mode==EDITORFOCUSED && (e!=currentfocus() || fieldmode == FIELDSHOW)) - { + if(layoutpass) { + if(initval && e->mode==EDITORFOCUSED && (e!=currentfocus() || fieldmode == FIELDSHOW)) { if(strcmp(e->lines[0].text, initval)) e->clear(initval); } e->linewrap = (length<0); e->maxx = (e->linewrap) ? -1 : length; e->maxy = (height<=0)?1:-1; e->pixelwidth = abs(length)*FONTW; - if(e->linewrap && e->maxy==1) - { + if(e->linewrap && e->maxy==1) { int temp; text_bounds(e->lines[0].text, temp, e->pixelheight, e->pixelwidth); //only single line editors can have variable height } @@ -538,20 +439,14 @@ struct gui : g3d_gui } int h = e->pixelheight; int w = e->pixelwidth + FONTW; - bool wasvertical = isvertical(); if(wasvertical && e->maxy != 1) pushlist(); - char *result = NULL; - if(visible() && !layoutpass) - { + if(visible() && !layoutpass) { e->rendered = true; - bool hit = ishit(w, h); - if(hit) - { - if(mousebuttons&G3D_DOWN) //mouse request focus - { + if(hit) { + if(mousebuttons&G3D_DOWN) { //mouse request focus { if(fieldtype==FIELDKEY) e->clear(); useeditor(name, initmode, true); e->mark(false); @@ -560,16 +455,13 @@ struct gui : g3d_gui } bool editing = (fieldmode != FIELDSHOW) && (e==currentfocus()); if(hit && editing && (mousebuttons&G3D_PRESSED)!=0 && fieldtype==FIELDEDIT) e->hit(int(floor(hitx-(curx+FONTW/2))), int(floor(hity-cury)), (mousebuttons&G3D_DRAGGED)!=0); //mouse request position - if(editing && ((fieldmode==FIELDCOMMIT) || (fieldmode==FIELDABORT) || !hit)) // commit field if user pressed enter or wandered out of focus - { + if(editing && ((fieldmode==FIELDCOMMIT) || (fieldmode==FIELDABORT) || !hit)) { // commit field if user pressed enter or wandered out of focus { if(fieldmode==FIELDCOMMIT || (fieldmode!=FIELDABORT && !hit)) result = e->currentline().text; e->active = (e->mode!=EDITORFOCUSED); fieldmode = FIELDSHOW; } else fieldsactive = true; - e->draw(curx+FONTW/2, cury, color, hit && editing); - hudnotextureshader->set(); glDisable(GL_BLEND); if(editing) gle::colorf(1, 0, 0); @@ -579,24 +471,18 @@ struct gui : g3d_gui hudshader->set(); } layout(w, h); - - if(e->maxy != 1) - { + if(e->maxy != 1) { int slines = e->limitscrolly(); - if(slines > 0) - { + if(slines > 0) { int pos = e->scrolly; slider(e->scrolly, slines, 0, color, NULL); if(pos != e->scrolly) e->cy = e->scrolly; } if(wasvertical) poplist(); } - return result; } - - void rect_(float x, float y, float w, float h, bool lines = false) - { + void rect_(float x, float y, float w, float h, bool lines = false) { gle::defvertex(2); gle::begin(lines ? GL_LINE_LOOP : GL_TRIANGLE_STRIP); gle::attribf(x, y); @@ -606,9 +492,7 @@ struct gui : g3d_gui if(!lines) gle::attribf(x + w, y + h); xtraverts += gle::end(); } - - void rect_(float x, float y, float w, float h, int usetc) - { + void rect_(float x, float y, float w, float h, int usetc) { gle::defvertex(2); gle::deftexcoord0(); gle::begin(GL_TRIANGLE_STRIP); @@ -619,29 +503,23 @@ struct gui : g3d_gui gle::attribf(x + w, y + h); gle::attrib(tc[usetc+2]); xtraverts += gle::end(); } - - void text_(const char *text, int x, int y, int color, bool shadow, bool force = false) - { + void text_(const char *text, int x, int y, int color, bool shadow, bool force = false) { if(shadow) draw_text(text, x+SHADOW, y+SHADOW, 0x00, 0x00, 0x00, -0xC0); draw_text(text, x, y, color>>16, (color>>8)&0xFF, color&0xFF, force ? -0xFF : 0xFF); } - - void background(int color, int inheritw, int inherith) - { + void background(int color, int inheritw, int inherith) { if(layoutpass) return; hudnotextureshader->set(); gle::colorub(color>>16, (color>>8)&0xFF, color&0xFF, 0x80); int w = xsize, h = ysize; - if(inheritw>0) - { + if(inheritw>0) { int parentw = curlist, parentdepth = 0; for(;parentdepth < inheritw && lists[parentw].parent>=0; parentdepth++) parentw = lists[parentw].parent; list &p = lists[parentw]; w = p.springs > 0 && (curdepth-parentdepth)&1 ? lists[p.parent].w : p.w; } - if(inherith>0) - { + if(inherith>0) { int parenth = curlist, parentdepth = 0; for(;parentdepth < inherith && lists[parenth].parent>=0; parentdepth++) parenth = lists[parenth].parent; @@ -651,25 +529,20 @@ struct gui : g3d_gui rect_(curx, cury, w, h); hudshader->set(); } - - void icon_(Texture *t, bool overlaid, int x, int y, int size, bool hit, const char *title = NULL) - { + void icon_(Texture *t, bool overlaid, int x, int y, int size, bool hit, const char *title = NULL) { float scale = float(size)/max(t->xs, t->ys); //scale and preserve aspect ratio float xs = t->xs*scale, ys = t->ys*scale; x += int((size-xs)/2); y += int((size-ys)/2); const vec &color = hit ? vec(1, 0.5f, 0.5f) : (overlaid ? vec(1, 1, 1) : light); glBindTexture(GL_TEXTURE_2D, t->id); - if(hit && actionon) - { + if(hit && actionon) { gle::colorf(0, 0, 0, 0.75f); rect_(x+SHADOW, y+SHADOW, xs, ys, 0); } gle::color(color); rect_(x, y, xs, ys, 0); - - if(overlaid) - { + if(overlaid) { if(!overlaytex) overlaytex = textureload("data/guioverlay.png", 3); glBindTexture(GL_TEXTURE_2D, overlaytex->id); gle::color(light); @@ -677,20 +550,15 @@ struct gui : g3d_gui if(title) text_(title, x + xs/12, y + ys - ys/12 - FONTH, hit ? 0xFF0000 : 0xFFFFFF, hit && actionon, hit); } } - - void previewslot(VSlot &vslot, bool overlaid, int x, int y, int size, bool hit) - { + void previewslot(VSlot &vslot, bool overlaid, int x, int y, int size, bool hit) { Slot &slot = *vslot.slot; if(slot.sts.empty()) return; VSlot *layer = NULL; Texture *t = NULL, *layertex = NULL; - if(slot.loaded) - { + if(slot.loaded) { t = slot.sts[0].t; if(t == notexture) return; - Slot &slot = *vslot.slot; - if(vslot.layer) - { + if(vslot.layer) { layer = &lookupvslot(vslot.layer); if(!layer->slot->sts.empty()) layertex = layer->slot->sts[0].t; } @@ -698,8 +566,7 @@ struct gui : g3d_gui else if(slot.thumbnail && slot.thumbnail != notexture) t = slot.thumbnail; else return; float xt = min(1.0f, t->xs/(float)t->ys), yt = min(1.0f, t->ys/(float)t->xs), xs = size, ys = size; - if(hit && actionon) - { + if(hit && actionon) { hudnotextureshader->set(); gle::colorf(0, 0, 0, 0.75f); rect_(x+SHADOW, y+SHADOW, xs, ys); @@ -711,8 +578,7 @@ struct gui : g3d_gui const vec &color = hit ? vec(1, 0.5f, 0.5f) : (overlaid ? vec(1, 1, 1) : light); vec2 tc[4] = { vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1) }; float xoff = vslot.offset.x, yoff = vslot.offset.y; - if(vslot.rotation) - { + if(vslot.rotation) { const texrotation &r = texrotations[vslot.rotation]; if(r.swapxy) { swap(xoff, yoff); loopk(4) swap(tc[k].x, tc[k].y); } if(r.flipx) { xoff *= -1; loopk(4) tc[k].x *= -1; } @@ -728,8 +594,7 @@ struct gui : g3d_gui gle::attribf(x, y+ys); gle::attrib(tc[3]); gle::attribf(x+xs, y+ys); gle::attrib(tc[2]); gle::end(); - if(layertex) - { + if(layertex) { glBindTexture(GL_TEXTURE_2D, layertex->id); gle::color(vec(color).mul(layer->colorscale)); gle::begin(GL_TRIANGLE_STRIP); @@ -739,25 +604,19 @@ struct gui : g3d_gui gle::attribf(x+xs, y+ys); gle::attrib(tc[2]); gle::end(); } - hudshader->set(); - if(overlaid) - { + if(overlaid) { if(!overlaytex) overlaytex = textureload("data/guioverlay.png", 3); glBindTexture(GL_TEXTURE_2D, overlaytex->id); gle::color(light); rect_(x, y, xs, ys, 0); } } - - void line_(int size, float percent = 1.0f) - { - if(visible()) - { + void line_(int size, float percent = 1.0f) { + if(visible()) { if(!slidertex) slidertex = textureload("data/guislider.png", 3); glBindTexture(GL_TEXTURE_2D, slidertex->id); - if(percent < 0.99f) - { + if(percent < 0.99f) { gle::colorf(light.x, light.y, light.z, 0.375f); if(ishorizontal()) rect_(curx + FONTH/2 - size/2, cury, size, ysize, 0); @@ -772,9 +631,7 @@ struct gui : g3d_gui } layout(ishorizontal() ? FONTH : 0, ishorizontal() ? 0 : FONTH); } - - void textbox(const char *text, int width, int height, int color) - { + void textbox(const char *text, int width, int height, int color) { width *= FONTW; height *= FONTH; int w, h; @@ -783,26 +640,19 @@ struct gui : g3d_gui if(visible()) draw_text(text, curx, cury, color>>16, (color>>8)&0xFF, color&0xFF, 0xFF, -1, width); layout(width, height); } - - int button_(const char *text, int color, const char *icon, bool clickable, bool center) - { + int button_(const char *text, int color, const char *icon, bool clickable, bool center) { const int padding = 10; int w = 0; if(icon) w += ICON_SIZE; if(icon && text) w += padding; if(text) w += text_width(text); - - if(visible()) - { + if(visible()) { bool hit = ishit(w, FONTH); if(hit && clickable) color = 0xFF0000; int x = curx; if(isvertical() && center) x += (xsize-w)/2; - - if(icon) - { - if(icon[0] != ' ') - { + if(icon) { + if(icon[0] != ' ') { const char *ext = strrchr(icon, '.'); defformatstring(tname, "packages/icons/%s%s", icon, ext ? "" : ".png"); icon_(textureload(tname, 3), false, x, cury, ICON_SIZE, clickable && hit); @@ -814,73 +664,57 @@ struct gui : g3d_gui } return layout(w, FONTH); } - static Texture *skintex, *overlaytex, *slidertex; static const int skinx[], skiny[]; static const struct patch { ushort left, right, top, bottom; uchar flags; } patches[]; - - static void drawskin(int x, int y, int gapw, int gaph, int start, int n, int passes = 1, const vec &light = vec(1, 1, 1), float alpha = 0.80f)//int vleft, int vright, int vtop, int vbottom, int start, int n) - { + static void drawskin(int x, int y, int gapw, int gaph, int start, int n, int passes = 1, const vec &light = vec(1, 1, 1), float alpha = 0.80f) {//int vleft, int vright, int vtop, int vbottom, int start, int n) { if(!skintex) skintex = textureload("data/guiskin.png", 3); glBindTexture(GL_TEXTURE_2D, skintex->id); int gapx1 = INT_MAX, gapy1 = INT_MAX, gapx2 = INT_MAX, gapy2 = INT_MAX; float wscale = 1.0f/(SKIN_W*SKIN_SCALE), hscale = 1.0f/(SKIN_H*SKIN_SCALE); - - loopj(passes) - { + loopj(passes) { bool quads = false; if(passes>1) glDepthFunc(j ? GL_LEQUAL : GL_GREATER); gle::color(j ? light : vec(1, 1, 1), passes<=1 || j ? alpha : alpha/2); //ghost when its behind something in depth - loopi(n) - { + loopi(n) { const patch &p = patches[start+i]; int left = skinx[p.left]*SKIN_SCALE, right = skinx[p.right]*SKIN_SCALE, top = skiny[p.top]*SKIN_SCALE, bottom = skiny[p.bottom]*SKIN_SCALE; float tleft = left*wscale, tright = right*wscale, ttop = top*hscale, tbottom = bottom*hscale; - if(p.flags&0x1) - { + if(p.flags&0x1) { gapx1 = left; gapx2 = right; } - else if(left >= gapx2) - { + else if(left >= gapx2) { left += gapw - (gapx2-gapx1); right += gapw - (gapx2-gapx1); } - if(p.flags&0x10) - { + if(p.flags&0x10) { gapy1 = top; gapy2 = bottom; } - else if(top >= gapy2) - { + else if(top >= gapy2) { top += gaph - (gapy2-gapy1); bottom += gaph - (gapy2-gapy1); } - //multiple tiled quads if necessary rather than a single stretched one int ystep = bottom-top; int yo = y+top; - while(ystep > 0) - { - if(p.flags&0x10 && yo+ystep-(y+top) > gaph) - { + while(ystep > 0) { + if(p.flags&0x10 && yo+ystep-(y+top) > gaph) { ystep = gaph+y+top-yo; tbottom = ttop+ystep*hscale; } int xstep = right-left; int xo = x+left; float tright2 = tright; - while(xstep > 0) - { - if(p.flags&0x01 && xo+xstep-(x+left) > gapw) - { + while(xstep > 0) { + if(p.flags&0x01 && xo+xstep-(x+left) > gapw) { xstep = gapw+x+left-xo; tright = tleft+xstep*wscale; } - if(!quads) - { + if(!quads) { quads = true; gle::defvertex(2); gle::deftexcoord0(); @@ -903,34 +737,26 @@ struct gui : g3d_gui } if(passes>1) glDepthFunc(GL_ALWAYS); } - vec origin, scale, *savedorigin; float dist; g3d_callback *cb; bool gui2d; - static float basescale, maxscale; static bool passthrough; static float alpha; static vec light; - - void adjustscale() - { + void adjustscale() { int w = xsize + (skinx[2]-skinx[1])*SKIN_SCALE + (skinx[10]-skinx[9])*SKIN_SCALE, h = ysize + (skiny[9]-skiny[7])*SKIN_SCALE; if(tcurrent) h += ((skiny[5]-skiny[1])-(skiny[3]-skiny[2]))*SKIN_SCALE + FONTH-2*INSERT; else h += (skiny[6]-skiny[3])*SKIN_SCALE; - float aspect = forceaspect ? 1.0f/forceaspect : float(screenh)/float(screenw), fit = 1.0f; if(w*aspect*basescale>1.0f) fit = 1.0f/(w*aspect*basescale); if(h*basescale*fit>maxscale) fit *= maxscale/(h*basescale*fit); origin = vec(0.5f-((w-xsize)/2 - (skinx[2]-skinx[1])*SKIN_SCALE)*aspect*scale.x*fit, 0.5f + (0.5f*h-(skiny[9]-skiny[7])*SKIN_SCALE)*scale.y*fit, 0); scale = vec(aspect*scale.x*fit, scale.y*fit, 1); } - - void start(int starttime, float initscale, int *tab, bool allowinput) - { - if(gui2d) - { + void start(int starttime, float initscale, int *tab, bool allowinput) { + if(gui2d) { initscale *= 0.025f; if(allowinput) hascursor = true; } @@ -946,53 +772,41 @@ struct gui : g3d_gui tcurrent = tab; tcolor = 0xFFFFFF; pushlist(); - if(layoutpass) - { + if(layoutpass) { firstlist = nextlist = curlist; memset(columns, 0, sizeof(columns)); } - else - { + else { if(tcurrent && !*tcurrent) tcurrent = NULL; cury = -ysize; curx = -xsize/2; - - if(gui2d) - { + if(gui2d) { hudmatrix.ortho(0, 1, 1, 0, -1, 1); hudmatrix.translate(origin); hudmatrix.scale(scale); - light = vec(1, 1, 1); } - else - { + else { float yaw = atan2f(origin.y-camera1->o.y, origin.x-camera1->o.x); hudmatrix = camprojmatrix; hudmatrix.translate(origin); hudmatrix.rotate_around_z(yaw - 90*RAD); hudmatrix.rotate_around_x(-90*RAD); hudmatrix.scale(-scale.x, scale.y, scale.z); - vec dir; lightreaching(origin, light, dir, false, 0, 0.5f); float intensity = vec(yaw, 0.0f).dot(dir); light.mul(1.0f + max(intensity, 0.0f)); } - resethudmatrix(); hudshader->set(); - drawskin(curx-skinx[2]*SKIN_SCALE, cury-skiny[6]*SKIN_SCALE, xsize, ysize, 0, 9, gui2d ? 1 : 2, light, alpha); if(!tcurrent) drawskin(curx-skinx[5]*SKIN_SCALE, cury-skiny[6]*SKIN_SCALE, xsize, 0, 9, 1, gui2d ? 1 : 2, light, alpha); } } - - void adjusthorizontalcolumn(int col, int i) - { + void adjusthorizontalcolumn(int col, int i) { int h = columns[col], dh = 0; - for(int d = 1; i >= 0; d ^= 1) - { + for(int d = 1; i >= 0; d ^= 1) { list &p = lists[i]; if(d&1) { dh = h - p.h; if(dh <= 0) break; p.h = h; } else { p.h += dh; h = p.h; } @@ -1000,12 +814,9 @@ struct gui : g3d_gui } ysize += max(dh, 0); } - - void adjustverticalcolumn(int col, int i) - { + void adjustverticalcolumn(int col, int i) { int w = columns[col], dw = 0; - for(int d = 0; i >= 0; d ^= 1) - { + for(int d = 0; i >= 0; d ^= 1) { list &p = lists[i]; if(d&1) { p.w += dw; w = p.w; } else { dw = w - p.w; if(dw <= 0) break; p.w = w; } @@ -1013,59 +824,45 @@ struct gui : g3d_gui } xsize = max(xsize, w); } - - void adjustcolumns() - { - if(lists.inrange(curlist)) - { + void adjustcolumns() { + if(lists.inrange(curlist)) { list &l = lists[curlist]; if(l.column >= 0) columns[l.column] = max(columns[l.column], ishorizontal() ? ysize : xsize); } int parent = -1, depth = 0; - for(int i = firstlist; i < lists.length(); i++) - { + for(int i = firstlist; i < lists.length(); i++) { list &l = lists[i]; if(l.parent > parent) { parent = l.parent; depth++; } - else if(l.parent < parent) - { - while(parent > l.parent && depth > 0) - { + else if(l.parent < parent) { + while(parent > l.parent && depth > 0) { parent = lists[parent].parent; depth--; } } - if(l.column >= 0) - { + if(l.column >= 0) { if(depth&1) adjusthorizontalcolumn(l.column, i); else adjustverticalcolumn(l.column, i); } } } - - void end() - { - if(layoutpass) - { + void end() { + if(layoutpass) { adjustcolumns(); xsize = max(tx, xsize); ysize = max(ty, ysize); ysize = max(ysize, (skiny[7]-skiny[6])*SKIN_SCALE); if(tcurrent) *tcurrent = max(1, min(*tcurrent, tpos)); if(gui2d) adjustscale(); - if(!windowhit && !passthrough) - { + if(!windowhit && !passthrough) { float dist = 0; - if(gui2d) - { + if(gui2d) { hitx = (cursorx - origin.x)/scale.x; hity = (cursory - origin.y)/scale.y; } - else - { + else { plane p; p.toplane(vec(origin).sub(camera1->o).set(2, 0).normalize(), origin); - if(p.rayintersect(camera1->o, camdir, dist) && dist>=0) - { + if(p.rayintersect(camera1->o, camdir, dist) && dist>=0) { vec hitpos(camdir); hitpos.mul(dist).add(camera1->o).sub(origin); hitx = vec(-p.y, p.x, 0).dot(hitpos)/scale.x; @@ -1073,22 +870,18 @@ struct gui : g3d_gui } } if((mousebuttons & G3D_PRESSED) && (fabs(hitx-firstx) > 2 || fabs(hity - firsty) > 2)) mousebuttons |= G3D_DRAGGED; - if(dist>=0 && hitx>=-xsize/2 && hitx<=xsize/2 && hity<=0) - { + if(dist>=0 && hitx>=-xsize/2 && hitx<=xsize/2 && hity<=0) { if(hity>=-ysize || (tcurrent && hity>=-ysize-(FONTH-2*INSERT)-((skiny[6]-skiny[1])-(skiny[3]-skiny[2]))*SKIN_SCALE && hitx<=tx-xsize/2)) windowhit = this; } } } - else - { + else { if(tcurrent && txgui(*this, layoutpass); } }; @@ -1097,44 +890,39 @@ Texture *gui::skintex = NULL, *gui::overlaytex = NULL, *gui::slidertex = NULL; //chop skin into a grid const int gui::skiny[] = {0, 7, 21, 34, 43, 48, 56, 104, 111, 117, 128}, - gui::skinx[] = {0, 11, 23, 37, 105, 119, 137, 151, 215, 229, 246, 256}; + gui::skinx[] = {0, 11, 23, 37, 105, 119, 137, 151, 215, 229, 246, 256}; //Note: skinx[3]-skinx[2] = skinx[7]-skinx[6] // skinx[5]-skinx[4] = skinx[9]-skinx[8] -const gui::patch gui::patches[] = -{ //arguably this data can be compressed - it depends on what else needs to be skinned in the future - {1,2,3,6, 0}, // body - {2,9,5,6, 0x01}, - {9,10,3,6, 0}, - - {1,2,6,7, 0x10}, - {2,9,6,7, 0x11}, - {9,10,6,7, 0x10}, - - {1,2,7,9, 0}, - {2,9,7,9, 0x01}, - {9,10,7,9, 0}, - - {5,6,3,5, 0x01}, // top - - {2,3,1,2, 0}, // selected tab - {3,4,1,2, 0x01}, - {4,5,1,2, 0}, - {2,3,2,3, 0x10}, - {3,4,2,3, 0x11}, - {4,5,2,3, 0x10}, - {2,3,3,5, 0}, - {3,4,3,5, 0x01}, - {4,5,3,5, 0}, - - {6,7,1,2, 0}, // deselected tab - {7,8,1,2, 0x01}, - {8,9,1,2, 0}, - {6,7,2,3, 0x10}, - {7,8,2,3, 0x11}, - {8,9,2,3, 0x10}, - {6,7,3,5, 0}, - {7,8,3,5, 0x01}, - {8,9,3,5, 0}, +const gui::patch gui::patches[] = { + //arguably this data can be compressed - it depends on what else needs to be skinned in the future { + { 1,2,3,6, 0}, // body { + { 2,9,5,6, 0x01}, + { 9,10,3,6, 0}, + { 1,2,6,7, 0x10}, + { 2,9,6,7, 0x11}, + { 9,10,6,7, 0x10}, + { 1,2,7,9, 0}, + { 2,9,7,9, 0x01}, + { 9,10,7,9, 0}, + { 5,6,3,5, 0x01}, // top + { 2,3,1,2, 0}, // selected tab { + { 3,4,1,2, 0x01}, + { 4,5,1,2, 0}, + { 2,3,2,3, 0x10}, + { 3,4,2,3, 0x11}, + { 4,5,2,3, 0x10}, + { 2,3,3,5, 0}, + { 3,4,3,5, 0x01}, + { 4,5,3,5, 0}, + { 6,7,1,2, 0}, // deselected tab { + { 7,8,1,2, 0x01}, + { 8,9,1,2, 0}, + { 6,7,2,3, 0x10}, + { 7,8,2,3, 0x11}, + { 8,9,2,3, 0x10}, + { 6,7,3,5, 0}, + { 7,8,3,5, 0x01}, + { 8,9,3,5, 0}, }; vector gui::lists; @@ -1147,53 +935,40 @@ static vector guis2d, guis3d; VARP(guipushdist, 1, 4, 64); -bool g3d_input(const char *str, int len) -{ +bool g3d_input(const char *str, int len) { editor *e = currentfocus(); if(fieldmode == FIELDKEY || fieldmode == FIELDSHOW || !e) return false; - e->input(str, len); return true; } -bool g3d_key(int code, bool isdown) -{ +bool g3d_key(int code, bool isdown) { editor *e = currentfocus(); - if(fieldmode == FIELDKEY) - { - switch(code) - { + if(fieldmode == FIELDKEY) { + switch(code) { case SDLK_ESCAPE: if(isdown) fieldmode = FIELDCOMMIT; return true; } const char *keyname = getkeyname(code); - if(keyname && isdown) - { + if(keyname && isdown) { if(e->lines.length()!=1 || !e->lines[0].empty()) e->insert(" "); e->insert(keyname); } return true; } - if(code==-1 && g3d_windowhit(isdown, true)) return true; else if(code==-3 && g3d_windowhit(isdown, false)) return true; - - if(fieldmode == FIELDSHOW || !e) - { - if(windowhit) switch(code) - { + if(fieldmode == FIELDSHOW || !e) { + if(windowhit) switch(code) { case -4: // window "management" - if(isdown) - { - if(windowhit->gui2d) - { + if(isdown) { + if(windowhit->gui2d) { vec origin = *guis2d.last().savedorigin; int i = windowhit - &guis2d[0]; for(int j = guis2d.length()-1; j > i; j--) *guis2d[j].savedorigin = *guis2d[j-1].savedorigin; *windowhit->savedorigin = origin; - if(guis2d.length() > 1) - { + if(guis2d.length() > 1) { if(camera1->o.dist(*windowhit->savedorigin) <= camera1->o.dist(*guis2d.last().savedorigin)) windowhit->savedorigin->add(camdir); } @@ -1202,15 +977,12 @@ bool g3d_key(int code, bool isdown) } return true; case -5: - if(isdown) - { - if(windowhit->gui2d) - { + if(isdown) { + if(windowhit->gui2d) { vec origin = *guis2d[0].savedorigin; loopj(guis2d.length()-1) *guis2d[j].savedorigin = *guis2d[j + 1].savedorigin; *guis2d.last().savedorigin = origin; - if(guis2d.length() > 1) - { + if(guis2d.length() > 1) { if(camera1->o.dist(*guis2d.last().savedorigin) >= camera1->o.dist(*guis2d[0].savedorigin)) guis2d.last().savedorigin->sub(camdir); } @@ -1219,11 +991,9 @@ bool g3d_key(int code, bool isdown) } return true; } - return false; } - switch(code) - { + switch(code) { case SDLK_ESCAPE: //cancel editing without commit if(isdown) fieldmode = FIELDABORT; return true; @@ -1240,21 +1010,18 @@ bool g3d_key(int code, bool isdown) return true; } -void g3d_cursorpos(float &x, float &y) -{ +void g3d_cursorpos(float &x, float &y) { if(guis2d.length()) { x = cursorx; y = cursory; } else x = y = 0.5f; } -void g3d_resetcursor() -{ +void g3d_resetcursor() { cursorx = cursory = 0.5f; } FVARP(guisens, 1e-3f, 1, 1e3f); -bool g3d_movecursor(int dx, int dy) -{ +bool g3d_movecursor(int dx, int dy) { if(!guis2d.length() || !hascursor) return false; const float CURSORSCALE = 500.0f; cursorx = max(0.0f, min(1.0f, cursorx+guisens*dx*(screenh/(screenw*CURSORSCALE)))); @@ -1265,8 +1032,7 @@ bool g3d_movecursor(int dx, int dy) VARNP(guifollow, useguifollow, 0, 1, 1); VARNP(gui2d, usegui2d, 0, 1, 1); -void g3d_addgui(g3d_callback *cb, vec &origin, int flags) -{ +void g3d_addgui(g3d_callback *cb, vec &origin, int flags) { bool gui2d = flags&GUI_FORCE_2D || (flags&GUI_2D && usegui2d) || mainmenu; if(!gui2d && flags&GUI_FOLLOW && useguifollow) origin.z = player->o.z-(player->eyeheight-1); gui &g = (gui2d ? guis2d : guis3d).add(); @@ -1277,20 +1043,16 @@ void g3d_addgui(g3d_callback *cb, vec &origin, int flags) g.gui2d = gui2d; } -void g3d_limitscale(float scale) -{ +void g3d_limitscale(float scale) { gui::maxscale = scale; } static inline bool g3d_sort(const gui &a, const gui &b) { return a.dist < b.dist; } -bool g3d_windowhit(bool on, bool act) -{ +bool g3d_windowhit(bool on, bool act) { extern int cleargui(int n); - if(act) - { - if(actionon || windowhit) - { + if(act) { + if(actionon || windowhit) { if(on) { firstx = gui::hitx; firsty = gui::hity; } mousebuttons |= (actionon=on) ? G3D_DOWN : G3D_UP; } @@ -1298,76 +1060,55 @@ bool g3d_windowhit(bool on, bool act) return (guis2d.length() && hascursor) || (windowhit && !windowhit->gui2d); } -void g3d_render() -{ +void g3d_render() { windowhit = NULL; if(actionon) mousebuttons |= G3D_PRESSED; - gui::reset(); guis2d.shrink(0); guis3d.shrink(0); - // call all places in the engine that may want to render a gui from here, they call g3d_addgui() extern void g3d_texturemenu(); - if(!mainmenu) g3d_texturemenu(); g3d_mainmenu(); if(!mainmenu) game::g3d_gamemenus(); - guis2d.sort(g3d_sort); guis3d.sort(g3d_sort); - readyeditors(); fieldsactive = false; - hascursor = false; - layoutpass = true; loopv(guis2d) guis2d[i].draw(); loopv(guis3d) guis3d[i].draw(); layoutpass = false; - - if(guis3d.length()) - { + if(guis3d.length()) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); glDepthMask(GL_FALSE); - loopvrev(guis3d) guis3d[i].draw(); - glDepthFunc(GL_LESS); glDepthMask(GL_TRUE); glDisable(GL_DEPTH_TEST); - glDisable(GL_BLEND); } } -void g3d_render2d() -{ - if(guis2d.length()) - { +void g3d_render2d() { + if(guis2d.length()) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - loopvrev(guis2d) guis2d[i].draw(); - glDisable(GL_BLEND); } - flusheditors(); if(!fieldsactive) fieldmode = FIELDSHOW; //didn't draw any fields, so lose focus - mainly for menu closed textinput(fieldmode!=FIELDSHOW, TI_GUI); keyrepeat(fieldmode!=FIELDSHOW, KR_GUI); - mousebuttons = 0; } -void consolebox(int x1, int y1, int x2, int y2) -{ +void consolebox(int x1, int y1, int x2, int y2) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); float bw = x2 - x1, bh = y2 - y1, aspect = bw/bh, sh = bh, sw = sh*aspect; bw *= float(4*FONTH)/(SKIN_H*SKIN_SCALE); diff --git a/src/engine/animmodel.h b/src/engine/animmodel.h index 13705f4..51d09e8 100644 --- a/src/engine/animmodel.h +++ b/src/engine/animmodel.h @@ -1,93 +1,66 @@ -VARFP(bumpmodels, 0, 1, 1, preloadmodelshaders(true)); +VARFP(bumpmodels, 0, 1, 1, preloadmodelshaders()); VARP(fullbrightmodels, 0, 0, 200); -struct animmodel : model -{ - struct animspec - { +struct animmodel : model { + struct animspec { int frame, range; float speed; int priority; }; - - struct animpos - { + struct animpos { int anim, fr1, fr2; float t; - - void setframes(const animinfo &info) - { + void setframes(const animinfo &info) { anim = info.anim; - if(info.range<=1) - { + if(info.range<=1) { fr1 = 0; t = 0; } - else - { + else { int time = info.anim&ANIM_SETTIME ? info.basetime : lastmillis-info.basetime; fr1 = (int)(time/info.speed); // round to full frames t = (time-fr1*info.speed)/info.speed; // progress of the frame, value from 0.0f to 1.0f } - if(info.anim&ANIM_LOOP) - { + if(info.anim&ANIM_LOOP) { fr1 = fr1%info.range+info.frame; fr2 = fr1+1; if(fr2>=info.frame+info.range) fr2 = info.frame; } - else - { + else { fr1 = min(fr1, info.range-1)+info.frame; fr2 = min(fr1+1, info.frame+info.range-1); } - if(info.anim&ANIM_REVERSE) - { + if(info.anim&ANIM_REVERSE) { fr1 = (info.frame+info.range-1)-(fr1-info.frame); fr2 = (info.frame+info.range-1)-(fr2-info.frame); } } - bool operator==(const animpos &a) const { return fr1==a.fr1 && fr2==a.fr2 && (fr1==fr2 || t==a.t); } bool operator!=(const animpos &a) const { return fr1!=a.fr1 || fr2!=a.fr2 || (fr1!=fr2 && t!=a.t); } }; - struct part; - - struct animstate - { + struct animstate { part *owner; animpos cur, prev; float interp; - bool operator==(const animstate &a) const { return cur==a.cur && (interp<1 ? interp==a.interp && prev==a.prev : a.interp>=1); } bool operator!=(const animstate &a) const { return cur!=a.cur || (interp<1 ? interp!=a.interp || prev!=a.prev : a.interp<1); } }; - struct linkedpart; struct mesh; - - struct shaderparams - { + struct shaderparams { float spec, ambient, fullbright, scrollu, scrollv, alphatest; - shaderparams() : spec(1.0f), ambient(0.3f), fullbright(0), scrollu(0), scrollv(0), alphatest(0.9f) {} }; - - struct shaderparamskey - { + struct shaderparamskey { static hashtable keys; static int firstversion, lastversion; - int version; - shaderparamskey() : version(-1) {} - - bool checkversion() - { + bool checkversion() { if(version >= firstversion) return true; version = lastversion; - if(++lastversion <= 0) - { + if(++lastversion <= 0) { enumerate(keys, shaderparamskey, key, key.version = -1); firstversion = 0; lastversion = 1; @@ -95,67 +68,47 @@ struct animmodel : model } return false; } - - static inline void invalidate() - { + static inline void invalidate() { firstversion = lastversion; } }; - - struct skin : shaderparams - { + struct skin : shaderparams { part *owner; Texture *tex, *masks, *normalmap; Shader *shader; bool alphablend, cullface; shaderparamskey *key; - skin() : owner(0), tex(notexture), masks(notexture), normalmap(NULL), shader(NULL), alphablend(true), cullface(true), key(NULL) {} - bool masked() const { return masks != notexture; } bool bumpmapped() { return normalmap && bumpmodels; } bool tangents() { return bumpmapped(); } bool alphatested() const { return alphatest > 0 && tex->type&Texture::ALPHA; } - - void setkey() - { + void setkey() { key = &shaderparamskey::keys[*this]; } - - void setshaderparams(mesh *m, const animstate *as) - { + void setshaderparams(mesh *m, const animstate *as) { if(!Shader::lastshader) return; - float mincolor = as->cur.anim&ANIM_FULLBRIGHT ? fullbrightmodels/100.0f : 0.0f; - if(fullbright) - { + if(fullbright) { gle::colorf(fullbright/2, fullbright/2, fullbright/2, transparent); } - else - { + else { gle::color(vec(lightcolor).max(mincolor), transparent); } - if(key->checkversion() && Shader::lastshader->owner == key) return; Shader::lastshader->owner = key; - if(alphatested()) LOCALPARAMF(alphatest, alphatest); - - if(fullbright) - { + if(fullbright) { LOCALPARAMF(lightscale, 0, 0, 2); } - else - { + else { float bias = max(mincolor-1.0f, 0.2f), scale = 0.5f*max(0.8f-bias, 0.0f), minshade = scale*max(ambient, mincolor); LOCALPARAMF(lightscale, scale - minshade, scale, minshade + bias); } LOCALPARAMF(texscroll, scrollu*lastmillis/1000.0f, scrollv*lastmillis/1000.0f); } - - Shader *loadshader() - { + Shader *loadshader() { #define DOMODELSHADER(name, body) \ do { \ static Shader *name##shader = NULL; \ @@ -165,7 +118,6 @@ struct animmodel : model #define LOADMODELSHADER(name) DOMODELSHADER(name, return name##shader) #define SETMODELSHADER(m, name) DOMODELSHADER(name, (m)->setshader(name##shader)) if(shader) return shader; - string opts; int optslen = 0; if(alphatested()) opts[optslen++] = 'a'; @@ -174,40 +126,27 @@ struct animmodel : model if(masked()) opts[optslen++] = 'm'; if(!fullbright && (masked() || spec>=0.01f)) opts[optslen++] = 's'; opts[optslen++] = '\0'; - defformatstring(name, "model%s", opts); shader = generateshader(name, "modelshader \"%s\"", opts); return shader; } - - void cleanup() - { + void cleanup() { if(shader && shader->standard) shader = NULL; } - - void preloadBIH() - { + void preloadBIH() { if(tex->type&Texture::ALPHA && !tex->alphamask) loadalphamask(tex); } - - void preloadshader(bool force) - { - if(force) cleanup(); + void preloadshader() { + //~if(force) cleanup(); loadshader(); } - - void setshader(mesh *m, const animstate *as) - { + void setshader(mesh *m, const animstate *as) { m->setshader(loadshader()); } - - void bind(mesh *b, const animstate *as) - { + void bind(mesh *b, const animstate *as) { if(!cullface && enablecullface) { glDisable(GL_CULL_FACE); enablecullface = false; } else if(cullface && !enablecullface) { glEnable(GL_CULL_FACE); enablecullface = true; } - - if(as->cur.anim&ANIM_NOSKIN) - { + if(as->cur.anim&ANIM_NOSKIN) { if(enablealphablend) { glDisable(GL_BLEND); enablealphablend = false; } if(shadowmapping) SETMODELSHADER(b, shadowmapcaster); else /*if(as->cur.anim&ANIM_SHADOW)*/ SETMODELSHADER(b, notexturemodel); @@ -216,24 +155,19 @@ struct animmodel : model setshader(b, as); setshaderparams(b, as); int activetmu = 0; - if(tex!=lasttex) - { + if(tex!=lasttex) { glBindTexture(GL_TEXTURE_2D, tex->id); lasttex = tex; } - if(bumpmapped() && normalmap !=lastnormalmap) - { + if(bumpmapped() && normalmap !=lastnormalmap) { glActiveTexture_(GL_TEXTURE3); activetmu = 3; glBindTexture(GL_TEXTURE_2D, normalmap->id); lastnormalmap = normalmap; } - if(tex->type&Texture::ALPHA) - { - if(alphablend) - { - if(!enablealphablend) - { + if(tex->type&Texture::ALPHA) { + if(alphablend) { + if(!enablealphablend) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); enablealphablend = true; @@ -242,8 +176,7 @@ struct animmodel : model else if(enablealphablend) { glDisable(GL_BLEND); enablealphablend = false; } } else if(enablealphablend && transparent>=1) { glDisable(GL_BLEND); enablealphablend = false; } - if(masked() && masks!=lastmasks) - { + if(masked() && masks!=lastmasks) { glActiveTexture_(GL_TEXTURE1); activetmu = 1; glBindTexture(GL_TEXTURE_2D, masks->id); @@ -252,29 +185,19 @@ struct animmodel : model if(activetmu != 0) glActiveTexture_(GL_TEXTURE0); } }; - struct meshgroup; - - struct mesh - { + struct mesh { meshgroup *group; char *name; bool noclip; - - mesh() : group(NULL), name(NULL), noclip(false) - { + mesh() : group(NULL), name(NULL), noclip(false) { } - - virtual ~mesh() - { + virtual ~mesh() { DELETEA(name); } - virtual void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) {} - virtual void genBIH(BIH::mesh &m) {} - void genBIH(skin &s, vector &bih, const matrix4x3 &t) - { + void genBIH(skin &s, vector &bih, const matrix4x3 &t) { BIH::mesh &m = bih.add(); m.xform = t; m.tex = s.tex; @@ -282,35 +205,28 @@ struct animmodel : model if(noclip) m.flags |= BIH::MESH_NOCLIP; if(s.cullface) m.flags |= BIH::MESH_CULLFACE; genBIH(m); - while(bih.last().numtris > BIH::mesh::MAXTRIS) - { + while(bih.last().numtris > BIH::mesh::MAXTRIS) { BIH::mesh &overflow = bih.dup(); overflow.tris += BIH::mesh::MAXTRIS; overflow.numtris -= BIH::mesh::MAXTRIS; bih[bih.length()-2].numtris = BIH::mesh::MAXTRIS; } } - - virtual void setshader(Shader *s) - { + virtual void setshader(Shader *s) { s->set(); } - - template void smoothnorms(V *verts, int numverts, T *tris, int numtris, float limit, bool areaweight) - { + template void smoothnorms(V *verts, int numverts, T *tris, int numtris, float limit, bool areaweight) { hashtable share; int *next = new int[numverts]; for(int i=0;i= 0) - { + if(next[i] >= 0) { float vlimit = limit*v.norm.magnitude(); - for(int j = next[i]; j >= 0; j = next[j]) - { + for(int j = next[i]; j >= 0; j = next[j]) { V &o = verts[j]; - if(v.norm.dot(o.norm) >= vlimit*o.norm.magnitude()) - { + if(v.norm.dot(o.norm) >= vlimit*o.norm.magnitude()) { norms[i].add(o.norm); norms[j].add(v.norm); } @@ -345,12 +257,9 @@ struct animmodel : model delete[] next; delete[] norms; } - - template void buildnorms(V *verts, int numverts, T *tris, int numtris, bool areaweight) - { + template void buildnorms(V *verts, int numverts, T *tris, int numtris, bool areaweight) { loopi(numverts) verts[i].norm = vec(0, 0, 0); - loopi(numtris) - { + loopi(numtris) { T &t = tris[i]; V &v1 = verts[t.vert[0]], &v2 = verts[t.vert[1]], &v3 = verts[t.vert[2]]; vec norm; @@ -362,26 +271,19 @@ struct animmodel : model } loopi(numverts) verts[i].norm.normalize(); } - - template void buildnorms(V *verts, int numverts, T *tris, int numtris, bool areaweight, int numframes) - { + template void buildnorms(V *verts, int numverts, T *tris, int numtris, bool areaweight, int numframes) { if(!numverts) return; loopi(numframes) buildnorms(&verts[i*numverts], numverts, tris, numtris, areaweight); } - - static inline void fixqtangent(quat &q, float bt) - { + static inline void fixqtangent(quat &q, float bt) { static const float bias = -1.5f/65535, biasscale = sqrtf(1 - bias*bias); - if(bt < 0) - { + if(bt < 0) { if(q.w >= 0) q.neg(); if(q.w > bias) { q.mul3(biasscale); q.w = bias; } } else if(q.w < 0) q.neg(); } - - template static inline void calctangent(V &v, const vec &n, const vec &t, float bt) - { + template static inline void calctangent(V &v, const vec &n, const vec &t, float bt) { matrix3 m; m.c = n; m.a = t; @@ -390,18 +292,14 @@ struct animmodel : model fixqtangent(q, bt); v.tangent = q; } - - template void calctangents(B *bumpverts, V *verts, TC *tcverts, int numverts, T *tris, int numtris, bool areaweight) - { + template void calctangents(B *bumpverts, V *verts, TC *tcverts, int numverts, T *tris, int numtris, bool areaweight) { vec *tangent = new vec[2*numverts], *bitangent = tangent+numverts; for(int i=0;i<2*numverts;++i)tangent[i]=vec(0,0,0); //~memclear(tangent, 2*numverts); - loopi(numtris) - { + loopi(numtris) { const T &t = tris[i]; const vec &e0 = verts[t.vert[0]].pos; vec e1 = vec(verts[t.vert[1]].pos).sub(e0), e2 = vec(verts[t.vert[2]].pos).sub(e0); - const vec2 &tc0 = tcverts[t.vert[0]].tc, &tc1 = tcverts[t.vert[1]].tc, &tc2 = tcverts[t.vert[2]].tc; @@ -410,27 +308,20 @@ struct animmodel : model vec u(e2), v(e2); u.mul(v1).sub(vec(e1).mul(v2)); v.mul(u1).sub(vec(e1).mul(u2)); - - if(vec().cross(e2, e1).dot(vec().cross(v, u)) >= 0) - { + if(vec().cross(e2, e1).dot(vec().cross(v, u)) >= 0) { u.neg(); v.neg(); } - - if(!areaweight) - { + if(!areaweight) { u.normalize(); v.normalize(); } - - loopj(3) - { + loopj(3) { tangent[t.vert[j]].sub(u); bitangent[t.vert[j]].add(v); } } - loopi(numverts) - { + loopi(numverts) { const vec &n = verts[i].norm, &t = tangent[i], &bt = bitangent[i]; @@ -445,136 +336,97 @@ struct animmodel : model } delete[] tangent; } - - template void calctangents(B *bumpverts, V *verts, TC *tcverts, int numverts, T *tris, int numtris, bool areaweight, int numframes) - { + template void calctangents(B *bumpverts, V *verts, TC *tcverts, int numverts, T *tris, int numtris, bool areaweight, int numframes) { loopi(numframes) calctangents(&bumpverts[i*numverts], &verts[i*numverts], tcverts, numverts, tris, numtris, areaweight); } }; - - struct meshgroup - { + struct meshgroup { meshgroup *next; int shared; char *name; vector meshes; - - meshgroup() : next(NULL), shared(0), name(NULL) - { + meshgroup() : next(NULL), shared(0), name(NULL) { } - - virtual ~meshgroup() - { + virtual ~meshgroup() { DELETEA(name); meshes.deletecontents(); DELETEP(next); } - virtual int findtag(const char *name) { return -1; } virtual void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) {} - - void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) - { + void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) { loopv(meshes) meshes[i]->calcbb(bbmin, bbmax, m); } - - void genBIH(vector &skins, vector &bih, const matrix4x3 &t) - { + void genBIH(vector &skins, vector &bih, const matrix4x3 &t) { loopv(meshes) meshes[i]->genBIH(skins[i], bih, t); } - virtual void *animkey() { return this; } virtual int totalframes() const { return 1; } bool hasframe(int i) const { return i>=0 && i=0 && i+n<=totalframes(); } int clipframes(int i, int n) const { return min(n, totalframes() - i); } - virtual void cleanup() {} virtual void preload(part *p) {} virtual void render(const animstate *as, float pitch, const vec &axis, const vec &forward, dynent *d, part *p) {} - - void bindpos(GLuint ebuf, GLuint vbuf, void *v, int stride) - { - if(lastebuf!=ebuf) - { + void bindpos(GLuint ebuf, GLuint vbuf, void *v, int stride) { + if(lastebuf!=ebuf) { gle::bindebo(ebuf); lastebuf = ebuf; } - if(lastvbuf!=vbuf) - { + if(lastvbuf!=vbuf) { gle::bindvbo(vbuf); if(!lastvbuf) gle::enablevertex(); gle::vertexpointer(stride, v); lastvbuf = vbuf; } } - - void bindtc(void *v, int stride) - { - if(!enabletc) - { + void bindtc(void *v, int stride) { + if(!enabletc) { gle::enabletexcoord0(); enabletc = true; } - if(lasttcbuf!=lastvbuf) - { + if(lasttcbuf!=lastvbuf) { gle::texcoord0pointer(stride, v); lasttcbuf = lastvbuf; } } - - void bindnormals(void *v, int stride) - { - if(!enablenormals) - { + void bindnormals(void *v, int stride) { + if(!enablenormals) { gle::enablenormal(); enablenormals = true; } - if(lastnbuf!=lastvbuf) - { + if(lastnbuf!=lastvbuf) { gle::normalpointer(stride, v); lastnbuf = lastvbuf; } } - - void bindtangents(void *v, int stride) - { - if(!enabletangents) - { + void bindtangents(void *v, int stride) { + if(!enabletangents) { gle::enabletangent(); enabletangents = true; } - if(lastxbuf!=lastvbuf) - { + if(lastxbuf!=lastvbuf) { gle::tangentpointer(stride, v, GL_SHORT); lastxbuf = lastvbuf; } } - - void bindbones(void *wv, void *bv, int stride) - { - if(!enablebones) - { + void bindbones(void *wv, void *bv, int stride) { + if(!enablebones) { gle::enableboneweight(); gle::enableboneindex(); enablebones = true; } - if(lastbbuf!=lastvbuf) - { + if(lastbbuf!=lastvbuf) { gle::boneweightpointer(stride, wv); gle::boneindexpointer(stride, bv); lastbbuf = lastvbuf; } } }; - virtual meshgroup *loadmeshes(const char *name, va_list args) { return NULL; } - - meshgroup *sharemeshes(const char *name, ...) - { + meshgroup *sharemeshes(const char *name, ...) { static hashnameset meshgroups; - if(!meshgroups.access(name)) - { + if(!meshgroups.access(name)) { va_list args; va_start(args, name); meshgroup *group = loadmeshes(name, args); @@ -584,20 +436,15 @@ struct animmodel : model } return meshgroups[name]; } - - struct linkedpart - { + struct linkedpart { part *p; int tag, anim, basetime; vec translate; vec *pos; matrix4 matrix; - linkedpart() : p(NULL), tag(-1), anim(-1), basetime(0), translate(0, 0, 0), pos(NULL) {} }; - - struct part - { + struct part { animmodel *model; int index; meshgroup *meshes; @@ -607,57 +454,43 @@ struct animmodel : model int numanimparts; float pitchscale, pitchoffset, pitchmin, pitchmax; vec translate; - - part(animmodel *model, int index = 0) : model(model), index(index), meshes(NULL), numanimparts(1), pitchscale(1), pitchoffset(0), pitchmin(0), pitchmax(0), translate(0, 0, 0) - { + part(animmodel *model, int index = 0) : model(model), index(index), meshes(NULL), numanimparts(1), pitchscale(1), pitchoffset(0), pitchmin(0), pitchmax(0), translate(0, 0, 0) { loopk(MAXANIMPARTS) anims[k] = NULL; } - virtual ~part() - { + virtual ~part() { loopk(MAXANIMPARTS) DELETEA(anims[k]); } - - virtual void cleanup() - { + virtual void cleanup() { if(meshes) meshes->cleanup(); loopv(skins) skins[i].cleanup(); } - - void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) - { + void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) { matrix4x3 t = m; t.scale(model->scale); t.translate(translate); meshes->calcbb(bbmin, bbmax, t); - loopv(links) - { + loopv(links) { matrix4x3 n; meshes->concattagtransform(this, links[i].tag, m, n); n.translate(links[i].translate, model->scale); links[i].p->calcbb(bbmin, bbmax, n); } } - - void genBIH(vector &bih, const matrix4x3 &m) - { + void genBIH(vector &bih, const matrix4x3 &m) { matrix4x3 t = m; t.scale(model->scale); t.translate(translate); meshes->genBIH(skins, bih, t); - loopv(links) - { + loopv(links) { matrix4x3 n; meshes->concattagtransform(this, links[i].tag, m, n); n.translate(links[i].translate, model->scale); links[i].p->genBIH(bih, n); } } - - bool link(part *p, const char *tag, const vec &translate = vec(0, 0, 0), int anim = -1, int basetime = 0, vec *pos = NULL) - { + bool link(part *p, const char *tag, const vec &translate = vec(0, 0, 0), int anim = -1, int basetime = 0, vec *pos = NULL) { int i = meshes ? meshes->findtag(tag) : -1; - if(i<0) - { + if(i<0) { loopv(links) if(links[i].p && links[i].p->link(p, tag, translate, anim, basetime, pos)) return true; return false; } @@ -670,86 +503,62 @@ struct animmodel : model l.pos = pos; return true; } - - bool unlink(part *p) - { + bool unlink(part *p) { loopvrev(links) if(links[i].p==p) { links.remove(i, 1); return true; } loopv(links) if(links[i].p && links[i].p->unlink(p)) return true; return false; } - - void initskins(Texture *tex = notexture, Texture *masks = notexture, int limit = 0) - { - if(!limit) - { + void initskins(Texture *tex = notexture, Texture *masks = notexture, int limit = 0) { + if(!limit) { if(!meshes) return; limit = meshes->meshes.length(); } - while(skins.length() < limit) - { + while(skins.length() < limit) { skin &s = skins.add(); s.owner = this; s.tex = tex; s.masks = masks; } } - - bool tangents() - { + bool tangents() { loopv(skins) if(skins[i].tangents()) return true; return false; } - - void preloadBIH() - { + void preloadBIH() { loopv(skins) skins[i].preloadBIH(); } - - void preloadshaders(bool force) - { - loopv(skins) skins[i].preloadshader(force); + void preloadshaders() { + loopv(skins) skins[i].preloadshader(); } - - void preloadmeshes() - { + void preloadmeshes() { if(meshes) meshes->preload(this); } - - virtual void getdefaultanim(animinfo &info, int anim, uint varseed, dynent *d) - { + virtual void getdefaultanim(animinfo &info, int anim, uint varseed, dynent *d) { (void) anim; (void) varseed; (void) d; info.frame = 0; info.range = 1; } - - bool calcanim(int animpart, int anim, int basetime, int basetime2, dynent *d, int interp, animinfo &info, int &aitime) - { + bool calcanim(int animpart, int anim, int basetime, int basetime2, dynent *d, int interp, animinfo &info, int &aitime) { uint varseed = uint((size_t)d); info.anim = anim; info.basetime = basetime; info.varseed = varseed; info.speed = anim&ANIM_SETSPEED ? basetime2 : 100.0f; - if((anim&ANIM_INDEX)==ANIM_ALL) - { + if((anim&ANIM_INDEX)==ANIM_ALL) { info.frame = 0; info.range = meshes->totalframes(); } - else - { + else { animspec *spec = NULL; - if(anims[animpart]) - { + if(anims[animpart]) { int primaryidx = anim&ANIM_INDEX; - if(primaryidx < NUMANIMS) - { + if(primaryidx < NUMANIMS) { vector &primary = anims[animpart][primaryidx]; if(primary.length()) spec = &primary[uint(varseed + basetime)%primary.length()]; } - if((anim>>ANIM_SECONDARY)&(ANIM_INDEX|ANIM_DIR)) - { + if((anim>>ANIM_SECONDARY)&(ANIM_INDEX|ANIM_DIR)) { int secondaryidx = (anim>>ANIM_SECONDARY)&ANIM_INDEX; - if(secondaryidx < NUMANIMS) - { + if(secondaryidx < NUMANIMS) { vector &secondary = anims[animpart][secondaryidx]; if(secondary.length()) { @@ -764,54 +573,42 @@ struct animmodel : model } } } - if(spec) - { + if(spec) { info.frame = spec->frame; info.range = spec->range; if(spec->speed>0) info.speed = 1000.0f/spec->speed; } else getdefaultanim(info, anim, uint(varseed + info.basetime), d); } - info.anim &= (1<hasframes(info.frame, info.range)) - { + if(!meshes->hasframes(info.frame, info.range)) { if(!meshes->hasframe(info.frame)) return false; info.range = meshes->clipframes(info.frame, info.range); } - - if(d && interp>=0) - { + if(d && interp>=0) { animinterpinfo &ai = d->animinterp[interp]; if((info.anim&ANIM_CLAMP)==ANIM_CLAMP) aitime = min(aitime, int(info.range*info.speed*0.5e-3f)); void *ak = meshes->animkey(); - if(d->ragdoll && !(anim&ANIM_RAGDOLL)) - { + if(d->ragdoll && !(anim&ANIM_RAGDOLL)) { ai.prev.range = ai.cur.range = 0; ai.lastswitch = -1; } - else if(ai.lastmodel!=ak || ai.lastswitch<0 || lastmillis-d->lastrendered>aitime) - { + else if(ai.lastmodel!=ak || ai.lastswitch<0 || lastmillis-d->lastrendered>aitime) { ai.prev = ai.cur = info; ai.lastswitch = lastmillis-aitime*2; } - else if(ai.cur!=info) - { + else if(ai.cur!=info) { if(lastmillis-ai.lastswitch>aitime/2) ai.prev = ai.cur; ai.cur = info; ai.lastswitch = lastmillis; @@ -821,17 +618,12 @@ struct animmodel : model } return true; } - - void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d) - { + void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d) { animstate as[MAXANIMPARTS]; render(anim, basetime, basetime2, pitch, axis, forward, d, as); } - - void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d, animstate *as) - { - if(!(anim&ANIM_REUSE)) loopi(numanimparts) - { + void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d, animstate *as) { + if(!(anim&ANIM_REUSE)) loopi(numanimparts) { animinfo info; int interp = d && index+numanimparts<=MAXANIMPARTS ? index+i : -1, aitime = animationinterpolationtime; if(!calcanim(i, anim, basetime, basetime2, d, interp, info, aitime)) return; @@ -839,41 +631,33 @@ struct animmodel : model p.owner = this; p.cur.setframes(info); p.interp = 1; - if(interp>=0 && d->animinterp[interp].prev.range>0) - { + if(interp>=0 && d->animinterp[interp].prev.range>0) { int diff = lastmillis-d->animinterp[interp].lastswitch; - if(diffaniminterp[interp].prev); p.interp = diff/float(aitime); } } } - vec oaxis, oforward; matrixstack[matrixpos].transposedtransformnormal(axis, oaxis); float pitchamount = pitchscale*pitch + pitchoffset; if((pitchmin || pitchmax) && pitchmin <= pitchmax) pitchamount = clamp(pitchamount, pitchmin, pitchmax); if(as->cur.anim&ANIM_NOPITCH || (as->interp < 1 && as->prev.anim&ANIM_NOPITCH)) pitchamount *= (as->cur.anim&ANIM_NOPITCH ? 0 : as->interp) + (as->interp < 1 && as->prev.anim&ANIM_NOPITCH ? 0 : 1-as->interp); - if(pitchamount) - { + if(pitchamount) { ++matrixpos; matrixstack[matrixpos] = matrixstack[matrixpos-1]; matrixstack[matrixpos].rotate(pitchamount*RAD, oaxis); } matrixstack[matrixpos].transposedtransformnormal(forward, oforward); - - if(!(anim&ANIM_NORENDER)) - { + if(!(anim&ANIM_NORENDER)) { matrix4 modelmatrix; modelmatrix.mul(shadowmapping ? shadowmatrix : camprojmatrix, matrixstack[matrixpos]); if(model->scale!=1) modelmatrix.scale(model->scale); if(!translate.iszero()) modelmatrix.translate(translate); GLOBALPARAM(modelmatrix, modelmatrix); - - if(!(anim&ANIM_NOSKIN)) - { + if(!(anim&ANIM_NOSKIN)) { vec odir, ocampos; matrixstack[matrixpos].transposedtransformnormal(lightdir, odir); GLOBALPARAM(lightdir, odir); @@ -882,48 +666,33 @@ struct animmodel : model GLOBALPARAM(modelcamera, ocampos); } } - meshes->render(as, pitch, oaxis, oforward, d, this); - - if(!(anim&ANIM_REUSE)) - { - loopv(links) - { + if(!(anim&ANIM_REUSE)) { + loopv(links) { linkedpart &link = links[i]; link.matrix.translate(links[i].translate, model->scale); - matrixpos++; matrixstack[matrixpos].mul(matrixstack[matrixpos-1], link.matrix); - if(link.pos) *link.pos = matrixstack[matrixpos].gettranslation(); - - if(!link.p) - { + if(!link.p) { matrixpos--; continue; } - int nanim = anim, nbasetime = basetime, nbasetime2 = basetime2; - if(link.anim>=0) - { + if(link.anim>=0) { nanim = link.anim | (anim&ANIM_FLAGS); nbasetime = link.basetime; nbasetime2 = 0; } link.p->render(nanim, nbasetime, nbasetime2, pitch, axis, forward, d); - matrixpos--; } } - if(pitchamount) matrixpos--; } - - void setanim(int animpart, int num, int frame, int range, float speed, int priority = 0) - { + void setanim(int animpart, int num, int frame, int range, float speed, int priority = 0) { if(animpart<0 || animpart>=MAXANIMPARTS) return; - if(frame<0 || range<=0 || !meshes || !meshes->hasframes(frame, range)) - { + if(frame<0 || range<=0 || !meshes || !meshes->hasframes(frame, range)) { conoutf(CON_ERROR, "invalid frame %d, range %d in model %s", frame, range, model->name); return; } @@ -934,99 +703,73 @@ struct animmodel : model spec.speed = speed; spec.priority = priority; } - - virtual void loaded() - { + virtual void loaded() { meshes->shared++; loopv(skins) skins[i].setkey(); } }; - - enum - { + enum { LINK_TAG = 0, LINK_COOP, LINK_REUSE }; - virtual int linktype(animmodel *m) const { (void) m; return LINK_TAG; } - - void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d, modelattach *a) - { + void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d, modelattach *a) { int numtags = 0; - if(a) - { + if(a) { int index = parts.last()->index + parts.last()->numanimparts; - for(int i = 0; a[i].tag; i++) - { + for(int i = 0; a[i].tag; i++) { numtags++; - animmodel *m = (animmodel *)a[i].m; - if(!m) - { + if(!m) { if(a[i].pos) link(NULL, a[i].tag, vec(0, 0, 0), 0, 0, a[i].pos); continue; } part *p = m->parts[0]; - switch(linktype(m)) - { + switch(linktype(m)) { case LINK_TAG: p->index = link(p, a[i].tag, vec(0, 0, 0), a[i].anim, a[i].basetime, a[i].pos) ? index : -1; break; - case LINK_COOP: p->index = index; break; - default: continue; } index += p->numanimparts; } } - animstate as[MAXANIMPARTS]; parts[0]->render(anim, basetime, basetime2, pitch, axis, forward, d, as); - - if(a) for(int i = numtags-1; i >= 0; i--) - { + if(a) for(int i = numtags-1; i >= 0; i--) { animmodel *m = (animmodel *)a[i].m; - if(!m) - { + if(!m) { if(a[i].pos) unlink(NULL); continue; } part *p = m->parts[0]; - switch(linktype(m)) - { + switch(linktype(m)) { case LINK_TAG: if(p->index >= 0) unlink(p); p->index = 0; break; - case LINK_COOP: p->render(anim, basetime, basetime2, pitch, axis, forward, d); p->index = 0; break; - case LINK_REUSE: p->render(anim | ANIM_REUSE, basetime, basetime2, pitch, axis, forward, d, as); break; } } } - - void render(int anim, int basetime, int basetime2, const vec &o, float yaw, float pitch, dynent *d, modelattach *a, const vec &color, const vec &dir, float trans) - { + void render(int anim, int basetime, int basetime2, const vec &o, float yaw, float pitch, dynent *d, modelattach *a, const vec &color, const vec &dir, float trans) { yaw += spinyaw*lastmillis/1000.0f; pitch += offsetpitch + spinpitch*lastmillis/1000.0f; - vec axis(0, -1, 0), forward(1, 0, 0); - matrixpos = 0; matrixstack[0].identity(); - if(!d || !d->ragdoll || anim&ANIM_RAGDOLL) - { + if(!d || !d->ragdoll || anim&ANIM_RAGDOLL) { matrixstack[0].settranslation(o); matrixstack[0].rotate_around_z(yaw*RAD); matrixstack[0].transformnormal(vec(axis), axis); @@ -1034,138 +777,96 @@ struct animmodel : model if(offsetyaw) matrixstack[0].rotate_around_z(offsetyaw*RAD); } else pitch = 0; - - if(anim&ANIM_NORENDER) - { + if(anim&ANIM_NORENDER) { render(anim, basetime, basetime2, pitch, axis, forward, d, a); if(d) d->lastrendered = lastmillis; return; } - - if(!(anim&ANIM_NOSKIN)) - { + if(!(anim&ANIM_NOSKIN)) { transparent = trans; lightdir = dir; lightcolor = color; } - - if(depthoffset && !enabledepthoffset) - { + if(depthoffset && !enabledepthoffset) { enablepolygonoffset(GL_POLYGON_OFFSET_FILL); enabledepthoffset = true; } - - if(transparent<1) - { - if(anim&ANIM_GHOST) - { + if(transparent<1) { + if(anim&ANIM_GHOST) { glDepthFunc(GL_GREATER); glDepthMask(GL_FALSE); } - else if(alphadepth) - { + else if(alphadepth) { glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); render(anim|ANIM_NOSKIN, basetime, basetime2, pitch, axis, forward, d, a); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDepthFunc(GL_LEQUAL); } - - if(!enablealphablend) - { + if(!enablealphablend) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); enablealphablend = true; } } - render(anim, basetime, basetime2, pitch, axis, forward, d, a); - - if(transparent<1 && (alphadepth || anim&ANIM_GHOST)) - { + if(transparent<1 && (alphadepth || anim&ANIM_GHOST)) { glDepthFunc(GL_LESS); if(anim&ANIM_GHOST) glDepthMask(GL_TRUE); } - if(d) d->lastrendered = lastmillis; } - vector parts; - - animmodel(const char *name) : model(name) - { + animmodel(const char *name) : model(name) { } - - ~animmodel() - { + ~animmodel() { parts.deletecontents(); } - - void cleanup() - { + void cleanup() { loopv(parts) parts[i]->cleanup(); } - virtual void flushpart() {} - - part &addpart() - { + part &addpart() { flushpart(); part *p = new part(this, parts.length()); parts.add(p); return *p; } - - void initmatrix(matrix4x3 &m) - { + void initmatrix(matrix4x3 &m) { m.identity(); if(offsetyaw) m.rotate_around_z(offsetyaw*RAD); if(offsetpitch) m.rotate_around_y(-offsetpitch*RAD); } - - void genBIH(vector &bih) - { + void genBIH(vector &bih) { if(parts.empty()) return; matrix4x3 m; initmatrix(m); parts[0]->genBIH(bih, m); } - - void preloadBIH() - { + void preloadBIH() { model::preloadBIH(); if(bih) loopv(parts) parts[i]->preloadBIH(); } - - BIH *setBIH() - { + BIH *setBIH() { if(bih) return bih; vector meshes; genBIH(meshes); bih = new BIH(meshes); return bih; } - - bool link(part *p, const char *tag, const vec &translate = vec(0, 0, 0), int anim = -1, int basetime = 0, vec *pos = NULL) - { + bool link(part *p, const char *tag, const vec &translate = vec(0, 0, 0), int anim = -1, int basetime = 0, vec *pos = NULL) { if(parts.empty()) return false; return parts[0]->link(p, tag, translate, anim, basetime, pos); } - - bool unlink(part *p) - { + bool unlink(part *p) { if(parts.empty()) return false; return parts[0]->unlink(p); } - virtual bool flipy() const { return false; } virtual bool loadconfig() { return false; } virtual bool loaddefaultparts() { return false; } virtual void startload() {} virtual void endload() {} - - bool load() - { + bool load() { startload(); bool success = loadconfig() && parts.length(); // configured model, will call the model commands below if(!success) @@ -1173,68 +874,46 @@ struct animmodel : model flushpart(); endload(); if(flipy()) translate.y = -translate.y; - if(!success) return false; loopv(parts) if(!parts[i]->meshes) return false; - loaded(); return true; } - - void preloadshaders(bool force) - { - loopv(parts) parts[i]->preloadshaders(force); + void preloadshaders() { + loopv(parts) parts[i]->preloadshaders(); } - - void preloadmeshes() - { + void preloadmeshes() { loopv(parts) parts[i]->preloadmeshes(); } - - void setshader(Shader *shader) - { + void setshader(Shader *shader) { if(parts.empty()) loaddefaultparts(); loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].shader = shader; } - - void setspec(float spec) - { + void setspec(float spec) { if(parts.empty()) loaddefaultparts(); loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].spec = spec; } - - void setambient(float ambient) - { + void setambient(float ambient) { if(parts.empty()) loaddefaultparts(); loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].ambient = ambient; } - - void setalphatest(float alphatest) - { + void setalphatest(float alphatest) { if(parts.empty()) loaddefaultparts(); loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].alphatest = alphatest; } - - void setalphablend(bool alphablend) - { + void setalphablend(bool alphablend) { if(parts.empty()) loaddefaultparts(); loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].alphablend = alphablend; } - - void setfullbright(float fullbright) - { + void setfullbright(float fullbright) { if(parts.empty()) loaddefaultparts(); loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].fullbright = fullbright; } - - void setcullface(bool cullface) - { + void setcullface(bool cullface) { if(parts.empty()) loaddefaultparts(); loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].cullface = cullface; } - - void calcbb(vec ¢er, vec &radius) - { + void calcbb(vec ¢er, vec &radius) { if(parts.empty()) return; vec bbmin(1e16f, 1e16f, 1e16f), bbmax(-1e16f, -1e16f, -1e16f); matrix4x3 m; @@ -1246,14 +925,11 @@ struct animmodel : model center = bbmin; center.add(radius); } - - virtual void loaded() - { + virtual void loaded() { scale /= 4; if(parts.length()) parts[0]->translate = translate; loopv(parts) parts[i]->loaded(); } - static bool enabletc, enablealphablend, enablecullface, enablenormals, enabletangents, enablebones, enabledepthoffset; static vec lightdir, lightcolor; static float transparent, lastalphatest; @@ -1261,9 +937,7 @@ struct animmodel : model static Texture *lasttex, *lastmasks, *lastnormalmap; static int matrixpos; static matrix4 matrixstack[64]; - - void startrender() - { + void startrender() { enabletc = enablealphablend = enablenormals = enabletangents = enablebones = enabledepthoffset = false; enablecullface = true; lastalphatest = -1; @@ -1272,37 +946,26 @@ struct animmodel : model transparent = 1; shaderparamskey::invalidate(); } - - static void disablebones() - { + static void disablebones() { gle::disableboneweight(); gle::disableboneindex(); enablebones = false; } - - static void disabletangents() - { + static void disabletangents() { gle::disabletangent(); enabletangents = false; } - - static void disabletc() - { + static void disabletc() { gle::disabletexcoord0(); enabletc = false; } - - static void disablenormals() - { + static void disablenormals() { gle::disablenormal(); enablenormals = false; } - - static void disablevbo() - { + static void disablevbo() { if(lastebuf) gle::clearebo(); - if(lastvbuf) - { + if(lastvbuf) { gle::clearvbo(); gle::disablevertex(); } @@ -1312,9 +975,7 @@ struct animmodel : model if(enablebones) disablebones(); lastvbuf = lasttcbuf = lastxbuf = lastnbuf = lastbbuf = lastebuf = 0; } - - void endrender() - { + void endrender() { if(lastvbuf || lastebuf) disablevbo(); if(enablealphablend) glDisable(GL_BLEND); if(!enablecullface) glEnable(GL_CULL_FACE); @@ -1333,45 +994,33 @@ Texture *animmodel::lasttex = NULL, *animmodel::lastmasks = NULL, *animmodel::la int animmodel::matrixpos = 0; matrix4 animmodel::matrixstack[64]; -static inline uint hthash(const animmodel::shaderparams &k) -{ +static inline uint hthash(const animmodel::shaderparams &k) { return memhash(&k, sizeof(k)); } -static inline bool htcmp(const animmodel::shaderparams &x, const animmodel::shaderparams &y) -{ +static inline bool htcmp(const animmodel::shaderparams &x, const animmodel::shaderparams &y) { return !memcmp(&x, &y, sizeof(animmodel::shaderparams)); } hashtable animmodel::shaderparamskey::keys; int animmodel::shaderparamskey::firstversion = 0, animmodel::shaderparamskey::lastversion = 1; -template struct modelloader : BASE -{ +template struct modelloader : BASE { static MDL *loading; static string dir; - modelloader(const char *name) : BASE(name) {} - static bool animated() { return true; } static bool multiparted() { return true; } static bool multimeshed() { return true; } - - void startload() - { + void startload() { loading = (MDL *)this; } - - void endload() - { + void endload() { loading = NULL; } - - bool loadconfig() - { + bool loadconfig() { formatstring(dir, "packages/models/%s", BASE::name); defformatstring(cfgname, "packages/models/%s/%s.cfg", BASE::name, MDL::formatname()); - identflags &= ~IDF_PERSIST; bool success = execfile(cfgname, false); identflags |= IDF_PERSIST; @@ -1382,118 +1031,84 @@ template struct modelloader : BASE template MDL *modelloader::loading = NULL; template string modelloader::dir = {'\0'}; // crashes clang if "" is used here -template struct modelcommands -{ +template struct modelcommands { typedef struct MDL::part part; typedef struct MDL::skin skin; - - static void setdir(char *name) - { + static void setdir(char *name) { if(!MDL::loading) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } formatstring(MDL::dir, "packages/models/%s", name); } - #define loopmeshes(meshname, m, body) \ if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } \ part &mdl = *MDL::loading->parts.last(); \ if(!mdl.meshes) return; \ - loopv(mdl.meshes->meshes) \ - { \ + loopv(mdl.meshes->meshes) { \ + \ MESH &m = *(MESH *)mdl.meshes->meshes[i]; \ - if(!strcmp(meshname, "*") || (m.name && !strcmp(m.name, meshname))) \ - { \ + if(!strcmp(meshname, "*") || (m.name && !strcmp(m.name, meshname))) { \ + \ body; \ } \ } - #define loopskins(meshname, s, body) loopmeshes(meshname, m, { skin &s = mdl.skins[i]; body; }) - - static void setskin(char *meshname, char *tex, char *masks, float *envmapmax, float *envmapmin) - {(void)envmapmax;(void)envmapmin; + static void setskin(char *meshname, char *tex, char *masks, float *envmapmax, float *envmapmin) { + (void)envmapmax;(void)envmapmin; loopskins(meshname, s, s.tex = textureload(makerelpath(MDL::dir, tex), 0, true, false); - if(*masks) - { + if(*masks) { s.masks = textureload(makerelpath(MDL::dir, masks), 0, true, false); } ); } - - static void setspec(char *meshname, int *percent) - { + static void setspec(char *meshname, int *percent) { float spec = 1.0f; if(*percent>0) spec = *percent/100.0f; else if(*percent<0) spec = 0.0f; loopskins(meshname, s, s.spec = spec); } - - static void setambient(char *meshname, int *percent) - { + static void setambient(char *meshname, int *percent) { float ambient = 0.3f; if(*percent>0) ambient = *percent/100.0f; else if(*percent<0) ambient = 0.0f; loopskins(meshname, s, s.ambient = ambient); } - - static void setalphatest(char *meshname, float *cutoff) - { + static void setalphatest(char *meshname, float *cutoff) { loopskins(meshname, s, s.alphatest = max(0.0f, min(1.0f, *cutoff))); } - - static void setalphablend(char *meshname, int *blend) - { + static void setalphablend(char *meshname, int *blend) { loopskins(meshname, s, s.alphablend = *blend!=0); } - - static void setcullface(char *meshname, int *cullface) - { + static void setcullface(char *meshname, int *cullface) { loopskins(meshname, s, s.cullface = *cullface!=0); } - - static void setbumpmap(char *meshname, char *normalmapfile) - { + static void setbumpmap(char *meshname, char *normalmapfile) { Texture *normalmaptex = textureload(makerelpath(MDL::dir, normalmapfile), 0, true, false); loopskins(meshname, s, s.normalmap = normalmaptex); } - - static void setfullbright(char *meshname, float *fullbright) - { + static void setfullbright(char *meshname, float *fullbright) { loopskins(meshname, s, s.fullbright = *fullbright); } - - static void setshader(char *meshname, char *shader) - { + static void setshader(char *meshname, char *shader) { loopskins(meshname, s, s.shader = lookupshaderbyname(shader)); } - - static void setscroll(char *meshname, float *scrollu, float *scrollv) - { + static void setscroll(char *meshname, float *scrollu, float *scrollv) { loopskins(meshname, s, { s.scrollu = *scrollu; s.scrollv = *scrollv; }); } - - static void setnoclip(char *meshname, int *noclip) - { + static void setnoclip(char *meshname, int *noclip) { loopmeshes(meshname, m, m.noclip = *noclip!=0); } - - static void setlink(int *parent, int *child, char *tagname, float *x, float *y, float *z) - { + static void setlink(int *parent, int *child, char *tagname, float *x, float *y, float *z) { if(!MDL::loading) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } if(!MDL::loading->parts.inrange(*parent) || !MDL::loading->parts.inrange(*child)) { conoutf(CON_ERROR, "no models loaded to link"); return; } if(!MDL::loading->parts[*parent]->link(MDL::loading->parts[*child], tagname, vec(*x, *y, *z))) conoutf(CON_ERROR, "could not link model %s", MDL::loading->name); } - - template void modelcommand(F *fun, const char *suffix, const char *args) - { + template void modelcommand(F *fun, const char *suffix, const char *args) { defformatstring(name, "%s%s", MDL::formatname(), suffix); addcommand(newstring(name), (void (*)())fun, args); } - - modelcommands() - { + modelcommands() { modelcommand(setdir, "dir", "s"); - if(MDL::multimeshed()) - { + if(MDL::multimeshed()) { modelcommand(setskin, "skin", "sssff"); modelcommand(setspec, "spec", "si"); modelcommand(setambient, "ambient", "si"); diff --git a/src/engine/bih.cpp b/src/engine/bih.cpp index c983805..e406008 100644 --- a/src/engine/bih.cpp +++ b/src/engine/bih.cpp @@ -1,13 +1,11 @@ #include "engine.h" -bool BIH::triintersect(const mesh &m, int tidx, const vec &mo, const vec &mray, float maxdist, float &dist, int mode) -{ +bool BIH::triintersect(const mesh &m, int tidx, const vec &mo, const vec &mray, float maxdist, float &dist, int mode) { const tri &t = m.tris[tidx]; vec a = m.getpos(t.vert[0]), b = m.getpos(t.vert[1]).sub(a), c = m.getpos(t.vert[2]).sub(a), n = vec().cross(b, c), r = vec(a).sub(mo), e = vec().cross(r, mray); float det = mray.dot(n), v, w, f; - if(det >= 0) - { + if(det >= 0) { if(!(mode&RAY_SHADOW) && m.flags&MESH_CULLFACE) return false; v = e.dot(c); if(v < 0 || v > det) return false; @@ -16,8 +14,7 @@ bool BIH::triintersect(const mesh &m, int tidx, const vec &mo, const vec &mray, f = r.dot(n)*m.scale; if(f < 0 || f > maxdist*det || !det) return false; } - else - { + else { v = e.dot(c); if(v > 0 || v < det) return false; w = -e.dot(b); @@ -26,8 +23,7 @@ bool BIH::triintersect(const mesh &m, int tidx, const vec &mo, const vec &mray, if(f > 0 || f < maxdist*det) return false; } float invdet = 1/det; - if(m.flags&MESH_ALPHA && (mode&RAY_ALPHAPOLY)==RAY_ALPHAPOLY && (m.tex->alphamask || (lightmapping <= 1 && loadalphamask(m.tex)))) - { + if(m.flags&MESH_ALPHA && (mode&RAY_ALPHAPOLY)==RAY_ALPHAPOLY && (m.tex->alphamask || (lightmapping <= 1 && loadalphamask(m.tex)))) { vec2 at = m.gettc(t.vert[0]), bt = m.gettc(t.vert[1]).sub(at).mul(v*invdet), ct = m.gettc(t.vert[2]).sub(at).mul(w*invdet); at.add(bt).add(ct); int si = clamp(int(m.tex->xs * at.x), 0, m.tex->xs-1), @@ -38,31 +34,24 @@ bool BIH::triintersect(const mesh &m, int tidx, const vec &mo, const vec &mray, return true; } -struct traversestate -{ +struct traversestate { BIH::node *node; float tmin, tmax; }; -inline bool BIH::traverse(const mesh &m, const vec &o, const vec &ray, const vec &invray, float maxdist, float &dist, int mode, node *curnode, float tmin, float tmax) -{ +inline bool BIH::traverse(const mesh &m, const vec &o, const vec &ray, const vec &invray, float maxdist, float &dist, int mode, node *curnode, float tmin, float tmax) { traversestate stack[128]; int stacksize = 0; ivec order(ray.x>0 ? 0 : 1, ray.y>0 ? 0 : 1, ray.z>0 ? 0 : 1); vec mo = m.invxform.transform(o), mray = m.invxformnorm.transform(ray); - for(;;) - { + for(;;) { int axis = curnode->axis(); int nearidx = order[axis], faridx = nearidx^1; float nearsplit = (curnode->split[nearidx] - o[axis])*invray[axis], farsplit = (curnode->split[faridx] - o[axis])*invray[axis]; - - if(nearsplit <= tmin) - { - if(farsplit < tmax) - { - if(!curnode->isleaf(faridx)) - { + if(nearsplit <= tmin) { + if(farsplit < tmax) { + if(!curnode->isleaf(faridx)) { curnode += curnode->childindex(faridx); tmin = max(tmin, farsplit); continue; @@ -70,13 +59,10 @@ inline bool BIH::traverse(const mesh &m, const vec &o, const vec &ray, const vec else if(triintersect(m, curnode->childindex(faridx), mo, mray, maxdist, dist, mode)) return true; } } - else if(curnode->isleaf(nearidx)) - { + else if(curnode->isleaf(nearidx)) { if(triintersect(m, curnode->childindex(nearidx), mo, mray, maxdist, dist, mode)) return true; - if(farsplit < tmax) - { - if(!curnode->isleaf(faridx)) - { + if(farsplit < tmax) { + if(!curnode->isleaf(faridx)) { curnode += curnode->childindex(faridx); tmin = max(tmin, farsplit); continue; @@ -84,21 +70,16 @@ inline bool BIH::traverse(const mesh &m, const vec &o, const vec &ray, const vec else if(triintersect(m, curnode->childindex(faridx), mo, mray, maxdist, dist, mode)) return true; } } - else - { - if(farsplit < tmax) - { - if(!curnode->isleaf(faridx)) - { - if(stacksize < int(sizeof(stack)/sizeof(stack[0]))) - { + else { + if(farsplit < tmax) { + if(!curnode->isleaf(faridx)) { + if(stacksize < int(sizeof(stack)/sizeof(stack[0]))) { traversestate &save = stack[stacksize++]; save.node = curnode + curnode->childindex(faridx); save.tmin = max(tmin, farsplit); save.tmax = tmax; } - else - { + else { if(traverse(m, o, ray, invray, maxdist, dist, mode, curnode + curnode->childindex(nearidx), tmin, min(tmax, nearsplit))) return true; curnode += curnode->childindex(faridx); tmin = max(tmin, farsplit); @@ -119,11 +100,9 @@ inline bool BIH::traverse(const mesh &m, const vec &o, const vec &ray, const vec } } -inline bool BIH::traverse(const vec &o, const vec &ray, float maxdist, float &dist, int mode) -{ +inline bool BIH::traverse(const vec &o, const vec &ray, float maxdist, float &dist, int mode) { vec invray(ray.x ? 1/ray.x : 1e16f, ray.y ? 1/ray.y : 1e16f, ray.z ? 1/ray.z : 1e16f); - loopi(nummeshes) - { + loopi(nummeshes) { mesh &m = meshes[i]; if(!(mode&RAY_SHADOW) && m.flags&MESH_NOCLIP) continue; float t1 = (m.bbmin.x - o.x)*invray.x, @@ -142,34 +121,28 @@ inline bool BIH::traverse(const vec &o, const vec &ray, float maxdist, float &di return false; } -void BIH::build(mesh &m, ushort *indices, int numindices, const ivec &vmin, const ivec &vmax) -{ +void BIH::build(mesh &m, ushort *indices, int numindices, const ivec &vmin, const ivec &vmax) { int axis = 2; loopk(2) if(vmax[k] - vmin[k] > vmax[axis] - vmin[axis]) axis = k; - ivec leftmin, leftmax, rightmin, rightmax; int splitleft, splitright; int left, right; - loopk(3) - { + loopk(3) { leftmin = rightmin = ivec(INT_MAX, INT_MAX, INT_MAX); leftmax = rightmax = ivec(INT_MIN, INT_MIN, INT_MIN); int split = (vmax[axis] + vmin[axis])/2; - for(left = 0, right = numindices, splitleft = SHRT_MIN, splitright = SHRT_MAX; left < right;) - { + for(left = 0, right = numindices, splitleft = SHRT_MIN, splitright = SHRT_MAX; left < right;) { const tribb &tri = m.tribbs[indices[left]]; ivec trimin = ivec(tri.center).sub(ivec(tri.radius)), trimax = ivec(tri.center).add(ivec(tri.radius)); int amin = trimin[axis], amax = trimax[axis]; - if(max(split - amin, 0) > max(amax - split, 0)) - { + if(max(split - amin, 0) > max(amax - split, 0)) { ++left; splitleft = max(splitleft, amax); leftmin.min(trimin); leftmax.max(trimax); } - else - { + else { --right; swap(indices[left], indices[right]); splitright = min(splitright, amin); @@ -180,68 +153,55 @@ void BIH::build(mesh &m, ushort *indices, int numindices, const ivec &vmin, cons if(left > 0 && right < numindices) break; axis = (axis+1)%3; } - - if(!left || right==numindices) - { + if(!left || right==numindices) { leftmin = rightmin = ivec(INT_MAX, INT_MAX, INT_MAX); leftmax = rightmax = ivec(INT_MIN, INT_MIN, INT_MIN); left = right = numindices/2; splitleft = SHRT_MIN; splitright = SHRT_MAX; - loopi(numindices) - { + loopi(numindices) { const tribb &tri = m.tribbs[indices[i]]; ivec trimin = ivec(tri.center).sub(ivec(tri.radius)), trimax = ivec(tri.center).add(ivec(tri.radius)); - if(i < left) - { + if(i < left) { splitleft = max(splitleft, trimax[axis]); leftmin.min(trimin); leftmax.max(trimax); } - else - { + else { splitright = min(splitright, trimin[axis]); rightmin.min(trimin); rightmax.max(trimax); } } } - int offset = m.numnodes++; node &curnode = m.nodes[offset]; curnode.split[0] = short(splitleft); curnode.split[1] = short(splitright); - if(left==1) curnode.child[0] = (axis<<14) | indices[0]; - else - { + else { curnode.child[0] = (axis<<14) | (m.numnodes - offset); build(m, indices, left, leftmin, leftmax); } - if(numindices-right==1) curnode.child[1] = (1<<15) | (left==1 ? 1<<14 : 0) | indices[right]; - else - { + else { curnode.child[1] = (left==1 ? 1<<14 : 0) | (m.numnodes - offset); build(m, &indices[right], numindices-right, rightmin, rightmax); } } BIH::BIH(vector &buildmeshes) - : meshes(NULL), nummeshes(0), nodes(NULL), numnodes(0), tribbs(NULL), numtris(0), bbmin(1e16f, 1e16f, 1e16f), bbmax(-1e16f, -1e16f, -1e16f), center(0, 0, 0), radius(0), entradius(0) -{ + : meshes(NULL), nummeshes(0), nodes(NULL), numnodes(0), tribbs(NULL), numtris(0), bbmin(1e16f, 1e16f, 1e16f), bbmax(-1e16f, -1e16f, -1e16f), center(0, 0, 0), radius(0), entradius(0) { if(buildmeshes.empty()) return; loopv(buildmeshes) numtris += buildmeshes[i].numtris; if(!numtris) return; - nummeshes = buildmeshes.length(); meshes = new mesh[nummeshes]; memcpy(meshes, buildmeshes.getbuf(), sizeof(mesh)*buildmeshes.length()); tribbs = new tribb[numtris]; tribb *dsttri = tribbs; - loopi(nummeshes) - { + loopi(nummeshes) { mesh &m = meshes[i]; m.scale = m.xform.a.magnitude(); m.invscale = 1/m.scale; @@ -253,8 +213,7 @@ BIH::BIH(vector &buildmeshes) m.tribbs = dsttri; const tri *srctri = m.tris; vec mmin(1e16f, 1e16f, 1e16f), mmax(-1e16f, -1e16f, -1e16f); - loopj(m.numtris) - { + loopj(m.numtris) { vec s0 = m.getpos(srctri->vert[0]), s1 = m.getpos(srctri->vert[1]), s2 = m.getpos(srctri->vert[2]), v0 = m.xform.transform(s0), v1 = m.xform.transform(s1), v2 = m.xform.transform(s2), vmin = vec(v0).min(v1).min(v2), @@ -267,8 +226,7 @@ BIH::BIH(vector &buildmeshes) ++srctri; ++dsttri; } - loopk(3) if(fabs(mmax[k] - mmin[k]) < 0.125f) - { + loopk(3) if(fabs(mmax[k] - mmin[k]) < 0.125f) { float mid = (mmin[k] + mmax[k]) / 2; mmin[k] = mid - 0.0625f; mmax[k] = mid + 0.0625f; @@ -278,16 +236,13 @@ BIH::BIH(vector &buildmeshes) bbmin.min(mmin); bbmax.max(mmax); } - center = vec(bbmin).add(bbmax).mul(0.5f); radius = vec(bbmax).sub(bbmin).mul(0.5f).magnitude(); entradius = max(bbmin.squaredlen(), bbmax.squaredlen()); - nodes = new node[numtris]; node *curnode = nodes; ushort *indices = new ushort[numtris]; - loopi(nummeshes) - { + loopi(nummeshes) { mesh &m = meshes[i]; m.nodes = curnode; loopj(m.numtris) indices[j] = j; @@ -298,19 +253,16 @@ BIH::BIH(vector &buildmeshes) numnodes = int(curnode - nodes); } -BIH::~BIH() -{ +BIH::~BIH() { delete[] meshes; delete[] nodes; delete[] tribbs; } -bool mmintersect(const extentity &e, const vec &o, const vec &ray, float maxdist, int mode, float &dist) -{ +bool mmintersect(const extentity &e, const vec &o, const vec &ray, float maxdist, int mode, float &dist) { model *m = loadmapmodel(e.attr2); if(!m) return false; - if(mode&RAY_SHADOW) - { + if(mode&RAY_SHADOW) { if(!m->shadow || e.flags&EF_NOSHADOW) return false; } else if((mode&RAY_ENTS)!=RAY_ENTS && (!m->collide || e.flags&EF_NOCOLLIDE)) return false; @@ -319,8 +271,7 @@ bool mmintersect(const extentity &e, const vec &o, const vec &ray, float maxdist float v = mo.dot(mray), inside = m->bih->entradius - mo.squaredlen(); if((inside < 0 && v > 0) || inside + v*v < 0) return false; int yaw = e.attr1; - if(yaw != 0) - { + if(yaw != 0) { const vec2 &rot = sincosmod360(-yaw); mo.rotate_around_z(rot); mray.rotate_around_z(rot); diff --git a/src/engine/bih.h b/src/engine/bih.h index 16da278..ac49c66 100644 --- a/src/engine/bih.h +++ b/src/engine/bih.h @@ -1,38 +1,25 @@ -struct BIH -{ - struct node - { +struct BIH { + struct node { short split[2]; ushort child[2]; - int axis() const { return child[0]>>14; } int childindex(int which) const { return child[which]&0x3FFF; } bool isleaf(int which) const { return (child[1]&(1<<(14+which)))!=0; } }; - - struct tri - { + struct tri { ushort vert[3]; }; - - struct tribb - { + struct tribb { svec center, radius; - - bool outside(const ivec &bo, const ivec &br) const - { + bool outside(const ivec &bo, const ivec &br) const { return abs(bo.x - center.x) > br.x + radius.x || abs(bo.y - center.y) > br.y + radius.y || abs(bo.z - center.z) > br.z + radius.z; } }; - enum { MESH_NOCLIP = 1<<0, MESH_ALPHA = 1<<1, MESH_CULLFACE = 1<<2 }; - - struct mesh - { + struct mesh { enum { MAXTRIS = 1<<14 }; - matrix4x3 xform, invxform; matrix3 xformnorm, invxformnorm; float scale, invscale; @@ -46,13 +33,10 @@ struct BIH Texture *tex; int flags; vec bbmin, bbmax; - mesh() : numnodes(0), numtris(0), tex(NULL), flags(0) {} - vec getpos(int i) const { return *(const vec *)(pos + i*posstride); } vec2 gettc(int i) const { return *(const vec2 *)(tc + i*tcstride); } }; - mesh *meshes; int nummeshes; node *nodes; @@ -61,17 +45,12 @@ struct BIH int numtris; vec bbmin, bbmax, center; float radius, entradius; - BIH(vector &buildmeshes); - ~BIH(); - void build(mesh &m, ushort *indices, int numindices, const ivec &vmin, const ivec &vmax); - bool traverse(const vec &o, const vec &ray, float maxdist, float &dist, int mode); bool traverse(const mesh &m, const vec &o, const vec &ray, const vec &invray, float maxdist, float &dist, int mode, node *curnode, float tmin, float tmax); bool triintersect(const mesh &m, int tidx, const vec &mo, const vec &mray, float maxdist, float &dist, int mode); - void preload(); }; diff --git a/src/engine/client.cpp b/src/engine/client.cpp index bd46b24..6ae6c27 100644 --- a/src/engine/client.cpp +++ b/src/engine/client.cpp @@ -6,15 +6,13 @@ ENetHost *clienthost = NULL; ENetPeer *curpeer = NULL, *connpeer = NULL; int connmillis = 0, connattempts = 0, discmillis = 0; -bool multiplayer(bool msg) -{ +bool multiplayer(bool msg) { bool val = curpeer || hasnonlocalclients(); if(val && msg) conoutf(CON_ERROR, "operation not available in multiplayer"); return val; } -void setrate(int rate) -{ +void setrate(int rate) { if(!curpeer) return; enet_host_bandwidth_limit(clienthost, rate*1024, rate*1024); } @@ -27,40 +25,34 @@ VARF(throttle_interval, 0, 5, 30, throttle()); VARF(throttle_accel, 0, 2, 32, throttle()); VARF(throttle_decel, 0, 2, 32, throttle()); -void throttle() -{ +void throttle() { if(!curpeer) return; ASSERT(ENET_PEER_PACKET_THROTTLE_SCALE==32); enet_peer_throttle_configure(curpeer, throttle_interval*1000, throttle_accel, throttle_decel); } -bool isconnected(bool attempt, bool local) -{ +bool isconnected(bool attempt, bool local) { return curpeer || (attempt && connpeer) || (local && haslocalclients()); } ICOMMAND(isconnected, "bb", (int *attempt, int *local), intret(isconnected(*attempt > 0, *local != 0) ? 1 : 0)); -const ENetAddress *connectedpeer() -{ +const ENetAddress *connectedpeer() { return curpeer ? &curpeer->address : NULL; } -ICOMMAND(connectedip, "", (), -{ +ICOMMAND(connectedip, "", (), { const ENetAddress *address = connectedpeer(); string hostname; result(address && enet_address_get_host_ip(address, hostname, sizeof(hostname)) >= 0 ? hostname : ""); }); -ICOMMAND(connectedport, "", (), -{ +ICOMMAND(connectedport, "", (), { const ENetAddress *address = connectedpeer(); intret(address ? address->port : -1); }); -void abortconnect() -{ +void abortconnect() { if(!connpeer) return; game::connectfail(); if(connpeer->state!=ENET_PEER_STATE_DISCONNECTED) enet_peer_reset(connpeer); @@ -73,81 +65,61 @@ void abortconnect() SVARP(connectname, ""); VARP(connectport, 0, 0, 0xFFFF); -void connectserv(const char *servername, int serverport, const char *serverpassword) -{ - if(connpeer) - { +void connectserv(const char *servername, int serverport, const char *serverpassword) { + if(connpeer) { conoutf("aborting connection attempt"); abortconnect(); } - if(serverport <= 0) serverport = server::serverport(); - ENetAddress address; address.port = serverport; - - if(servername) - { + if(servername) { if(strcmp(servername, connectname)) setsvar("connectname", servername); if(serverport != connectport) setvar("connectport", serverport); addserver(servername, serverport, serverpassword && serverpassword[0] ? serverpassword : NULL); conoutf("attempting to connect to %s:%d", servername, serverport); - if(!resolverwait(servername, &address)) - { + if(!resolverwait(servername, &address)) { conoutf(CON_ERROR, "\f3could not resolve server %s", servername); return; } } - else - { + else { setsvar("connectname", ""); setvar("connectport", 0); conoutf("attempting to connect over LAN"); address.host = ENET_HOST_BROADCAST; } - - if(!clienthost) - { + if(!clienthost) { clienthost = enet_host_create(NULL, 2, server::numchannels(), rate*1024, rate*1024); - if(!clienthost) - { + if(!clienthost) { conoutf(CON_ERROR, "\f3could not connect to server"); return; } clienthost->duplicatePeers = 0; } - connpeer = enet_host_connect(clienthost, &address, server::numchannels(), 0); enet_host_flush(clienthost); connmillis = totalmillis; connattempts = 0; - game::connectattempt(servername ? servername : "", serverpassword ? serverpassword : "", address); } -void reconnect(const char *serverpassword) -{ - if(!connectname[0] || connectport <= 0) - { +void reconnect(const char *serverpassword) { + if(!connectname[0] || connectport <= 0) { conoutf(CON_ERROR, "no previous connection"); return; } - connectserv(connectname, connectport, serverpassword); } -void disconnect(bool async, bool cleanup) -{ - if(curpeer) - { - if(!discmillis) - { +void disconnect(bool async, bool cleanup) { + if(curpeer) { + if(!discmillis) { enet_peer_disconnect(curpeer, DISC_NONE); enet_host_flush(clienthost); discmillis = totalmillis; } - if(curpeer->state!=ENET_PEER_STATE_DISCONNECTED) - { + if(curpeer->state!=ENET_PEER_STATE_DISCONNECTED) { if(async) return; enet_peer_reset(curpeer); } @@ -157,22 +129,18 @@ void disconnect(bool async, bool cleanup) game::gamedisconnect(cleanup); mainmenu = 1; } - if(!connpeer && clienthost) - { + if(!connpeer && clienthost) { enet_host_destroy(clienthost); clienthost = NULL; } } -void trydisconnect(bool local) -{ - if(connpeer) - { +void trydisconnect(bool local) { + if(connpeer) { conoutf("aborting connection attempt"); abortconnect(); } - else if(curpeer) - { + else if(curpeer) { conoutf("attempting to disconnect..."); disconnect(!discmillis); } @@ -187,50 +155,42 @@ ICOMMAND(disconnect, "b", (int *local), trydisconnect(*local != 0)); ICOMMAND(localconnect, "", (), { if(!isconnected()) localconnect(); }); ICOMMAND(localdisconnect, "", (), { if(haslocalclients()) localdisconnect(); }); -void sendclientpacket(ENetPacket *packet, int chan) -{ +void sendclientpacket(ENetPacket *packet, int chan) { if(curpeer) enet_peer_send(curpeer, chan, packet); else localclienttoserver(chan, packet); } -void flushclient() -{ +void flushclient() { if(clienthost) enet_host_flush(clienthost); } -void neterr(const char *s, bool disc) -{ +void neterr(const char *s, bool disc) { conoutf(CON_ERROR, "\f3illegal network message (%s)", s); if(disc) disconnect(); } -void localservertoclient(int chan, ENetPacket *packet) // processes any updates from the server -{ +void localservertoclient(int chan, ENetPacket *packet) { // processes any updates from the server { packetbuf p(packet); game::parsepacketclient(chan, p); } void clientkeepalive() { if(clienthost) enet_host_service(clienthost, NULL, 0); } -void gets2c() // get updates from the server -{ +void gets2c() { // get updates from the server { ENetEvent event; if(!clienthost) return; - if(connpeer && totalmillis/3000 > connmillis/3000) - { + if(connpeer && totalmillis/3000 > connmillis/3000) { conoutf("attempting to connect..."); connmillis = totalmillis; ++connattempts; - if(connattempts > 3) - { + if(connattempts > 3) { conoutf(CON_ERROR, "\f3could not connect to server"); abortconnect(); return; } } while(clienthost && enet_host_service(clienthost, &event, 0)>0) - switch(event.type) - { + switch(event.type) { case ENET_EVENT_TYPE_CONNECT: disconnect(false, false); localdisconnect(false); @@ -241,24 +201,19 @@ void gets2c() // get updates from the server if(rate) setrate(rate); game::gameconnect(true); break; - case ENET_EVENT_TYPE_RECEIVE: if(discmillis) conoutf("attempting to disconnect..."); else localservertoclient(event.channelID, event.packet); enet_packet_destroy(event.packet); break; - case ENET_EVENT_TYPE_DISCONNECT: if(event.data>=DISC_NUM) event.data = DISC_NONE; - if(event.peer==connpeer) - { + if(event.peer==connpeer) { conoutf(CON_ERROR, "\f3could not connect to server"); abortconnect(); } - else - { - if(!discmillis || event.data) - { + else { + if(!discmillis || event.data) { const char *msg = disconnectreason(event.data); if(msg) conoutf(CON_ERROR, "\f3server network error, disconnecting (%s) ...", msg); else conoutf(CON_ERROR, "\f3server network error, disconnecting..."); @@ -266,7 +221,6 @@ void gets2c() // get updates from the server disconnect(); } return; - default: break; } diff --git a/src/engine/command.cpp b/src/engine/command.cpp index 012b8c1..5248899 100644 --- a/src/engine/command.cpp +++ b/src/engine/command.cpp @@ -9,38 +9,31 @@ ident *dummyident = NULL; int identflags = 0; -enum -{ +enum { MAXARGS = 25, MAXCOMARGS = 12 }; VARN(numargs, _numargs, MAXARGS, 0, 0); -static inline void freearg(tagval &v) -{ - switch(v.type) - { +static inline void freearg(tagval &v) { + switch(v.type) { case VAL_STR: delete[] v.s; break; case VAL_CODE: if(v.code[-1] == CODE_START) delete[] (uchar *)&v.code[-1]; break; } } -static inline void forcenull(tagval &v) -{ - switch(v.type) - { +static inline void forcenull(tagval &v) { + switch(v.type) { case VAL_NULL: return; } freearg(v); v.setnull(); } -static inline float forcefloat(tagval &v) -{ +static inline float forcefloat(tagval &v) { float f = 0.0f; - switch(v.type) - { + switch(v.type) { case VAL_INT: f = v.i; break; case VAL_STR: f = parsefloat(v.s); break; case VAL_MACRO: f = parsefloat(v.s); break; @@ -51,11 +44,9 @@ static inline float forcefloat(tagval &v) return f; } -static inline int forceint(tagval &v) -{ +static inline int forceint(tagval &v) { int i = 0; - switch(v.type) - { + switch(v.type) { case VAL_FLOAT: i = v.f; break; case VAL_STR: i = parseint(v.s); break; case VAL_MACRO: i = parseint(v.s); break; @@ -66,11 +57,9 @@ static inline int forceint(tagval &v) return i; } -static inline const char *forcestr(tagval &v) -{ +static inline const char *forcestr(tagval &v) { const char *s = ""; - switch(v.type) - { + switch(v.type) { case VAL_FLOAT: s = floatstr(v.f); break; case VAL_INT: s = intstr(v.i); break; case VAL_STR: @@ -82,29 +71,23 @@ static inline const char *forcestr(tagval &v) return s; } -static inline void forcearg(tagval &v, int type) -{ - switch(type) - { +static inline void forcearg(tagval &v, int type) { + switch(type) { case RET_STR: if(v.type != VAL_STR) forcestr(v); break; case RET_INT: if(v.type != VAL_INT) forceint(v); break; case RET_FLOAT: if(v.type != VAL_FLOAT) forcefloat(v); break; } } -static inline ident *forceident(tagval &v) -{ - switch(v.type) - { +static inline ident *forceident(tagval &v) { + switch(v.type) { case VAL_IDENT: return v.id; - case VAL_MACRO: - { + case VAL_MACRO: { ident *id = newident(v.s, IDF_UNKNOWN); v.setident(id); return id; } - case VAL_STR: - { + case VAL_STR: { ident *id = newident(v.s, IDF_UNKNOWN); delete[] v.s; v.setident(id); @@ -116,39 +99,31 @@ static inline ident *forceident(tagval &v) return dummyident; } -void tagval::cleanup() -{ +void tagval::cleanup() { freearg(*this); } -static inline void freeargs(tagval *args, int &oldnum, int newnum) -{ +static inline void freeargs(tagval *args, int &oldnum, int newnum) { for(int i = newnum; i < oldnum; i++) freearg(args[i]); oldnum = newnum; } -static inline void cleancode(ident &id) -{ - if(id.code) - { +static inline void cleancode(ident &id) { + if(id.code) { id.code[0] -= 0x100; if(int(id.code[0]) < 0x100) delete[] id.code; id.code = NULL; } } -struct nullval : tagval -{ +struct nullval : tagval { nullval() { setnull(); } } nullval; tagval noret = nullval, *commandret = &noret; -void clear_command() -{ - enumerate(idents, ident, i, - { - if(i.type==ID_ALIAS) - { +void clear_command() { + enumerate(idents, ident, i, { + if(i.type==ID_ALIAS) { DELETEA(i.name); i.forcenull(); DELETEA(i.code); @@ -156,14 +131,11 @@ void clear_command() }); } -void clearoverride(ident &i) -{ +void clearoverride(ident &i) { if(!(i.flags&IDF_OVERRIDDEN)) return; - switch(i.type) - { + switch(i.type) { case ID_ALIAS: - if(i.valtype==VAL_STR) - { + if(i.valtype==VAL_STR) { if(!i.val.s[0]) break; delete[] i.val.s; } @@ -188,18 +160,15 @@ void clearoverride(ident &i) i.flags &= ~IDF_OVERRIDDEN; } -void clearoverrides() -{ +void clearoverrides() { enumerate(idents, ident, i, clearoverride(i)); } static bool initedidents = false; static vector *identinits = NULL; -static inline ident *addident(const ident &id) -{ - if(!initedidents) - { +static inline ident *addident(const ident &id) { + if(!initedidents) { if(!identinits) identinits = new vector; identinits->add(id); return NULL; @@ -209,17 +178,14 @@ static inline ident *addident(const ident &id) return identmap.add(&def); } -static bool initidents() -{ +static bool initidents() { initedidents = true; - for(int i = 0; i < MAXARGS; i++) - { + for(int i = 0; i < MAXARGS; i++) { defformatstring(argname, "arg%d", i+1); newident(argname, IDF_ARG); } dummyident = newident("//dummy", IDF_UNKNOWN); - if(identinits) - { + if(identinits) { loopv(*identinits) addident((*identinits)[i]); DELETEP(identinits); } @@ -229,17 +195,14 @@ UNUSED static bool forceinitidents = initidents(); static const char *sourcefile = NULL, *sourcestr = NULL; -static const char *debugline(const char *p, const char *fmt) -{ +static const char *debugline(const char *p, const char *fmt) { if(!sourcestr) return fmt; int num = 1; const char *line = sourcestr; - for(;;) - { + for(;;) { const char *end = strchr(line, '\n'); if(!end) end = line + strlen(line); - if(p >= line && p <= end) - { + if(p >= line && p <= end) { static string buf; if(sourcefile) formatstring(buf, "%s:%d: %s", sourcefile, num, fmt); else formatstring(buf, "%d: %s", num, fmt); @@ -252,8 +215,7 @@ static const char *debugline(const char *p, const char *fmt) return fmt; } -static struct identlink -{ +static struct identlink { ident *id; identlink *next; int usedargs; @@ -262,13 +224,11 @@ static struct identlink VAR(dbgalias, 0, 4, 1000); -static void debugalias() -{ +static void debugalias() { if(!dbgalias) return; int total = 0, depth = 0; for(identlink *l = aliasstack; l != &noalias; l = l->next) total++; - for(identlink *l = aliasstack; l != &noalias; l = l->next) - { + for(identlink *l = aliasstack; l != &noalias; l = l->next) { ident *id = l->id; ++depth; if(depth < dbgalias) conoutf(CON_ERROR, " %d) %s", total-depth+1, id->name); @@ -280,41 +240,33 @@ static int nodebug = 0; static void debugcode(const char *fmt, ...) PRINTFARGS(1, 2); -static void debugcode(const char *fmt, ...) -{ +static void debugcode(const char *fmt, ...) { if(nodebug) return; - va_list args; va_start(args, fmt); conoutfv(CON_ERROR, fmt, args); va_end(args); - debugalias(); } static void debugcodeline(const char *p, const char *fmt, ...) PRINTFARGS(2, 3); -static void debugcodeline(const char *p, const char *fmt, ...) -{ +static void debugcodeline(const char *p, const char *fmt, ...) { if(nodebug) return; - va_list args; va_start(args, fmt); conoutfv(CON_ERROR, debugline(p, fmt), args); va_end(args); - debugalias(); } ICOMMAND(nodebug, "e", (uint *body), { nodebug++; executeret(body, *commandret); nodebug--; }); -void addident(ident *id) -{ +void addident(ident *id) { addident(*id); } -static inline void pusharg(ident &id, const tagval &v, identstack &stack) -{ +static inline void pusharg(ident &id, const tagval &v, identstack &stack) { stack.val = id.val; stack.valtype = id.valtype; stack.next = id.stack; @@ -323,8 +275,7 @@ static inline void pusharg(ident &id, const tagval &v, identstack &stack) cleancode(id); } -static inline void poparg(ident &id) -{ +static inline void poparg(ident &id) { if(!id.stack) return; identstack *stack = id.stack; if(id.valtype == VAL_STR) delete[] id.val.s; @@ -333,8 +284,7 @@ static inline void poparg(ident &id) id.stack = stack->next; } -ICOMMAND(push, "rte", (ident *id, tagval *v, uint *code), -{ +ICOMMAND(push, "rte", (ident *id, tagval *v, uint *code), { if(id->type != ID_ALIAS || id->index < MAXARGS) return; identstack stack; pusharg(*id, *v, stack); @@ -344,40 +294,32 @@ ICOMMAND(push, "rte", (ident *id, tagval *v, uint *code), poparg(*id); }); -static inline void pushalias(ident &id, identstack &stack) -{ - if(id.type == ID_ALIAS && id.index >= MAXARGS) - { +static inline void pushalias(ident &id, identstack &stack) { + if(id.type == ID_ALIAS && id.index >= MAXARGS) { pusharg(id, nullval, stack); id.flags &= ~IDF_UNKNOWN; } } -static inline void popalias(ident &id) -{ +static inline void popalias(ident &id) { if(id.type == ID_ALIAS && id.index >= MAXARGS) poparg(id); } KEYWORD(local, ID_LOCAL); -static inline bool checknumber(const char *s) -{ +static inline bool checknumber(const char *s) { if(isdigit(s[0])) return true; - else switch(s[0]) - { + else switch(s[0]) { case '+': case '-': return isdigit(s[1]) || (s[1] == '.' && isdigit(s[2])); case '.': return isdigit(s[1]) != 0; default: return false; } } -ident *newident(const char *name, int flags) -{ +ident *newident(const char *name, int flags) { ident *id = idents.access(name); - if(!id) - { - if(checknumber(name)) - { + if(!id) { + if(checknumber(name)) { debugcode("number %s is not a valid identifier name", name); return dummyident; } @@ -386,27 +328,23 @@ ident *newident(const char *name, int flags) return id; } -ident *writeident(const char *name, int flags) -{ +ident *writeident(const char *name, int flags) { ident *id = newident(name, flags); - if(id->index < MAXARGS && !(aliasstack->usedargs&(1<index))) - { + if(id->index < MAXARGS && !(aliasstack->usedargs&(1<index))) { pusharg(*id, nullval, aliasstack->argstack[id->index]); aliasstack->usedargs |= 1<index; } return id; } -ident *readident(const char *name) -{ +ident *readident(const char *name) { ident *id = idents.access(name); if(id && id->index < MAXARGS && !(aliasstack->usedargs&(1<index))) return NULL; return id; } -void resetvar(char *name) -{ +void resetvar(char *name) { ident *id = idents.access(name); if(!id) return; if(id->flags&IDF_READONLY) debugcode("variable %s is read-only", id->name); @@ -415,89 +353,73 @@ void resetvar(char *name) COMMAND(resetvar, "s"); -static inline void setarg(ident &id, tagval &v) -{ - if(aliasstack->usedargs&(1<usedargs&(1<argstack[id.index]); aliasstack->usedargs |= 1<type == ID_ALIAS) - { + if(id) { + if(id->type == ID_ALIAS) { if(id->index < MAXARGS) setarg(*id, v); else setalias(*id, v); } - else - { + else { debugcode("cannot redefine builtin %s with an alias", id->name); freearg(v); } } - else if(checknumber(name)) - { + else if(checknumber(name)) { debugcode("cannot alias number %s", name); freearg(v); } - else - { + else { addident(ident(ID_ALIAS, newstring(name), v, identflags)); } } -void alias(const char *name, const char *str) -{ +void alias(const char *name, const char *str) { tagval v; v.setstr(newstring(str)); setalias(name, v); } -void alias(const char *name, tagval &v) -{ +void alias(const char *name, tagval &v) { setalias(name, v); } -ICOMMAND(alias, "st", (const char *name, tagval *v), -{ +ICOMMAND(alias, "st", (const char *name, tagval *v), { setalias(name, *v); v->type = VAL_NULL; }); // variable's and commands are registered through globals, see cube.h -int variable(const char *name, int min, int cur, int max, int *storage, identfun fun, int flags) -{ +int variable(const char *name, int min, int cur, int max, int *storage, identfun fun, int flags) { addident(ident(ID_VAR, name, min, max, storage, (void *)fun, flags)); return cur; } -float fvariable(const char *name, float min, float cur, float max, float *storage, identfun fun, int flags) -{ +float fvariable(const char *name, float min, float cur, float max, float *storage, identfun fun, int flags) { addident(ident(ID_FVAR, name, min, max, storage, (void *)fun, flags)); return cur; } -char *svariable(const char *name, const char *cur, char **storage, identfun fun, int flags) -{ +char *svariable(const char *name, const char *cur, char **storage, identfun fun, int flags) { addident(ident(ID_SVAR, name, storage, (void *)fun, flags)); return newstring(cur); } @@ -507,67 +429,59 @@ char *svariable(const char *name, const char *cur, char **storage, identfun fun, if(!id || id->type!=vartype) return retval; #define GETVAR(id, name, retval) _GETVAR(id, ID_VAR, name, retval) #define OVERRIDEVAR(errorval, saveval, resetval, clearval) \ - if(identflags&IDF_OVERRIDDEN || id->flags&IDF_OVERRIDE) \ - { \ - if(id->flags&IDF_PERSIST) \ - { \ + if(identflags&IDF_OVERRIDDEN || id->flags&IDF_OVERRIDE) { \ + \ + if(id->flags&IDF_PERSIST) { \ + \ debugcode("cannot override persistent variable %s", id->name); \ errorval; \ } \ if(!(id->flags&IDF_OVERRIDDEN)) { saveval; id->flags |= IDF_OVERRIDDEN; } \ else { clearval; } \ } \ - else \ - { \ + else { \ + \ if(id->flags&IDF_OVERRIDDEN) { resetval; id->flags &= ~IDF_OVERRIDDEN; } \ clearval; \ } -void setvar(const char *name, int i, bool dofunc, bool doclamp) -{ +void setvar(const char *name, int i, bool dofunc, bool doclamp) { GETVAR(id, name, ); OVERRIDEVAR(return, id->overrideval.i = *id->storage.i, , ) if(doclamp) *id->storage.i = clamp(i, id->minval, id->maxval); else *id->storage.i = i; if(dofunc) id->changed(); } -void setfvar(const char *name, float f, bool dofunc, bool doclamp) -{ +void setfvar(const char *name, float f, bool dofunc, bool doclamp) { _GETVAR(id, ID_FVAR, name, ); OVERRIDEVAR(return, id->overrideval.f = *id->storage.f, , ); if(doclamp) *id->storage.f = clamp(f, id->minvalf, id->maxvalf); else *id->storage.f = f; if(dofunc) id->changed(); } -void setsvar(const char *name, const char *str, bool dofunc) -{ +void setsvar(const char *name, const char *str, bool dofunc) { _GETVAR(id, ID_SVAR, name, ); OVERRIDEVAR(return, id->overrideval.s = *id->storage.s, delete[] id->overrideval.s, delete[] *id->storage.s); *id->storage.s = newstring(str); if(dofunc) id->changed(); } -int getvar(const char *name) -{ +int getvar(const char *name) { GETVAR(id, name, 0); return *id->storage.i; } -int getvarmin(const char *name) -{ +int getvarmin(const char *name) { GETVAR(id, name, 0); return id->minval; } -int getvarmax(const char *name) -{ +int getvarmax(const char *name) { GETVAR(id, name, 0); return id->maxval; } -float getfvarmin(const char *name) -{ +float getfvarmin(const char *name) { _GETVAR(id, ID_FVAR, name, 0); return id->minvalf; } -float getfvarmax(const char *name) -{ +float getfvarmax(const char *name) { _GETVAR(id, ID_FVAR, name, 0); return id->maxvalf; } @@ -580,11 +494,9 @@ ICOMMAND(getfvarmax, "s", (char *s), floatret(getfvarmax(s))); bool identexists(const char *name) { return idents.access(name)!=NULL; } ident *getident(const char *name) { return idents.access(name); } -void touchvar(const char *name) -{ +void touchvar(const char *name) { ident *id = idents.access(name); - if(id) switch(id->type) - { + if(id) switch(id->type) { case ID_VAR: case ID_FVAR: case ID_SVAR: @@ -593,16 +505,14 @@ void touchvar(const char *name) } } -const char *getalias(const char *name) -{ +const char *getalias(const char *name) { ident *i = idents.access(name); return i && i->type==ID_ALIAS && (i->index >= MAXARGS || aliasstack->usedargs&(1<index)) ? i->getstr() : ""; } ICOMMAND(getalias, "s", (char *s), result(getalias(s))); -int clampvar(ident *id, int val, int minval, int maxval) -{ +int clampvar(ident *id, int val, int minval, int maxval) { if(val < minval) val = minval; else if(val > maxval) val = maxval; else return val; @@ -613,15 +523,13 @@ int clampvar(ident *id, int val, int minval, int maxval) return val; } -void setvarchecked(ident *id, int val) -{ +void setvarchecked(ident *id, int val) { if(id->flags&IDF_READONLY) debugcode("variable %s is read-only", id->name); #ifndef STANDALONE - else if(!(id->flags&IDF_OVERRIDE) || identflags&IDF_OVERRIDDEN || game::allowedittoggle()) + else if(!(id->flags&IDF_OVERRIDE) || identflags&IDF_OVERRIDDEN || game::allowedittoggle()) { #else - else + else { #endif - { OVERRIDEVAR(return, id->overrideval.i = *id->storage.i, , ) if(val < id->minval || val > id->maxval) val = clampvar(id, val, id->minval, id->maxval); *id->storage.i = val; @@ -632,19 +540,16 @@ void setvarchecked(ident *id, int val) } } -static inline void setvarchecked(ident *id, tagval *args, int numargs) -{ +static inline void setvarchecked(ident *id, tagval *args, int numargs) { int val = forceint(args[0]); - if(id->flags&IDF_HEX && numargs > 1) - { + if(id->flags&IDF_HEX && numargs > 1) { val = (val << 16) | (forceint(args[1])<<8); if(numargs > 2) val |= forceint(args[2]); } setvarchecked(id, val); } -float clampfvar(ident *id, float val, float minval, float maxval) -{ +float clampfvar(ident *id, float val, float minval, float maxval) { if(val < minval) val = minval; else if(val > maxval) val = maxval; else return val; @@ -652,15 +557,13 @@ float clampfvar(ident *id, float val, float minval, float maxval) return val; } -void setfvarchecked(ident *id, float val) -{ +void setfvarchecked(ident *id, float val) { if(id->flags&IDF_READONLY) debugcode("variable %s is read-only", id->name); #ifndef STANDALONE - else if(!(id->flags&IDF_OVERRIDE) || identflags&IDF_OVERRIDDEN || game::allowedittoggle()) + else if(!(id->flags&IDF_OVERRIDE) || identflags&IDF_OVERRIDDEN || game::allowedittoggle()) { #else - else + else { #endif - { OVERRIDEVAR(return, id->overrideval.f = *id->storage.f, , ); if(val < id->minvalf || val > id->maxvalf) val = clampfvar(id, val, id->minvalf, id->maxvalf); *id->storage.f = val; @@ -671,15 +574,13 @@ void setfvarchecked(ident *id, float val) } } -void setsvarchecked(ident *id, const char *val) -{ +void setsvarchecked(ident *id, const char *val) { if(id->flags&IDF_READONLY) debugcode("variable %s is read-only", id->name); #ifndef STANDALONE - else if(!(id->flags&IDF_OVERRIDE) || identflags&IDF_OVERRIDDEN || game::allowedittoggle()) + else if(!(id->flags&IDF_OVERRIDE) || identflags&IDF_OVERRIDDEN || game::allowedittoggle()) { #else - else + else { #endif - { OVERRIDEVAR(return, id->overrideval.s = *id->storage.s, delete[] id->overrideval.s, delete[] *id->storage.s); *id->storage.s = newstring(val); id->changed(); @@ -689,10 +590,8 @@ void setsvarchecked(ident *id, const char *val) } } -ICOMMAND(set, "rt", (ident *id, tagval *v), -{ - switch(id->type) - { +ICOMMAND(set, "rt", (ident *id, tagval *v), { + switch(id->type) { case ID_ALIAS: if(id->index < MAXARGS) setarg(*id, *v); else setalias(*id, *v); v->type = VAL_NULL; @@ -707,8 +606,7 @@ ICOMMAND(set, "rt", (ident *id, tagval *v), setsvarchecked(id, forcestr(*v)); break; case ID_COMMAND: - if(id->flags&IDF_EMUVAR) - { + if(id->flags&IDF_EMUVAR) { execute(id, v, 1); v->type = VAL_NULL; break; @@ -720,13 +618,11 @@ ICOMMAND(set, "rt", (ident *id, tagval *v), } }); -bool addcommand(const char *name, identfun fun, const char *args) -{ +bool addcommand(const char *name, identfun fun, const char *args) { uint argmask = 0; int numargs = 0, flags = 0; bool limit = true; - for(const char *fmt = args; *fmt; fmt++) switch(*fmt) - { + for(const char *fmt = args; *fmt; fmt++) switch(*fmt) { case 'i': case 'b': case 'f': case 't': case 'N': case 'D': if(numargs < MAXARGS) numargs++; break; case '$': flags |= IDF_EMUVAR; // fall through case 's': case 'e': case 'r': if(numargs < MAXARGS) { argmask |= 1<= end) break; int e = *src++; - switch(e) - { + switch(e) { case 'n': *dst++ = '\n'; break; case 't': *dst++ = '\t'; break; case 'f': *dst++ = '\f'; break; @@ -783,19 +672,15 @@ int unescapestring(char *dst, const char *src, const char *end) return dst - start; } -static char *conc(vector &buf, tagval *v, int n, bool space, const char *prefix = NULL, int prefixlen = 0) -{ - if(prefix) - { +static char *conc(vector &buf, tagval *v, int n, bool space, const char *prefix = NULL, int prefixlen = 0) { + if(prefix) { buf.put(prefix, prefixlen); if(space && n) buf.add(' '); } - loopi(n) - { + loopi(n) { const char *s = ""; int len = 0; - switch(v[i].type) - { + switch(v[i].type) { case VAL_INT: s = intstr(v[i].i); break; case VAL_FLOAT: s = floatstr(v[i].f); break; case VAL_STR: s = v[i].s; break; @@ -811,13 +696,11 @@ static char *conc(vector &buf, tagval *v, int n, bool space, const char *p return buf.getbuf(); } -static char *conc(tagval *v, int n, bool space, const char *prefix, int prefixlen) -{ +static char *conc(tagval *v, int n, bool space, const char *prefix, int prefixlen) { static int vlen[MAXARGS]; static char numbuf[3*MAXSTRLEN]; int len = prefixlen, numlen = 0, i = 0; - for(; i < n; i++) switch(v[i].type) - { + for(; i < n; i++) switch(v[i].type) { case VAL_MACRO: len += (vlen[i] = v[i].code[-1]>>8); break; case VAL_STR: len += (vlen[i] = int(strlen(v[i].s))); break; case VAL_INT: @@ -836,16 +719,13 @@ overflow: if(space) len += max(prefix ? i : i-1, 0); char *buf = newstring(len + numlen); int offset = 0, numoffset = 0; - if(prefix) - { + if(prefix) { memcpy(buf, prefix, prefixlen); offset += prefixlen; if(space && i) buf[offset++] = ' '; } - loopj(i) - { - if(v[j].type == VAL_INT || v[j].type == VAL_FLOAT) - { + loopj(i) { + if(v[j].type == VAL_INT || v[j].type == VAL_FLOAT) { memcpy(&buf[offset], &numbuf[numoffset], vlen[j]); numoffset += vlen[j]; } @@ -855,8 +735,7 @@ overflow: if(space) buf[offset++] = ' '; } buf[offset] = '\0'; - if(i < n) - { + if(i < n) { char *morebuf = conc(&v[i], n-i, space, buf, offset); delete[] buf; return morebuf; @@ -864,28 +743,23 @@ overflow: return buf; } -static inline char *conc(tagval *v, int n, bool space) -{ +static inline char *conc(tagval *v, int n, bool space) { return conc(v, n, space, NULL, 0); } -static inline char *conc(tagval *v, int n, bool space, const char *prefix) -{ +static inline char *conc(tagval *v, int n, bool space, const char *prefix) { return conc(v, n, space, prefix, strlen(prefix)); } -static inline void skipcomments(const char *&p) -{ - for(;;) - { +static inline void skipcomments(const char *&p) { + for(;;) { p += strspn(p, " \t\r"); if(p[0]!='/' || p[1]!='/') break; p += strcspn(p, "\n\0"); } } -static inline char *cutstring(const char *&p, int &len) -{ +static inline char *cutstring(const char *&p, int &len) { p++; const char *end = parsestring(p); char *s = newstring(end - p); @@ -896,16 +770,13 @@ static inline char *cutstring(const char *&p, int &len) return s; } -static inline const char *parseword(const char *p) -{ +static inline const char *parseword(const char *p) { const int maxbrak = 100; static char brakstack[maxbrak]; int brakdepth = 0; - for(;; p++) - { + for(;; p++) { p += strcspn(p, "\"/;()[] \t\r\n\0"); - switch(p[0]) - { + switch(p[0]) { case '"': case ';': case ' ': case '\t': case '\r': case '\n': case '\0': return p; case '/': if(p[1] == '/') return p; break; case '[': case '(': if(brakdepth >= maxbrak) return p; brakstack[brakdepth++] = p[0]; break; @@ -916,8 +787,7 @@ static inline const char *parseword(const char *p) return p; } -static inline char *cutword(const char *&p, int &len) -{ +static inline char *cutword(const char *&p, int &len) { const char *word = p; p = parseword(p); len = p-word; @@ -925,10 +795,8 @@ static inline char *cutword(const char *&p, int &len) return newstring(word, len); } -static inline void compilestr(vector &code, const char *word, int len, bool macro = false) -{ - if(len <= 3 && !macro) - { +static inline void compilestr(vector &code, const char *word, int len, bool macro = false) { + if(len <= 3 && !macro) { uint op = CODE_VALI|RET_STR; for(int i = 0; i < len; i++) op |= uint(uchar(word[i]))<<((i+1)*8); code.add(op); @@ -937,8 +805,7 @@ static inline void compilestr(vector &code, const char *word, int len, boo code.add((macro ? CODE_MACRO : CODE_VAL|RET_STR)|(len<<8)); code.put((const uint *)word, len/sizeof(uint)); size_t endlen = len%sizeof(uint); - union - { + union { char c[sizeof(uint)]; uint u; } end; @@ -947,30 +814,25 @@ static inline void compilestr(vector &code, const char *word, int len, boo code.add(end.u); } -static inline void compilestr(vector &code, const char *word = NULL) -{ +static inline void compilestr(vector &code, const char *word = NULL) { if(!word) { code.add(CODE_VALI|RET_STR); return; } compilestr(code, word, int(strlen(word))); } -static inline void compileint(vector &code, int i) -{ +static inline void compileint(vector &code, int i) { if(i >= -0x800000 && i <= 0x7FFFFF) code.add(CODE_VALI|RET_INT|(i<<8)); - else - { + else { code.add(CODE_VAL|RET_INT); code.add(i); } } -static inline void compilenull(vector &code) -{ +static inline void compilenull(vector &code) { code.add(CODE_VALI|RET_NULL); } -static inline void compileblock(vector &code) -{ +static inline void compileblock(vector &code) { int start = code.length(); code.add(CODE_BLOCK); code.add(CODE_OFFSET|((start+2)<<8)); @@ -978,27 +840,22 @@ static inline void compileblock(vector &code) code[start] |= uint(code.length() - (start + 1))<<8; } -static inline void compileident(vector &code, ident *id) -{ +static inline void compileident(vector &code, ident *id) { code.add((id->index < MAXARGS ? CODE_IDENTARG : CODE_IDENT)|(id->index<<8)); } -static inline void compileident(vector &code, const char *word = NULL) -{ +static inline void compileident(vector &code, const char *word = NULL) { compileident(code, word ? newident(word, IDF_UNKNOWN) : dummyident); } -static inline void compileint(vector &code, const char *word = NULL) -{ +static inline void compileint(vector &code, const char *word = NULL) { return compileint(code, word ? parseint(word) : 0); } -static inline void compilefloat(vector &code, float f) -{ +static inline void compilefloat(vector &code, float f) { if(int(f) == f && f >= -0x800000 && f <= 0x7FFFFF) code.add(CODE_VALI|RET_FLOAT|(int(f)<<8)); - else - { + else { union { float f; uint u; } conv; conv.f = f; code.add(CODE_VAL|RET_FLOAT); @@ -1006,24 +863,20 @@ static inline void compilefloat(vector &code, float f) } } -static inline void compilefloat(vector &code, const char *word = NULL) -{ +static inline void compilefloat(vector &code, const char *word = NULL) { return compilefloat(code, word ? parsefloat(word) : 0.0f); } static bool compilearg(vector &code, const char *&p, int wordtype); static void compilestatements(vector &code, const char *&p, int rettype, int brak = '\0'); -static inline void compileval(vector &code, int wordtype, char *word, int wordlen) -{ - switch(wordtype) - { +static inline void compileval(vector &code, int wordtype, char *word, int wordlen) { + switch(wordtype) { case VAL_STR: compilestr(code, word, wordlen, true); break; case VAL_ANY: compilestr(code, word, wordlen); break; case VAL_FLOAT: compilefloat(code, word); break; case VAL_INT: compileint(code, word); break; - case VAL_CODE: - { + case VAL_CODE: { int start = code.length(); code.add(CODE_BLOCK); code.add(CODE_OFFSET|((start+2)<<8)); @@ -1041,12 +894,10 @@ static inline void compileval(vector &code, int wordtype, char *word, int static bool compileword(vector &code, const char *&p, int wordtype, char *&word, int &wordlen); -static void compilelookup(vector &code, const char *&p, int ltype) -{ +static void compilelookup(vector &code, const char *&p, int ltype) { char *lookup = NULL; int lookuplen = 0; - switch(*++p) - { + switch(*++p) { case '(': case '[': if(!compileword(code, p, VAL_STR, lookup, lookuplen)) goto invalid; @@ -1057,24 +908,20 @@ static void compilelookup(vector &code, const char *&p, int ltype) case '\"': lookup = cutstring(p, lookuplen); goto lookupid; - default: - { + default: { lookup = cutword(p, lookuplen); if(!lookup) goto invalid; lookupid: ident *id = newident(lookup, IDF_UNKNOWN); - if(id) switch(id->type) - { + if(id) switch(id->type) { case ID_VAR: code.add(CODE_IVAR|((ltype >= VAL_ANY ? VAL_INT : ltype)<index<<8)); goto done; case ID_FVAR: code.add(CODE_FVAR|((ltype >= VAL_ANY ? VAL_FLOAT : ltype)<index<<8)); goto done; case ID_SVAR: code.add(CODE_SVAR|((ltype >= VAL_ANY ? VAL_STR : ltype)<index<<8)); goto done; case ID_ALIAS: code.add((id->index < MAXARGS ? CODE_LOOKUPARG : CODE_LOOKUP)|((ltype >= VAL_ANY ? VAL_STR : ltype)<index<<8)); goto done; - case ID_COMMAND: - { + case ID_COMMAND: { int comtype = CODE_COM, numargs = 0; code.add(CODE_ENTER); - for(const char *fmt = id->args; *fmt; fmt++) switch(*fmt) - { + for(const char *fmt = id->args; *fmt; fmt++) switch(*fmt) { case 's': compilestr(code, NULL, 0, true); numargs++; break; case 'i': compileint(code); numargs++; break; case 'b': compileint(code, INT_MIN); numargs++; break; @@ -1105,37 +952,31 @@ static void compilelookup(vector &code, const char *&p, int ltype) code.add(CODE_LOOKUPU|((ltype < VAL_ANY ? ltype< &code, const char *str, const char *end, bool macro) -{ +static bool compileblockstr(vector &code, const char *str, const char *end, bool macro) { int start = code.length(); code.add(macro ? CODE_MACRO : CODE_VAL|RET_STR); char *buf = (char *)code.reserve((end-str)/sizeof(uint)+1).buf; int len = 0; - while(str < end) - { + while(str < end) { int n = strcspn(str, "\r/\"@]\0"); memcpy(&buf[len], str, n); len += n; str += n; - switch(*str) - { + switch(*str) { case '\r': str++; break; - case '\"': - { + case '\"': { const char *start = str; str = parsestring(str+1); if(*str=='\"') str++; @@ -1144,11 +985,9 @@ static bool compileblockstr(vector &code, const char *str, const char *end break; } case '/': - if(str[1] == '/') - { + if(str[1] == '/') { size_t comment = strcspn(str, "\n\0"); - if (iscubepunct(str[2])) - { + if (iscubepunct(str[2])) { memcpy(&buf[len], str, comment); len += comment; } @@ -1171,12 +1010,10 @@ done: return true; } -static bool compileblocksub(vector &code, const char *&p) -{ +static bool compileblocksub(vector &code, const char *&p) { char *lookup = NULL; int lookuplen = 0; - switch(*p) - { + switch(*p) { case '(': if(!compilearg(code, p, VAL_STR)) return false; break; @@ -1187,9 +1024,8 @@ static bool compileblocksub(vector &code, const char *&p) case '\"': lookup = cutstring(p, lookuplen); goto lookupid; - default: - { - { + default: { + { const char *start = p; while(iscubealnum(*p) || *p=='_') p++; lookuplen = p-start; @@ -1198,8 +1034,7 @@ static bool compileblocksub(vector &code, const char *&p) } lookupid: ident *id = newident(lookup, IDF_UNKNOWN); - if(id) switch(id->type) - { + if(id) switch(id->type) { case ID_VAR: code.add(CODE_IVAR|RET_STR|(id->index<<8)); goto done; case ID_FVAR: code.add(CODE_FVAR|RET_STR|(id->index<<8)); goto done; case ID_SVAR: code.add(CODE_SVAR|RET_STR|(id->index<<8)); goto done; @@ -1215,16 +1050,13 @@ static bool compileblocksub(vector &code, const char *&p) return true; } -static void compileblock(vector &code, const char *&p, int wordtype) -{ +static void compileblock(vector &code, const char *&p, int wordtype) { const char *line = p, *start = p; int concs = 0; - for(int brak = 1; brak;) - { + for(int brak = 1; brak;) { p += strcspn(p, "@\"/[]\0"); int c = *p++; - switch(c) - { + switch(c) { case '\0': debugcodeline(line, "missing \"]\""); p--; @@ -1238,16 +1070,14 @@ static void compileblock(vector &code, const char *&p, int wordtype) break; case '[': brak++; break; case ']': brak--; break; - case '@': - { + case '@': { const char *esc = p; while(*p == '@') p++; int level = p - (esc - 1); if(brak > level) continue; else if(brak < level) debugcodeline(line, "too many @s"); if(!concs) code.add(CODE_ENTER); - if(concs + 2 > MAXARGS) - { + if(concs + 2 > MAXARGS) { code.add(CODE_CONCW|RET_STR|(concs<<8)); concs = 1; } @@ -1260,12 +1090,9 @@ static void compileblock(vector &code, const char *&p, int wordtype) } } done: - if(p-1 > start) - { - if(!concs) switch(wordtype) - { - case VAL_CODE: - { + if(p-1 > start) { + if(!concs) switch(wordtype) { + case VAL_CODE: { p = start; int inst = code.length(); code.add(CODE_BLOCK); @@ -1275,8 +1102,7 @@ done: code[inst] |= uint(code.length() - (inst + 1))<<8; return; } - case VAL_IDENT: - { + case VAL_IDENT: { char *name = newstring(start, p-1-start); compileident(code, name); delete[] name; @@ -1286,21 +1112,18 @@ done: compileblockstr(code, start, p-1, concs > 0); if(concs > 1) concs++; } - if(concs) - { + if(concs) { code.add(CODE_CONCM|(wordtype < VAL_ANY ? wordtype< &code, const char *&p, int wordtype, char *&word, int &wordlen) -{ +static bool compileword(vector &code, const char *&p, int wordtype, char *&word, int &wordlen) { skipcomments(p); - switch(*p) - { + switch(*p) { case '\"': word = cutstring(p, wordlen); break; case '$': compilelookup(code, p, wordtype); return true; case '(': @@ -1320,8 +1141,7 @@ static bool compileword(vector &code, const char *&p, int wordtype, char * code.add(CODE_ENTER); compilestatements(code, p, VAL_ANY, ')'); code.add(CODE_EXIT|(wordtype < VAL_ANY ? wordtype< &code, const char *&p, int wordtype, char * return word!=NULL; } -static inline bool compilearg(vector &code, const char *&p, int wordtype) -{ +static inline bool compilearg(vector &code, const char *&p, int wordtype) { char *word = NULL; int wordlen = 0; bool more = compileword(code, p, wordtype, word, wordlen); if(!more) return false; - if(word) - { + if(word) { compileval(code, wordtype, word, wordlen); delete[] word; } return true; } -static void compilestatements(vector &code, const char *&p, int rettype, int brak) -{ +static void compilestatements(vector &code, const char *&p, int rettype, int brak) { const char *line = p; char *idname = NULL; int idlen = 0; ident *id = NULL; int numargs = 0; - for(;;) - { + for(;;) { skipcomments(p); idname = NULL; bool more = compileword(code, p, VAL_ANY, idname, idlen); if(!more) goto endstatement; skipcomments(p); - if(p[0] == '=') switch(p[1]) - { + if(p[0] == '=') switch(p[1]) { case '/': if(p[2] != '/') break; [[fallthrough]]; @@ -1380,11 +1195,9 @@ static void compilestatements(vector &code, const char *&p, int rettype, i [[fallthrough]]; case '\0': p++; - if(idname) - { + if(idname) { id = newident(idname, IDF_UNKNOWN); - if(id) switch(id->type) - { + if(id) switch(id->type) { case ID_ALIAS: if(!(more = compilearg(code, p, VAL_ANY))) compilestr(code); code.add((id->index < MAXARGS ? CODE_ALIASARG : CODE_ALIAS)|(id->index<<8)); @@ -1414,17 +1227,14 @@ static void compilestatements(vector &code, const char *&p, int rettype, i } compilecommand: numargs = 0; - if(!idname) - { + if(!idname) { noid: while(numargs < MAXARGS && (more = compilearg(code, p, VAL_ANY))) numargs++; code.add(CODE_CALLU); } - else - { + else { id = idents.access(idname); - if(!id) - { + if(!id) { if(!checknumber(idname)) { compilestr(code, idname, idlen); delete[] idname; goto noid; } char *end = idname; int val = int(strtoul(idname, &end, 0)); @@ -1432,28 +1242,23 @@ static void compilestatements(vector &code, const char *&p, int rettype, i else compileint(code, val); code.add(CODE_RESULT); } - else switch(id->type) - { + else switch(id->type) { case ID_ALIAS: while(numargs < MAXARGS && (more = compilearg(code, p, VAL_ANY))) numargs++; code.add((id->index < MAXARGS ? CODE_CALLARG : CODE_CALL)|(id->index<<8)); break; - case ID_COMMAND: - { + case ID_COMMAND: { int comtype = CODE_COM, fakeargs = 0; bool rep = false; - for(const char *fmt = id->args; *fmt; fmt++) switch(*fmt) - { + for(const char *fmt = id->args; *fmt; fmt++) switch(*fmt) { case 's': if(more) more = compilearg(code, p, VAL_STR); - if(!more) - { + if(!more) { if(rep) break; compilestr(code, NULL, 0, true); fakeargs++; } - else if(!fmt[1]) - { + else if(!fmt[1]) { int numconc = 0; while(numargs + numconc < MAXARGS && (more = compilearg(code, p, VAL_STR))) numconc++; if(numconc > 0) code.add(CODE_CONC|RET_STR|((numconc+1)<<8)); @@ -1474,8 +1279,7 @@ static void compilestatements(vector &code, const char *&p, int rettype, i case 'C': comtype = CODE_COMC; if(more) while(numargs < MAXARGS && (more = compilearg(code, p, VAL_ANY))) numargs++; numargs = 1; goto endfmt; case 'V': comtype = CODE_COMV; if(more) while(numargs < MAXARGS && (more = compilearg(code, p, VAL_ANY))) numargs++; numargs = 2; goto endfmt; case '1': case '2': case '3': case '4': - if(more && numargs < MAXARGS) - { + if(more && numargs < MAXARGS) { int numrep = *fmt-'0'+1; fmt -= numrep; rep = true; @@ -1504,8 +1308,7 @@ static void compilestatements(vector &code, const char *&p, int rettype, i break; case ID_SVAR: if(!(more = compilearg(code, p, VAL_STR))) code.add(CODE_PRINT|(id->index<<8)); - else - { + else { int numconc = 0; while(numconc+1 < MAXARGS && (more = compilearg(code, p, VAL_ANY))) numconc++; if(numconc > 0) code.add(CODE_CONC|RET_STR|((numconc+1)<<8)); @@ -1520,19 +1323,16 @@ static void compilestatements(vector &code, const char *&p, int rettype, i if(more) while(compilearg(code, p, VAL_ANY)) code.add(CODE_POP); p += strcspn(p, ")];/\n\0"); int c = *p++; - switch(c) - { + switch(c) { case '\0': if(c != brak) debugcodeline(line, "missing \"%c\"", brak); p--; return; - case ')': case ']': if(c == brak) return; debugcodeline(line, "unexpected \"%c\"", c); break; - case '/': if(*p == '/') p += strcspn(p, "\n\0"); goto endstatement; @@ -1540,15 +1340,13 @@ static void compilestatements(vector &code, const char *&p, int rettype, i } } -static void compilemain(vector &code, const char *p, int rettype = VAL_ANY) -{ +static void compilemain(vector &code, const char *p, int rettype = VAL_ANY) { code.add(CODE_START); compilestatements(code, p, VAL_ANY); code.add(CODE_EXIT|(rettype < VAL_ANY ? rettype< buf; buf.reserve(64); compilemain(buf, p); @@ -1558,17 +1356,14 @@ uint *compilecode(const char *p) return code; } -void keepcode(uint *code) -{ +void keepcode(uint *code) { if(!code) return; - switch(*code&CODE_OP_MASK) - { + switch(*code&CODE_OP_MASK) { case CODE_START: *code += 0x100; return; } - switch(code[-1]&CODE_OP_MASK) - { + switch(code[-1]&CODE_OP_MASK) { case CODE_START: code[-1] += 0x100; break; @@ -1579,18 +1374,15 @@ void keepcode(uint *code) } } -void freecode(uint *code) -{ +void freecode(uint *code) { if(!code) return; - switch(*code&CODE_OP_MASK) - { + switch(*code&CODE_OP_MASK) { case CODE_START: *code -= 0x100; if(int(*code) < 0x100) delete[] code; return; } - switch(code[-1]&CODE_OP_MASK) - { + switch(code[-1]&CODE_OP_MASK) { case CODE_START: code[-1] -= 0x100; if(int(code[-1]) < 0x100) delete[] &code[-1]; @@ -1603,8 +1395,7 @@ void freecode(uint *code) } } -void printvar(ident *id, int i) -{ +void printvar(ident *id, int i) { if(i < 0) conoutf(CON_INFO, id->index, "%s = %d", id->name, i); else if(id->flags&IDF_HEX && id->maxval==0xFFFFFF) conoutf(CON_INFO, id->index, "%s = 0x%.6X (%d, %d, %d)", id->name, i, (i>>16)&0xFF, (i>>8)&0xFF, i&0xFF); @@ -1612,38 +1403,31 @@ void printvar(ident *id, int i) conoutf(CON_INFO, id->index, id->flags&IDF_HEX ? "%s = 0x%X" : "%s = %d", id->name, i); } -void printfvar(ident *id, float f) -{ +void printfvar(ident *id, float f) { conoutf(CON_INFO, id->index, "%s = %s", id->name, floatstr(f)); } -void printsvar(ident *id, const char *s) -{ +void printsvar(ident *id, const char *s) { conoutf(CON_INFO, id->index, strchr(s, '"') ? "%s = [%s]" : "%s = \"%s\"", id->name, s); } template -static void printvar(ident *id, int type, V &val) -{ - switch(type) - { +static void printvar(ident *id, int type, V &val) { + switch(type) { case VAL_INT: printvar(id, val.getint()); break; case VAL_FLOAT: printfvar(id, val.getfloat()); break; default: printsvar(id, val.getstr()); break; } } -void printvar(ident *id) -{ - switch(id->type) - { +void printvar(ident *id) { + switch(id->type) { case ID_VAR: printvar(id, *id->storage.i); break; case ID_FVAR: printfvar(id, *id->storage.f); break; case ID_SVAR: printsvar(id, *id->storage.s); break; case ID_ALIAS: printvar(id, id->valtype, *id); break; case ID_COMMAND: - if(id->flags&IDF_EMUVAR) - { + if(id->flags&IDF_EMUVAR) { tagval result; executeret(id, NULL, 0, true, result); printvar(id, result.type, result); @@ -1669,23 +1453,18 @@ typedef void (__cdecl *comfun11)(void *, void *, void *, void *, void *, void *, typedef void (__cdecl *comfun12)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *); typedef void (__cdecl *comfunv)(tagval *, int); -static const uint *skipcode(const uint *code, tagval &result) -{ +static const uint *skipcode(const uint *code, tagval &result) { int depth = 0; - for(;;) - { + for(;;) { uint op = *code++; - switch(op&0xFF) - { + switch(op&0xFF) { case CODE_MACRO: - case CODE_VAL|RET_STR: - { + case CODE_VAL|RET_STR: { uint len = op>>8; code += len/sizeof(uint) + 1; continue; } - case CODE_BLOCK: - { + case CODE_BLOCK: { uint len = op>>8; code += len; continue; @@ -1694,8 +1473,7 @@ static const uint *skipcode(const uint *code, tagval &result) ++depth; continue; case CODE_EXIT|RET_NULL: case CODE_EXIT|RET_STR: case CODE_EXIT|RET_INT: case CODE_EXIT|RET_FLOAT: - if(depth <= 0) - { + if(depth <= 0) { forcearg(result, op&CODE_RET_MASK); return code; } @@ -1705,27 +1483,23 @@ static const uint *skipcode(const uint *code, tagval &result) } } -static inline void callcommand(ident *id, tagval *args, int numargs, bool lookup = false) -{ +static inline void callcommand(ident *id, tagval *args, int numargs, bool lookup = false) { int i = -1, fakeargs = 0; bool rep = false; - for(const char *fmt = id->args; *fmt; fmt++) switch(*fmt) - { + for(const char *fmt = id->args; *fmt; fmt++) switch(*fmt) { case 'i': if(++i >= numargs) { if(rep) break; args[i].setint(0); fakeargs++; } else forceint(args[i]); break; case 'b': if(++i >= numargs) { if(rep) break; args[i].setint(INT_MIN); fakeargs++; } else forceint(args[i]); break; case 'f': if(++i >= numargs) { if(rep) break; args[i].setfloat(0.0f); fakeargs++; } else forcefloat(args[i]); break; case 's': if(++i >= numargs) { if(rep) break; args[i].setstr(newstring("")); fakeargs++; } else forcestr(args[i]); break; case 't': if(++i >= numargs) { if(rep) break; args[i].setnull(); fakeargs++; } break; case 'e': - if(++i >= numargs) - { + if(++i >= numargs) { if(rep) break; static uint buf[2] = { CODE_START + 0x100, CODE_EXIT }; args[i].setcode(buf); fakeargs++; } - else - { + else { vector buf; buf.reserve(64); compilemain(buf, numargs <= i ? "" : args[i].getstr()); @@ -1746,8 +1520,8 @@ static inline void callcommand(ident *id, tagval *args, int numargs, bool lookup } #define ARG(n) (id->argmask&(1<fun)(); break; \ case 1: ((comfun1)id->fun)(ARG(0)); break; \ case 2: ((comfun2)id->fun)(ARG(0), ARG(1)); break; \ @@ -1772,11 +1546,9 @@ cleanup: #define MAXRUNDEPTH 255 static int rundepth = 0; -static const uint *runcode(const uint *code, tagval &result) -{ +static const uint *runcode(const uint *code, tagval &result) { result.setnull(); - if(rundepth >= MAXRUNDEPTH) - { + if(rundepth >= MAXRUNDEPTH) { debugcode("exceeded recursion limit"); return skipcode(code, result); } @@ -1785,13 +1557,10 @@ static const uint *runcode(const uint *code, tagval &result) int numargs = 0; tagval args[MAXARGS+1], *prevret = commandret; commandret = &result; - for(;;) - { + for(;;) { uint op = *code++; - switch(op&0xFF) - { + switch(op&0xFF) { case CODE_START: case CODE_OFFSET: continue; - case CODE_POP: freearg(args[--numargs]); continue; @@ -1804,8 +1573,7 @@ static const uint *runcode(const uint *code, tagval &result) case CODE_PRINT: printvar(identmap[op>>8]); continue; - case CODE_LOCAL: - { + case CODE_LOCAL: { identstack locals[MAXARGS]; freearg(result); loopi(numargs) pushalias(*args[i].id, locals[i]); @@ -1813,24 +1581,19 @@ static const uint *runcode(const uint *code, tagval &result) loopi(numargs) popalias(*args[i].id); goto exit; } - - case CODE_MACRO: - { + case CODE_MACRO: { uint len = op>>8; args[numargs++].setmacro(code); code += len/sizeof(uint) + 1; continue; } - - case CODE_VAL|RET_STR: - { + case CODE_VAL|RET_STR: { uint len = op>>8; args[numargs++].setstr(newstring((const char *)code, len)); code += len/sizeof(uint) + 1; continue; } - case CODE_VALI|RET_STR: - { + case CODE_VALI|RET_STR: { char s[4] = { char((op>>8)&0xFF), char((op>>16)&0xFF), char((op>>24)&0xFF), '\0' }; args[numargs++].setstr(newstring(s)); continue; @@ -1841,11 +1604,9 @@ static const uint *runcode(const uint *code, tagval &result) case CODE_VALI|RET_INT: args[numargs++].setint(int(op)>>8); continue; case CODE_VAL|RET_FLOAT: args[numargs++].setfloat(*(const float *)code++); continue; case CODE_VALI|RET_FLOAT: args[numargs++].setfloat(float(int(op)>>8)); continue; - case CODE_FORCE|RET_STR: forcestr(args[numargs-1]); continue; case CODE_FORCE|RET_INT: forceint(args[numargs-1]); continue; case CODE_FORCE|RET_FLOAT: forcefloat(args[numargs-1]); continue; - case CODE_RESULT|RET_NULL: case CODE_RESULT|RET_STR: case CODE_RESULT|RET_INT: case CODE_RESULT|RET_FLOAT: litval: freearg(result); @@ -1854,20 +1615,16 @@ static const uint *runcode(const uint *code, tagval &result) args[0].setnull(); freeargs(args, numargs, 0); continue; - - case CODE_BLOCK: - { + case CODE_BLOCK: { uint len = op>>8; args[numargs++].setcode(code+1); code += len; continue; } - case CODE_COMPILE: - { + case CODE_COMPILE: { tagval &arg = args[numargs-1]; vector buf; - switch(arg.type) - { + switch(arg.type) { case VAL_INT: buf.reserve(8); buf.add(CODE_START); compileint(buf, arg.i); buf.add(CODE_RESULT); buf.add(CODE_EXIT); break; case VAL_FLOAT: buf.reserve(8); buf.add(CODE_START); compilefloat(buf, arg.f); buf.add(CODE_RESULT); buf.add(CODE_EXIT); break; case VAL_STR: case VAL_MACRO: buf.reserve(64); compilemain(buf, arg.s); freearg(arg); break; @@ -1877,27 +1634,22 @@ static const uint *runcode(const uint *code, tagval &result) buf.disown(); continue; } - case CODE_IDENT: args[numargs++].setident(identmap[op>>8]); continue; - case CODE_IDENTARG: - { + case CODE_IDENTARG: { ident *id = identmap[op>>8]; - if(!(aliasstack->usedargs&(1<index))) - { + if(!(aliasstack->usedargs&(1<index))) { pusharg(*id, nullval, aliasstack->argstack[id->index]); aliasstack->usedargs |= 1<index; } args[numargs++].setident(id); continue; } - case CODE_IDENTU: - { + case CODE_IDENTU: { tagval &arg = args[numargs-1]; ident *id = arg.type == VAL_STR || arg.type == VAL_MACRO ? newident(arg.s, IDF_UNKNOWN) : dummyident; - if(id->index < MAXARGS && !(aliasstack->usedargs&(1<index))) - { + if(id->index < MAXARGS && !(aliasstack->usedargs&(1<index))) { pusharg(*id, nullval, aliasstack->argstack[id->index]); aliasstack->usedargs |= 1<index; } @@ -1905,14 +1657,13 @@ static const uint *runcode(const uint *code, tagval &result) arg.setident(id); continue; } - case CODE_LOOKUPU|RET_STR: #define LOOKUPU(aval, sval, ival, fval, nval) { \ tagval &arg = args[numargs-1]; \ if(arg.type != VAL_STR && arg.type != VAL_MACRO) continue; \ id = idents.access(arg.s); \ - if(id) switch(id->type) \ - { \ + if(id) switch(id->type) { \ + \ case ID_ALIAS: \ if(id->flags&IDF_UNKNOWN) break; \ freearg(arg); \ @@ -1922,8 +1673,8 @@ static const uint *runcode(const uint *code, tagval &result) case ID_SVAR: freearg(arg); sval; continue; \ case ID_VAR: freearg(arg); ival; continue; \ case ID_FVAR: freearg(arg); fval; continue; \ - case ID_COMMAND: \ - { \ + case ID_COMMAND: { \ + \ freearg(arg); \ arg.setnull(); \ commandret = &arg; \ @@ -1991,24 +1742,20 @@ static const uint *runcode(const uint *code, tagval &result) LOOKUP(id->getval(args[numargs++])); case CODE_LOOKUPARG|RET_NULL: LOOKUPARG(id->getval(args[numargs++]), args[numargs++].setnull()); - case CODE_SVAR|RET_STR: case CODE_SVAR|RET_NULL: args[numargs++].setstr(newstring(*identmap[op>>8]->storage.s)); continue; case CODE_SVAR|RET_INT: args[numargs++].setint(parseint(*identmap[op>>8]->storage.s)); continue; case CODE_SVAR|RET_FLOAT: args[numargs++].setfloat(parsefloat(*identmap[op>>8]->storage.s)); continue; case CODE_SVAR1: setsvarchecked(identmap[op>>8], args[0].s); freeargs(args, numargs, 0); continue; - case CODE_IVAR|RET_INT: case CODE_IVAR|RET_NULL: args[numargs++].setint(*identmap[op>>8]->storage.i); continue; case CODE_IVAR|RET_STR: args[numargs++].setstr(newstring(intstr(*identmap[op>>8]->storage.i))); continue; case CODE_IVAR|RET_FLOAT: args[numargs++].setfloat(float(*identmap[op>>8]->storage.i)); continue; case CODE_IVAR1: setvarchecked(identmap[op>>8], args[0].i); numargs = 0; continue; case CODE_IVAR2: setvarchecked(identmap[op>>8], (args[0].i<<16)|(args[1].i<<8)); numargs = 0; continue; case CODE_IVAR3: setvarchecked(identmap[op>>8], (args[0].i<<16)|(args[1].i<<8)|args[2].i); numargs = 0; continue; - case CODE_FVAR|RET_FLOAT: case CODE_FVAR|RET_NULL: args[numargs++].setfloat(*identmap[op>>8]->storage.f); continue; case CODE_FVAR|RET_STR: args[numargs++].setstr(newstring(floatstr(*identmap[op>>8]->storage.f))); continue; case CODE_FVAR|RET_INT: args[numargs++].setint(int(*identmap[op>>8]->storage.f)); continue; case CODE_FVAR1: setfvarchecked(identmap[op>>8], args[0].f); numargs = 0; continue; - case CODE_COM|RET_NULL: case CODE_COM|RET_STR: case CODE_COM|RET_FLOAT: case CODE_COM|RET_INT: id = identmap[op>>8]; #ifndef STANDALONE @@ -2034,17 +1781,14 @@ static const uint *runcode(const uint *code, tagval &result) goto forceresult; case CODE_COMC|RET_NULL: case CODE_COMC|RET_STR: case CODE_COMC|RET_FLOAT: case CODE_COMC|RET_INT: id = identmap[op>>8]; - forcenull(result); - { + forcenull(result); { vector buf; buf.reserve(MAXSTRLEN); ((comfun1)id->fun)(conc(buf, args, numargs, true)); } goto forceresult; - case CODE_CONC|RET_NULL: case CODE_CONC|RET_STR: case CODE_CONC|RET_FLOAT: case CODE_CONC|RET_INT: - case CODE_CONCW|RET_NULL: case CODE_CONCW|RET_STR: case CODE_CONCW|RET_FLOAT: case CODE_CONCW|RET_INT: - { + case CODE_CONCW|RET_NULL: case CODE_CONCW|RET_STR: case CODE_CONCW|RET_FLOAT: case CODE_CONCW|RET_INT: { int numconc = op>>8; char *s = conc(&args[numargs-numconc], numconc, (op&CODE_OP_MASK)==CODE_CONC); freeargs(args, numargs, numargs-numconc); @@ -2052,9 +1796,7 @@ static const uint *runcode(const uint *code, tagval &result) forcearg(args[numargs-1], op&CODE_RET_MASK); continue; } - - case CODE_CONCM|RET_NULL: case CODE_CONCM|RET_STR: case CODE_CONCM|RET_FLOAT: case CODE_CONCM|RET_INT: - { + case CODE_CONCM|RET_NULL: case CODE_CONCM|RET_STR: case CODE_CONCM|RET_FLOAT: case CODE_CONCM|RET_INT: { int numconc = op>>8; char *s = conc(&args[numargs-numconc], numconc, false); freeargs(args, numargs, numargs-numconc); @@ -2062,7 +1804,6 @@ static const uint *runcode(const uint *code, tagval &result) forcearg(result, op&CODE_RET_MASK); continue; } - case CODE_ALIAS: setalias(*identmap[op>>8], args[--numargs]); freeargs(args, numargs, 0); @@ -2076,7 +1817,6 @@ static const uint *runcode(const uint *code, tagval &result) setalias(args[0].s, args[--numargs]); freeargs(args, numargs, 0); continue; - case CODE_CALL|RET_NULL: case CODE_CALL|RET_STR: case CODE_CALL|RET_FLOAT: case CODE_CALL|RET_INT: #define CALLALIAS(offset) { \ identstack argstack[MAXARGS]; \ @@ -2106,8 +1846,7 @@ static const uint *runcode(const uint *code, tagval &result) } forcenull(result); id = identmap[op>>8]; - if(id->flags&IDF_UNKNOWN) - { + if(id->flags&IDF_UNKNOWN) { debugcode("unknown command: %s", id->name); goto forceresult; } @@ -2119,12 +1858,10 @@ static const uint *runcode(const uint *code, tagval &result) if(!(aliasstack->usedargs&(1<index))) goto forceresult; CALLALIAS(0); continue; - case CODE_CALLU|RET_NULL: case CODE_CALLU|RET_STR: case CODE_CALLU|RET_FLOAT: case CODE_CALLU|RET_INT: if(args[0].type != VAL_STR) goto litval; id = idents.access(args[0].s); - if(!id) - { + if(!id) { noid: if(checknumber(args[0].s)) goto litval; debugcode("unknown command: %s", args[0].s); @@ -2132,16 +1869,14 @@ static const uint *runcode(const uint *code, tagval &result) goto forceresult; } forcenull(result); - switch(id->type) - { + switch(id->type) { case ID_COMMAND: freearg(args[0]); callcommand(id, args+1, numargs-1); forcearg(result, op&CODE_RET_MASK); numargs = 0; continue; - case ID_LOCAL: - { + case ID_LOCAL: { identstack locals[MAXARGS]; freearg(args[0]); loopj(numargs-1) pushalias(*forceident(args[j+1]), locals[j]); @@ -2175,13 +1910,11 @@ exit: return code; } -void executeret(const uint *code, tagval &result) -{ +void executeret(const uint *code, tagval &result) { runcode(code, result); } -void executeret(const char *p, tagval &result) -{ +void executeret(const char *p, tagval &result) { vector code; code.reserve(64); compilemain(code, p, VAL_ANY); @@ -2189,21 +1922,18 @@ void executeret(const char *p, tagval &result) if(int(code[0]) >= 0x100) code.disown(); } -void executeret(ident *id, tagval *args, int numargs, bool lookup, tagval &result) -{ +void executeret(ident *id, tagval *args, int numargs, bool lookup, tagval &result) { result.setnull(); ++rundepth; tagval *prevret = commandret; commandret = &result; if(rundepth > MAXRUNDEPTH) debugcode("exceeded recursion limit"); - else if(id) switch(id->type) - { + else if(id) switch(id->type) { default: if(!id->fun) break; // fall-through case ID_COMMAND: - if(numargs < id->numargs) - { + if(numargs < id->numargs) { tagval buf[MAXARGS]; memcpy(buf, args, numargs*sizeof(tagval)); callcommand(id, buf, numargs, lookup); @@ -2233,8 +1963,7 @@ void executeret(ident *id, tagval *args, int numargs, bool lookup, tagval &resul --rundepth; } -char *executestr(const uint *code) -{ +char *executestr(const uint *code) { tagval result; runcode(code, result); if(result.type == VAL_NULL) return NULL; @@ -2242,8 +1971,7 @@ char *executestr(const uint *code) return result.s; } -char *executestr(const char *p) -{ +char *executestr(const char *p) { tagval result; executeret(p, result); if(result.type == VAL_NULL) return NULL; @@ -2251,8 +1979,7 @@ char *executestr(const char *p) return result.s; } -char *executestr(ident *id, tagval *args, int numargs, bool lookup) -{ +char *executestr(ident *id, tagval *args, int numargs, bool lookup) { tagval result; executeret(id, args, numargs, lookup, result); if(result.type == VAL_NULL) return NULL; @@ -2260,14 +1987,12 @@ char *executestr(ident *id, tagval *args, int numargs, bool lookup) return result.s; } -char *execidentstr(const char *name, bool lookup) -{ +char *execidentstr(const char *name, bool lookup) { ident *id = idents.access(name); return id ? executestr(id, NULL, 0, lookup) : NULL; } -int execute(const uint *code) -{ +int execute(const uint *code) { tagval result; runcode(code, result); int i = result.getint(); @@ -2275,8 +2000,7 @@ int execute(const uint *code) return i; } -int execute(const char *p) -{ +int execute(const char *p) { vector code; code.reserve(64); compilemain(code, p, VAL_INT); @@ -2288,8 +2012,7 @@ int execute(const char *p) return i; } -int execute(ident *id, tagval *args, int numargs, bool lookup) -{ +int execute(ident *id, tagval *args, int numargs, bool lookup) { tagval result; executeret(id, args, numargs, lookup, result); int i = result.getint(); @@ -2297,31 +2020,25 @@ int execute(ident *id, tagval *args, int numargs, bool lookup) return i; } -int execident(const char *name, int noid, bool lookup) -{ +int execident(const char *name, int noid, bool lookup) { ident *id = idents.access(name); return id ? execute(id, NULL, 0, lookup) : noid; } -static inline bool getbool(const char *s) -{ - switch(s[0]) - { +static inline bool getbool(const char *s) { + switch(s[0]) { case '+': case '-': - switch(s[1]) - { + switch(s[1]) { case '0': break; case '.': return !isdigit(s[2]) || parsefloat(s) != 0; default: return true; } // fall through - case '0': - { + case '0': { char *end; int val = int(strtoul((char *)s, &end, 0)); if(val) return true; - switch(*end) - { + switch(*end) { case 'e': case '.': return parsefloat(s) != 0; default: return false; } @@ -2332,10 +2049,8 @@ static inline bool getbool(const char *s) } } -static inline bool getbool(const tagval &v) -{ - switch(v.type) - { +static inline bool getbool(const tagval &v) { + switch(v.type) { case VAL_FLOAT: return v.f!=0; case VAL_INT: return v.i!=0; case VAL_STR: case VAL_MACRO: return getbool(v.s); @@ -2343,8 +2058,7 @@ static inline bool getbool(const tagval &v) } } -bool executebool(const uint *code) -{ +bool executebool(const uint *code) { tagval result; runcode(code, result); bool b = getbool(result); @@ -2352,8 +2066,7 @@ bool executebool(const uint *code) return b; } -bool executebool(const char *p) -{ +bool executebool(const char *p) { tagval result; executeret(p, result); bool b = getbool(result); @@ -2361,8 +2074,7 @@ bool executebool(const char *p) return b; } -bool executebool(ident *id, tagval *args, int numargs, bool lookup) -{ +bool executebool(ident *id, tagval *args, int numargs, bool lookup) { tagval result; executeret(id, args, numargs, lookup, result); bool b = getbool(result); @@ -2370,19 +2082,16 @@ bool executebool(ident *id, tagval *args, int numargs, bool lookup) return b; } -bool execidentbool(const char *name, bool noid, bool lookup) -{ +bool execidentbool(const char *name, bool noid, bool lookup) { ident *id = idents.access(name); return id ? executebool(id, NULL, 0, lookup) : noid; } -bool execfile(const char *cfgfile, bool msg) -{ +bool execfile(const char *cfgfile, bool msg) { string s; copystring(s, cfgfile); char *buf = loadfile(path(s), NULL); - if(!buf) - { + if(!buf) { if(msg) conoutf(CON_ERROR, "could not read \"%s\"", cfgfile); return false; } @@ -2397,16 +2106,14 @@ bool execfile(const char *cfgfile, bool msg) } ICOMMAND(exec, "sb", (char *file, int *msg), intret(execfile(file, *msg != 0) ? 1 : 0)); -const char *escapestring(const char *s) -{ +const char *escapestring(const char *s) { static vector strbuf[3]; static int stridx = 0; stridx = (stridx + 1)%3; vector &buf = strbuf[stridx]; buf.setsize(0); buf.add('"'); - for(; *s; s++) switch(*s) - { + for(; *s; s++) switch(*s) { case '\n': buf.put("^n", 2); break; case '\t': buf.put("^t", 2); break; case '\f': buf.put("^f", 2); break; @@ -2419,27 +2126,23 @@ const char *escapestring(const char *s) } ICOMMAND(escape, "s", (char *s), result(escapestring(s))); -ICOMMAND(unescape, "s", (char *s), -{ +ICOMMAND(unescape, "s", (char *s), { int len = strlen(s); char *d = newstring(len); d[unescapestring(d, s, &s[len])] = '\0'; stringret(d); }); -const char *escapeid(const char *s) -{ +const char *escapeid(const char *s) { const char *end = s + strcspn(s, "\"/;()[]@ \f\t\r\n\0"); return *end ? escapestring(s) : s; } -bool validateblock(const char *s) -{ +bool validateblock(const char *s) { const int maxbrak = 100; static char brakstack[maxbrak]; int brakdepth = 0; - for(; *s; s++) switch(*s) - { + for(; *s; s++) switch(*s) { case '[': case '(': if(brakdepth >= maxbrak) return false; brakstack[brakdepth++] = *s; break; case ']': if(brakdepth <= 0 || brakstack[--brakdepth] != '[') return false; break; case ')': if(brakdepth <= 0 || brakstack[--brakdepth] != '(') return false; break; @@ -2451,8 +2154,7 @@ bool validateblock(const char *s) } #ifndef STANDALONE -void writecfg(const char *name) -{ +void writecfg(const char *name) { stream *f = openutf8file(path(name && name[0] ? name : game::savedconfig(), true), "w"); if(!f) return; f->printf("// automatically written on exit, DO NOT MODIFY\n// delete this file to have %s overwrite these settings\n// modify settings in game, or put settings in %s to override anything\n\n", game::defaultconfig(), game::autoexec()); @@ -2462,11 +2164,9 @@ void writecfg(const char *name) vector ids; enumerate(idents, ident, id, ids.add(&id)); ids.sortname(); - loopv(ids) - { + loopv(ids) { ident &id = *ids[i]; - if(id.flags&IDF_PERSIST) switch(id.type) - { + if(id.flags&IDF_PERSIST) switch(id.type) { case ID_VAR: f->printf("%s %d\n", escapeid(id), *id.storage.i); break; case ID_FVAR: f->printf("%s %s\n", escapeid(id), floatstr(*id.storage.f)); break; case ID_SVAR: f->printf("%s %s\n", escapeid(id), escapestring(*id.storage.s)); break; @@ -2475,11 +2175,9 @@ void writecfg(const char *name) f->printf("\n"); writebinds(f); f->printf("\n"); - loopv(ids) - { + loopv(ids) { ident &id = *ids[i]; - if(id.type==ID_ALIAS && id.flags&IDF_PERSIST && !(id.flags&IDF_OVERRIDDEN)) switch(id.valtype) - { + if(id.type==ID_ALIAS && id.flags&IDF_PERSIST && !(id.flags&IDF_OVERRIDDEN)) switch(id.valtype) { case VAL_STR: if(!id.val.s[0]) break; if(!validateblock(id.val.s)) { f->printf("%s = %s\n", escapeid(id), escapestring(id.val.s)); break; } @@ -2498,8 +2196,7 @@ void writecfg(const char *name) COMMAND(writecfg, "s"); #endif -void changedvars() -{ +void changedvars() { vector ids; enumerate(idents, ident, id, if(id.flags&IDF_OVERRIDDEN) ids.add(&id)); ids.sortname(); @@ -2513,27 +2210,23 @@ COMMAND(changedvars, ""); static string retbuf[4]; static int retidx = 0; -const char *intstr(int v) -{ +const char *intstr(int v) { retidx = (retidx + 1)%4; intformat(retbuf[retidx], v); return retbuf[retidx]; } -void intret(int v) -{ +void intret(int v) { commandret->setint(v); } -const char *floatstr(float v) -{ +const char *floatstr(float v) { retidx = (retidx + 1)%4; floatformat(retbuf[retidx], v); return retbuf[retidx]; } -void floatret(float v) -{ +void floatret(float v) { commandret->setfloat(v); } @@ -2544,11 +2237,9 @@ ICOMMAND(do, "e", (uint *body), executeret(body, *commandret)); ICOMMAND(if, "tee", (tagval *cond, uint *t, uint *f), executeret(getbool(*cond) ? t : f, *commandret)); ICOMMAND(?, "ttt", (tagval *cond, tagval *t, tagval *f), result(*(getbool(*cond) ? t : f))); -ICOMMAND(pushif, "rte", (ident *id, tagval *v, uint *code), -{ +ICOMMAND(pushif, "rte", (ident *id, tagval *v, uint *code), { if(id->type != ID_ALIAS || id->index < MAXARGS) return; - if(getbool(*v)) - { + if(getbool(*v)) { identstack stack; pusharg(*id, *v, stack); v->type = VAL_NULL; @@ -2558,63 +2249,51 @@ ICOMMAND(pushif, "rte", (ident *id, tagval *v, uint *code), } }); -void loopiter(ident *id, identstack &stack, const tagval &v) -{ - if(id->stack != &stack) - { +void loopiter(ident *id, identstack &stack, const tagval &v) { + if(id->stack != &stack) { pusharg(*id, v, stack); id->flags &= ~IDF_UNKNOWN; } - else - { + else { if(id->valtype == VAL_STR) delete[] id->val.s; cleancode(*id); id->setval(v); } } -void loopend(ident *id, identstack &stack) -{ +void loopend(ident *id, identstack &stack) { if(id->stack == &stack) poparg(*id); } -static inline void setiter(ident &id, int i, identstack &stack) -{ - if(id.stack == &stack) - { - if(id.valtype != VAL_INT) - { +static inline void setiter(ident &id, int i, identstack &stack) { + if(id.stack == &stack) { + if(id.valtype != VAL_INT) { if(id.valtype == VAL_STR) delete[] id.val.s; cleancode(id); id.valtype = VAL_INT; } id.val.i = i; } - else - { + else { tagval t; t.setint(i); pusharg(id, t, stack); id.flags &= ~IDF_UNKNOWN; } } -ICOMMAND(loop, "rie", (ident *id, int *n, uint *body), -{ +ICOMMAND(loop, "rie", (ident *id, int *n, uint *body), { if(*n <= 0 || id->type!=ID_ALIAS) return; identstack stack; - loopi(*n) - { + loopi(*n) { setiter(*id, i, stack); execute(body); } poparg(*id); }); -ICOMMAND(loopwhile, "riee", (ident *id, int *n, uint *cond, uint *body), -{ +ICOMMAND(loopwhile, "riee", (ident *id, int *n, uint *cond, uint *body), { if(*n <= 0 || id->type!=ID_ALIAS) return; identstack stack; - loopi(*n) - { + loopi(*n) { setiter(*id, i, stack); if(!executebool(cond)) break; execute(body); @@ -2623,12 +2302,10 @@ ICOMMAND(loopwhile, "riee", (ident *id, int *n, uint *cond, uint *body), }); ICOMMAND(while, "ee", (uint *cond, uint *body), while(executebool(cond)) execute(body)); -char *loopconc(ident *id, int n, uint *body, bool space) -{ +char *loopconc(ident *id, int n, uint *body, bool space) { identstack stack; vector s; - loopi(n) - { + loopi(n) { setiter(*id, i, stack); tagval v; executeret(body, v); @@ -2643,39 +2320,32 @@ char *loopconc(ident *id, int n, uint *body, bool space) return newstring(s.getbuf(), s.length()-1); } -ICOMMAND(loopconcat, "rie", (ident *id, int *n, uint *body), -{ +ICOMMAND(loopconcat, "rie", (ident *id, int *n, uint *body), { if(*n > 0 && id->type==ID_ALIAS) commandret->setstr(loopconc(id, *n, body, true)); }); -ICOMMAND(loopconcatword, "rie", (ident *id, int *n, uint *body), -{ +ICOMMAND(loopconcatword, "rie", (ident *id, int *n, uint *body), { if(*n > 0 && id->type==ID_ALIAS) commandret->setstr(loopconc(id, *n, body, false)); }); -void concat(tagval *v, int n) -{ +void concat(tagval *v, int n) { commandret->setstr(conc(v, n, true)); } COMMAND(concat, "V"); -void concatword(tagval *v, int n) -{ +void concatword(tagval *v, int n) { commandret->setstr(conc(v, n, false)); } COMMAND(concatword, "V"); -void append(ident *id, tagval *v, bool space) -{ +void append(ident *id, tagval *v, bool space) { if(id->type != ID_ALIAS || v->type == VAL_NULL) return; - if(id->valtype == VAL_NULL) - { + if(id->valtype == VAL_NULL) { noprefix: if(id->index < MAXARGS) setarg(*id, *v); else setalias(*id, *v); v->type = VAL_NULL; } - else - { + else { const char *prefix = id->getstr(); if(!prefix[0]) goto noprefix; tagval r; @@ -2686,40 +2356,32 @@ void append(ident *id, tagval *v, bool space) ICOMMAND(append, "rt", (ident *id, tagval *v), append(id, v, true)); ICOMMAND(appendword, "rt", (ident *id, tagval *v), append(id, v, false)); -void result(tagval &v) -{ +void result(tagval &v) { *commandret = v; v.type = VAL_NULL; } -void stringret(char *s) -{ +void stringret(char *s) { commandret->setstr(s); } -void result(const char *s) -{ +void result(const char *s) { commandret->setstr(newstring(s)); } -ICOMMAND(result, "t", (tagval *v), -{ +ICOMMAND(result, "t", (tagval *v), { *commandret = *v; v->type = VAL_NULL; }); -void format(tagval *args, int numargs) -{ +void format(tagval *args, int numargs) { vector s; const char *f = args[0].getstr(); - while(*f) - { + while(*f) { int c = *f++; - if(c == '%') - { + if(c == '%') { int i = *f++; - if(i >= '1' && i <= '9') - { + if(i >= '1' && i <= '9') { i -= '0'; const char *sub = i < numargs ? args[i].getstr() : ""; while(*sub) s.add(*sub++); @@ -2735,31 +2397,25 @@ COMMAND(format, "V"); static const char *liststart = NULL, *listend = NULL, *listquotestart = NULL, *listquoteend = NULL; -static inline void skiplist(const char *&p) -{ - for(;;) - { +static inline void skiplist(const char *&p) { + for(;;) { p += strspn(p, " \t\r\n"); if(p[0]!='/' || p[1]!='/') break; p += strcspn(p, "\n\0"); } } -static bool parselist(const char *&s, const char *&start = liststart, const char *&end = listend, const char *"estart = listquotestart, const char *"eend = listquoteend) -{ +static bool parselist(const char *&s, const char *&start = liststart, const char *&end = listend, const char *"estart = listquotestart, const char *"eend = listquoteend) { skiplist(s); - switch(*s) - { + switch(*s) { case '"': quotestart = s++; start = s; s = parsestring(s); end = s; if(*s == '"') s++; quoteend = s; break; case '(': case '[': quotestart = s; start = s+1; - for(int braktype = *s++, brak = 1;;) - { + for(int braktype = *s++, brak = 1;;) { s += strcspn(s, "\"/;()[]\0"); int c = *s++; - switch(c) - { + switch(c) { case '\0': s--; quoteend = end = s; return true; case '"': s = parsestring(s); if(*s == '"') s++; break; case '/': if(*s == '/') s += strcspn(s, "\n\0"); break; @@ -2780,34 +2436,29 @@ static bool parselist(const char *&s, const char *&start = liststart, const char return true; } -void explodelist(const char *s, vector &elems, int limit) -{ +void explodelist(const char *s, vector &elems, int limit) { const char *start, *end; while((limit < 0 || elems.length() < limit) && parselist(s, start, end)) elems.add(newstring(start, end-start)); } -char *indexlist(const char *s, int pos) -{ +char *indexlist(const char *s, int pos) { loopi(pos) if(!parselist(s)) return newstring(""); const char *start, *end; return parselist(s, start, end) ? newstring(start, end-start) : newstring(""); } -int listlen(const char *s) -{ +int listlen(const char *s) { int n = 0; while(parselist(s)) n++; return n; } ICOMMAND(listlen, "s", (char *s), intret(listlen(s))); -void at(tagval *args, int numargs) -{ +void at(tagval *args, int numargs) { if(!numargs) return; const char *start = args[0].getstr(), *end = start + strlen(start); - for(int i = 1; i < numargs; i++) - { + for(int i = 1; i < numargs; i++) { const char *list = start; int pos = args[i].getint(); for(; pos > 0; pos--) if(!parselist(list)) break; @@ -2817,28 +2468,23 @@ void at(tagval *args, int numargs) } COMMAND(at, "si1V"); -void substr(char *s, int *start, int *count, int *numargs) -{ +void substr(char *s, int *start, int *count, int *numargs) { int len = strlen(s), offset = clamp(*start, 0, len); commandret->setstr(newstring(&s[offset], *numargs >= 3 ? clamp(*count, 0, len - offset) : len - offset)); } COMMAND(substr, "siiN"); -void chopstr(char *s, int *lim, char *ellipsis) -{ +void chopstr(char *s, int *lim, char *ellipsis) { int len = strlen(s), maxlen = abs(*lim); - if(len > maxlen) - { + if(len > maxlen) { int elen = strlen(ellipsis); maxlen = max(maxlen, elen); char *chopped = newstring(maxlen); - if(*lim < 0) - { + if(*lim < 0) { memcpy(chopped, ellipsis, elen); memcpy(&chopped[elen], &s[len - (maxlen - elen)], maxlen - elen); } - else - { + else { memcpy(chopped, s, maxlen - elen); memcpy(&chopped[maxlen - elen], ellipsis, elen); } @@ -2849,8 +2495,7 @@ void chopstr(char *s, int *lim, char *ellipsis) } COMMAND(chopstr, "sis"); -void sublist(const char *s, int *skip, int *count, int *numargs) -{ +void sublist(const char *s, int *skip, int *count, int *numargs) { int offset = max(*skip, 0), len = *numargs >= 3 ? max(*count, 0) : -1; loopi(offset) if(!parselist(s)) break; if(len < 0) { if(offset > 0) skiplist(s); commandret->setstr(newstring(s)); return; } @@ -2860,25 +2505,21 @@ void sublist(const char *s, int *skip, int *count, int *numargs) } COMMAND(sublist, "siiN"); -ICOMMAND(stripcolors, "s", (char *s), -{ +ICOMMAND(stripcolors, "s", (char *s), { int len = strlen(s); char *d = newstring(len); filtertext(d, s, true, false, len); stringret(d); }); -static inline void setiter(ident &id, char *val, identstack &stack) -{ - if(id.stack == &stack) - { +static inline void setiter(ident &id, char *val, identstack &stack) { + if(id.stack == &stack) { if(id.valtype == VAL_STR) delete[] id.val.s; else id.valtype = VAL_STR; cleancode(id); id.val.s = val; } - else - { + else { tagval t; t.setstr(val); pusharg(id, t, stack); @@ -2886,13 +2527,11 @@ static inline void setiter(ident &id, char *val, identstack &stack) } } -void listfind(ident *id, const char *list, const uint *body) -{ +void listfind(ident *id, const char *list, const uint *body) { if(id->type!=ID_ALIAS) { intret(-1); return; } identstack stack; int n = -1; - for(const char *s = list, *start, *end; parselist(s, start, end);) - { + for(const char *s = list, *start, *end; parselist(s, start, end);) { ++n; char *val = newstring(start, end-start); setiter(*id, val, stack); @@ -2904,13 +2543,11 @@ found: } COMMAND(listfind, "rse"); -void looplist(ident *id, const char *list, const uint *body) -{ +void looplist(ident *id, const char *list, const uint *body) { if(id->type!=ID_ALIAS) return; identstack stack; int n = 0; - for(const char *s = list, *start, *end; parselist(s, start, end); n++) - { + for(const char *s = list, *start, *end; parselist(s, start, end); n++) { char *val = newstring(start, end-start); setiter(*id, val, stack); execute(body); @@ -2919,13 +2556,11 @@ void looplist(ident *id, const char *list, const uint *body) } COMMAND(looplist, "rse"); -void loopsublist(ident *id, const char *list, int *skip, int *count, const uint *body) -{ +void loopsublist(ident *id, const char *list, int *skip, int *count, const uint *body) { if(id->type!=ID_ALIAS) return; identstack stack; int n = 0, offset = max(*skip, 0), len = *count < 0 ? INT_MAX : offset + *count; - for(const char *s = list, *start, *end; parselist(s, start, end) && n < len; n++) if(n >= offset) - { + for(const char *s = list, *start, *end; parselist(s, start, end) && n < len; n++) if(n >= offset) { char *val = newstring(start, end-start); setiter(*id, val, stack); execute(body); @@ -2934,19 +2569,15 @@ void loopsublist(ident *id, const char *list, int *skip, int *count, const uint } COMMAND(loopsublist, "rsiie"); -void looplistconc(ident *id, const char *list, const uint *body, bool space) -{ +void looplistconc(ident *id, const char *list, const uint *body, bool space) { if(id->type!=ID_ALIAS) return; identstack stack; vector r; int n = 0; - for(const char *s = list, *start, *end; parselist(s, start, end); n++) - { + for(const char *s = list, *start, *end; parselist(s, start, end); n++) { char *val = newstring(start, end-start); setiter(*id, val, stack); - if(n && space) r.add(' '); - tagval v; executeret(body, v); const char *vstr = v.getstr(); @@ -2961,19 +2592,15 @@ void looplistconc(ident *id, const char *list, const uint *body, bool space) ICOMMAND(looplistconcat, "rse", (ident *id, char *list, uint *body), looplistconc(id, list, body, true)); ICOMMAND(looplistconcatword, "rse", (ident *id, char *list, uint *body), looplistconc(id, list, body, false)); -void listfilter(ident *id, const char *list, const uint *body) -{ +void listfilter(ident *id, const char *list, const uint *body) { if(id->type!=ID_ALIAS) return; identstack stack; vector r; int n = 0; - for(const char *s = list, *start, *end, *quotestart, *quoteend; parselist(s, start, end, quotestart, quoteend); n++) - { + for(const char *s = list, *start, *end, *quotestart, *quoteend; parselist(s, start, end, quotestart, quoteend); n++) { char *val = newstring(start, end-start); setiter(*id, val, stack); - - if(executebool(body)) - { + if(executebool(body)) { if(r.length()) r.add(' '); r.put(quotestart, quoteend-quotestart); } @@ -2984,18 +2611,14 @@ void listfilter(ident *id, const char *list, const uint *body) } COMMAND(listfilter, "rse"); -void prettylist(const char *s, const char *conj) -{ +void prettylist(const char *s, const char *conj) { vector p; const char *start, *end; - for(int len = listlen(s), n = 0; parselist(s, start, end); n++) - { + for(int len = listlen(s), n = 0; parselist(s, start, end); n++) { p.put(start, end - start); - if(n+1 < len) - { + if(n+1 < len) { if(len > 2 || !conj[0]) p.add(','); - if(n+2 == len && conj[0]) - { + if(n+2 == len && conj[0]) { p.add(' '); p.put(conj, strlen(conj)); } @@ -3007,11 +2630,9 @@ void prettylist(const char *s, const char *conj) } COMMAND(prettylist, "ss"); -int listincludes(const char *list, const char *needle, int needlelen) -{ +int listincludes(const char *list, const char *needle, int needlelen) { int offset = 0; - for(const char *s = list, *start, *end; parselist(s, start, end);) - { + for(const char *s = list, *start, *end; parselist(s, start, end);) { int len = end - start; if(needlelen == len && !strncmp(needle, start, len)) return offset; offset++; @@ -3020,13 +2641,10 @@ int listincludes(const char *list, const char *needle, int needlelen) } ICOMMAND(indexof, "ss", (char *list, char *elem), intret(listincludes(list, elem, strlen(elem)))); -char *listdel(const char *s, const char *del) -{ +char *listdel(const char *s, const char *del) { vector p; - for(const char *start, *end, *qstart, *qend; parselist(s, start, end, qstart, qend);) - { - if(listincludes(del, start, end-start) < 0) - { + for(const char *start, *end, *qstart, *qend; parselist(s, start, end, qstart, qend);) { + if(listincludes(del, start, end-start) < 0) { if(!p.empty()) p.add(' '); p.put(qstart, qend-qstart); } @@ -3036,22 +2654,19 @@ char *listdel(const char *s, const char *del) } ICOMMAND(listdel, "ss", (char *list, char *del), commandret->setstr(listdel(list, del))); -void listsplice(const char *s, const char *vals, int *skip, int *count) -{ +void listsplice(const char *s, const char *vals, int *skip, int *count) { int offset = max(*skip, 0), len = max(*count, 0); const char *list = s, *start, *end, *qstart, *qend = s; loopi(offset) if(!parselist(s, start, end, qstart, qend)) break; vector p; if(qend > list) p.put(list, qend-list); - if(*vals) - { + if(*vals) { if(!p.empty()) p.add(' '); p.put(vals, strlen(vals)); } loopi(len) if(!parselist(s)) break; skiplist(s); - switch(*s) - { + switch(*s) { case '\0': case ')': case ']': break; default: if(!p.empty()) p.add(' '); @@ -3063,30 +2678,25 @@ void listsplice(const char *s, const char *vals, int *skip, int *count) } COMMAND(listsplice, "ssii"); -ICOMMAND(loopfiles, "rsse", (ident *id, char *dir, char *ext, uint *body), -{ +ICOMMAND(loopfiles, "rsse", (ident *id, char *dir, char *ext, uint *body), { if(id->type!=ID_ALIAS) return; identstack stack; vector files; listfiles(dir, ext[0] ? ext : NULL, files); - loopvrev(files) - { + loopvrev(files) { char *file = files[i]; bool redundant = false; loopj(i) if(!strcmp(files[j], file)) { redundant = true; break; } if(redundant) delete[] files.removeunordered(i); } - loopv(files) - { + loopv(files) { char *file = files[i]; - if(i) - { + if(i) { if(id->valtype == VAL_STR) delete[] id->val.s; else id->valtype = VAL_STR; id->val.s = file; } - else - { + else { tagval t; t.setstr(file); pusharg(*id, t, stack); @@ -3097,8 +2707,7 @@ ICOMMAND(loopfiles, "rsse", (ident *id, char *dir, char *ext, uint *body), if(files.length()) poparg(*id); }); -void findfile_(char *name) -{ +void findfile_(char *name) { string fname; copystring(fname, name); path(fname); @@ -3111,18 +2720,14 @@ void findfile_(char *name) } COMMANDN(findfile, findfile_, "s"); -struct sortitem -{ +struct sortitem { const char *str, *quotestart, *quoteend; }; -struct sortfun -{ +struct sortfun { ident *x, *y; uint *body; - - bool operator()(const sortitem &xval, const sortitem &yval) - { + bool operator()(const sortitem &xval, const sortitem &yval) { if(x->valtype != VAL_MACRO) x->valtype = VAL_MACRO; cleancode(*x); x->val.code = (const uint *)xval.str; @@ -3133,43 +2738,33 @@ struct sortfun } }; -void sortlist(char *list, ident *x, ident *y, uint *body) -{ +void sortlist(char *list, ident *x, ident *y, uint *body) { if(x == y || x->type != ID_ALIAS || y->type != ID_ALIAS) return; - vector items; int macrolen = strlen(list), total = 0; char *macros = newstring(list, macrolen); const char *curlist = list, *start, *end, *quotestart, *quoteend; - while(parselist(curlist, start, end, quotestart, quoteend)) - { + while(parselist(curlist, start, end, quotestart, quoteend)) { macros[end - list] = '\0'; sortitem item = { ¯os[start - list], quotestart, quoteend }; items.add(item); total += int(quoteend - quotestart); } - identstack xstack, ystack; pusharg(*x, nullval, xstack); x->flags &= ~IDF_UNKNOWN; pusharg(*y, nullval, ystack); y->flags &= ~IDF_UNKNOWN; - sortfun f = { x, y, body }; items.sort(f); - poparg(*x); poparg(*y); - char *sorted = macros; int sortedlen = total + max(items.length() - 1, 0); - if(macrolen < sortedlen) - { + if(macrolen < sortedlen) { delete[] macros; sorted = newstring(sortedlen); } - int offset = 0; - loopv(items) - { + loopv(items) { sortitem &item = items[i]; int len = int(item.quoteend - item.quotestart); if(i) sorted[offset++] = ' '; @@ -3177,7 +2772,6 @@ void sortlist(char *list, ident *x, ident *y, uint *body) offset += len; } sorted[offset] = '\0'; - commandret->setstr(sorted); } COMMAND(sortlist, "srre"); @@ -3210,21 +2804,17 @@ ICOMMAND(&~, "ii", (int *a, int *b), intret(*a & ~*b)); ICOMMAND(|~, "ii", (int *a, int *b), intret(*a | ~*b)); ICOMMAND(<<, "ii", (int *a, int *b), intret(*b < 32 ? *a << max(*b, 0) : 0)); ICOMMAND(>>, "ii", (int *a, int *b), intret(*a >> clamp(*b, 0, 31))); -ICOMMAND(&&, "e1V", (tagval *args, int numargs), -{ +ICOMMAND(&&, "e1V", (tagval *args, int numargs), { if(!numargs) intret(1); - else loopi(numargs) - { + else loopi(numargs) { if(i) freearg(*commandret); executeret(args[i].code, *commandret); if(!getbool(*commandret)) break; } }); -ICOMMAND(||, "e1V", (tagval *args, int numargs), -{ +ICOMMAND(||, "e1V", (tagval *args, int numargs), { if(!numargs) intret(0); - else loopi(numargs) - { + else loopi(numargs) { if(i) freearg(*commandret); executeret(args[i].code, *commandret); if(getbool(*commandret)) break; @@ -3248,26 +2838,22 @@ ICOMMAND(loge, "f", (float *a), floatret(log(*a))); ICOMMAND(log2, "f", (float *a), floatret(log(*a)/M_LN2)); ICOMMAND(log10, "f", (float *a), floatret(log10(*a))); ICOMMAND(exp, "f", (float *a), floatret(exp(*a))); -ICOMMAND(min, "V", (tagval *args, int numargs), -{ +ICOMMAND(min, "V", (tagval *args, int numargs), { int val = numargs > 0 ? args[numargs - 1].getint() : 0; loopi(numargs - 1) val = min(val, args[i].getint()); intret(val); }); -ICOMMAND(max, "V", (tagval *args, int numargs), -{ +ICOMMAND(max, "V", (tagval *args, int numargs), { int val = numargs > 0 ? args[numargs - 1].getint() : 0; loopi(numargs - 1) val = max(val, args[i].getint()); intret(val); }); -ICOMMAND(minf, "V", (tagval *args, int numargs), -{ +ICOMMAND(minf, "V", (tagval *args, int numargs), { float val = numargs > 0 ? args[numargs - 1].getfloat() : 0.0f; loopi(numargs - 1) val = min(val, args[i].getfloat()); floatret(val); }); -ICOMMAND(maxf, "V", (tagval *args, int numargs), -{ +ICOMMAND(maxf, "V", (tagval *args, int numargs), { float val = numargs > 0 ? args[numargs - 1].getfloat() : 0.0f; loopi(numargs - 1) val = max(val, args[i].getfloat()); floatret(val); @@ -3277,12 +2863,10 @@ ICOMMAND(absf, "f", (float *n), floatret(fabs(*n))); ICOMMAND(floor, "f", (float *n), floatret(floor(*n))); ICOMMAND(ceil, "f", (float *n), floatret(ceil(*n))); -ICOMMAND(round, "ff", (float *n, float *k), -{ +ICOMMAND(round, "ff", (float *n, float *k), { double step = *k; double r = *n; - if(step > 0) - { + if(step > 0) { r += step * (r < 0 ? -0.5 : 0.5); r -= fmod(r, step); } @@ -3290,34 +2874,29 @@ ICOMMAND(round, "ff", (float *n, float *k), floatret(float(r)); }); -ICOMMAND(cond, "ee2V", (tagval *args, int numargs), -{ - for(int i = 0; i < numargs; i += 2) - { - if(i+1 < numargs) - { - if(executebool(args[i].code)) - { +ICOMMAND(cond, "ee2V", (tagval *args, int numargs), { + for(int i = 0; i < numargs; i += 2) { + if(i+1 < numargs) { + if(executebool(args[i].code)) { executeret(args[i+1].code, *commandret); break; } } - else - { + else { executeret(args[i].code, *commandret); break; } } }); #define CASECOMMAND(name, fmt, type, acc, compare) \ - ICOMMAND(name, fmt "te2V", (tagval *args, int numargs), \ - { \ + ICOMMAND(name, fmt "te2V", (tagval *args, int numargs), { \ + \ type val = acc; \ int i; \ - for(i = 1; i+1 < numargs; i += 2) \ - { \ - if(compare) \ - { \ + for(i = 1; i+1 < numargs; i += 2) { \ + \ + if(compare) { \ + \ executeret(args[i+1].code, *commandret); \ return; \ } \ @@ -3328,15 +2907,12 @@ CASECOMMAND(casef, "f", float, args[0].getfloat(), args[i].type == VAL_NULL || a CASECOMMAND(cases, "s", const char *, args[0].getstr(), args[i].type == VAL_NULL || !strcmp(args[i].getstr(), val)); ICOMMAND(rnd, "ii", (int *a, int *b), intret(*a - *b > 0 ? rnd(*a - *b) + *b : *b)); -ICOMMAND(rndstr, "i", (int *len), -{ +ICOMMAND(rndstr, "i", (int *len), { int n = clamp(*len, 0, 10000); char *s = newstring(n); - for(int i = 0; i < n;) - { + for(int i = 0; i < n;) { uint r = randomMT(); - for(int j = min(i + 4, n); i < j; i++) - { + for(int j = min(i + 4, n); i < j; i++) { s[i] = (r%255) + 1; r /= 255; } @@ -3361,15 +2937,12 @@ ICOMMAND(codestr, "i", (int *i), { char *s = newstring(1); s[0] = char(*i); s[1] ICOMMAND(struni, "si", (char *s, int *i), intret(*i > 0 ? (memchr(s, 0, *i) ? 0 : cube2uni(s[*i])) : cube2uni(s[0]))); ICOMMAND(unistr, "i", (int *i), { char *s = newstring(1); s[0] = uni2cube(*i); s[1] = '\0'; stringret(s); }); -int naturalsort(const char *a, const char *b) -{ - for(;;) - { +int naturalsort(const char *a, const char *b) { + for(;;) { int ac = *a, bc = *b; if(!ac) return bc ? -1 : 0; else if(!bc) return 1; - else if(isdigit(ac) && isdigit(bc)) - { + else if(isdigit(ac) && isdigit(bc)) { while(*a == '0') a++; while(*b == '0') b++; const char *a0 = a, *b0 = b; @@ -3388,8 +2961,8 @@ int naturalsort(const char *a, const char *b) ICOMMAND(naturalsort, "ss", (char *a, char *b), intret(naturalsort(a,b)<=0)); #define STRMAPCOMMAND(name, map) \ - ICOMMAND(name, "s", (char *s), \ - { \ + ICOMMAND(name, "s", (char *s), { \ + \ int len = strlen(s); \ char *m = newstring(len); \ loopi(len) m[i] = map(s[i]); \ @@ -3400,23 +2973,18 @@ ICOMMAND(naturalsort, "ss", (char *a, char *b), intret(naturalsort(a,b)<=0)); STRMAPCOMMAND(strlower, cubelower); STRMAPCOMMAND(strupper, cubeupper); -char *strreplace(const char *s, const char *oldval, const char *newval) -{ +char *strreplace(const char *s, const char *oldval, const char *newval) { vector buf; - int oldlen = strlen(oldval); if(!oldlen) return newstring(s); - for(;;) - { + for(;;) { const char *found = strstr(s, oldval); - if(found) - { + if(found) { while(s < found) buf.add(*s++); for(const char *n = newval; *n; n++) buf.add(*n); s = found + oldlen; } - else - { + else { while(*s) buf.add(*s++); buf.add('\0'); return newstring(buf.getbuf(), buf.length()); @@ -3426,8 +2994,7 @@ char *strreplace(const char *s, const char *oldval, const char *newval) ICOMMAND(strreplace, "sss", (char *s, char *o, char *n), commandret->setstr(strreplace(s, o, n))); -void strsplice(const char *s, const char *vals, int *skip, int *count) -{ +void strsplice(const char *s, const char *vals, int *skip, int *count) { int slen = strlen(s), vlen = strlen(vals), offset = clamp(*skip, 0, slen), len = clamp(*count, 0, slen - offset); @@ -3443,15 +3010,13 @@ COMMAND(strsplice, "ssii"); #ifndef STANDALONE ICOMMAND(getmillis, "i", (int *total), intret(*total ? totalmillis : lastmillis)); -struct sleepcmd -{ +struct sleepcmd { int delay, millis, flags; char *command; }; vector sleepcmds; -void addsleep(int *msec, char *cmd) -{ +void addsleep(int *msec, char *cmd) { sleepcmd &s = sleepcmds.add(); s.delay = max(*msec, 1); s.millis = lastmillis; @@ -3461,13 +3026,10 @@ void addsleep(int *msec, char *cmd) COMMANDN(sleep, addsleep, "is"); -void checksleep(int millis) -{ - loopv(sleepcmds) - { +void checksleep(int millis) { + loopv(sleepcmds) { sleepcmd &s = sleepcmds[i]; - if(millis - s.millis >= s.delay) - { + if(millis - s.millis >= s.delay) { char *cmd = s.command; // execute might create more sleep commands s.command = NULL; int oldflags = identflags; @@ -3480,19 +3042,16 @@ void checksleep(int millis) } } -void clearsleep(bool clearoverrides) -{ +void clearsleep(bool clearoverrides) { int len = 0; - loopv(sleepcmds) if(sleepcmds[i].command) - { + loopv(sleepcmds) if(sleepcmds[i].command) { if(clearoverrides && !(sleepcmds[i].flags&IDF_OVERRIDDEN)) sleepcmds[len++] = sleepcmds[i]; else delete[] sleepcmds[i].command; } sleepcmds.shrink(len); } -void clearsleep_(int *clearoverrides) -{ +void clearsleep_(int *clearoverrides) { clearsleep(*clearoverrides!=0 || identflags&IDF_OVERRIDDEN); } diff --git a/src/engine/console.cpp b/src/engine/console.cpp index c979215..1386570 100644 --- a/src/engine/console.cpp +++ b/src/engine/console.cpp @@ -18,15 +18,12 @@ VARFP(maxcon, 10, 200, MAXCONLINES, { while(conlines.length() > maxcon) delete[] VARP(contags, 0, 3, 3); -void conline(int type, const char *sf) // add a line to the console buffer -{ +void conline(int type, const char *sf) { // add a line to the console buffer { char *buf = NULL; - if(type&CON_TAG_MASK) for(int i = conlines.length()-1; i >= max(conlines.length()-contags, 0); i--) - { + if(type&CON_TAG_MASK) for(int i = conlines.length()-1; i >= max(conlines.length()-contags, 0); i--) { int prev = conlines.removing(i).type; if(!(prev&CON_TAG_MASK)) break; - if(type == prev) - { + if(type == prev) { buf = conlines.remove(i).line; break; } @@ -39,8 +36,7 @@ void conline(int type, const char *sf) // add a line to the console buffer copystring(cl.line, sf, CONSTRLEN); } -void conoutfv(int type, const char *fmt, va_list args) -{ +void conoutfv(int type, const char *fmt, va_list args) { static char buf[CONSTRLEN]; vformatstring(buf, fmt, args, sizeof(buf)); conline(type, buf); @@ -50,10 +46,8 @@ void conoutfv(int type, const char *fmt, va_list args) VAR(fullconsole, 0, 0, 1); ICOMMAND(toggleconsole, "", (), { fullconsole ^= 1; }); -int rendercommand(int x, int y, int w) -{ +int rendercommand(int x, int y, int w) { if(commandmillis < 0) return 0; - defformatstring(s, "%s %s", commandprompt ? commandprompt : ">", commandbuf); int width, height; text_bounds(s, width, height, w); @@ -74,16 +68,13 @@ HVARP(miniconfilter, 0, 0, 0x7FFFFFF); int conskip = 0, miniconskip = 0; -void setconskip(int &skip, int filter, int n) -{ +void setconskip(int &skip, int filter, int n) { filter &= CON_FLAGS; int offset = abs(n), dir = n < 0 ? -1 : 1; skip = clamp(skip, 0, conlines.length()-1); - while(offset) - { + while(offset) { skip += dir; - if(!conlines.inrange(skip)) - { + if(!conlines.inrange(skip)) { skip = clamp(skip, 0, conlines.length()-1); return; } @@ -96,24 +87,18 @@ ICOMMAND(miniconskip, "i", (int *n), setconskip(miniconskip, miniconfilter, *n)) ICOMMAND(clearconsole, "", (), { while(conlines.length()) delete[] conlines.pop().line; }); -int drawconlines(int conskip, int confade, int conwidth, int conheight, int conoff, int filter, int y = 0, int dir = 1) -{ +int drawconlines(int conskip, int confade, int conwidth, int conheight, int conoff, int filter, int y = 0, int dir = 1) { filter &= CON_FLAGS; int numl = conlines.length(), offset = min(conskip, numl); - - if(confade) - { - if(!conskip) - { + if(confade) { + if(!conskip) { numl = 0; loopvrev(conlines) if(totalmillis-conlines[i].outtime < confade*1000) { numl = i+1; break; } } else offset--; } - int totalheight = 0; - loopi(numl) //determine visible height - { + loopi(numl) { //determine visible height { // shuffle backwards to fill if necessary int idx = offset+i < numl ? offset+i : --offset; if(!(conlines[idx].type&filter)) continue; @@ -124,8 +109,7 @@ int drawconlines(int conskip, int confade, int conwidth, int conheight, int cono totalheight += height; } if(dir > 0) y = conoff; - loopi(numl) - { + loopi(numl) { int idx = offset + (dir > 0 ? numl-i-1 : i); if(!(conlines[idx].type&filter)) continue; char *line = conlines[idx].line; @@ -138,16 +122,13 @@ int drawconlines(int conskip, int confade, int conwidth, int conheight, int cono return y+conoff; } -int renderconsole(int w, int h, int abovehud) // render buffer taking into account time & scrolling -{ +int renderconsole(int w, int h, int abovehud) { // render buffer taking into account time & scrolling { int conpad = fullconsole ? 0 : FONTH/4, conoff = fullconsole ? FONTH : FONTH/3, conheight = min(fullconsole ? ((h*fullconsize/100)/FONTH)*FONTH : FONTH*consize, h - 2*(conpad + conoff)), conwidth = w - 2*(conpad + conoff) - (fullconsole ? 0 : game::clipconsole(w, h)); - extern void consolebox(int x1, int y1, int x2, int y2); if(fullconsole) consolebox(conpad, conpad, conwidth+conpad+2*conoff, conheight+conpad+2*conoff); - int y = drawconlines(conskip, fullconsole ? 0 : confade, conwidth, conheight, conpad+conoff, fullconsole ? fullconfilter : confilter); if(!fullconsole && (miniconsize && miniconwidth)) drawconlines(miniconskip, miniconfade, (miniconwidth*(w - 2*(conpad + conoff)))/100, min(FONTH*miniconsize, abovehud - y), conpad+conoff, miniconfilter, abovehud, -1); @@ -156,29 +137,24 @@ int renderconsole(int w, int h, int abovehud) // render buffer taking into // keymap is defined externally in keymap.cfg -struct keym -{ - enum - { +struct keym { + enum { ACTION_DEFAULT = 0, ACTION_SPECTATOR, ACTION_EDITING, NUMACTIONS }; - int code; char *name; char *actions[NUMACTIONS]; bool pressed; - keym() : code(-1), name(NULL), pressed(false) { loopi(NUMACTIONS) actions[i] = newstring(""); } ~keym() { DELETEA(name); loopi(NUMACTIONS) DELETEA(actions[i]); } }; hashtable keyms(128); -void keymap(int *code, char *key) -{ +void keymap(int *code, char *key) { if(identflags&IDF_OVERRIDDEN) { conoutf(CON_ERROR, "cannot override keymap %d", *code); return; } keym &km = keyms[*code]; km.code = *code; @@ -191,19 +167,15 @@ COMMAND(keymap, "is"); keym *keypressed = NULL; char *keyaction = NULL; -const char *getkeyname(int code) -{ +const char *getkeyname(int code) { keym *km = keyms.access(code); return km ? km->name : NULL; } -void searchbinds(char *action, int type) -{ +void searchbinds(char *action, int type) { vector names; - enumerate(keyms, keym, km, - { - if(!strcmp(km.actions[type], action)) - { + enumerate(keyms, keym, km, { + if(!strcmp(km.actions[type], action)) { if(names.length()) names.add(' '); names.put(km.name, strlen(km.name)); } @@ -212,23 +184,19 @@ void searchbinds(char *action, int type) result(names.getbuf()); } -keym *findbind(char *key) -{ - enumerate(keyms, keym, km, - { +keym *findbind(char *key) { + enumerate(keyms, keym, km, { if(!strcasecmp(km.name, key)) return &km; }); return NULL; } -void getbind(char *key, int type) -{ +void getbind(char *key, int type) { keym *km = findbind(key); result(km ? km->actions[type] : ""); } -void bindkey(char *key, char *action, int state, const char *cmd) -{ +void bindkey(char *key, char *action, int state, const char *cmd) { if(identflags&IDF_OVERRIDDEN) { conoutf(CON_ERROR, "cannot override %s \"%s\"", cmd, key); return; } keym *km = findbind(key); if(!km) { conoutf(CON_ERROR, "unknown key \"%s\"", key); return; } @@ -251,8 +219,7 @@ ICOMMAND(searchbinds, "s", (char *action), searchbinds(action, keym::ACTION_DEF ICOMMAND(searchspecbinds, "s", (char *action), searchbinds(action, keym::ACTION_SPECTATOR)); ICOMMAND(searcheditbinds, "s", (char *action), searchbinds(action, keym::ACTION_EDITING)); -void inputcommand(char *init, char *action = NULL, char *prompt = NULL, char *flags = NULL) // turns input to the command line on or off -{ +void inputcommand(char *init, char *action = NULL, char *prompt = NULL, char *flags = NULL) { // turns input to the command line on or off { commandmillis = init ? totalmillis : -1; textinput(commandmillis >= 0, TI_CONSOLE); keyrepeat(commandmillis >= 0, KR_CONSOLE); @@ -263,8 +230,7 @@ void inputcommand(char *init, char *action = NULL, char *prompt = NULL, char *fl if(action && action[0]) commandaction = newstring(action); if(prompt && prompt[0]) commandprompt = newstring(prompt); commandflags = 0; - if(flags) while(*flags) switch(*flags++) - { + if(flags) while(*flags) switch(*flags++) { case 'c': commandflags |= CF_COMPLETE; break; case 'x': commandflags |= CF_EXECUTE; break; case 's': commandflags |= CF_COMPLETE|CF_EXECUTE; break; @@ -275,8 +241,7 @@ void inputcommand(char *init, char *action = NULL, char *prompt = NULL, char *fl ICOMMAND(saycommand, "C", (char *init), inputcommand(init)); COMMAND(inputcommand, "ssss"); -void pasteconsole() -{ +void pasteconsole() { if(!SDL_HasClipboardText()) return; char *cb = SDL_GetClipboardText(); if(!cb) return; @@ -287,21 +252,16 @@ void pasteconsole() SDL_free(cb); } -struct hline -{ +struct hline { char *buf, *action, *prompt; int flags; - hline() : buf(NULL), action(NULL), prompt(NULL), flags(0) {} - ~hline() - { + ~hline() { DELETEA(buf); DELETEA(action); DELETEA(prompt); } - - void restore() - { + void restore() { copystring(commandbuf, buf); if(commandpos >= (int)strlen(commandbuf)) commandpos = -1; DELETEA(commandaction); @@ -310,28 +270,21 @@ struct hline if(prompt) commandprompt = newstring(prompt); commandflags = flags; } - - bool shouldsave() - { + bool shouldsave() { return strcmp(commandbuf, buf) || (commandaction ? !action || strcmp(commandaction, action) : action!=NULL) || (commandprompt ? !prompt || strcmp(commandprompt, prompt) : prompt!=NULL) || commandflags != flags; } - - void save() - { + void save() { buf = newstring(commandbuf); if(commandaction) action = newstring(commandaction); if(commandprompt) prompt = newstring(commandprompt); flags = commandflags; } - - void run() - { + void run() { if(flags&CF_EXECUTE && buf[0]=='/') execute(buf+1); - else if(action) - { + else if(action) { alias("commandbuf", buf); execute(action); } @@ -343,11 +296,9 @@ int histpos = 0; VARP(maxhistory, 0, 1000, 10000); -void history_(int *n) -{ +void history_(int *n) { static bool inhistory = false; - if(!inhistory && history.inrange(*n)) - { + if(!inhistory && history.inrange(*n)) { inhistory = true; history[history.length()-*n-1]->run(); inhistory = false; @@ -356,15 +307,13 @@ void history_(int *n) COMMANDN(history, history_, "i"); -struct releaseaction -{ +struct releaseaction { keym *key; char *action; }; vector releaseactions; -const char *addreleaseaction(char *s) -{ +const char *addreleaseaction(char *s) { if(!keypressed) { delete[] s; return NULL; } releaseaction &ra = releaseactions.add(); ra.key = keypressed; @@ -372,30 +321,24 @@ const char *addreleaseaction(char *s) return keypressed->name; } -void onrelease(const char *s) -{ +void onrelease(const char *s) { addreleaseaction(newstring(s)); } COMMAND(onrelease, "s"); -void execbind(keym &k, bool isdown) -{ - loopv(releaseactions) - { +void execbind(keym &k, bool isdown) { + loopv(releaseactions) { releaseaction &ra = releaseactions[i]; - if(ra.key==&k) - { + if(ra.key==&k) { if(!isdown) execute(ra.action); delete[] ra.action; releaseactions.remove(i--); } } - if(isdown) - { + if(isdown) { int state = keym::ACTION_DEFAULT; - if(!mainmenu) - { + if(!mainmenu) { if(editmode) state = keym::ACTION_EDITING; else if(player->state==CS_SPECTATOR) state = keym::ACTION_SPECTATOR; } @@ -409,52 +352,39 @@ void execbind(keym &k, bool isdown) k.pressed = isdown; } -bool consoleinput(const char *str, int len) -{ +bool consoleinput(const char *str, int len) { if(commandmillis < 0) return false; - resetcomplete(); int cmdlen = (int)strlen(commandbuf), cmdspace = int(sizeof(commandbuf)) - (cmdlen+1); len = min(len, cmdspace); - if(commandpos<0) - { + if(commandpos<0) { memcpy(&commandbuf[cmdlen], str, len); } - else - { + else { memmove(&commandbuf[commandpos+len], &commandbuf[commandpos], cmdlen - commandpos); memcpy(&commandbuf[commandpos], str, len); commandpos += len; } commandbuf[cmdlen + len] = '\0'; - return true; } -bool consolekey(int code, bool isdown) -{ +bool consolekey(int code, bool isdown) { if(commandmillis < 0) return false; #define MOD_KEYS (KMOD_LCTRL|KMOD_RCTRL) - - if(isdown) - { - switch(code) - { + if(isdown) { + switch(code) { case SDLK_RETURN: case SDLK_KP_ENTER: break; - case SDLK_HOME: if(strlen(commandbuf)) commandpos = 0; break; - case SDLK_END: commandpos = -1; break; - - case SDLK_DELETE: - { + case SDLK_DELETE: { int len = (int)strlen(commandbuf); if(commandpos<0) break; memmove(&commandbuf[commandpos], &commandbuf[commandpos+1], len - commandpos); @@ -462,9 +392,7 @@ bool consolekey(int code, bool isdown) if(commandpos>=len-1) commandpos = -1; break; } - - case SDLK_BACKSPACE: - { + case SDLK_BACKSPACE: { int len = (int)strlen(commandbuf), i = commandpos>=0 ? commandpos : len; if(i<1) break; memmove(&commandbuf[i-1], &commandbuf[i], len - i + 1); @@ -473,49 +401,37 @@ bool consolekey(int code, bool isdown) else if(!commandpos && len<=1) commandpos = -1; break; } - case SDLK_LEFT: if(commandpos>0) commandpos--; else if(commandpos<0) commandpos = (int)strlen(commandbuf)-1; break; - case SDLK_RIGHT: if(commandpos>=0 && ++commandpos>=(int)strlen(commandbuf)) commandpos = -1; break; - case SDLK_UP: if(histpos > history.length()) histpos = history.length(); if(histpos > 0) history[--histpos]->restore(); break; - case SDLK_DOWN: if(histpos + 1 < history.length()) history[++histpos]->restore(); break; - case SDLK_TAB: - if(commandflags&CF_COMPLETE) - { + if(commandflags&CF_COMPLETE) { complete(commandbuf, sizeof(commandbuf), commandflags&CF_EXECUTE ? "/" : NULL); if(commandpos>=0 && commandpos>=(int)strlen(commandbuf)) commandpos = -1; } break; - case SDLK_v: if(SDL_GetModState()&MOD_KEYS) pasteconsole(); break; } } - else - { - if(code==SDLK_RETURN || code==SDLK_KP_ENTER) - { + else { + if(code==SDLK_RETURN || code==SDLK_KP_ENTER) { hline *h = NULL; - if(commandbuf[0]) - { - if(history.empty() || history.last()->shouldsave()) - { - if(maxhistory && history.length() >= maxhistory) - { + if(commandbuf[0]) { + if(history.empty() || history.last()->shouldsave()) { + if(maxhistory && history.length() >= maxhistory) { loopi(history.length()-maxhistory+1) delete history[i]; history.remove(0, history.length()-maxhistory+1); } @@ -527,59 +443,47 @@ bool consolekey(int code, bool isdown) inputcommand(NULL); if(h) h->run(); } - else if(code==SDLK_ESCAPE) - { + else if(code==SDLK_ESCAPE) { histpos = history.length(); inputcommand(NULL); } } - return true; } -void processtextinput(const char *str, int len) -{ +void processtextinput(const char *str, int len) { if(!g3d_input(str, len)) consoleinput(str, len); } -void processkey(int code, bool isdown, int modstate) -{ - switch(code) - { +void processkey(int code, bool isdown, int modstate) { + switch(code) { case SDLK_LGUI: case SDLK_RGUI: return; } keym *haskey = keyms.access(code); if(haskey && haskey->pressed) execbind(*haskey, isdown); // allow pressed keys to release - else if(!g3d_key(code, isdown)) // 3D GUI mouse button intercept - { - if(!consolekey(code, isdown)) - { + else if(!g3d_key(code, isdown)) { // 3D GUI mouse button intercept { + if(!consolekey(code, isdown)) { if(modstate&KMOD_GUI) return; if(haskey) execbind(*haskey, isdown); } } } -void clear_console() -{ +void clear_console() { keyms.clear(); } -void writebinds(stream *f) -{ +void writebinds(stream *f) { static const char * const cmds[3] = { "bind", "specbind", "editbind" }; vector binds; enumerate(keyms, keym, km, binds.add(&km)); binds.sortname(); - loopj(3) - { - loopv(binds) - { + loopj(3) { + loopv(binds) { keym &km = *binds[i]; - if(*km.actions[j]) - { + if(*km.actions[j]) { if(validateblock(km.actions[j])) f->printf("%s %s [%s]\n", cmds[j], escapestring(km.name), km.actions[j]); else f->printf("%s %s %s\n", cmds[j], escapestring(km.name), escapestring(km.actions[j])); } @@ -591,42 +495,33 @@ void writebinds(stream *f) enum { FILES_DIR = 0, FILES_VAR, FILES_LIST }; -struct fileskey -{ +struct fileskey { int type; const char *dir, *ext; - fileskey() {} fileskey(int type, const char *dir, const char *ext) : type(type), dir(dir), ext(ext) {} }; -static void cleanfilesdir(char *dir) -{ +static void cleanfilesdir(char *dir) { int dirlen = (int)strlen(dir); while(dirlen > 0 && (dir[dirlen-1] == '/' || dir[dirlen-1] == '\\')) dir[--dirlen] = '\0'; } -struct filesval -{ +struct filesval { int type; char *dir, *ext; vector files; int millis; - filesval(int type, const char *dir, const char *ext) : type(type), dir(newstring(dir)), ext(ext && ext[0] ? newstring(ext) : NULL), millis(-1) {} ~filesval() { DELETEA(dir); DELETEA(ext); files.deletearrays(); } - - void update() - { + void update() { if((type!=FILES_DIR && type!=FILES_VAR) || millis >= commandmillis) return; files.deletearrays(); - if(type==FILES_VAR) - { + if(type==FILES_VAR) { string buf; buf[0] = '\0'; - if(ident *id = readident(dir)) switch(id->type) - { + if(ident *id = readident(dir)) switch(id->type) { case ID_SVAR: copystring(buf, *id->storage.s); break; case ID_ALIAS: copystring(buf, id->getstr()); break; } @@ -641,13 +536,11 @@ struct filesval } }; -static inline bool htcmp(const fileskey &x, const fileskey &y) -{ +static inline bool htcmp(const fileskey &x, const fileskey &y) { return x.type==y.type && !strcmp(x.dir, y.dir) && (x.ext == y.ext || (x.ext && y.ext && !strcmp(x.ext, y.ext))); } -static inline uint hthash(const fileskey &k) -{ +static inline uint hthash(const fileskey &k) { return hthash(k.dir); } @@ -659,29 +552,24 @@ char *lastcomplete = NULL; void resetcomplete() { completesize = 0; } -void addcomplete(char *command, int type, char *dir, char *ext) -{ - if(identflags&IDF_OVERRIDDEN) - { +void addcomplete(char *command, int type, char *dir, char *ext) { + if(identflags&IDF_OVERRIDDEN) { conoutf(CON_ERROR, "cannot override complete %s", command); return; } - if(!dir[0]) - { + if(!dir[0]) { filesval **hasfiles = completions.access(command); if(hasfiles) *hasfiles = NULL; return; } if(type==FILES_DIR) cleanfilesdir(dir); - if(ext) - { + if(ext) { if(strchr(ext, '*')) ext[0] = '\0'; if(!ext[0]) ext = NULL; } fileskey key(type, dir, ext); filesval **val = completefiles.access(key); - if(!val) - { + if(!val) { filesval *f = new filesval(type, dir, ext); if(type==FILES_LIST) explodelist(dir, f->files); val = &completefiles[fileskey(type, f->dir, f->ext)]; @@ -692,18 +580,15 @@ void addcomplete(char *command, int type, char *dir, char *ext) else completions[newstring(command)] = *val; } -void addfilecomplete(char *command, char *dir, char *ext) -{ +void addfilecomplete(char *command, char *dir, char *ext) { addcomplete(command, FILES_DIR, dir, ext); } -void addvarcomplete(char *command, char *var, char *ext) -{ +void addvarcomplete(char *command, char *var, char *ext) { addcomplete(command, FILES_VAR, var, ext); } -void addlistcomplete(char *command, char *list) -{ +void addlistcomplete(char *command, char *list) { addcomplete(command, FILES_LIST, list, NULL); } @@ -711,31 +596,24 @@ COMMANDN(complete, addfilecomplete, "sss"); COMMANDN(varcomplete, addvarcomplete, "sss"); COMMANDN(listcomplete, addlistcomplete, "ss"); -void complete(char *s, int maxlen, const char *cmdprefix) -{ +void complete(char *s, int maxlen, const char *cmdprefix) { int cmdlen = 0; - if(cmdprefix) - { + if(cmdprefix) { cmdlen = strlen(cmdprefix); if(strncmp(s, cmdprefix, cmdlen)) prependstring(s, cmdprefix, maxlen); } if(!s[cmdlen]) return; if(!completesize) { completesize = (int)strlen(&s[cmdlen]); DELETEA(lastcomplete); } - filesval *f = NULL; - if(completesize) - { + if(completesize) { char *end = strchr(&s[cmdlen], ' '); if(end) f = completions.find(stringslice(&s[cmdlen], end), NULL); } - const char *nextcomplete = NULL; - if(f) // complete using filenames - { + if(f) { // complete using filenames { int commandsize = strchr(&s[cmdlen], ' ')+1-s; f->update(); - loopv(f->files) - { + loopv(f->files) { if(strncmp(f->files[i], &s[commandsize], completesize+cmdlen-commandsize)==0 && (!lastcomplete || strcmp(f->files[i], lastcomplete) > 0) && (!nextcomplete || strcmp(f->files[i], nextcomplete) < 0)) nextcomplete = f->files[i]; @@ -743,8 +621,7 @@ void complete(char *s, int maxlen, const char *cmdprefix) cmdprefix = s; cmdlen = commandsize; } - else // complete using command names - { + else { // complete using command names { enumerate(idents, ident, id, if(strncmp(id.name, &s[cmdlen], completesize)==0 && (!lastcomplete || strcmp(id.name, lastcomplete) > 0) && (!nextcomplete || strcmp(id.name, nextcomplete) < 0)) @@ -752,8 +629,7 @@ void complete(char *s, int maxlen, const char *cmdprefix) ); } DELETEA(lastcomplete); - if(nextcomplete) - { + if(nextcomplete) { cmdlen = min(cmdlen, maxlen-1); if(cmdlen) memmove(s, cmdprefix, cmdlen); copystring(&s[cmdlen], nextcomplete, maxlen-cmdlen); @@ -761,17 +637,14 @@ void complete(char *s, int maxlen, const char *cmdprefix) } } -void writecompletions(stream *f) -{ +void writecompletions(stream *f) { vector cmds; enumeratekt(completions, char *, k, filesval *, v, { if(v) cmds.add(k); }); cmds.sort(); - loopv(cmds) - { + loopv(cmds) { char *k = cmds[i]; filesval *v = completions[k]; - if(v->type==FILES_LIST) - { + if(v->type==FILES_LIST) { if(validateblock(v->dir)) f->printf("listcomplete %s [%s]\n", escapeid(k), v->dir); else f->printf("listcomplete %s %s\n", escapeid(k), escapestring(v->dir)); } diff --git a/src/engine/decal.cpp b/src/engine/decal.cpp index 43ef667..bc39c1f 100644 --- a/src/engine/decal.cpp +++ b/src/engine/decal.cpp @@ -1,21 +1,18 @@ #include "engine.h" -struct decalvert -{ +struct decalvert { vec pos; bvec4 color; vec2 tc; }; -struct decalinfo -{ +struct decalinfo { int millis; bvec color; ushort startvert, endvert; }; -enum -{ +enum { DF_RND4 = 1<<0, DF_ROTATE = 1<<1, DF_INVMOD = 1<<2, @@ -27,8 +24,7 @@ enum VARFP(maxdecaltris, 1, 1024, 16384, initdecals()); VARP(decalfade, 1000, 10000, 60000); -struct decalrenderer -{ +struct decalrenderer { const char *texname; int flags, fadeintime, fadeouttime, timetolive; Texture *tex; @@ -38,7 +34,6 @@ struct decalrenderer int maxverts, startvert, endvert, lastvert, availverts; GLuint vbo; bool dirty; - decalrenderer(const char *texname, int flags = 0, int fadeintime = 0, int fadeouttime = 1000, int timetolive = -1) : texname(texname), flags(flags), fadeintime(fadeintime), fadeouttime(fadeouttime), timetolive(timetolive), @@ -46,25 +41,18 @@ struct decalrenderer decals(NULL), maxdecals(0), startdecal(0), enddecal(0), verts(NULL), maxverts(0), startvert(0), endvert(0), lastvert(0), availverts(0), vbo(0), dirty(false), - decalu(0), decalv(0) - { + decalu(0), decalv(0) { } - - ~decalrenderer() - { + ~decalrenderer() { DELETEA(decals); DELETEA(verts); } - - void init(int tris) - { - if(decals) - { + void init(int tris) { + if(decals) { DELETEA(decals); maxdecals = startdecal = enddecal = 0; } - if(verts) - { + if(verts) { DELETEA(verts); maxverts = startvert = endvert = lastvert = availverts = 0; } @@ -75,80 +63,59 @@ struct decalrenderer availverts = maxverts - 3; verts = new decalvert[maxverts]; } - - int hasdecals() - { + int hasdecals() { return enddecal < startdecal ? maxdecals - (startdecal - enddecal) : enddecal - startdecal; } - - void cleanup() - { + void cleanup() { if(vbo) { glDeleteBuffers_(1, &vbo); vbo = 0; } } - - void cleardecals() - { + void cleardecals() { startdecal = enddecal = 0; startvert = endvert = lastvert = 0; availverts = maxverts - 3; dirty = true; } - - int freedecal() - { + int freedecal() { if(startdecal==enddecal) return 0; - decalinfo &d = decals[startdecal]; startdecal++; if(startdecal >= maxdecals) startdecal = 0; - int removed = d.endvert < d.startvert ? maxverts - (d.startvert - d.endvert) : d.endvert - d.startvert; startvert = d.endvert; if(startvert==endvert) startvert = endvert = lastvert = 0; availverts += removed; - return removed; } - - void fadedecal(decalinfo &d, uchar alpha) - { + void fadedecal(decalinfo &d, uchar alpha) { bvec rgb; if(flags&DF_OVERBRIGHT) rgb = bvec(128, 128, 128); - else - { + else { rgb = d.color; if(flags&(DF_ADD|DF_INVMOD)) rgb.scale(alpha, 255); } bvec4 color(rgb, alpha); - decalvert *vert = &verts[d.startvert], *end = &verts[d.endvert < d.startvert ? maxverts : d.endvert]; - while(vert < end) - { + while(vert < end) { vert->color = color; vert++; } - if(d.endvert < d.startvert) - { + if(d.endvert < d.startvert) { vert = verts; end = &verts[d.endvert]; - while(vert < end) - { + while(vert < end) { vert->color = color; vert++; } } dirty = true; } - - void clearfadeddecals() - { + void clearfadeddecals() { int threshold = lastmillis - (timetolive>=0 ? timetolive : decalfade) - fadeouttime; decalinfo *d = &decals[startdecal], *end = &decals[enddecal < startdecal ? maxdecals : enddecal]; while(d < end && d->millis <= threshold) d++; - if(d >= end && enddecal < startdecal) - { + if(d >= end && enddecal < startdecal) { d = decals; end = &decals[enddecal]; while(d < end && d->millis <= threshold) d++; @@ -161,25 +128,20 @@ struct decalrenderer availverts = endvert < startvert ? startvert - endvert - 3 : maxverts - 3 - (endvert - startvert); dirty = true; } - - void fadeindecals() - { + void fadeindecals() { if(!fadeintime) return; decalinfo *d = &decals[enddecal], *end = &decals[enddecal < startdecal ? 0 : startdecal]; - while(d > end) - { + while(d > end) { d--; int fade = lastmillis - d->millis; if(fade >= fadeintime) return; fadedecal(*d, (fade<<8)/fadeintime); } - if(enddecal < startdecal) - { + if(enddecal < startdecal) { d = &decals[maxdecals]; end = &decals[startdecal]; - while(d > end) - { + while(d > end) { d--; int fade = lastmillis - d->millis; if(fade >= fadeintime) return; @@ -187,25 +149,20 @@ struct decalrenderer } } } - - void fadeoutdecals() - { + void fadeoutdecals() { decalinfo *d = &decals[startdecal], *end = &decals[enddecal < startdecal ? maxdecals : enddecal]; int offset = (timetolive>=0 ? timetolive : decalfade) + fadeouttime - lastmillis; - while(d < end) - { + while(d < end) { int fade = d->millis + offset; if(fade >= fadeouttime) return; fadedecal(*d, (fade<<8)/fadeouttime); d++; } - if(enddecal < startdecal) - { + if(enddecal < startdecal) { d = decals; end = &decals[enddecal]; - while(d < end) - { + while(d < end) { int fade = d->millis + offset; if(fade >= fadeouttime) return; fadedecal(*d, (fade<<8)/fadeouttime); @@ -213,84 +170,59 @@ struct decalrenderer } } } - - static void setuprenderstate() - { + static void setuprenderstate() { enablepolygonoffset(GL_POLYGON_OFFSET_FILL); - glDepthMask(GL_FALSE); glEnable(GL_BLEND); - gle::enablevertex(); gle::enabletexcoord0(); gle::enablecolor(); } - - static void cleanuprenderstate() - { + static void cleanuprenderstate() { gle::clearvbo(); - gle::disablevertex(); gle::disabletexcoord0(); gle::disablecolor(); - glDepthMask(GL_TRUE); glDisable(GL_BLEND); - disablepolygonoffset(GL_POLYGON_OFFSET_FILL); } - - void render() - { + void render() { if(startvert==endvert) return; - - if(flags&DF_OVERBRIGHT) - { + if(flags&DF_OVERBRIGHT) { glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR); SETSHADER(overbrightdecal); } - else - { + else { if(flags&DF_INVMOD) { glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); } else if(flags&DF_ADD) { glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); } else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - if(flags&DF_SATURATE) SETSHADER(saturatedecal); } - glBindTexture(GL_TEXTURE_2D, tex->id); - if(!vbo) { glGenBuffers_(1, &vbo); dirty = true; } gle::bindvbo(vbo); - int count = endvert < startvert ? maxverts - startvert : endvert - startvert; - if(dirty) - { + if(dirty) { glBufferData_(GL_ARRAY_BUFFER, maxverts*sizeof(decalvert), NULL, GL_STREAM_DRAW); glBufferSubData_(GL_ARRAY_BUFFER, 0, count*sizeof(decalvert), &verts[startvert]); - if(endvert < startvert) - { + if(endvert < startvert) { glBufferSubData_(GL_ARRAY_BUFFER, count*sizeof(decalvert), endvert*sizeof(decalvert), verts); count += endvert; } dirty = false; } else if(endvert < startvert) count += endvert; - const decalvert *ptr = 0; gle::vertexpointer(sizeof(decalvert), ptr->pos.v); gle::texcoord0pointer(sizeof(decalvert), ptr->tc.v); gle::colorpointer(sizeof(decalvert), ptr->color.v); - glDrawArrays(GL_TRIANGLES, 0, count); xtravertsva += count; - extern int intel_vertexarray_bug; if(intel_vertexarray_bug) glFlush(); } - - decalinfo &newdecal() - { + decalinfo &newdecal() { decalinfo &d = decals[enddecal]; int next = enddecal + 1; if(next>=maxdecals) next = 0; @@ -299,20 +231,15 @@ struct decalrenderer dirty = true; return d; } - ivec bbmin, bbmax; vec decalcenter, decalnormal, decaltangent, decalbitangent; float decalradius, decalu, decalv; bvec4 decalcolor; - - void adddecal(const vec ¢er, const vec &dir, float radius, const bvec &color, int info) - { + void adddecal(const vec ¢er, const vec &dir, float radius, const bvec &color, int info) { if(dir.iszero()) return; - int bbradius = int(ceil(radius)); bbmin = ivec(center).sub(bbradius); bbmax = ivec(center).add(bbradius); - decalcolor = bvec4(color, 255); decalcenter = center; decalradius = radius; @@ -326,46 +253,36 @@ struct decalrenderer if(flags&DF_ROTATE) decaltangent.rotate(rnd(360)*RAD, dir); decaltangent.normalize(); decalbitangent.cross(decaltangent, dir); - if(flags&DF_RND4) - { + if(flags&DF_RND4) { decalu = 0.5f*(info&1); decalv = 0.5f*((info>>1)&1); } - lastvert = endvert; gentris(worldroot, ivec(0, 0, 0), worldsize>>1); if(endvert==lastvert) return; - decalinfo &d = newdecal(); d.color = color; d.millis = lastmillis; d.startvert = lastvert; d.endvert = endvert; } - - static int clip(const vec *in, int numin, const vec &dir, float below, float above, vec *out) - { + static int clip(const vec *in, int numin, const vec &dir, float below, float above, vec *out) { int numout = 0; const vec *p = &in[numin-1]; float pc = dir.dot(*p); - loopi(numin) - { + loopi(numin) { const vec &v = in[i]; float c = dir.dot(v); - if(c < below) - { + if(c < below) { if(pc > above) out[numout++] = vec(*p).sub(v).mul((above - c)/(pc - c)).add(v); if(pc > below) out[numout++] = vec(*p).sub(v).mul((below - c)/(pc - c)).add(v); } - else if(c > above) - { + else if(c > above) { if(pc < below) out[numout++] = vec(*p).sub(v).mul((below - c)/(pc - c)).add(v); if(pc < above) out[numout++] = vec(*p).sub(v).mul((above - c)/(pc - c)).add(v); } - else - { - if(pc < below) - { + else { + if(pc < below) { if(c > below) out[numout++] = vec(*p).sub(v).mul((below - c)/(pc - c)).add(v); } else if(pc > above && c < above) out[numout++] = vec(*p).sub(v).mul((above - c)/(pc - c)).add(v); @@ -376,17 +293,13 @@ struct decalrenderer } return numout; } - - void gentris(cube &cu, int orient, const ivec &o, int size, materialsurface *mat = NULL, int vismask = 0) - { + void gentris(cube &cu, int orient, const ivec &o, int size, materialsurface *mat = NULL, int vismask = 0) { vec pos[MAXFACEVERTS+4] = { vec(0, 0, 0) }; int numverts = 0, numplanes = 1; vec planes[2] = { vec(0, 0, 0) }; - if(mat) - { + if(mat) { planes[0] = vec(0, 0, 0); - switch(orient) - { + switch(orient) { #define GENFACEORIENT(orient, v0, v1, v2, v3) \ case orient: \ planes[0][dimension(orient)] = dimcoord(orient) ? 1 : -1; \ @@ -399,21 +312,18 @@ struct decalrenderer #undef GENFACEVERT } } - else if(cu.ext && (numverts = cu.ext->surfaces[orient].numverts&MAXFACEVERTS)) - { + else if(cu.ext && (numverts = cu.ext->surfaces[orient].numverts&MAXFACEVERTS)) { vertinfo *verts = cu.ext->verts() + cu.ext->surfaces[orient].verts; ivec vo = ivec(o).mask(~0xFFF).shl(3); loopj(numverts) pos[j] = vec(verts[j].getxyz().add(vo)).mul(1/8.0f); planes[0].cross(pos[0], pos[1], pos[2]).normalize(); - if(numverts >= 4 && !(cu.merged&(1<= 4 && !(cu.merged&(1<= 2) - { + if(numplanes >= 2) { if(l) { pos[1] = pos[2]; pos[2] = pos[3]; } numv = clip(pos, 3, pt, ptc - decalradius, ptc + decalradius, v1); if(numv<3) continue; } - else - { + else { numv = clip(pos, numverts, pt, ptc - decalradius, ptc + decalradius, v1); if(numv<3) continue; } @@ -475,13 +381,11 @@ struct decalrenderer dv2 = { v2[1], decalcolor, vec2(pt.dot(v2[1]) + tu, pb.dot(v2[1]) + tv) }; int totalverts = 3*(numv-2); if(totalverts > maxverts-3) return; - while(availverts < totalverts) - { + while(availverts < totalverts) { if(!freedecal()) return; } availverts -= totalverts; - loopk(numv-2) - { + loopk(numv-2) { verts[endvert++] = dv1; verts[endvert++] = dv2; dv2.pos = v2[k+2]; @@ -491,25 +395,20 @@ struct decalrenderer } } } - - void findmaterials(vtxarray *va) - { + void findmaterials(vtxarray *va) { materialsurface *matbuf = va->matbuf; int matsurfs = va->matsurfs; - loopi(matsurfs) - { + loopi(matsurfs) { materialsurface &m = matbuf[i]; if(1) { i += m.skip; continue; } int dim = dimension(m.orient), dc = dimcoord(m.orient); if(dc ? decalnormal[dim] <= 0 : decalnormal[dim] >= 0) { i += m.skip; continue; } int c = C[dim], r = R[dim]; - for(;;) - { + for(;;) { materialsurface &m = matbuf[i]; if(m.o[dim] >= bbmin[dim] && m.o[dim] <= bbmax[dim] && m.o[c] + m.csize >= bbmin[c] && m.o[c] <= bbmax[c] && - m.o[r] + m.rsize >= bbmin[r] && m.o[r] <= bbmax[r]) - { + m.o[r] + m.rsize >= bbmin[r] && m.o[r] <= bbmax[r]) { static cube dummy; gentris(dummy, m.orient, m.o, max(m.csize, m.rsize), &m); } @@ -520,51 +419,38 @@ struct decalrenderer } } } - - void findescaped(cube *cu, const ivec &o, int size, int escaped) - { - loopi(8) - { - if(escaped&(1<>1, cu[i].escaped); - else - { + else { int vismask = cu[i].merged; if(vismask) loopj(6) if(vismask&(1<va && cu[i].ext->va->matsurfs) findmaterials(cu[i].ext->va); if(cu[i].children) gentris(cu[i].children, co, size>>1, cu[i].escaped); - else - { + else { int vismask = cu[i].visible; - if(vismask&0xC0) - { + if(vismask&0xC0) { if(vismask&0x80) loopj(6) gentris(cu[i], j, co, size, NULL, vismask); else loopj(6) if(vismask&(1<>1, cu[i].escaped); - else - { + else { int vismask = cu[i].merged; if(vismask) loopj(6) if(vismask&(1<packages/particles/scorch.png", DF_ROTATE, 500), decalrenderer("packages/particles/blood.png", DF_RND4|DF_ROTATE|DF_INVMOD), decalrenderer("packages/particles/bullet.png", DF_OVERBRIGHT) }; -void initdecals() -{ +void initdecals() { loopi(sizeof(decals)/sizeof(decals[0])) decals[i].init(maxdecaltris); } -void cleardecals() -{ +void cleardecals() { loopi(sizeof(decals)/sizeof(decals[0])) decals[i].cleardecals(); } -void cleanupdecals() -{ +void cleanupdecals() { loopi(sizeof(decals)/sizeof(decals[0])) decals[i].cleanup(); } VARNP(decals, showdecals, 0, 1, 1); -void renderdecals(bool mainpass) -{ +void renderdecals(bool mainpass) { bool rendered = false; - loopi(sizeof(decals)/sizeof(decals[0])) - { + loopi(sizeof(decals)/sizeof(decals[0])) { decalrenderer &d = decals[i]; - if(mainpass) - { + if(mainpass) { d.clearfadeddecals(); d.fadeindecals(); d.fadeoutdecals(); } if(!showdecals || !d.hasdecals()) continue; - if(!rendered) - { + if(!rendered) { rendered = true; decalrenderer::setuprenderstate(); } @@ -623,8 +501,7 @@ void renderdecals(bool mainpass) VARP(maxdecaldistance, 1, 512, 10000); -void adddecal(int type, const vec ¢er, const vec &surface, float radius, const bvec &color, int info) -{ +void adddecal(int type, const vec ¢er, const vec &surface, float radius, const bvec &color, int info) { if(!showdecals || type<0 || (size_t)type>=sizeof(decals)/sizeof(decals[0]) || center.dist(camera1->o) - radius > maxdecaldistance) return; decalrenderer &d = decals[type]; d.adddecal(center, surface, radius, color, info); diff --git a/src/engine/dynlight.cpp b/src/engine/dynlight.cpp index d018480..0c2a08d 100644 --- a/src/engine/dynlight.cpp +++ b/src/engine/dynlight.cpp @@ -3,18 +3,14 @@ VARP(maxdynlights, 0, min(3, MAXDYNLIGHTS), MAXDYNLIGHTS); VARP(dynlightdist, 0, 1024, 10000); -struct dynlight -{ +struct dynlight { vec o, hud; float radius, initradius, curradius, dist; vec color, initcolor, curcolor; int fade, peak, expire, flags; physent *owner; - - void calcradius() - { - if(fade + peak > 0) - { + void calcradius() { + if(fade + peak > 0) { int remaining = expire - lastmillis; if(flags&DL_EXPAND) curradius = initradius + (radius - initradius) * (1.0f - remaining/float(fade + peak)); @@ -26,20 +22,15 @@ struct dynlight } else curradius = radius; } - - void calccolor() - { + void calccolor() { if(flags&DL_FLASH || peak <= 0) curcolor = color; - else - { + else { int peaking = expire - lastmillis - fade; if(peaking <= 0) curcolor = color; else curcolor.lerp(initcolor, color, 1.0f - float(peaking)/peak); } - float intensity = 1.0f; - if(fade > 0) - { + if(fade > 0) { int fading = expire - lastmillis; if(fading < fade) intensity = float(fading)/fade; } @@ -52,11 +43,9 @@ struct dynlight vector dynlights; vector closedynlights; -void adddynlight(const vec &o, float radius, const vec &color, int fade, int peak, int flags, float initradius, const vec &initcolor, physent *owner) -{ +void adddynlight(const vec &o, float radius, const vec &color, int fade, int peak, int flags, float initradius, const vec &initcolor, physent *owner) { if(!maxdynlights) return; if(o.dist(camera1->o) > dynlightdist || radius <= 0) return; - int insert = 0, expire = fade + peak + lastmillis; loopvrev(dynlights) if(expire>=dynlights[i].expire) { insert = i+1; break; } dynlight d; @@ -73,26 +62,21 @@ void adddynlight(const vec &o, float radius, const vec &color, int fade, int pea dynlights.insert(insert, d); } -void cleardynlights() -{ +void cleardynlights() { int faded = -1; loopv(dynlights) if(lastmillis0) dynlights.remove(0, faded); } -void removetrackeddynlights(physent *owner) -{ +void removetrackeddynlights(physent *owner) { loopvrev(dynlights) if(owner ? dynlights[i].owner == owner : dynlights[i].owner != NULL) dynlights.remove(i); } -void updatedynlights() -{ +void updatedynlights() { cleardynlights(); game::adddynlights(); - - loopv(dynlights) - { + loopv(dynlights) { dynlight &d = dynlights[i]; if(d.owner) game::dynlighttrack(d.owner, d.o, d.hud); d.calcradius(); @@ -100,14 +84,12 @@ void updatedynlights() } } -int finddynlights() -{ +int finddynlights() { closedynlights.setsize(0); if(!maxdynlights) return 0; physent e; e.type = ENT_CAMERA; - loopvj(dynlights) - { + loopvj(dynlights) { dynlight &d = dynlights[j]; if(d.curradius <= 0) continue; d.dist = camera1->o.dist(d.o) - d.curradius; @@ -116,7 +98,6 @@ int finddynlights() e.o = d.o; e.radius = e.xradius = e.yradius = e.eyeheight = e.aboveeye = d.curradius; if(!collide(&e, vec(0, 0, 0), 0, false)) continue; - int insert = 0; loopvrev(closedynlights) if(d.dist >= closedynlights[i]->dist) { insert = i+1; break; } closedynlights.insert(insert, &d); @@ -125,8 +106,7 @@ int finddynlights() return closedynlights.length(); } -bool getdynlight(int n, vec &o, float &radius, vec &color) -{ +bool getdynlight(int n, vec &o, float &radius, vec &color) { if(!closedynlights.inrange(n)) return false; dynlight &d = *closedynlights[n]; o = d.o; @@ -135,31 +115,25 @@ bool getdynlight(int n, vec &o, float &radius, vec &color) return true; } -void dynlightreaching(const vec &target, vec &color, vec &dir, bool hud) -{ +void dynlightreaching(const vec &target, vec &color, vec &dir, bool hud) { vec dyncolor(0, 0, 0);//, dyndir(0, 0, 0); - loopv(dynlights) - { + loopv(dynlights) { dynlight &d = dynlights[i]; if(d.curradius<=0) continue; - vec ray(hud ? d.hud : d.o); ray.sub(target); float mag = ray.squaredlen(); if(mag >= d.curradius*d.curradius) continue; - vec color = d.curcolor; color.mul(1 - sqrtf(mag)/d.curradius); dyncolor.add(color); //dyndir.add(ray.mul(intensity/mag)); } #if 0 - if(!dyndir.iszero()) - { + if(!dyndir.iszero()) { dyndir.normalize(); float x = dyncolor.magnitude(), y = color.magnitude(); - if(x+y>0) - { + if(x+y>0) { dir.mul(x); dyndir.mul(y); dir.add(dyndir).div(x+y); @@ -171,15 +145,12 @@ void dynlightreaching(const vec &target, vec &color, vec &dir, bool hud) color.add(dyncolor); } -void calcdynlightmask(vtxarray *va) -{ +void calcdynlightmask(vtxarray *va) { uint mask = 0; int offset = 0; - loopv(closedynlights) - { + loopv(closedynlights) { dynlight &d = *closedynlights[i]; if(d.o.dist_to_bb(va->geommin, va->geommax) >= d.curradius) continue; - mask |= (i+1)<= maxdynlights*DYNLIGHTBITS) break; @@ -187,35 +158,24 @@ void calcdynlightmask(vtxarray *va) va->dynlightmask = mask; } -int setdynlights(vtxarray *va) -{ +int setdynlights(vtxarray *va) { if(closedynlights.empty() || !va->dynlightmask) return 0; - extern bool minimizedynlighttcusage(); - static vec4 posv[MAXDYNLIGHTS]; static vec colorv[MAXDYNLIGHTS]; - int index = 0; - for(uint mask = va->dynlightmask; mask; mask >>= DYNLIGHTBITS, index++) - { + for(uint mask = va->dynlightmask; mask; mask >>= DYNLIGHTBITS, index++) { dynlight &d = *closedynlights[(mask&DYNLIGHTMASK)-1]; - float scale = 1.0f/d.curradius; vec origin = vec(d.o).mul(-scale); - - if(index>0 && minimizedynlighttcusage()) - { + if(index>0 && minimizedynlighttcusage()) { scale /= posv[0].w; origin.sub(vec(posv[0]).mul(scale)); } - posv[index] = vec4(origin, scale); colorv[index] = d.curcolor; } - GLOBALPARAMV(dynlightpos, posv, index); GLOBALPARAMV(dynlightcolor, colorv, index); - return index; } diff --git a/src/engine/engine.h b/src/engine/engine.h index e37ac4f..7bc0ef1 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -34,18 +34,14 @@ extern int zpass; extern vector entgroup; // rendertext -struct font -{ - struct charinfo - { +struct font { + struct charinfo { short x, y, w, h, offsetx, offsety, advance, tex; }; - char *name; vector texs; vector chars; int charoffset, defaultw, defaulth, scale; - font() : name(NULL) {} ~font() { DELETEA(name); } }; @@ -97,7 +93,6 @@ extern bool addshadowmapcaster(const vec &o, float xyrad, float zrad); extern bool isshadowmapreceiver(vtxarray *va); extern void rendershadowmap(); extern void pushshadowmap(); -extern void popshadowmap(); extern void rendershadowmapreceivers(); extern void guessshadowdir(); @@ -137,8 +132,7 @@ extern void screenquadoffset(float x, float y, float w, float h, float x2, float extern void hudquad(float x, float y, float w, float h, float tx = 0, float ty = 0, float tw = 1, float th = 1); extern void writecrosshairs(stream *f); -namespace modelpreview -{ +namespace modelpreview { extern void start(int x, int y, int w, int h, bool background = true); extern void end(); } @@ -195,8 +189,7 @@ extern void calcmerges(); extern int mergefaces(int orient, facebounds *m, int sz); extern void mincubeface(const cube &cu, int orient, const ivec &o, int size, const facebounds &orig, facebounds &cf, ushort nmat = MAT_AIR, ushort matmask = 0); -static inline cubeext &ext(cube &c) -{ +static inline cubeext &ext(cube &c) { return *(c.ext ? c.ext : newcubeext(c)); } @@ -336,8 +329,7 @@ extern void writebinds(stream *f); extern void writecompletions(stream *f); // main -enum -{ +enum { NOT_INITING = 0, INIT_GAME, INIT_LOAD, @@ -345,8 +337,7 @@ enum }; extern int initing, numcpus; -enum -{ +enum { CHANGE_GFX = 1<<0, CHANGE_SOUND = 1<<1 }; @@ -410,14 +401,12 @@ extern void loadskin(const char *dir, const char *altdir, Texture *&skin, Textur extern mapmodelinfo *getmminfo(int i); extern void startmodelquery(occludequery *query); extern void endmodelquery(); -extern void preloadmodelshaders(bool force = false); +extern void preloadmodelshaders(); extern void preloadusedmapmodels(bool msg = false, bool bih = false); -static inline model *loadmapmodel(int n) -{ +static inline model *loadmapmodel(int n) { extern vector mapmodels; - if(mapmodels.inrange(n)) - { + if(mapmodels.inrange(n)) { model *m = mapmodels[n].m; return m ? m : loadmodel(NULL, n); } diff --git a/src/engine/explosion.h b/src/engine/explosion.h deleted file mode 100644 index 819b0a3..0000000 --- a/src/engine/explosion.h +++ /dev/null @@ -1,179 +0,0 @@ -namespace sphere -{ - struct vert - { - vec pos; - ushort s, t; - } *verts = NULL; - GLushort *indices = NULL; - int numverts = 0, numindices = 0; - GLuint vbuf = 0, ebuf = 0; - - void init(int slices, int stacks) - { - numverts = (stacks+1)*(slices+1); - verts = new vert[numverts]; - float ds = 1.0f/slices, dt = 1.0f/stacks, t = 1.0f; - loopi(stacks+1) - { - float rho = M_PI*(1-t), s = 0.0f, sinrho = i && i < stacks ? sin(rho) : 0, cosrho = !i ? 1 : (i < stacks ? cos(rho) : -1); - loopj(slices+1) - { - float theta = j==slices ? 0 : 2*M_PI*s; - vert &v = verts[i*(slices+1) + j]; - v.pos = vec(-sin(theta)*sinrho, cos(theta)*sinrho, cosrho); - v.s = ushort(s*0xFFFF); - v.t = ushort(t*0xFFFF); - s += ds; - } - t -= dt; - } - - numindices = (stacks-1)*slices*3*2; - indices = new ushort[numindices]; - GLushort *curindex = indices; - loopi(stacks) - { - loopk(slices) - { - int j = i%2 ? slices-k-1 : k; - if(i) - { - *curindex++ = i*(slices+1)+j; - *curindex++ = (i+1)*(slices+1)+j; - *curindex++ = i*(slices+1)+j+1; - } - if(i+1 < stacks) - { - *curindex++ = i*(slices+1)+j+1; - *curindex++ = (i+1)*(slices+1)+j; - *curindex++ = (i+1)*(slices+1)+j+1; - } - } - } - - if(!vbuf) glGenBuffers_(1, &vbuf); - gle::bindvbo(vbuf); - glBufferData_(GL_ARRAY_BUFFER, numverts*sizeof(vert), verts, GL_STATIC_DRAW); - DELETEA(verts); - - if(!ebuf) glGenBuffers_(1, &ebuf); - gle::bindebo(ebuf); - glBufferData_(GL_ELEMENT_ARRAY_BUFFER, numindices*sizeof(GLushort), indices, GL_STATIC_DRAW); - DELETEA(indices); - } - - void enable() - { - if(!vbuf) init(12, 6); - - gle::bindvbo(vbuf); - gle::bindebo(ebuf); - - gle::vertexpointer(sizeof(vert), &verts->pos); - gle::texcoord0pointer(sizeof(vert), &verts->s, GL_UNSIGNED_SHORT, 2, GL_TRUE); - gle::enablevertex(); - gle::enabletexcoord0(); - } - - void draw() - { - glDrawRangeElements_(GL_TRIANGLES, 0, numverts-1, numindices, GL_UNSIGNED_SHORT, indices); - xtraverts += numindices; - glde++; - } - - void disable() - { - gle::disablevertex(); - gle::disabletexcoord0(); - - gle::clearvbo(); - gle::clearebo(); - } - - void cleanup() - { - if(vbuf) { glDeleteBuffers_(1, &vbuf); vbuf = 0; } - if(ebuf) { glDeleteBuffers_(1, &ebuf); ebuf = 0; } - } -} - -static const float WOBBLE = 1.25f; - -struct fireballrenderer : listrenderer -{ - fireballrenderer(const char *texname) - : listrenderer(texname, 0, PT_FIREBALL|PT_GLARE|PT_SHADER) - {} - - void startrender() - { - SETSHADER(explosion); - sphere::enable(); - } - - void endrender() - { - sphere::disable(); - } - - void cleanup() - { - sphere::cleanup(); - } - - void seedemitter(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int gravity) - { - pe.maxfade = max(pe.maxfade, fade); - pe.extendbb(o, (size+1+pe.ent->attr2)*WOBBLE); - } - - void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) - { - float pmax = p->val, size = p->fade ? float(ts)/p->fade : 1, psize = p->size + pmax * size; - - vec dir = vec(o).sub(camera1->o), s, t; - float dist = dir.magnitude(); - bool inside = dist <= psize*WOBBLE; - if(inside) - { - s = camright; - t = camup; - } - else - { - float mag2 = dir.magnitude2(); - dir.x /= mag2; - dir.y /= mag2; - dir.z /= dist; - s = vec(dir.y, -dir.x, 0); - t = vec(dir.x*dir.z, dir.y*dir.z, -mag2/dist); - } - - matrix3 rot(lastmillis/1000.0f*143*RAD, vec(1/SQRT3, 1/SQRT3, 1/SQRT3)); - LOCALPARAM(texgenS, rot.transposedtransform(s)); - LOCALPARAM(texgenT, rot.transposedtransform(t)); - - matrix4 m(rot, o); - m.scale(psize, psize, inside ? -psize : psize); - m.mul(camprojmatrix, m); - LOCALPARAM(explosionmatrix, m); - - LOCALPARAM(center, o); - LOCALPARAMF(millis, lastmillis/1000.0f); - LOCALPARAMF(blendparams, inside ? 0.5f : 4, inside ? 0.25f : 0); - - int passes = inside ? 2 : 1; - loopi(passes) - { - gle::color(p->color, i ? blend/2 : blend); - if(i) glDepthFunc(GL_GEQUAL); - sphere::draw(); - if(i) glDepthFunc(GL_LESS); - } - } -}; - -static fireballrenderer fireballs("packages/particles/explosion.png"), bluefireballs("packages/particles/plasma.png"); - diff --git a/src/engine/iqm.h b/src/engine/iqm.h index e36a628..5e7323f 100644 --- a/src/engine/iqm.h +++ b/src/engine/iqm.h @@ -1,7 +1,6 @@ struct iqm; -struct iqmheader -{ +struct iqmheader { char magic[16]; uint version; uint filesize; @@ -18,16 +17,14 @@ struct iqmheader uint num_extensions, ofs_extensions; }; -struct iqmmesh -{ +struct iqmmesh { uint name; uint material; uint first_vertex, num_vertexes; uint first_triangle, num_triangles; }; -enum -{ +enum { IQM_POSITION = 0, IQM_TEXCOORD = 1, IQM_NORMAL = 2, @@ -38,8 +35,7 @@ enum IQM_CUSTOM = 0x10 }; -enum -{ +enum { IQM_BYTE = 0, IQM_UBYTE = 1, IQM_SHORT = 2, @@ -51,13 +47,11 @@ enum IQM_DOUBLE = 8, }; -struct iqmtriangle -{ +struct iqmtriangle { uint vertex[3]; }; -struct iqmjoint -{ +struct iqmjoint { uint name; int parent; vec pos; @@ -65,8 +59,7 @@ struct iqmjoint vec size; }; -struct iqmpose -{ +struct iqmpose { int parent; uint mask; vec offsetpos; @@ -77,16 +70,14 @@ struct iqmpose vec scalesize; }; -struct iqmanim -{ +struct iqmanim { uint name; uint first_frame, num_frames; float framerate; uint flags; }; -struct iqmvertexarray -{ +struct iqmvertexarray { uint type; uint flags; uint format; @@ -94,35 +85,25 @@ struct iqmvertexarray uint offset; }; -struct iqm : skelloader -{ +struct iqm : skelloader { iqm(const char *name) : skelloader(name) {} - static const char *formatname() { return "iqm"; } int type() const { return MDL_IQM; } - - struct iqmmeshgroup : skelmeshgroup - { - iqmmeshgroup() - { + struct iqmmeshgroup : skelmeshgroup { + iqmmeshgroup() { } - - bool loadiqmmeshes(const char *filename, const iqmheader &hdr, uchar *buf) - { + bool loadiqmmeshes(const char *filename, const iqmheader &hdr, uchar *buf) { lilswap((uint *)&buf[hdr.ofs_vertexarrays], hdr.num_vertexarrays*sizeof(iqmvertexarray)/sizeof(uint)); lilswap((uint *)&buf[hdr.ofs_triangles], hdr.num_triangles*sizeof(iqmtriangle)/sizeof(uint)); lilswap((uint *)&buf[hdr.ofs_meshes], hdr.num_meshes*sizeof(iqmmesh)/sizeof(uint)); lilswap((uint *)&buf[hdr.ofs_joints], hdr.num_joints*sizeof(iqmjoint)/sizeof(uint)); - const char *str = hdr.ofs_text ? (char *)&buf[hdr.ofs_text] : ""; float *vpos = NULL, *vnorm = NULL, *vtan = NULL, *vtc = NULL; uchar *vindex = NULL, *vweight = NULL; iqmvertexarray *vas = (iqmvertexarray *)&buf[hdr.ofs_vertexarrays]; - loopi(hdr.num_vertexarrays) - { + loopi(hdr.num_vertexarrays) { iqmvertexarray &va = vas[i]; - switch(va.type) - { + switch(va.type) { case IQM_POSITION: if(va.format != IQM_FLOAT || va.size != 3) return false; vpos = (float *)&buf[va.offset]; lilswap(vpos, 3*hdr.num_vertexes); break; case IQM_NORMAL: if(va.format != IQM_FLOAT || va.size != 3) return false; vnorm = (float *)&buf[va.offset]; lilswap(vnorm, 3*hdr.num_vertexes); break; case IQM_TANGENT: if(va.format != IQM_FLOAT || va.size != 4) return false; vtan = (float *)&buf[va.offset]; lilswap(vtan, 4*hdr.num_vertexes); break; @@ -132,25 +113,19 @@ struct iqm : skelloader } } if(!vpos) return false; - iqmtriangle *tris = (iqmtriangle *)&buf[hdr.ofs_triangles]; iqmmesh *imeshes = (iqmmesh *)&buf[hdr.ofs_meshes]; iqmjoint *joints = (iqmjoint *)&buf[hdr.ofs_joints]; - - if(hdr.num_joints) - { - if(skel->numbones <= 0) - { + if(hdr.num_joints) { + if(skel->numbones <= 0) { skel->numbones = hdr.num_joints; skel->bones = new boneinfo[skel->numbones]; - loopi(hdr.num_joints) - { + loopi(hdr.num_joints) { iqmjoint &j = joints[i]; boneinfo &b = skel->bones[i]; if(!b.name) b.name = newstring(&str[j.name]); b.parent = j.parent; - if(skel->shared <= 1) - { + if(skel->shared <= 1) { j.pos.y = -j.pos.y; j.orient.x = -j.orient.x; j.orient.z = -j.orient.z; @@ -161,13 +136,10 @@ struct iqm : skelloader } } } - if(skel->shared <= 1) skel->linkchildren(); } - - loopi(hdr.num_meshes) - { + loopi(hdr.num_meshes) { iqmmesh &im = imeshes[i]; skelmesh *m = new skelmesh; m->group = this; @@ -175,12 +147,10 @@ struct iqm : skelloader m->name = newstring(&str[im.name]); m->numverts = im.num_vertexes; int noblend = -1; - if(m->numverts) - { + if(m->numverts) { m->verts = new vert[m->numverts]; if(vtan) m->bumpverts = new bumpvert[m->numverts]; - if(!vindex || !vweight) - { + if(!vindex || !vweight) { blendcombo c; c.finalize(0); noblend = m->addblendcombo(c); @@ -192,30 +162,25 @@ struct iqm : skelloader *mtan = vtan ? vtan + 4*fv : NULL, *mtc = vtc ? vtc + 2*fv : NULL; uchar *mindex = vindex ? vindex + 4*fv : NULL, *mweight = vweight ? vweight + 4*fv : NULL; - loopj(im.num_vertexes) - { + loopj(im.num_vertexes) { vert &v = m->verts[j]; v.pos = vec(mpos[0], -mpos[1], mpos[2]); mpos += 3; - if(mtc) - { + if(mtc) { v.tc = vec2(mtc[0], mtc[1]); mtc += 2; } else v.tc = vec2(0, 0); - if(mnorm) - { + if(mnorm) { v.norm = vec(mnorm[0], -mnorm[1], mnorm[2]); mnorm += 3; - if(mtan) - { + if(mtan) { m->calctangent(m->bumpverts[j], v.norm, vec(mtan[0], -mtan[1], mtan[2]), mtan[3]); mtan += 4; } } else v.norm = vec(0, 0, 0); - if(noblend < 0) - { + if(noblend < 0) { blendcombo c; int sorted = 0; loopk(4) sorted = c.addweight(sorted, mweight[k], mindex[k]); @@ -229,39 +194,31 @@ struct iqm : skelloader m->numtris = im.num_triangles; if(m->numtris) m->tris = new tri[m->numtris]; iqmtriangle *mtris = tris + im.first_triangle; - loopj(im.num_triangles) - { + loopj(im.num_triangles) { tri &t = m->tris[j]; t.vert[0] = mtris->vertex[0] - fv; t.vert[1] = mtris->vertex[1] - fv; t.vert[2] = mtris->vertex[2] - fv; ++mtris; } - if(!m->numtris || !m->numverts) - { + if(!m->numtris || !m->numverts) { conoutf(CON_WARN, "empty mesh in %s", filename); meshes.removeobj(m); delete m; } } - sortblendcombos(); - return true; } - - bool loadiqmanims(const char *filename, const iqmheader &hdr, uchar *buf) - { + bool loadiqmanims(const char *filename, const iqmheader &hdr, uchar *buf) { lilswap((uint *)&buf[hdr.ofs_poses], hdr.num_poses*sizeof(iqmpose)/sizeof(uint)); lilswap((uint *)&buf[hdr.ofs_anims], hdr.num_anims*sizeof(iqmanim)/sizeof(uint)); lilswap((ushort *)&buf[hdr.ofs_frames], hdr.num_frames*hdr.num_framechannels); - const char *str = hdr.ofs_text ? (char *)&buf[hdr.ofs_text] : ""; iqmpose *poses = (iqmpose *)&buf[hdr.ofs_poses]; iqmanim *anims = (iqmanim *)&buf[hdr.ofs_anims]; ushort *frames = (ushort *)&buf[hdr.ofs_frames]; - loopi(hdr.num_anims) - { + loopi(hdr.num_anims) { iqmanim &a = anims[i]; string name; copystring(name, filename); @@ -273,8 +230,7 @@ struct iqm : skelloader sa->frame = skel->numframes; sa->range = a.num_frames; dualquat *animbones = new dualquat[(skel->numframes+a.num_frames)*skel->numbones]; - if(skel->bones) - { + if(skel->bones) { memcpy(animbones, skel->framebones, skel->numframes*skel->numbones*sizeof(dualquat)); delete[] skel->framebones; } @@ -282,11 +238,9 @@ struct iqm : skelloader animbones += skel->numframes*skel->numbones; skel->numframes += a.num_frames; ushort *animdata = &frames[a.first_frame*hdr.num_framechannels]; - loopj(a.num_frames) - { + loopj(a.num_frames) { dualquat *frame = &animbones[j*skel->numbones]; - loopk(skel->numbones) - { + loopk(skel->numbones) { iqmpose &p = poses[k]; vec pos; quat orient; @@ -298,8 +252,7 @@ struct iqm : skelloader orient.z = -p.offsetorient.z; if(p.mask&0x20) orient.z -= *animdata++ * p.scaleorient.z; orient.w = p.offsetorient.w; if(p.mask&0x40) orient.w += *animdata++ * p.scaleorient.w; orient.normalize(); - if(p.mask&0x380) - { + if(p.mask&0x380) { if(p.mask&0x80) animdata++; if(p.mask&0x100) animdata++; if(p.mask&0x200) animdata++; @@ -313,15 +266,11 @@ struct iqm : skelloader } } } - return true; } - - bool loadiqm(const char *filename, bool doloadmesh, bool doloadanim) - { + bool loadiqm(const char *filename, bool doloadmesh, bool doloadanim) { stream *f = openfile(filename, "rb"); if(!f) return false; - uchar *buf = NULL; iqmheader hdr; if(f->read(&hdr, sizeof(hdr)) != sizeof(hdr) || memcmp(hdr.magic, "INTERQUAKEMODEL", sizeof(hdr.magic))) goto error; @@ -330,33 +279,24 @@ struct iqm : skelloader if(hdr.filesize > (16<<20)) goto error; // sanity check... don't load files bigger than 16 MB buf = new (false) uchar[hdr.filesize]; if(!buf || f->read(buf + sizeof(hdr), hdr.filesize - sizeof(hdr)) != hdr.filesize - sizeof(hdr)) goto error; - if(doloadmesh && !loadiqmmeshes(filename, hdr, buf)) goto error; if(doloadanim && !loadiqmanims(filename, hdr, buf)) goto error; - delete[] buf; delete f; return true; - error: if(buf) delete[] buf; delete f; return false; } - - bool loadmesh(const char *filename) - { + bool loadmesh(const char *filename) { name = newstring(filename); - return loadiqm(filename, true, false); } - - skelanimspec *loadanim(const char *animname) - { + skelanimspec *loadanim(const char *animname) { const char *sep = strchr(animname, ':'); skelanimspec *sa = skel->findskelanim(animname, sep ? '\0' : ':'); - if(!sa) - { + if(!sa) { string filename; copystring(filename, animname); if(sep) filename[sep - animname] = '\0'; @@ -366,17 +306,13 @@ struct iqm : skelloader return sa; } }; - - meshgroup *loadmeshes(const char *name, va_list args) - { + meshgroup *loadmeshes(const char *name, va_list args) { iqmmeshgroup *group = new iqmmeshgroup; group->shareskeleton(va_arg(args, char *)); if(!group->loadmesh(name)) { delete group; return NULL; } return group; } - - bool loaddefaultparts() - { + bool loaddefaultparts() { skelpart &mdl = addpart(); mdl.pitchscale = mdl.pitchoffset = mdl.pitchmin = mdl.pitchmax = 0; adjustments.setsize(0); @@ -393,4 +329,3 @@ struct iqm : skelloader }; skelcommands iqmcommands; - diff --git a/src/engine/lightmap.cpp b/src/engine/lightmap.cpp index a317dd5..1481de9 100644 --- a/src/engine/lightmap.cpp +++ b/src/engine/lightmap.cpp @@ -6,8 +6,7 @@ struct lightmapinfo; struct lightmaptask; -struct lightmapworker -{ +struct lightmapworker { uchar *buf; int bufstart, bufused; lightmapinfo *firstlightmap, *lastlightmap, *curlightmaps; @@ -25,19 +24,15 @@ struct lightmapworker bool needspace, doneworking; SDL_cond *spacecond; SDL_Thread *thread; - lightmapworker(); ~lightmapworker(); - void reset(); bool setupthread(); void cleanupthread(); - static int work(void *data); }; -struct lightmapinfo -{ +struct lightmapinfo { lightmapinfo *next; cube *c; uchar *colorbuf; @@ -46,8 +41,7 @@ struct lightmapinfo int type, w, h, bpp, bufsize, surface, layers; }; -struct lightmaptask -{ +struct lightmaptask { ivec o; int size, usefaces, progress; cube *c; @@ -56,8 +50,7 @@ struct lightmaptask lightmapworker *worker; }; -struct lightmapext -{ +struct lightmapext { cube *c; cubeext *ext; }; @@ -78,14 +71,12 @@ VARR(lighterror, 1, 8, 16); VARR(bumperror, 1, 3, 16); VARR(lightlod, 0, 0, 10); bvec ambientcolor(36, 24, 12); -HVARFR(ambient, 1, 0x191919, 0xFFFFFF, -{ +HVARFR(ambient, 1, 0x191919, 0xFFFFFF, { if(ambient <= 255) ambient |= (ambient<<8) | (ambient<<16); ambientcolor = bvec((ambient>>16)&0xFF, (ambient>>8)&0xFF, ambient&0xFF); }); -static const surfaceinfo brightsurfaces[6] = -{ +static const surfaceinfo brightsurfaces[6] = { brightsurface, brightsurface, brightsurface, @@ -94,28 +85,23 @@ static const surfaceinfo brightsurfaces[6] = brightsurface }; -void brightencube(cube &c) -{ +void brightencube(cube &c) { if(!c.ext) newcubeext(c, 0, false); memcpy(c.ext->surfaces, brightsurfaces, sizeof(brightsurfaces)); } -void setsurfaces(cube &c, const surfaceinfo *surfs, const vertinfo *verts, int numverts) -{ +void setsurfaces(cube &c, const surfaceinfo *surfs, const vertinfo *verts, int numverts) { if(!c.ext || c.ext->maxverts < numverts) newcubeext(c, numverts, false); memcpy(c.ext->surfaces, surfs, sizeof(c.ext->surfaces)); memcpy(c.ext->verts(), verts, numverts*sizeof(vertinfo)); } -void setsurface(cube &c, int orient, const surfaceinfo &src, const vertinfo *srcverts, int numsrcverts) -{ +void setsurface(cube &c, int orient, const surfaceinfo &src, const vertinfo *srcverts, int numsrcverts) { int dstoffset = 0; if(!c.ext) newcubeext(c, numsrcverts, true); - else - { + else { int numbefore = 0, beforeoffset = 0; - loopi(orient) - { + loopi(orient) { surfaceinfo &surf = c.ext->surfaces[i]; int numverts = surf.totalverts(); if(!numverts) continue; @@ -123,8 +109,7 @@ void setsurface(cube &c, int orient, const surfaceinfo &src, const vertinfo *src beforeoffset = surf.verts + numverts; } int numafter = 0, afteroffset = c.ext->maxverts; - for(int i = 5; i > orient; i--) - { + for(int i = 5; i > orient; i--) { surfaceinfo &surf = c.ext->surfaces[i]; int numverts = surf.totalverts(); if(!numverts) continue; @@ -132,22 +117,18 @@ void setsurface(cube &c, int orient, const surfaceinfo &src, const vertinfo *src afteroffset = surf.verts; } if(afteroffset - beforeoffset >= numsrcverts) dstoffset = beforeoffset; - else - { + else { cubeext *ext = c.ext; - if(numbefore + numsrcverts + numafter > c.ext->maxverts) - { + if(numbefore + numsrcverts + numafter > c.ext->maxverts) { ext = growcubeext(c.ext, numbefore + numsrcverts + numafter); memcpy(ext->surfaces, c.ext->surfaces, sizeof(ext->surfaces)); } int offset = 0; - if(numbefore == beforeoffset) - { + if(numbefore == beforeoffset) { if(numbefore && c.ext != ext) memcpy(ext->verts(), c.ext->verts(), numbefore*sizeof(vertinfo)); offset = numbefore; } - else loopi(orient) - { + else loopi(orient) { surfaceinfo &surf = ext->surfaces[i]; int numverts = surf.totalverts(); if(!numverts) continue; @@ -157,11 +138,9 @@ void setsurface(cube &c, int orient, const surfaceinfo &src, const vertinfo *src } dstoffset = offset; offset += numsrcverts; - if(numafter && offset > afteroffset) - { + if(numafter && offset > afteroffset) { offset += numafter; - for(int i = 5; i > orient; i--) - { + for(int i = 5; i > orient; i--) { surfaceinfo &surf = ext->surfaces[i]; int numverts = surf.totalverts(); if(!numverts) continue; @@ -192,30 +171,23 @@ static int progresstexticks = 0, progresslightmap = -1; bool calclight_canceled = false; volatile bool check_calclight_progress = false; -void check_calclight_canceled() -{ - if(interceptkey(SDLK_ESCAPE)) - { +void check_calclight_canceled() { + if(interceptkey(SDLK_ESCAPE)) { calclight_canceled = true; loopv(lightmapworkers) lightmapworkers[i]->doneworking = true; } if(!calclight_canceled) check_calclight_progress = false; } -void show_calclight_progress() -{ +void show_calclight_progress() { float bar1 = float(progress) / float(allocnodes); defformatstring(text1, "%d%% using %d textures", int(bar1 * 100), lightmaps.length()); - - if(LM_PACKW <= hwtexsize && !progresstex) - { + if(LM_PACKW <= hwtexsize && !progresstex) { glGenTextures(1, &progresstex); createtexture(progresstex, LM_PACKW, LM_PACKH, NULL, 3, 1, GL_RGB); } - // only update once a sec (4 * 250 ms ticks) to not kill performance - if(progresstex && !calclight_canceled && progresslightmap >= 0 && !(progresstexticks++ % 4)) - { + if(progresstex && !calclight_canceled && progresslightmap >= 0 && !(progresstexticks++ % 4)) { if(tasklock) SDL_LockMutex(tasklock); LightMap &lm = lightmaps[progresslightmap]; uchar *data = lm.data; @@ -231,56 +203,45 @@ void show_calclight_progress() #define CHECK_PROGRESS_LOCKED(exit, before, after) CHECK_CALCLIGHT_PROGRESS_LOCKED(exit, show_calclight_progress, before, after) #define CHECK_PROGRESS(exit) CHECK_PROGRESS_LOCKED(exit, , ) -bool PackNode::insert(ushort &tx, ushort &ty, ushort tw, ushort th) -{ +bool PackNode::insert(ushort &tx, ushort &ty, ushort tw, ushort th) { if((available < tw && available < th) || w < tw || h < th) return false; - if(child1) - { + if(child1) { bool inserted = child1->insert(tx, ty, tw, th) || child2->insert(tx, ty, tw, th); available = max(child1->available, child2->available); if(!available) clear(); return inserted; } - if(w == tw && h == th) - { + if(w == tw && h == th) { available = 0; tx = x; ty = y; return true; } - - if(w - tw > h - th) - { + if(w - tw > h - th) { child1 = new PackNode(x, y, tw, h); child2 = new PackNode(x + tw, y, w - tw, h); } - else - { + else { child1 = new PackNode(x, y, w, th); child2 = new PackNode(x, y + th, w, h - th); } - bool inserted = child1->insert(tx, ty, tw, th); available = max(child1->available, child2->available); return inserted; } -bool LightMap::insert(ushort &tx, ushort &ty, uchar *src, ushort tw, ushort th) -{ +bool LightMap::insert(ushort &tx, ushort &ty, uchar *src, ushort tw, ushort th) { if((type&LM_TYPE) != LM_BUMPMAP1 && !packroot.insert(tx, ty, tw, th)) return false; - copy(tx, ty, src, tw, th); return true; } -void LightMap::copy(ushort tx, ushort ty, uchar *src, ushort tw, ushort th) -{ +void LightMap::copy(ushort tx, ushort ty, uchar *src, ushort tw, ushort th) { uchar *dst = data + bpp * tx + ty * bpp * LM_PACKW; - loopi(th) - { + loopi(th) { memcpy(dst, src, bpp * tw); dst += bpp * LM_PACKW; src += bpp * tw; @@ -289,20 +250,16 @@ void LightMap::copy(ushort tx, ushort ty, uchar *src, ushort tw, ushort th) lumels += tw * th; } -static void insertunlit(int i) -{ +static void insertunlit(int i) { LightMap &l = lightmaps[i]; - if((l.type&LM_TYPE) == LM_BUMPMAP1) - { + if((l.type&LM_TYPE) == LM_BUMPMAP1) { l.unlitx = l.unlity = -1; return; } ushort x, y; uchar unlit[4] = { ambientcolor[0], ambientcolor[1], ambientcolor[2], 255 }; - if(l.insert(x, y, unlit, 1, 1)) - { - if((l.type&LM_TYPE) == LM_BUMPMAP0) - { + if(l.insert(x, y, unlit, 1, 1)) { + if((l.type&LM_TYPE) == LM_BUMPMAP0) { bvec front(128, 128, 255); ASSERT(lightmaps[i+1].insert(x, y, front.v, 1, 1)); } @@ -311,26 +268,20 @@ static void insertunlit(int i) } } -struct layoutinfo -{ +struct layoutinfo { ushort x, y, lmid; uchar w, h; }; -static void insertlightmap(lightmapinfo &li, layoutinfo &si) -{ - loopv(lightmaps) - { - if(lightmaps[i].type == li.type && lightmaps[i].insert(si.x, si.y, li.colorbuf, si.w, si.h)) - { +static void insertlightmap(lightmapinfo &li, layoutinfo &si) { + loopv(lightmaps) { + if(lightmaps[i].type == li.type && lightmaps[i].insert(si.x, si.y, li.colorbuf, si.w, si.h)) { si.lmid = i + LMID_RESERVED; if((li.type&LM_TYPE) == LM_BUMPMAP0) ASSERT(lightmaps[i+1].insert(si.x, si.y, (uchar *)li.raybuf, si.w, si.h)); return; } } - progresslightmap = lightmaps.length(); - si.lmid = lightmaps.length() + LMID_RESERVED; LightMap &l = lightmaps.add(); l.type = li.type; @@ -338,8 +289,7 @@ static void insertlightmap(lightmapinfo &li, layoutinfo &si) l.data = new uchar[li.bpp*LM_PACKW*LM_PACKH]; memset(l.data, 0, li.bpp*LM_PACKW*LM_PACKH); ASSERT(l.insert(si.x, si.y, li.colorbuf, si.w, si.h)); - if((li.type&LM_TYPE) == LM_BUMPMAP0) - { + if((li.type&LM_TYPE) == LM_BUMPMAP0) { LightMap &r = lightmaps.add(); r.type = LM_BUMPMAP1 | (li.type&~LM_TYPE); r.bpp = 3; @@ -349,8 +299,7 @@ static void insertlightmap(lightmapinfo &li, layoutinfo &si) } } -static inline bool htcmp(const lightmapinfo &k, const layoutinfo &v) -{ +static inline bool htcmp(const lightmapinfo &k, const layoutinfo &v) { int kw = k.w, kh = k.h; if(kw != v.w || kh != v.h) return false; LightMap &vlm = lightmaps[v.lmid - LMID_RESERVED]; @@ -358,16 +307,14 @@ static inline bool htcmp(const lightmapinfo &k, const layoutinfo &v) if(ktype != vlm.type) return false; int kbpp = k.bpp; const uchar *kcolor = k.colorbuf, *vcolor = vlm.data + kbpp*(v.x + v.y*LM_PACKW); - loopi(kh) - { + loopi(kh) { if(memcmp(kcolor, vcolor, kbpp*kw)) return false; kcolor += kbpp*kw; vcolor += kbpp*LM_PACKW; } if((ktype&LM_TYPE) != LM_BUMPMAP0) return true; const bvec *kdir = k.raybuf, *vdir = (const bvec *)lightmaps[v.lmid+1 - LMID_RESERVED].data + (v.x + v.y*LM_PACKW); - loopi(kh) - { + loopi(kh) { if(memcmp(kdir, vdir, kw*sizeof(bvec))) return false; kdir += kw; vdir += LM_PACKW; @@ -375,13 +322,11 @@ static inline bool htcmp(const lightmapinfo &k, const layoutinfo &v) return true; } -static inline uint hthash(const lightmapinfo &k) -{ +static inline uint hthash(const lightmapinfo &k) { int kw = k.w, kh = k.h, kbpp = k.bpp; uint hash = kw + (kh<<8); const uchar *color = k.colorbuf; - loopi(kw*kh) - { + loopi(kw*kh) { hash ^= color[0] + (color[1] << 4) + (color[2] << 8); color += kbpp; } @@ -392,20 +337,16 @@ static hashset compressed; VAR(lightcompress, 0, 3, 6); -static bool packlightmap(lightmapinfo &l, layoutinfo &surface) -{ +static bool packlightmap(lightmapinfo &l, layoutinfo &surface) { surface.w = l.w; surface.h = l.h; - if((int)l.w <= lightcompress && (int)l.h <= lightcompress) - { + if((int)l.w <= lightcompress && (int)l.h <= lightcompress) { layoutinfo *val = compressed.access(l); - if(!val) - { + if(!val) { insertlightmap(l, surface); compressed[l] = surface; } - else - { + else { surface.x = val->x; surface.y = val->y; surface.lmid = val->lmid; @@ -416,13 +357,11 @@ static bool packlightmap(lightmapinfo &l, layoutinfo &surface) return true; } -static uint generatelumel(lightmapworker *w, const float tolerance, uint lightmask, const vector &lights, const vec &target, const vec &normal, vec &sample, int x, int y) -{ +static uint generatelumel(lightmapworker *w, const float tolerance, uint lightmask, const vector &lights, const vec &target, const vec &normal, vec &sample, int x, int y) { vec avgray(0, 0, 0); float r = 0, g = 0, b = 0; uint lightused = 0; - loopv(lights) - { + loopv(lights) { if(lightmask&(1<type==ET_SPOTLIGHT) - { + if(light.attached && light.attached->type==ET_SPOTLIGHT) { vec spot = vec(light.attached->o).sub(light.o).normalize(); float maxatten = sincos360[clamp(int(light.attached->attr1), 1, 89)].x, spotatten = (ray.dot(spot) - maxatten) / (1 - maxatten); if(spotatten <= 0) continue; attenuation *= spotatten; } - if(lmshadows && mag) - { + if(lmshadows && mag) { float dist = shadowray(w->shadowraycache, light.o, ray, mag - tolerance, RAY_SHADOW | (lmshadows > 1 ? RAY_ALPHAPOLY : 0)); if(dist < mag - tolerance) continue; } lightused |= 1<type&LM_TYPE) - { + switch(w->type&LM_TYPE) { case LM_BUMPMAP0: intensity = attenuation; avgray.add(ray.mul(-attenuation)); @@ -466,8 +401,7 @@ static uint generatelumel(lightmapworker *w, const float tolerance, uint lightma g += intensity * float(light.attr3); b += intensity * float(light.attr4); } - switch(w->type&LM_TYPE) - { + switch(w->type&LM_TYPE) { case LM_BUMPMAP0: if(avgray.iszero()) break; // transform to tangent space @@ -486,8 +420,7 @@ static uint generatelumel(lightmapworker *w, const float tolerance, uint lightma return lightused; } -static bool lumelsample(const vec &sample, int aasample, int stride) -{ +static bool lumelsample(const vec &sample, int aasample, int stride) { if(sample.x >= int(ambientcolor[0])+1 || sample.y >= int(ambientcolor[1])+1 || sample.z >= int(ambientcolor[2])+1) return true; #define NCHECK(n) \ if((n).x >= int(ambientcolor[0])+1 || (n).y >= int(ambientcolor[1])+1 || (n).z >= int(ambientcolor[2])+1) \ @@ -501,11 +434,9 @@ static bool lumelsample(const vec &sample, int aasample, int stride) return false; } -static inline void generatealpha(lightmapworker *w, float tolerance, const vec &pos, uchar &alpha) -{ +static inline void generatealpha(lightmapworker *w, float tolerance, const vec &pos, uchar &alpha) { alpha = 0; - if(w->slot->layermask) - { + if(w->slot->layermask) { static const int sdim[] = { 1, 0, 0 }, tdim[] = { 2, 2, 1 }; int dim = dimension(w->orient); float k = 8.0f/w->vslot->scale, @@ -520,8 +451,7 @@ static inline void generatealpha(lightmapworker *w, float tolerance, const vec & if(mx < 0) mx += mask.w; if(my < 0) my += mask.h; uchar maskval = mask.data[mask.bpp*(mx + 1) - 1 + mask.pitch*my]; - switch(w->slot->layermaskmode) - { + switch(w->slot->layermaskmode) { case 2: alpha = min(alpha, maskval); break; case 3: alpha = max(alpha, maskval); break; case 4: alpha = min(alpha, uchar(0xFF - maskval)); break; @@ -534,8 +464,7 @@ static inline void generatealpha(lightmapworker *w, float tolerance, const vec & VAR(edgetolerance, 1, 4, 64); VAR(adaptivesample, 0, 2, 2); -enum -{ +enum { NO_SURFACE = 0, SURFACE_AMBIENT_BOTTOM, SURFACE_AMBIENT_TOP, @@ -547,33 +476,29 @@ enum #define SURFACE_AMBIENT SURFACE_AMBIENT_BOTTOM #define SURFACE_LIGHTMAP SURFACE_LIGHTMAP_BOTTOM -static bool generatelightmap(lightmapworker *w, float lpu, const lerpvert *lv, int numv, vec origin1, const vec &xstep1, const vec &ystep1, vec origin2, const vec &xstep2, const vec &ystep2, float side0, float sidestep) -{ - static const float aacoords[8][2] = - { - {0.0f, 0.0f}, - {-0.5f, -0.5f}, - {0.0f, -0.5f}, - {-0.5f, 0.0f}, - - {0.3f, -0.6f}, - {0.6f, 0.3f}, - {-0.3f, 0.6f}, - {-0.6f, -0.3f}, +static bool generatelightmap(lightmapworker *w, float lpu, const lerpvert *lv, int numv, vec origin1, const vec &xstep1, const vec &ystep1, vec origin2, const vec &xstep2, const vec &ystep2, float side0, float sidestep) { + static const float aacoords[8][2] = { + { + 0.0f, 0.0f}, { + -0.5f, -0.5f}, { + 0.0f, -0.5f}, { + -0.5f, 0.0f}, + { + 0.3f, -0.6f}, { + 0.6f, 0.3f}, { + -0.3f, 0.6f}, { + -0.6f, -0.3f}, }; float tolerance = 0.5 / lpu; uint lightmask = 0, lightused = 0; vec offsets1[8], offsets2[8]; - loopi(8) - { + loopi(8) { offsets1[i] = vec(xstep1).mul(aacoords[i][0]).add(vec(ystep1).mul(aacoords[i][1])); offsets2[i] = vec(xstep2).mul(aacoords[i][0]).add(vec(ystep2).mul(aacoords[i][1])); } if((w->type&LM_TYPE) == LM_BUMPMAP0) memclear(w->raydata, (LM_MAXW + 4)*(LM_MAXH + 4)); - origin1.sub(vec(ystep1).add(xstep1).mul(0)); origin2.sub(vec(ystep2).add(xstep2).mul(0)); - int aasample = min(1 << lmaa, 4); int stride = aasample*(w->w+1); vec *sample = w->colordata; @@ -581,13 +506,10 @@ static bool generatelightmap(lightmapworker *w, float lpu, const lerpvert *lv, i lerpbounds start, end; initlerpbounds(-0, -0, lv, numv, start, end); float sidex = side0 + 0*sidestep; - for(int y = 0; y < w->h; ++y, sidex += sidestep) - { + for(int y = 0; y < w->h; ++y, sidex += sidestep) { vec normal, nstep; lerpnormal(-0, y - 0, lv, numv, start, end, normal, nstep); - - for(int x = 0; x < w->w; ++x, normal.add(nstep), amb += w->bpp) - { + for(int x = 0; x < w->w; ++x, normal.add(nstep), amb += w->bpp) { #define EDGE_TOLERANCE(x, y) \ (x < 0 \ || x+1 > w->w - 0 \ @@ -605,28 +527,22 @@ static bool generatelightmap(lightmapworker *w, float lpu, const lerpvert *lv, i sample = w->colordata; initlerpbounds(-0, -0, lv, numv, start, end); sidex = side0 + 0*sidestep; - for(int y = 0; y < w->h; ++y, sidex += sidestep) - { + for(int y = 0; y < w->h; ++y, sidex += sidestep) { vec normal, nstep; lerpnormal(-0, y - 0, lv, numv, start, end, normal, nstep); - - for(int x = 0; x < w->w; ++x, normal.add(nstep)) - { + for(int x = 0; x < w->w; ++x, normal.add(nstep)) { vec ¢er = *sample++; if(adaptivesample && x > 0 && x+1 < w->w && y > 0 && y+1 < w->h && !lumelsample(center, aasample, stride)) loopi(aasample-1) *sample++ = center; - else - { + else { #define AA_EDGE_TOLERANCE(x, y, i) EDGE_TOLERANCE(x + aacoords[i][0], y + aacoords[i][1]) vec u = x < sidex ? vec(xstep1).mul(x).add(vec(ystep1).mul(y)).add(origin1) : vec(xstep2).mul(x).add(vec(ystep2).mul(y)).add(origin2); const vec *offsets = x < sidex ? offsets1 : offsets2; vec n = vec(normal).normalize(); loopi(aasample-1) generatelumel(w, AA_EDGE_TOLERANCE(x, y, i+1) * tolerance, lightmask, w->lights, vec(u).add(offsets[i+1]), n, *sample++, x, y); - if(lmaa == 3) - { - loopi(4) - { + if(lmaa == 3) { + loopi(4) { vec s; generatelumel(w, AA_EDGE_TOLERANCE(x, y, i+4) * tolerance, lightmask, w->lights, vec(u).add(offsets[i+4]), n, s, x, y); center.add(s); @@ -635,8 +551,7 @@ static bool generatelightmap(lightmapworker *w, float lpu, const lerpvert *lv, i } } } - if(aasample > 1) - { + if(aasample > 1) { vec u = w->w < sidex ? vec(xstep1).mul(w->w).add(vec(ystep1).mul(y)).add(origin1) : vec(xstep2).mul(w->w).add(vec(ystep2).mul(y)).add(origin2); const vec *offsets = w->w < sidex ? offsets1 : offsets2; vec n = vec(normal).normalize(); @@ -646,14 +561,10 @@ static bool generatelightmap(lightmapworker *w, float lpu, const lerpvert *lv, i } sample += aasample; } - - if(aasample > 1) - { + if(aasample > 1) { vec normal, nstep; lerpnormal(-0, w->h - 0, lv, numv, start, end, normal, nstep); - - for(int x = 0; x <= w->w; ++x, normal.add(nstep)) - { + for(int x = 0; x <= w->w; ++x, normal.add(nstep)) { vec u = x < sidex ? vec(xstep1).mul(x).add(vec(ystep1).mul(w->h)).add(origin1) : vec(xstep2).mul(x).add(vec(ystep2).mul(w->h)).add(origin2); const vec *offsets = x < sidex ? offsets1 : offsets2; vec n = vec(normal).normalize(); @@ -666,8 +577,7 @@ static bool generatelightmap(lightmapworker *w, float lpu, const lerpvert *lv, i return true; } -static int finishlightmap(lightmapworker *w) -{ +static int finishlightmap(lightmapworker *w) { vec *sample = w->colordata; int aasample = min(1 << lmaa, 4), stride = aasample*(w->w+1); float weight = 1.0f / (1.0f + 4.0f*lmaa), @@ -677,26 +587,21 @@ static int finishlightmap(lightmapworker *w) uchar mincolor[4] = { 255, 255, 255, 255 }, maxcolor[4] = { 0, 0, 0, 0 }; bvec *dstray = 0 && (w->w > 1 || w->h > 1) ? (bvec *)w->raydata : w->raybuf; bvec minray(255, 255, 255), maxray(0, 0, 0); - loop(y, w->h) - { - loop(x, w->w) - { + loop(y, w->h) { + loop(x, w->w) { vec l(0, 0, 0); const vec ¢er = *sample++; loopi(aasample-1) l.add(*sample++); - if(aasample > 1) - { + if(aasample > 1) { l.add(sample[1]); if(aasample > 2) l.add(sample[3]); } vec *next = sample + stride - aasample; - if(aasample > 1) - { + if(aasample > 1) { l.add(next[1]); if(aasample > 2) l.add(next[2]); l.add(next[aasample+1]); } - int r = int(center.x*cweight + l.x*weight), g = int(center.y*cweight + l.y*weight), b = int(center.z*cweight + l.z*weight), @@ -704,30 +609,25 @@ static int finishlightmap(lightmapworker *w) dstcolor[0] = max(ar, r); dstcolor[1] = max(ag, g); dstcolor[2] = max(ab, b); - loopk(3) - { + loopk(3) { mincolor[k] = min(mincolor[k], dstcolor[k]); maxcolor[k] = max(maxcolor[k], dstcolor[k]); } - if(w->type&LM_ALPHA) - { + if(w->type&LM_ALPHA) { dstcolor[3] = 127;///TODO mincolor[3] = min(mincolor[3], dstcolor[3]); maxcolor[3] = max(maxcolor[3], dstcolor[3]); } - if((w->type&LM_TYPE) == LM_BUMPMAP0) - { + if((w->type&LM_TYPE) == LM_BUMPMAP0) { if(ray->iszero()) dstray[0] = bvec(128, 128, 255); - else - { + else { ray->normalize(); int l = max(r, max(g, b)), a = max(ar, max(ag, ab)); ray->mul(max(l-a, 0)); ray->z += a; dstray[0] = bvec(ray->normalize()); } - loopk(3) - { + loopk(3) { minray[k] = min(minray[k], dstray[0][k]); maxray[k] = max(maxray[k], dstray[0][k]); } @@ -741,8 +641,7 @@ static int finishlightmap(lightmapworker *w) if(int(maxcolor[0]) - int(mincolor[0]) <= lighterror && int(maxcolor[1]) - int(mincolor[1]) <= lighterror && int(maxcolor[2]) - int(mincolor[2]) <= lighterror && - mincolor[3] >= maxcolor[3]) - { + mincolor[3] >= maxcolor[3]) { uchar color[3]; loopk(3) color[k] = (int(maxcolor[k]) + int(mincolor[k])) / 2; if(color[0] <= int(ambientcolor[0]) + lighterror && @@ -754,12 +653,10 @@ static int finishlightmap(lightmapworker *w) (int(maxray.x) - int(minray.x) <= bumperror && int(maxray.y) - int(minray.z) <= bumperror && int(maxray.z) - int(minray.z) <= bumperror)) - - { + { memcpy(w->colorbuf, color, 3); if(w->type&LM_ALPHA) w->colorbuf[3] = mincolor[3]; - if((w->type&LM_TYPE) == LM_BUMPMAP0) - { + if((w->type&LM_TYPE) == LM_BUMPMAP0) { loopk(3) w->raybuf[0][k] = uchar((int(maxray[k])+int(minray[k]))/2); } w->lastlightmap->w = w->w = 1; @@ -771,17 +668,14 @@ static int finishlightmap(lightmapworker *w) else return SURFACE_LIGHTMAP_BLEND; } -static int previewlightmapalpha(lightmapworker *w, float lpu, const vec &origin1, const vec &xstep1, const vec &ystep1, const vec &origin2, const vec &xstep2, const vec &ystep2, float side0, float sidestep) -{ +static int previewlightmapalpha(lightmapworker *w, float lpu, const vec &origin1, const vec &xstep1, const vec &ystep1, const vec &origin2, const vec &xstep2, const vec &ystep2, float side0, float sidestep) { extern int fullbrightlevel; float tolerance = 0.5 / lpu; uchar *dst = w->colorbuf; uchar minalpha = 255, maxalpha = 0; float sidex = side0; - for(int y = 0; y < w->h; ++y, sidex += sidestep) - { - for(int x = 0; x < w->w; ++x, dst += 4) - { + for(int y = 0; y < w->h; ++y, sidex += sidestep) { + for(int x = 0; x < w->w; ++x, dst += 4) { vec u = x < sidex ? vec(xstep1).mul(x).add(vec(ystep1).mul(y)).add(origin1) : vec(xstep2).mul(x).add(vec(ystep2).mul(y)).add(origin2); @@ -798,25 +692,18 @@ static int previewlightmapalpha(lightmapworker *w, float lpu, const vec &origin1 return SURFACE_LIGHTMAP_BLEND; } -static void clearsurfaces(cube *c) -{ - loopi(8) - { - if(c[i].ext) - { - loopj(6) - { +static void clearsurfaces(cube *c) { + loopi(8) { + if(c[i].ext) { + loopj(6) { surfaceinfo &surf = c[i].ext->surfaces[j]; if(!surf.used()) continue; surf.clear(); int numverts = surf.numverts&MAXFACEVERTS; - if(numverts) - { + if(numverts) { if(!(c[i].merged&(1<verts() + surf.verts; - loopk(numverts) - { + loopk(numverts) { vertinfo &v = verts[k]; v.u = 0; v.v = 0; @@ -831,8 +718,7 @@ static void clearsurfaces(cube *c) #define LIGHTCACHESIZE 1024 -static struct lightcacheentry -{ +static struct lightcacheentry { int x, y; vector lights; } lightcache[LIGHTCACHESIZE]; @@ -841,17 +727,13 @@ static struct lightcacheentry VARF(lightcachesize, 4, 6, 12, clearlightcache()); -void clearlightcache(int id) -{ - if(id >= 0) - { +void clearlightcache(int id) { + if(id >= 0) { const extentity &light = *entities::getents()[id]; int radius = light.attr1; - if(radius) - { + if(radius) { for(int x = int(max(light.o.x-radius, 0.0f))>>lightcachesize, ex = int(min(light.o.x+radius, worldsize-1.0f))>>lightcachesize; x <= ex; x++) - for(int y = int(max(light.o.y-radius, 0.0f))>>lightcachesize, ey = int(min(light.o.y+radius, worldsize-1.0f))>>lightcachesize; y <= ey; y++) - { + for(int y = int(max(light.o.y-radius, 0.0f))>>lightcachesize, ey = int(min(light.o.y+radius, worldsize-1.0f))>>lightcachesize; y <= ey; y++) { lightcacheentry &lce = lightcache[LIGHTCACHEHASH(x, y)]; if(lce.x != x || lce.y != y) continue; lce.x = -1; @@ -860,34 +742,26 @@ void clearlightcache(int id) return; } } - - for(lightcacheentry *lce = lightcache; lce < &lightcache[LIGHTCACHESIZE]; lce++) - { + for(lightcacheentry *lce = lightcache; lce < &lightcache[LIGHTCACHESIZE]; lce++) { lce->x = -1; lce->lights.setsize(0); } } -const vector &checklightcache(int x, int y) -{ +const vector &checklightcache(int x, int y) { x >>= lightcachesize; y >>= lightcachesize; lightcacheentry &lce = lightcache[LIGHTCACHEHASH(x, y)]; if(lce.x == x && lce.y == y) return lce.lights; - lce.lights.setsize(0); int csize = 1< &ents = entities::getents(); - loopv(ents) - { + loopv(ents) { const extentity &light = *ents[i]; - switch(light.type) - { - case ET_LIGHT: - { + switch(light.type) { + case ET_LIGHT: { int radius = light.attr1; - if(radius > 0) - { + if(radius > 0) { if(light.o.x + radius < cx || light.o.x - radius > cx + csize || light.o.y + radius < cy || light.o.y - radius > cy + csize) continue; @@ -898,60 +772,48 @@ const vector &checklightcache(int x, int y) } lce.lights.add(i); } - lce.x = x; lce.y = y; return lce.lights; } -static inline void addlight(lightmapworker *w, const extentity &light, int cx, int cy, int cz, int size, const vec *v, const vec *n, int numv) -{ +static inline void addlight(lightmapworker *w, const extentity &light, int cx, int cy, int cz, int size, const vec *v, const vec *n, int numv) { int radius = light.attr1; - if(radius > 0) - { + if(radius > 0) { if(light.o.x + radius < cx || light.o.x - radius > cx + size || light.o.y + radius < cy || light.o.y - radius > cy + size || light.o.z + radius < cz || light.o.z - radius > cz + size) return; } - - loopi(4) - { + loopi(4) { vec p(light.o); p.sub(v[i]); float dist = p.dot(n[i]); - if(dist >= 0 && (!radius || dist < radius)) - { + if(dist >= 0 && (!radius || dist < radius)) { w->lights.add(&light); break; } } } -static bool findlights(lightmapworker *w, int cx, int cy, int cz, int size, const vec *v, const vec *n, int numv, const Slot &slot, const VSlot &vslot) -{ +static bool findlights(lightmapworker *w, int cx, int cy, int cz, int size, const vec *v, const vec *n, int numv, const Slot &slot, const VSlot &vslot) { w->lights.setsize(0); const vector &ents = entities::getents(); static volatile bool usinglightcache = false; - if(size <= 1< &lights = checklightcache(cx, cy); - loopv(lights) - { + loopv(lights) { const extentity &light = *ents[lights[i]]; - switch(light.type) - { + switch(light.type) { case ET_LIGHT: addlight(w, light, cx, cy, cz, size, v, n, numv); break; } } if(lightlock) { usinglightcache = false; SDL_UnlockMutex(lightlock); } } - else loopv(ents) - { + else loopv(ents) { const extentity &light = *ents[i]; - switch(light.type) - { + switch(light.type) { case ET_LIGHT: addlight(w, light, cx, cy, cz, size, v, n, numv); break; } } @@ -959,15 +821,12 @@ static bool findlights(lightmapworker *w, int cx, int cy, int cz, int size, cons return w->lights.length(); } -static int packlightmaps(lightmapworker *w = NULL) -{ +static int packlightmaps(lightmapworker *w = NULL) { int numpacked = 0; - for(; packidx < lightmaptasks[0].length(); packidx++, numpacked++) - { + for(; packidx < lightmaptasks[0].length(); packidx++, numpacked++) { lightmaptask &t = lightmaptasks[0][packidx]; if(!t.lightmaps) break; - if(t.ext && t.c->ext != t.ext) - { + if(t.ext && t.c->ext != t.ext) { lightmapext &e = lightmapexts.add(); e.c = t.c; e.ext = t.ext; @@ -976,8 +835,7 @@ static int packlightmaps(lightmapworker *w = NULL) lightmapinfo *l = t.lightmaps; if(l == (lightmapinfo *)-1) continue; int space = 0; - for(; l && l->c == t.c; l = l->next) - { + for(; l && l->c == t.c; l = l->next) { l->packed = true; space += l->bufsize; if(l->surface < 0 || !t.ext) continue; @@ -986,31 +844,26 @@ static int packlightmaps(lightmapworker *w = NULL) packlightmap(*l, layout); int numverts = surf.numverts&MAXFACEVERTS; vertinfo *verts = t.ext->verts() + surf.verts; - if(l->layers&LAYER_DUP) - { + if(l->layers&LAYER_DUP) { if(l->type&LM_ALPHA) surf.lmid[0] = layout.lmid; else { surf.lmid[1] = layout.lmid; verts += numverts; } } - else - { + else { if(l->layers&LAYER_TOP) surf.lmid[0] = layout.lmid; if(l->layers&LAYER_BOTTOM) surf.lmid[1] = layout.lmid; } ushort offsetx = layout.x*((USHRT_MAX+1)/LM_PACKW), offsety = layout.y*((USHRT_MAX+1)/LM_PACKH); - loopk(numverts) - { + loopk(numverts) { vertinfo &v = verts[k]; v.u += offsetx; v.v += offsety; } } - if(t.worker == w) - { + if(t.worker == w) { w->bufused -= space; w->bufstart = (w->bufstart + space)%LIGHTMAPBUFSIZE; w->firstlightmap = l; - if(!l) - { + if(!l) { w->lastlightmap = NULL; w->bufstart = w->bufused = 0; } @@ -1020,8 +873,7 @@ static int packlightmaps(lightmapworker *w = NULL) return numpacked; } -static lightmapinfo *alloclightmap(lightmapworker *w) -{ +static lightmapinfo *alloclightmap(lightmapworker *w) { int needspace1 = sizeof(lightmapinfo) + w->w*w->h*w->bpp, needspace2 = (w->type&LM_TYPE) == LM_BUMPMAP0 ? w->w*w->h*3 : 0, needspace = needspace1 + needspace2, @@ -1029,20 +881,16 @@ static lightmapinfo *alloclightmap(lightmapworker *w) availspace = LIGHTMAPBUFSIZE - w->bufused, availspace1 = min(availspace, LIGHTMAPBUFSIZE - bufend), availspace2 = min(availspace, w->bufstart); - if(availspace < needspace || (max(availspace1, availspace2) < needspace && (availspace1 < needspace1 || availspace2 < needspace2))) - { + if(availspace < needspace || (max(availspace1, availspace2) < needspace && (availspace1 < needspace1 || availspace2 < needspace2))) { if(tasklock) SDL_LockMutex(tasklock); - while(!w->doneworking) - { + while(!w->doneworking) { lightmapinfo *l = w->firstlightmap; - for(; l && l->packed; l = l->next) - { + for(; l && l->packed; l = l->next) { w->bufused -= l->bufsize; w->bufstart = (w->bufstart + l->bufsize)%LIGHTMAPBUFSIZE; } w->firstlightmap = l; - if(!l) - { + if(!l) { w->lastlightmap = NULL; w->bufstart = w->bufused = 0; } @@ -1061,20 +909,17 @@ static lightmapinfo *alloclightmap(lightmapworker *w) } int usedspace = needspace; lightmapinfo *l = NULL; - if(availspace1 >= needspace1) - { + if(availspace1 >= needspace1) { l = (lightmapinfo *)&w->buf[bufend]; w->colorbuf = (uchar *)(l + 1); if((w->type&LM_TYPE) != LM_BUMPMAP0) w->raybuf = NULL; else if(availspace1 >= needspace) w->raybuf = (bvec *)&w->buf[bufend + needspace1]; - else - { + else { w->raybuf = (bvec *)w->buf; usedspace += availspace1 - needspace1; } } - else if(availspace2 >= needspace) - { + else if(availspace2 >= needspace) { usedspace += availspace1; l = (lightmapinfo *)w->buf; w->colorbuf = (uchar *)(l + 1); @@ -1101,17 +946,14 @@ static lightmapinfo *alloclightmap(lightmapworker *w) return l; } -static void freelightmap(lightmapworker *w) -{ +static void freelightmap(lightmapworker *w) { lightmapinfo *l = w->lastlightmap; if(!l || l->surface >= 0) return; - if(w->firstlightmap == w->lastlightmap) - { + if(w->firstlightmap == w->lastlightmap) { w->firstlightmap = w->lastlightmap = w->curlightmaps = NULL; w->bufstart = w->bufused = 0; } - else - { + else { w->bufused -= l->bufsize - sizeof(lightmapinfo); l->bufsize = sizeof(lightmapinfo); l->packed = true; @@ -1119,11 +961,9 @@ static void freelightmap(lightmapworker *w) if(w->curlightmaps == l) w->curlightmaps = NULL; } -static int setupsurface(lightmapworker *w, plane planes[2], int numplanes, const vec *p, const vec *n, int numverts, vertinfo *litverts, bool preview = false) -{ +static int setupsurface(lightmapworker *w, plane planes[2], int numplanes, const vec *p, const vec *n, int numverts, vertinfo *litverts, bool preview = false) { vec u, v, t; vec2 c[MAXFACEVERTS]; - u = vec(p[2]).sub(p[0]).normalize(); v.cross(planes[0], u); c[0] = vec2(0, 0); @@ -1131,24 +971,20 @@ static int setupsurface(lightmapworker *w, plane planes[2], int numplanes, const vec r1 = vec(p[1]).sub(p[0]); c[1] = vec2(r1.dot(u), min(r1.dot(v), 0.0f)); c[2] = vec2(vec(p[2]).sub(p[0]).dot(u), 0); - for(int i = 3; i < numverts; i++) - { + for(int i = 3; i < numverts; i++) { vec r = vec(p[i]).sub(p[0]); c[i] = vec2(r.dot(u), max(r.dot(t), 0.0f)); } - float carea = 1e16f; vec2 cx(0, 0), cy(0, 0), co(0, 0), cmin(0, 0), cmax(0, 0); - loopi(numverts) - { + loopi(numverts) { vec2 px = vec2(c[i+1 < numverts ? i+1 : 0]).sub(c[i]); float len = px.squaredlen(); if(!len) continue; px.mul(1/sqrtf(len)); vec2 py(-px.y, px.x), pmin(0, 0), pmax(0, 0); if(numplanes >= 2 && (i == 0 || i >= 3)) px.neg(); - loopj(numverts) - { + loopj(numverts) { vec2 rj = vec2(c[j]).sub(c[i]), pj(rj.dot(px), rj.dot(py)); pmin.x = min(pmin.x, pj.x); pmin.y = min(pmin.y, pj.y); @@ -1158,29 +994,24 @@ static int setupsurface(lightmapworker *w, plane planes[2], int numplanes, const float area = (pmax.x-pmin.x)*(pmax.y-pmin.y); if(area < carea) { carea = area; cx = px; cy = py; co = c[i]; cmin = pmin; cmax = pmax; } } - int scale = int(min(cmax.x - cmin.x, cmax.y - cmin.y)); float lpu = 16.0f / float(lightlod && scale < (1 << lightlod) ? max(lightprecision / 2, 1) : lightprecision); int lw = clamp(int(ceil((cmax.x - cmin.x + 1)*lpu)), LM_MINW, LM_MAXW), lh = clamp(int(ceil((cmax.y - cmin.y + 1)*lpu)), LM_MINH, LM_MAXH); w->w = lw; w->h = lh; if(!alloclightmap(w)) return NO_SURFACE; - vec2 cscale = vec2(cmax).sub(cmin).div(vec2(lw-1, lh-1)), comin = vec2(cx).mul(cmin.x).add(vec2(cy).mul(cmin.y)).add(co); - loopi(numverts) - { + loopi(numverts) { vec2 ri = vec2(c[i]).sub(comin); c[i] = vec2(ri.dot(cx)/cscale.x, ri.dot(cy)/cscale.y); } - vec xstep1 = vec(v).mul(cx.y).add(vec(u).mul(cx.x)).mul(cscale.x), ystep1 = vec(v).mul(cy.y).add(vec(u).mul(cy.x)).mul(cscale.y), origin1 = vec(v).mul(comin.y).add(vec(u).mul(comin.x)).add(p[0]), xstep2 = xstep1, ystep2 = ystep1, origin2 = origin1; float side0 = LM_MAXW + 1, sidestep = 0; - if(numplanes >= 2) - { + if(numplanes >= 2) { xstep2 = vec(t).mul(cx.y).add(vec(u).mul(cx.x)).mul(cscale.x); ystep2 = vec(t).mul(cy.y).add(vec(u).mul(cy.x)).mul(cscale.y); origin2 = vec(t).mul(comin.y).add(vec(u).mul(comin.x)).add(p[0]); @@ -1188,41 +1019,33 @@ static int setupsurface(lightmapworker *w, plane planes[2], int numplanes, const else if(cy.y) { side0 = ceil(comin.y/-(cy.y*cscale.y))*(LM_MAXW + 1); sidestep = -(LM_MAXW + 1); if(cy.y < 0) { side0 = (LM_MAXW + 1) - side0; sidestep = -sidestep; } } else side0 = comin.y <= 0 ? LM_MAXW + 1 : -1; } - int surftype = NO_SURFACE; - if(preview) - { + if(preview) { surftype = previewlightmapalpha(w, lpu, origin1, xstep1, ystep1, origin2, xstep2, ystep2, side0, sidestep); } - else - { + else { lerpvert lv[MAXFACEVERTS]; int numv = numverts; calclerpverts(c, n, lv, numv); - if(!generatelightmap(w, lpu, lv, numv, origin1, xstep1, ystep1, origin2, xstep2, ystep2, side0, sidestep)) return NO_SURFACE; surftype = finishlightmap(w); } if(surftypew) texscale.x *= float(w->w - 1) / (lw - 1); if(lh != w->h) texscale.y *= float(w->h - 1) / (lh - 1); - loopk(numverts) - { + loopk(numverts) { litverts[k].u = ushort(floor(clamp(c[k].x*texscale.x, 0.0f, float(USHRT_MAX)))); litverts[k].v = ushort(floor(clamp(c[k].y*texscale.y, 0.0f, float(USHRT_MAX)))); } return surftype; } -static void removelmalpha(lightmapworker *w) -{ +static void removelmalpha(lightmapworker *w) { if(!(w->type&LM_ALPHA)) return; for(uchar *dst = w->colorbuf, *src = w->colorbuf, *end = &src[w->w*w->h*4]; src < end; - dst += 3, src += 4) - { + dst += 3, src += 4) { dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; @@ -1233,60 +1056,48 @@ static void removelmalpha(lightmapworker *w) w->lastlightmap->bpp = w->bpp; } -static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) -{ +static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) { cube &c = *task.c; const ivec &co = task.o; int size = task.size, usefacemask = task.usefaces; - w->curlightmaps = NULL; w->c = &c; - surfaceinfo surfaces[6]; vertinfo litverts[6*2*MAXFACEVERTS]; int numlitverts = 0; memclear(surfaces); - loopi(6) - { + loopi(6) { int usefaces = usefacemask&0xF; usefacemask >>= 4; - if(!usefaces) - { + if(!usefaces) { if(!c.ext) continue; surfaceinfo &surf = surfaces[i]; surf = c.ext->surfaces[i]; int numverts = surf.totalverts(); - if(numverts) - { + if(numverts) { memcpy(&litverts[numlitverts], c.ext->verts() + surf.verts, numverts*sizeof(vertinfo)); surf.verts = numlitverts; numlitverts += numverts; } continue; } - VSlot &vslot = lookupvslot(c.texture[i], false), *layer = vslot.layer && !(c.material&MAT_ALPHA) ? &lookupvslot(vslot.layer, false) : NULL; Shader *shader = vslot.slot->shader; int shadertype = shader->type; if(layer) shadertype |= layer->slot->shader->type; - surfaceinfo &surf = surfaces[i]; vertinfo *curlitverts = &litverts[numlitverts]; int numverts = c.ext ? c.ext->surfaces[i].numverts&MAXFACEVERTS : 0; ivec mo(co); int msz = size, convex = 0; - if(numverts) - { + if(numverts) { vertinfo *verts = c.ext->verts() + c.ext->surfaces[i].verts; loopj(numverts) curlitverts[j].set(verts[j].getxyz()); - if(c.merged&(1<slot = vslot.slot; w->vslot = &vslot; w->type = shader->type&SHADER_NORMALSLMS ? LM_BUMPMAP0 : LM_DIFFUSE; @@ -1349,30 +1150,24 @@ static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) w->orient = i; w->rotate = vslot.rotation; int surftype = setupsurface(w, planes, numplanes, pos, n, numverts, curlitverts); - switch(surftype) - { + switch(surftype) { case SURFACE_LIGHTMAP_BOTTOM: if((shader->type^layer->slot->shader->type)&SHADER_NORMALSLMS || - (shader->type&SHADER_NORMALSLMS && vslot.rotation!=layer->rotation)) - { + (shader->type&SHADER_NORMALSLMS && vslot.rotation!=layer->rotation)) { freelightmap(w); break; } // fall through case SURFACE_LIGHTMAP_BLEND: - case SURFACE_LIGHTMAP_TOP: - { - if(!(surf.numverts&MAXFACEVERTS)) - { + case SURFACE_LIGHTMAP_TOP: { + if(!(surf.numverts&MAXFACEVERTS)) { surf.verts = numlitverts; surf.numverts |= numverts; numlitverts += numverts; } - w->lastlightmap->surface = i; w->lastlightmap->layers = (surftype==SURFACE_LIGHTMAP_BOTTOM ? LAYER_BOTTOM : LAYER_TOP); - if(surftype==SURFACE_LIGHTMAP_BLEND) - { + if(surftype==SURFACE_LIGHTMAP_BLEND) { surf.numverts |= LAYER_BLEND; w->lastlightmap->layers = LAYER_TOP; if((shader->type^layer->slot->shader->type)&SHADER_NORMALSLMS || @@ -1380,15 +1175,12 @@ static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) break; w->lastlightmap->layers |= LAYER_BOTTOM; } - else - { - if(surftype==SURFACE_LIGHTMAP_BOTTOM) - { + else { + if(surftype==SURFACE_LIGHTMAP_BOTTOM) { surf.numverts |= LAYER_BOTTOM; w->lastlightmap->layers = LAYER_BOTTOM; } - else - { + else { surf.numverts |= LAYER_TOP; w->lastlightmap->layers = LAYER_TOP; } @@ -1396,44 +1188,35 @@ static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) } continue; } - case SURFACE_AMBIENT_BOTTOM: freelightmap(w); surf.numverts |= layer ? LAYER_BOTTOM : LAYER_TOP; continue; - case SURFACE_AMBIENT_TOP: freelightmap(w); surf.numverts |= LAYER_TOP; continue; - default: freelightmap(w); continue; } - w->slot = layer->slot; w->vslot = layer; w->type = layer->slot->shader->type&SHADER_NORMALSLMS ? LM_BUMPMAP0 : LM_DIFFUSE; w->bpp = 3; w->rotate = layer->rotation; vertinfo *blendverts = surf.numverts&MAXFACEVERTS ? &curlitverts[numverts] : curlitverts; - switch(setupsurface(w, planes, numplanes, pos, n, numverts, blendverts)) - { - case SURFACE_LIGHTMAP_TOP: - { - if(!(surf.numverts&MAXFACEVERTS)) - { + switch(setupsurface(w, planes, numplanes, pos, n, numverts, blendverts)) { + case SURFACE_LIGHTMAP_TOP: { + if(!(surf.numverts&MAXFACEVERTS)) { surf.verts = numlitverts; surf.numverts |= numverts; numlitverts += numverts; } - else if(!(surf.numverts&LAYER_DUP)) - { + else if(!(surf.numverts&LAYER_DUP)) { surf.numverts |= LAYER_DUP; w->lastlightmap->layers |= LAYER_DUP; - loopk(numverts) - { + loopk(numverts) { vertinfo &src = curlitverts[k]; vertinfo &dst = blendverts[k]; dst.setxyz(src.getxyz()); @@ -1443,26 +1226,20 @@ static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) } surf.numverts |= LAYER_BOTTOM; w->lastlightmap->layers |= LAYER_BOTTOM; - w->lastlightmap->surface = i; break; } - - case SURFACE_AMBIENT_TOP: - { + case SURFACE_AMBIENT_TOP: { freelightmap(w); surf.numverts |= LAYER_BOTTOM; break; } - default: freelightmap(w); break; } } - loopk(6) - { + loopk(6) { surfaceinfo &surf = surfaces[k]; - if(surf.used()) - { + if(surf.used()) { cubeext *ext = c.ext && c.ext->maxverts >= numlitverts ? c.ext : growcubeext(c.ext, numlitverts); memcpy(ext->surfaces, surfaces, sizeof(ext->surfaces)); memcpy(ext->verts(), litverts, numlitverts*sizeof(vertinfo)); @@ -1473,14 +1250,11 @@ static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) return w->curlightmaps ? w->curlightmaps : (lightmapinfo *)-1; } -int lightmapworker::work(void *data) -{ +int lightmapworker::work(void *data) { lightmapworker *w = (lightmapworker *)data; SDL_LockMutex(tasklock); - while(!w->doneworking) - { - if(allocidx < lightmaptasks[0].length()) - { + while(!w->doneworking) { + if(allocidx < lightmaptasks[0].length()) { lightmaptask &t = lightmaptasks[0][allocidx++]; t.worker = w; SDL_UnlockMutex(tasklock); @@ -1489,8 +1263,7 @@ int lightmapworker::work(void *data) t.lightmaps = l; packlightmaps(w); } - else - { + else { if(packidx >= lightmaptasks[0].length()) SDL_CondSignal(emptycond); SDL_CondWait(fullcond, tasklock); } @@ -1499,28 +1272,22 @@ int lightmapworker::work(void *data) return 0; } -static bool processtasks(bool finish = false) -{ +static bool processtasks(bool finish = false) { if(tasklock) SDL_LockMutex(tasklock); - while(finish || lightmaptasks[1].length()) - { - if(packidx >= lightmaptasks[0].length()) - { + while(finish || lightmaptasks[1].length()) { + if(packidx >= lightmaptasks[0].length()) { if(lightmaptasks[1].empty()) break; lightmaptasks[0].setsize(0); lightmaptasks[0].move(lightmaptasks[1]); packidx = allocidx = 0; if(fullcond) SDL_CondBroadcast(fullcond); } - else if(lightmapping > 1) - { + else if(lightmapping > 1) { SDL_CondWaitTimeout(emptycond, tasklock, 250); CHECK_PROGRESS_LOCKED({ SDL_UnlockMutex(tasklock); return false; }, SDL_UnlockMutex(tasklock), SDL_LockMutex(tasklock)); } - else - { - while(allocidx < lightmaptasks[0].length()) - { + else { + while(allocidx < lightmaptasks[0].length()) { lightmaptask &t = lightmaptasks[0][allocidx++]; t.worker = lightmapworkers[0]; t.lightmaps = setupsurfaces(lightmapworkers[0], t); @@ -1533,35 +1300,26 @@ static bool processtasks(bool finish = false) return true; } -static void generatelightmaps(cube *c, const ivec &co, int size) -{ +static void generatelightmaps(cube *c, const ivec &co, int size) { CHECK_PROGRESS(return); - taskprogress++; - - loopi(8) - { + loopi(8) { ivec o(i, co, size); if(c[i].children) generatelightmaps(c[i].children, o, size >> 1); - else if(!isempty(c[i])) - { - if(c[i].ext) - { - loopj(6) - { + else if(!isempty(c[i])) { + if(c[i].ext) { + loopj(6) { surfaceinfo &surf = c[i].ext->surfaces[j]; if(surf.lmid[0] >= LMID_RESERVED || surf.lmid[1] >= LMID_RESERVED) goto nextcube; surf.clear(); } } int usefacemask = 0; - loopj(6) if(!(c[i].merged&(1<surfaces[j].numverts&MAXFACEVERTS)) - { + loopj(6) if(!(c[i].merged&(1<surfaces[j].numverts&MAXFACEVERTS)) { usefacemask |= visibletris(c[i], j, o, size)<<(4*j); } - if(usefacemask) - { + if(usefacemask) { lightmaptask &t = lightmaptasks[1].add(); t.o = o; t.size = size; @@ -1577,10 +1335,8 @@ static void generatelightmaps(cube *c, const ivec &co, int size) } } -void cleanuplightmaps() -{ - loopv(lightmaps) - { +void cleanuplightmaps() { + loopv(lightmaps) { LightMap &lm = lightmaps[i]; lm.tex = lm.offsetx = lm.offsety = -1; } @@ -1589,8 +1345,7 @@ void cleanuplightmaps() if(progresstex) { glDeleteTextures(1, &progresstex); progresstex = 0; } } -void resetlightmaps(bool fullclean) -{ +void resetlightmaps(bool fullclean) { cleanuplightmaps(); lightmaps.shrink(0); compressed.clear(); @@ -1598,8 +1353,7 @@ void resetlightmaps(bool fullclean) if(fullclean) while(lightmapworkers.length()) delete lightmapworkers.pop(); } -lightmapworker::lightmapworker() -{ +lightmapworker::lightmapworker() { buf = new uchar[LIGHTMAPBUFSIZE]; bufstart = bufused = 0; firstlightmap = lastlightmap = curlightmaps = NULL; @@ -1613,8 +1367,7 @@ lightmapworker::lightmapworker() thread = NULL; } -lightmapworker::~lightmapworker() -{ +lightmapworker::~lightmapworker() { cleanupthread(); delete[] buf; delete[] ambient; @@ -1624,38 +1377,32 @@ lightmapworker::~lightmapworker() freeshadowraycache(shadowraycache); } -void lightmapworker::cleanupthread() -{ +void lightmapworker::cleanupthread() { if(spacecond) { SDL_DestroyCond(spacecond); spacecond = NULL; } thread = NULL; } -void lightmapworker::reset() -{ +void lightmapworker::reset() { bufstart = bufused = 0; firstlightmap = lastlightmap = curlightmaps = NULL; needspace = doneworking = false; resetshadowraycache(shadowraycache); } -bool lightmapworker::setupthread() -{ +bool lightmapworker::setupthread() { if(!spacecond) spacecond = SDL_CreateCond(); if(!spacecond) return false; thread = SDL_CreateThread(work, "lightmap worker", this); return thread!=NULL; } -static Uint32 calclighttimer(Uint32 interval, void *param) -{ +static Uint32 calclighttimer(Uint32 interval, void *param) { check_calclight_progress = true; return interval; } -bool setlightmapquality(int quality) -{ - switch(quality) - { +bool setlightmapquality(int quality) { + switch(quality) { case 1: lmshadows = 2; lmaa = 3; lerptjoints = 1; break; case 0: lmshadows = lmshadows_; lmaa = lmaa_; lerptjoints = lerptjoints_; break; case -1: lmshadows = 1; lmaa = 0; lerptjoints = 0; break; @@ -1669,30 +1416,26 @@ VARP(lightthreads, 0, 0, 16); #define ALLOCLOCK(name, init) { if(lightmapping > 1) name = init(); if(!name) lightmapping = 1; } #define FREELOCK(name, destroy) { if(name) { destroy(name); name = NULL; } } -static void cleanuplocks() -{ +static void cleanuplocks() { FREELOCK(lightlock, SDL_DestroyMutex); FREELOCK(tasklock, SDL_DestroyMutex); FREELOCK(fullcond, SDL_DestroyCond); FREELOCK(emptycond, SDL_DestroyCond); } -static void setupthreads(int numthreads) -{ +static void setupthreads(int numthreads) { loopi(2) lightmaptasks[i].setsize(0); lightmapexts.setsize(0); packidx = allocidx = 0; lightmapping = numthreads; - if(lightmapping > 1) - { + if(lightmapping > 1) { ALLOCLOCK(lightlock, SDL_CreateMutex); ALLOCLOCK(tasklock, SDL_CreateMutex); ALLOCLOCK(fullcond, SDL_CreateCond); ALLOCLOCK(emptycond, SDL_CreateCond); } while(lightmapworkers.length() < lightmapping) lightmapworkers.add(new lightmapworker); - loopi(lightmapping) - { + loopi(lightmapping) { lightmapworker *w = lightmapworkers[i]; w->reset(); if(lightmapping <= 1 || w->setupthread()) continue; @@ -1703,28 +1446,23 @@ static void setupthreads(int numthreads) if(lightmapping <= 1) cleanuplocks(); } -static void cleanupthreads() -{ +static void cleanupthreads() { processtasks(true); - if(lightmapping > 1) - { + if(lightmapping > 1) { SDL_LockMutex(tasklock); loopv(lightmapworkers) lightmapworkers[i]->doneworking = true; SDL_CondBroadcast(fullcond); - loopv(lightmapworkers) - { + loopv(lightmapworkers) { lightmapworker *w = lightmapworkers[i]; if(w->needspace && w->spacecond) SDL_CondSignal(w->spacecond); } SDL_UnlockMutex(tasklock); - loopv(lightmapworkers) - { + loopv(lightmapworkers) { lightmapworker *w = lightmapworkers[i]; if(w->thread) SDL_WaitThread(w->thread, NULL); } } - loopv(lightmapexts) - { + loopv(lightmapexts) { lightmapext &e = lightmapexts[i]; setcubeext(*e.c, e.ext); } @@ -1733,10 +1471,8 @@ static void cleanupthreads() lightmapping = 0; } -void calclight(int *quality) -{ - if(!setlightmapquality(*quality)) - { +void calclight(int *quality) { + if(!setlightmapquality(*quality)) { conoutf(CON_ERROR, "valid range for calclight quality is -1..1"); return; } @@ -1763,8 +1499,7 @@ void calclight(int *quality) Uint32 end = SDL_GetTicks(); if(timer) SDL_RemoveTimer(timer); uint total = 0, lumels = 0; - loopv(lightmaps) - { + loopv(lightmaps) { insertunlit(i); if(!editmode) lightmaps[i].finalize(); total += lightmaps[i].lightmaps; @@ -1786,8 +1521,7 @@ void calclight(int *quality) COMMAND(calclight, "i"); -void clearlightmaps() -{ +void clearlightmaps() { if(noedit(true)) return; renderprogress(0, "clearing lightmaps..."); resetlightmaps(false); @@ -1798,10 +1532,8 @@ void clearlightmaps() COMMAND(clearlightmaps, ""); -void setfullbrightlevel(int fullbrightlevel) -{ - if(lightmaptexs.length() > LMID_BRIGHT) - { +void setfullbrightlevel(int fullbrightlevel) { + if(lightmaptexs.length() > LMID_BRIGHT) { uchar bright[3] = { uchar(fullbrightlevel), uchar(fullbrightlevel), uchar(fullbrightlevel) }; createtexture(lightmaptexs[LMID_BRIGHT].id, 1, 1, bright, 0, 1); } @@ -1813,21 +1545,17 @@ VARF(fullbrightlevel, 0, 128, 255, setfullbrightlevel(fullbrightlevel)); vector lightmaptexs; -static void copylightmap(LightMap &lm, uchar *dst, size_t stride) -{ +static void copylightmap(LightMap &lm, uchar *dst, size_t stride) { const uchar *c = lm.data; - loopi(LM_PACKH) - { + loopi(LM_PACKH) { memcpy(dst, c, lm.bpp*LM_PACKW); c += lm.bpp*LM_PACKW; dst += stride; } } -void genreservedlightmaptexs() -{ - while(lightmaptexs.length() < LMID_RESERVED) - { +void genreservedlightmaptexs() { + while(lightmaptexs.length() < LMID_RESERVED) { LightMapTexture &tex = lightmaptexs.add(); tex.type = lightmaptexs.length()&1 ? LM_DIFFUSE : LM_BUMPMAP1; glGenTextures(1, &tex.id); @@ -1844,30 +1572,24 @@ void genreservedlightmaptexs() createtexture(lightmaptexs[LMID_DARK1].id, 1, 1, &front, 0, 1); } -static void findunlit(int i) -{ +static void findunlit(int i) { LightMap &lm = lightmaps[i]; if(lm.unlitx>=0) return; - else if((lm.type&LM_TYPE)==LM_BUMPMAP0) - { + else if((lm.type&LM_TYPE)==LM_BUMPMAP0) { if(i+1>=lightmaps.length() || (lightmaps[i+1].type&LM_TYPE)!=LM_BUMPMAP1) return; } else if((lm.type&LM_TYPE)!=LM_DIFFUSE) return; uchar *data = lm.data; - loop(y, 2) loop(x, LM_PACKW) - { - if(!data[0] && !data[1] && !data[2]) - { + loop(y, 2) loop(x, LM_PACKW) { + if(!data[0] && !data[1] && !data[2]) { memcpy(data, ambientcolor.v, 3); if((lm.type&LM_TYPE)==LM_BUMPMAP0) ((bvec *)lightmaps[i+1].data)[y*LM_PACKW + x] = bvec(128, 128, 255); lm.unlitx = x; lm.unlity = y; return; } - if(data[0]==ambientcolor[0] && data[1]==ambientcolor[1] && data[2]==ambientcolor[2]) - { - if((lm.type&LM_TYPE)!=LM_BUMPMAP0 || ((bvec *)lightmaps[i+1].data)[y*LM_PACKW + x] == bvec(128, 128, 255)) - { + if(data[0]==ambientcolor[0] && data[1]==ambientcolor[1] && data[2]==ambientcolor[2]) { + if((lm.type&LM_TYPE)!=LM_BUMPMAP0 || ((bvec *)lightmaps[i+1].data)[y*LM_PACKW + x] == bvec(128, 128, 255)) { lm.unlitx = x; lm.unlity = y; return; @@ -1880,13 +1602,10 @@ static void findunlit(int i) VARF(roundlightmaptex, 0, 4, 16, { cleanuplightmaps(); initlights(); allchanged(); }); VARF(batchlightmaps, 0, 4, 256, { cleanuplightmaps(); initlights(); allchanged(); }); -void genlightmaptexs(int flagmask, int flagval) -{ +void genlightmaptexs(int flagmask, int flagval) { if(lightmaptexs.length() < LMID_RESERVED) genreservedlightmaptexs(); - int remaining[LM_TYPE+1] = { 0 }, total = 0; - loopv(lightmaps) - { + loopv(lightmaps) { LightMap &lm = lightmaps[i]; if(lm.tex >= 0 || (lm.type&flagmask)!=flagval) continue; int type = lm.type&LM_TYPE; @@ -1894,15 +1613,12 @@ void genlightmaptexs(int flagmask, int flagval) total++; if(lm.unlitx < 0) findunlit(i); } - int sizelimit = (maxtexsize ? min(maxtexsize, hwtexsize) : hwtexsize)/max(LM_PACKW, LM_PACKH); sizelimit = min(batchlightmaps, sizelimit*sizelimit); - while(total) - { + while(total) { int type = LM_DIFFUSE; LightMap *firstlm = NULL; - loopv(lightmaps) - { + loopv(lightmaps) { LightMap &lm = lightmaps[i]; if(lm.tex >= 0 || (lm.type&flagmask) != flagval) continue; type = lm.type&LM_TYPE; @@ -1915,8 +1631,7 @@ void genlightmaptexs(int flagmask, int flagval) used--; int oldval = remaining[type]; remaining[type] -= 1<bpp; uchar *data = used ? new uchar[bpp*tex.w*tex.h] : NULL; int offsetx = 0, offsety = 0; - loopv(lightmaps) - { + loopv(lightmaps) { LightMap &lm = lightmaps[i]; if(lm.tex >= 0 || (lm.type&flagmask) != flagval || (lm.type&LM_TYPE) != type) continue; - lm.tex = lightmaptexs.length()-1; lm.offsetx = offsetx; lm.offsety = offsety; - if(tex.unlitx < 0 && lm.unlitx >= 0) - { + if(tex.unlitx < 0 && lm.unlitx >= 0) { tex.unlitx = offsetx + lm.unlitx; tex.unlity = offsety + lm.unlity; } - if(data) copylightmap(lm, &data[bpp*(offsety*tex.w + offsetx)], bpp*tex.w); - offsetx += LM_PACKW; if(offsetx >= tex.w) { offsetx = 0; offsety += LM_PACKH; } if(offsety >= tex.h) break; } - glGenTextures(1, &tex.id); createtexture(tex.id, tex.w, tex.h, data ? data : firstlm->data, 3, 1, bpp==4 ? GL_RGBA : GL_RGB); if(data) delete[] data; @@ -1957,29 +1666,24 @@ void genlightmaptexs(int flagmask, int flagval) bool brightengeom = false, shouldlightents = false; -void clearlights() -{ +void clearlights() { clearlightcache(); const vector &ents = entities::getents(); - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; e.light.color = vec(1, 1, 1); e.light.dir = vec(0, 0, 1); } shouldlightents = false; - genlightmaptexs(LM_ALPHA, 0); genlightmaptexs(LM_ALPHA, LM_ALPHA); brightengeom = true; } -void lightent(extentity &e, float height) -{ +void lightent(extentity &e, float height) { if(e.type==ET_LIGHT) return; float ambient = 0.0f; - if(e.type==ET_MAPMODEL) - { + if(e.type==ET_MAPMODEL) { model *m = loadmodel(NULL, e.attr2); if(m) height = m->above()*0.75f; } @@ -1988,24 +1692,18 @@ void lightent(extentity &e, float height) lightreaching(target, e.light.color, e.light.dir, false, &e, ambient); } -void lightents(bool force) -{ +void lightents(bool force) { if(!force && !shouldlightents) return; - const vector &ents = entities::getents(); loopv(ents) lightent(*ents[i]); - shouldlightents = false; } -void initlights() -{ - if((fullbright && editmode) || lightmaps.empty()) - { +void initlights() { + if((fullbright && editmode) || lightmaps.empty()) { clearlights(); return; } - clearlightcache(); genlightmaptexs(LM_ALPHA, 0); genlightmaptexs(LM_ALPHA, LM_ALPHA); @@ -2013,49 +1711,39 @@ void initlights() shouldlightents = true; } -void lightreaching(const vec &target, vec &color, vec &dir, bool fast, extentity *t, float ambient) -{ - if((fullbright && editmode) || lightmaps.empty()) - { +void lightreaching(const vec &target, vec &color, vec &dir, bool fast, extentity *t, float ambient) { + if((fullbright && editmode) || lightmaps.empty()) { color = vec(1, 1, 1); dir = vec(0, 0, 1); return; } - color = dir = vec(0, 0, 0); const vector &ents = entities::getents(); const vector &lights = checklightcache(int(target.x), int(target.y)); - loopv(lights) - { + loopv(lights) { extentity &e = *ents[lights[i]]; if(e.type != ET_LIGHT) continue; - vec ray(target); ray.sub(e.o); float mag = ray.magnitude(); if(e.attr1 && mag >= float(e.attr1)) continue; - if(mag < 1e-4f) ray = vec(0, 0, -1); - else - { + else { ray.div(mag); if(shadowray(e.o, ray, mag, RAY_SHADOW | RAY_POLY, t) < mag) continue; } - float intensity = 1; if(e.attr1) intensity -= mag / float(e.attr1); - if(e.attached && e.attached->type==ET_SPOTLIGHT) - { + if(e.attached && e.attached->type==ET_SPOTLIGHT) { vec spot = vec(e.attached->o).sub(e.o).normalize(); float maxatten = sincos360[clamp(int(e.attached->attr1), 1, 89)].x, spotatten = (ray.dot(spot) - maxatten) / (1 - maxatten); if(spotatten <= 0) continue; intensity *= spotatten; } - vec lightcol = vec(e.attr2, e.attr3, e.attr4).mul(1.0f/255); color.add(vec(lightcol).mul(intensity)); dir.add(vec(ray).mul(-intensity*lightcol.x*lightcol.y*lightcol.z)); @@ -2065,40 +1753,33 @@ void lightreaching(const vec &target, vec &color, vec &dir, bool fast, extentity else dir.normalize(); } -entity *brightestlight(const vec &target, const vec &dir) -{ +entity *brightestlight(const vec &target, const vec &dir) { const vector &ents = entities::getents(); const vector &lights = checklightcache(int(target.x), int(target.y)); extentity *brightest = NULL; float bintensity = 0; - loopv(lights) - { + loopv(lights) { extentity &e = *ents[lights[i]]; if(e.type != ET_LIGHT || vec(e.o).sub(target).dot(dir)<0) continue; - vec ray(target); ray.sub(e.o); float mag = ray.magnitude(); if(e.attr1 && mag >= float(e.attr1)) continue; - ray.div(mag); if(shadowray(e.o, ray, mag, RAY_SHADOW | RAY_POLY) < mag) continue; float intensity = 1; if(e.attr1) intensity -= mag / float(e.attr1); - if(e.attached && e.attached->type==ET_SPOTLIGHT) - { + if(e.attached && e.attached->type==ET_SPOTLIGHT) { vec spot = vec(e.attached->o).sub(e.o).normalize(); float maxatten = sincos360[clamp(int(e.attached->attr1), 1, 89)].x, spotatten = (ray.dot(spot) - maxatten) / (1 - maxatten); if(spotatten <= 0) continue; intensity *= spotatten; } - - if(!brightest || intensity > bintensity) - { + if(!brightest || intensity > bintensity) { brightest = &e; bintensity = intensity; } @@ -2106,10 +1787,8 @@ entity *brightestlight(const vec &target, const vec &dir) return brightest; } -void dumplms() -{ - loopv(lightmaps) - { +void dumplms() { + loopv(lightmaps) { ImageData temp(LM_PACKW, LM_PACKH, lightmaps[i].bpp, lightmaps[i].data); const char *map = game::getclientmap(), *name = strrchr(map, '/'); defformatstring(buf, "lightmap_%s_%d.png", name ? name+1 : map, i); diff --git a/src/engine/lightmap.h b/src/engine/lightmap.h index 0f00d61..d15c6a7 100644 --- a/src/engine/lightmap.h +++ b/src/engine/lightmap.h @@ -5,81 +5,62 @@ #define LM_PACKW 512 #define LM_PACKH 512 -struct PackNode -{ +struct PackNode { PackNode *child1, *child2; ushort x, y, w, h; int available; - PackNode() : child1(0), child2(0), x(0), y(0), w(LM_PACKW), h(LM_PACKH), available(min(LM_PACKW, LM_PACKH)) {} PackNode(ushort x, ushort y, ushort w, ushort h) : child1(0), child2(0), x(x), y(y), w(w), h(h), available(min(w, h)) {} - - void clear() - { + void clear() { DELETEP(child1); DELETEP(child2); } - - ~PackNode() - { + ~PackNode() { clear(); } - bool insert(ushort &tx, ushort &ty, ushort tw, ushort th); }; -enum -{ +enum { LM_DIFFUSE = 0, LM_BUMPMAP0, LM_BUMPMAP1, LM_TYPE = 0x0F, - LM_ALPHA = 1<<4, LM_FLAGS = 0xF0 }; -struct LightMap -{ +struct LightMap { int type, bpp, tex, offsetx, offsety; PackNode packroot; uint lightmaps, lumels; int unlitx, unlity; uchar *data; - LightMap() : type(LM_DIFFUSE), bpp(3), tex(-1), offsetx(-1), offsety(-1), lightmaps(0), lumels(0), unlitx(-1), unlity(-1), - data(NULL) - { + data(NULL) { } - - ~LightMap() - { + ~LightMap() { if(data) delete[] data; } - - void finalize() - { + void finalize() { packroot.clear(); packroot.available = 0; } - void copy(ushort tx, ushort ty, uchar *src, ushort tw, ushort th); bool insert(ushort &tx, ushort &ty, uchar *src, ushort tw, ushort th); }; extern vector lightmaps; -struct LightMapTexture -{ +struct LightMapTexture { int w, h, type; GLuint id; int unlitx, unlity; - LightMapTexture() - : w(0), h(0), type(LM_DIFFUSE), id(0), unlitx(-1), unlity(-1) - {} + : w(0), h(0), type(LM_DIFFUSE), id(0), unlitx(-1), unlity(-1) { + } }; extern vector lightmaptexs; @@ -95,17 +76,14 @@ extern void brightencube(cube &c); extern void setsurfaces(cube &c, const surfaceinfo *surfs, const vertinfo *verts, int numverts); extern void setsurface(cube &c, int orient, const surfaceinfo &surf, const vertinfo *verts, int numverts); -struct lerpvert -{ +struct lerpvert { vec normal; vec2 tc; - bool operator==(const lerpvert &l) const { return tc == l.tc;; } bool operator!=(const lerpvert &l) const { return tc != l.tc; } }; -struct lerpbounds -{ +struct lerpbounds { const lerpvert *min; const lerpvert *max; float u, ustep; @@ -121,10 +99,10 @@ extern void initlerpbounds(float u, float v, const lerpvert *lv, int numv, lerpb extern void lerpnormal(float u, float v, const lerpvert *lv, int numv, lerpbounds &start, lerpbounds &end, vec &normal, vec &nstep); #define CHECK_CALCLIGHT_PROGRESS_LOCKED(exit, show_calclight_progress, before, after) \ - if(check_calclight_progress) \ - { \ - if(!calclight_canceled) \ - { \ + if(check_calclight_progress) { \ + \ + if(!calclight_canceled) { \ + \ before; \ show_calclight_progress(); \ check_calclight_canceled(); \ diff --git a/src/engine/lightning.h b/src/engine/lightning.h deleted file mode 100644 index cec993a..0000000 --- a/src/engine/lightning.h +++ /dev/null @@ -1,123 +0,0 @@ -#define MAXLIGHTNINGSTEPS 64 -#define LIGHTNINGSTEP 8 -int lnjitterx[2][MAXLIGHTNINGSTEPS], lnjittery[2][MAXLIGHTNINGSTEPS]; -int lnjitterframe = 0, lastlnjitter = 0; - -VAR(lnjittermillis, 0, 100, 1000); -VAR(lnjitterradius, 0, 4, 100); -FVAR(lnjitterscale, 0, 0.5f, 10); -VAR(lnscrollmillis, 1, 300, 5000); -FVAR(lnscrollscale, 0, 0.125f, 10); -FVAR(lnblendpower, 0, 0.25f, 1000); - -static void calclightningjitter(int frame) -{ - loopi(MAXLIGHTNINGSTEPS) - { - lnjitterx[lnjitterframe][i] = -lnjitterradius + rnd(2*lnjitterradius + 1); - lnjittery[lnjitterframe][i] = -lnjitterradius + rnd(2*lnjitterradius + 1); - } -} - -static void setuplightning() -{ - if(!lastlnjitter || lastmillis-lastlnjitter > lnjittermillis) - { - if(!lastlnjitter) calclightningjitter(lnjitterframe); - lastlnjitter = lastmillis - (lastmillis%lnjittermillis); - calclightningjitter(lnjitterframe ^= 1); - } -} - -static void renderlightning(Texture *tex, const vec &o, const vec &d, float sz) -{ - vec step(d); - step.sub(o); - float len = step.magnitude(); - int numsteps = clamp(int(ceil(len/LIGHTNINGSTEP)), 2, MAXLIGHTNINGSTEPS); - step.div(numsteps+1); - int jitteroffset = detrnd(int(d.x+d.y+d.z), MAXLIGHTNINGSTEPS); - vec cur(o), up, right; - up.orthogonal(step); - up.normalize(); - right.cross(up, step); - right.normalize(); - float scroll = -float(lastmillis%lnscrollmillis)/lnscrollmillis, - scrollscale = lnscrollscale*(LIGHTNINGSTEP*tex->ys)/(sz*tex->xs), - blend = pow(clamp(float(lastmillis - lastlnjitter)/lnjittermillis, 0.0f, 1.0f), lnblendpower), - jitter0 = (1-blend)*lnjitterscale*sz/lnjitterradius, jitter1 = blend*lnjitterscale*sz/lnjitterradius; - gle::begin(GL_TRIANGLE_STRIP); - loopj(numsteps) - { - vec next(cur); - next.add(step); - if(j+1==numsteps) next = d; - else - { - int lj = (j+jitteroffset)%MAXLIGHTNINGSTEPS; - next.add(vec(right).mul((jitter1*lnjitterx[lnjitterframe][lj] + jitter0*lnjitterx[lnjitterframe^1][lj]))); - next.add(vec(up).mul((jitter1*lnjittery[lnjitterframe][lj] + jitter0*lnjittery[lnjitterframe^1][lj]))); - } - vec dir1 = next, dir2 = next, across; - dir1.sub(cur); - dir2.sub(camera1->o); - across.cross(dir2, dir1).normalize().mul(sz); - gle::attribf(cur.x-across.x, cur.y-across.y, cur.z-across.z); - gle::attribf(scroll, 1); - gle::attribf(cur.x+across.x, cur.y+across.y, cur.z+across.z); - gle::attribf(scroll, 0); - scroll += scrollscale; - if(j+1==numsteps) - { - gle::attribf(next.x-across.x, next.y-across.y, next.z-across.z); - gle::attribf(scroll, 1); - gle::attribf(next.x+across.x, next.y+across.y, next.z+across.z); - gle::attribf(scroll, 0); - } - cur = next; - } - gle::end(); -} - -struct lightningrenderer : listrenderer -{ - lightningrenderer() - : listrenderer("packages/particles/lightning.png", 2, PT_LIGHTNING|PT_TRACK|PT_GLARE) - {} - - void startrender() - { - glDisable(GL_CULL_FACE); - gle::defattrib(gle::ATTRIB_VERTEX, 3, GL_FLOAT); - gle::defattrib(gle::ATTRIB_TEXCOORD0, 2, GL_FLOAT); - } - - void endrender() - { - glEnable(GL_CULL_FACE); - } - - void update() - { - setuplightning(); - } - - void seedemitter(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int gravity) - { - pe.maxfade = max(pe.maxfade, fade); - pe.extendbb(o, size); - pe.extendbb(d, size); - } - - void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) - { - blend = min(blend<<2, 255); - if(type&PT_MOD) //multiply alpha into color - gle::colorub((p->color.r*blend)>>8, (p->color.g*blend)>>8, (p->color.b*blend)>>8); - else - gle::color(p->color, blend); - renderlightning(tex, o, d, p->size); - } -}; -static lightningrenderer lightnings; - diff --git a/src/engine/main.cpp b/src/engine/main.cpp index 5d264ed..a059c13 100644 --- a/src/engine/main.cpp +++ b/src/engine/main.cpp @@ -10,8 +10,7 @@ float speedmodifier = 0.0f; extern void cleargamma(); -void cleanup() -{ +void cleanup() { cleanupserver(); SDL_ShowCursor(SDL_TRUE); SDL_SetRelativeMouseMode(SDL_FALSE); @@ -28,8 +27,7 @@ void cleanup() extern void writeinitcfg(); -void quit() // normal exit -{ +void quit() { // normal exit { writeinitcfg(); writeservercfg(); abortconnect(); @@ -40,20 +38,14 @@ void quit() // normal exit exit(EXIT_SUCCESS); } -void fatal(const char *s, ...) // failure exit -{ +void fatal(const char *s, ...) { // failure exit { static int errors = 0; errors++; - - if(errors <= 2) // print up to one extra recursive error - { + if(errors <= 2) { // print up to one extra recursive error { defvformatstring(msg,s,s); logoutf("%s", msg); - - if(errors <= 1) // avoid recursion - { - if(SDL_WasInit(SDL_INIT_VIDEO)) - { + if(errors <= 1) { // avoid recursion { + if(SDL_WasInit(SDL_INIT_VIDEO)) { SDL_ShowCursor(SDL_TRUE); SDL_SetRelativeMouseMode(SDL_FALSE); if(screen) SDL_SetWindowGrab(screen, SDL_FALSE); @@ -63,7 +55,6 @@ void fatal(const char *s, ...) // failure exit SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Cube 2: Sauerbraten fatal error", msg, NULL); } } - exit(EXIT_FAILURE); } @@ -73,10 +64,8 @@ dynent *player = NULL; int initing = NOT_INITING; -bool initwarning(const char *desc, int level, int type) -{ - if(initing < level) - { +bool initwarning(const char *desc, int level, int type) { + if(initing < level) { addchange(desc, type); return true; } @@ -100,8 +89,7 @@ VARF(scr_h, SCR_MINH, -1, SCR_MAXH, initwarning("screen resolution")); VARF(depthbits, 0, 0, 32, initwarning("depth-buffer precision")); VARF(fsaa, -1, -1, 16, initwarning("anti-aliasing")); -void writeinitcfg() -{ +void writeinitcfg() { stream *f = openutf8file("init.cfg", "w"); if(!f) return; f->printf("// automatically written on exit, DO NOT MODIFY\n// modify settings in game\n"); @@ -124,8 +112,7 @@ void writeinitcfg() COMMAND(quit, ""); -static void getbackgroundres(int &w, int &h) -{ +static void getbackgroundres(int &w, int &h) { float wk = 1, hk = 1; if(w < 1024) wk = 1024.0f/w; if(h < 768) hk = 768.0f/h; @@ -139,31 +126,26 @@ Texture *backgroundmapshot = NULL; string backgroundmapname = ""; char *backgroundmapinfo = NULL; -void setbackgroundinfo(const char *caption = NULL, Texture *mapshot = NULL, const char *mapname = NULL, const char *mapinfo = NULL) -{ +void setbackgroundinfo(const char *caption = NULL, Texture *mapshot = NULL, const char *mapname = NULL, const char *mapinfo = NULL) { renderedframe = false; copystring(backgroundcaption, caption ? caption : ""); backgroundmapshot = mapshot; copystring(backgroundmapname, mapname ? mapname : ""); - if(mapinfo != backgroundmapinfo) - { + if(mapinfo != backgroundmapinfo) { DELETEA(backgroundmapinfo); if(mapinfo) backgroundmapinfo = newstring(mapinfo); } } -void restorebackground(bool force = false) -{ - if(renderedframe) - { +void restorebackground(bool force = false) { + if(renderedframe) { if(!force) return; setbackgroundinfo(); } renderbackground(backgroundcaption[0] ? backgroundcaption : NULL, backgroundmapshot, backgroundmapname[0] ? backgroundmapname : NULL, backgroundmapinfo, true); } -void bgquad(float x, float y, float w, float h, float tx = 0, float ty = 0, float tw = 1, float th = 1) -{ +void bgquad(float x, float y, float w, float h, float tx = 0, float ty = 0, float tw = 1, float th = 1) { gle::begin(GL_TRIANGLE_STRIP); gle::attribf(x, y); gle::attribf(tx, ty); gle::attribf(x+w, y); gle::attribf(tx + tw, ty); @@ -172,48 +154,36 @@ void bgquad(float x, float y, float w, float h, float tx = 0, float ty = 0, floa gle::end(); } -void renderbackground(const char *caption, Texture *mapshot, const char *mapname, const char *mapinfo, bool restore, bool force) -{ +void renderbackground(const char *caption, Texture *mapshot, const char *mapname, const char *mapinfo, bool restore, bool force) { if(!inbetweenframes && !force) return; - if(!restore || force) stopsounds(); // stop sounds while loading - int w = screenw, h = screenh; if(forceaspect) w = int(ceil(h*forceaspect)); getbackgroundres(w, h); gettextres(w, h); - static int lastupdate = -1, lastw = -1, lasth = -1; static int numdecals = 0; static struct decal { float x, y, size; int side; } decals[12]; - if((renderedframe && !mainmenu && lastupdate != lastmillis) || lastw != w || lasth != h) - { + if((renderedframe && !mainmenu && lastupdate != lastmillis) || lastw != w || lasth != h) { lastupdate = lastmillis; lastw = w; lasth = h; - numdecals = sizeof(decals)/sizeof(decals[0]); numdecals = numdecals/3 + rnd((numdecals*2)/3 + 1); float maxsize = min(w, h)/16.0f; - loopi(numdecals) - { + loopi(numdecals) { decal d = { rndscale(w), rndscale(h), maxsize/2 + rndscale(maxsize/2), rnd(2) }; decals[i] = d; } } else if(lastupdate != lastmillis) lastupdate = lastmillis; - - loopi(restore ? 1 : 3) - { + loopi(restore ? 1 : 3) { hudmatrix.ortho(0, w, h, 0, -1, 1); resethudmatrix(); - hudshader->set(); gle::colorf(1, 1, 1); - gle::defvertex(2); gle::deftexcoord0(); - settexture("background/daemex.png", 0); bgquad(0, 0, screenw, screenh, 0, 0, 1, 1); glEnable(GL_BLEND); @@ -221,8 +191,7 @@ void renderbackground(const char *caption, Texture *mapshot, const char *mapname lx = 0.5f*(w - lw), ly = 0.5f*(h*0.5f - lh); settexture((maxtexsize ? min(maxtexsize, hwtexsize) : hwtexsize) >= 1024 && (screenw > 1280 || screenh > 800) ? "data/logo_1024.png" : "data/logo.png", 3); bgquad(lx, ly, lw, lh); - if(caption) - { + if(caption) { int tw = text_width(caption); float tsz = 0.04f*min(w, h)/FONTH, tx = 0.5f*(w - tw*tsz), ty = h - 0.075f*1.5f*min(w, h) - 1.25f*FONTH*tsz; @@ -233,23 +202,19 @@ void renderbackground(const char *caption, Texture *mapshot, const char *mapname draw_text(caption, 0, 0); pophudmatrix(); } - if(mapshot || mapname) - { + if(mapshot || mapname) { int infowidth = 12*FONTH; float sz = 0.35f*min(w, h), msz = (0.75f*min(w, h) - sz)/(infowidth + FONTH), x = 0.5f*(w-sz), y = ly+lh - sz/15; - if(mapinfo) - { + if(mapinfo) { int mw, mh; text_bounds(mapinfo, mw, mh, infowidth); x -= 0.5f*(mw*msz + FONTH*msz); } - if(mapshot && mapshot!=notexture) - { + if(mapshot && mapshot!=notexture) { glBindTexture(GL_TEXTURE_2D, mapshot->id); bgquad(x, y, sz, sz); } - else - { + else { int qw, qh; text_bounds("?", qw, qh); float qsz = sz*0.5f/max(qw, qh); @@ -263,8 +228,7 @@ void renderbackground(const char *caption, Texture *mapshot, const char *mapname } settexture("data/mapshot_frame.png", 3); bgquad(x, y, sz, sz); - if(mapname) - { + if(mapname) { int tw = text_width(mapname); float tsz = sz/(8*FONTH), tx = 0.9f*sz - tw*tsz, ty = 0.9f*sz - FONTH*tsz; @@ -276,8 +240,7 @@ void renderbackground(const char *caption, Texture *mapshot, const char *mapname draw_text(mapname, 0, 0); pophudmatrix(); } - if(mapinfo) - { + if(mapinfo) { pushhudmatrix(); hudmatrix.translate(x+sz+FONTH*msz, y, 0); hudmatrix.scale(msz, msz, 1); @@ -289,7 +252,6 @@ void renderbackground(const char *caption, Texture *mapshot, const char *mapname glDisable(GL_BLEND); if(!restore) swapbuffers(false); } - if(!restore) setbackgroundinfo(caption, mapshot, mapname, mapinfo); } @@ -297,42 +259,31 @@ VAR(progressbackground, 0, 0, 1); float loadprogress = 0; -void renderprogress(float bar, const char *text, GLuint tex, bool background) // also used during loading -{ +void renderprogress(float bar, const char *text, GLuint tex, bool background) { // also used during loading { if(!inbetweenframes || drawtex) return; - extern int menufps, maxfps; int fps = menufps ? (maxfps ? min(maxfps, menufps) : menufps) : maxfps; - if(fps) - { + if(fps) { static int lastprogress = 0; int ticks = SDL_GetTicks(), diff = ticks - lastprogress; if(bar > 0 && diff >= 0 && diff < (1000 + fps-1)/fps) return; lastprogress = ticks; } - clientkeepalive(); // make sure our connection doesn't time out while loading maps etc. - SDL_PumpEvents(); // keep the event queue awake to avoid 'beachball' cursor - extern int mesa_swap_bug, curvsync; bool forcebackground = progressbackground || (mesa_swap_bug && (curvsync || totalmillis==1)); if(background || forcebackground) restorebackground(forcebackground); - int w = screenw, h = screenh; if(forceaspect) w = int(ceil(h*forceaspect)); getbackgroundres(w, h); gettextres(w, h); - hudmatrix.ortho(0, w, h, 0, -1, 1); resethudmatrix(); - hudshader->set(); gle::colorf(1, 1, 1); - gle::defvertex(2); gle::deftexcoord0(); - float fh = 0.075f*min(w, h), fw = fh*10, fx = renderedframe ? w - fw - fh/4 : 0.5f*(w - fw), fy = renderedframe ? fh/4 : h - fh*1.5f, @@ -340,10 +291,8 @@ void renderprogress(float bar, const char *text, GLuint tex, bool background) fv1 = 0/64.0f, fv2 = 52/64.0f; settexture("data/loading_frame.png", 3); bgquad(fx, fy, fw, fh, fu1, fv1, fu2-fu1, fv2-fv1); - glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - float bw = fw*(511 - 2*17)/511.0f, bh = fh*20/52.0f, bx = fx + fw*17/511.0f, by = fy + fh*16/52.0f, bv1 = 0/32.0f, bv2 = 20/32.0f, @@ -351,29 +300,24 @@ void renderprogress(float bar, const char *text, GLuint tex, bool background) eu1 = 23/32.0f, eu2 = 30/32.0f, ew = fw*7/511.0f, mw = bw - sw - ew, ex = bx+sw + max(mw*bar, fw*7/511.0f); - if(bar > 0) - { + if(bar > 0) { settexture("data/loading_bar.png", 3); gle::begin(GL_QUADS); gle::attribf(bx, by); gle::attribf(su1, bv1); gle::attribf(bx+sw, by); gle::attribf(su2, bv1); gle::attribf(bx+sw, by+bh); gle::attribf(su2, bv2); gle::attribf(bx, by+bh); gle::attribf(su1, bv2); - gle::attribf(bx+sw, by); gle::attribf(su2, bv1); gle::attribf(ex, by); gle::attribf(eu1, bv1); gle::attribf(ex, by+bh); gle::attribf(eu1, bv2); gle::attribf(bx+sw, by+bh); gle::attribf(su2, bv2); - gle::attribf(ex, by); gle::attribf(eu1, bv1); gle::attribf(ex+ew, by); gle::attribf(eu2, bv1); gle::attribf(ex+ew, by+bh); gle::attribf(eu2, bv2); gle::attribf(ex, by+bh); gle::attribf(eu1, bv2); gle::end(); } - - if(text) - { + if(text) { int tw = text_width(text); float tsz = bh*0.8f/FONTH; if(tw*tsz > mw) tsz = mw/tw; @@ -384,22 +328,17 @@ void renderprogress(float bar, const char *text, GLuint tex, bool background) draw_text(text, 0, 0); pophudmatrix(); } - glDisable(GL_BLEND); - - if(tex) - { + if(tex) { glBindTexture(GL_TEXTURE_2D, tex); float sz = 0.35f*min(w, h), x = 0.5f*(w-sz), y = 0.5f*min(w, h) - sz/15; bgquad(x, y, sz, sz); - glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); settexture("data/mapshot_frame.png", 3); bgquad(x, y, sz, sz); glDisable(GL_BLEND); } - swapbuffers(false); } @@ -407,25 +346,20 @@ int keyrepeatmask = 0, textinputmask = 0; Uint32 textinputtime = 0; VAR(textinputfilter, 0, 5, 1000); -void keyrepeat(bool on, int mask) -{ +void keyrepeat(bool on, int mask) { if(on) keyrepeatmask |= mask; else keyrepeatmask &= ~mask; } -void textinput(bool on, int mask) -{ - if(on) - { - if(!textinputmask) - { +void textinput(bool on, int mask) { + if(on) { + if(!textinputmask) { SDL_StartTextInput(); textinputtime = SDL_GetTicks(); } textinputmask |= mask; } - else if(textinputmask) - { + else if(textinputmask) { textinputmask &= ~mask; if(!textinputmask) SDL_StopTextInput(); } @@ -439,34 +373,27 @@ bool shouldgrab = false, grabinput = false, minimized = false, canrelativemouse VAR(sdl_xgrab_bug, 0, 0, 1); #endif -void inputgrab(bool on, bool delay = false) -{ +void inputgrab(bool on, bool delay = false) { #ifdef SDL_VIDEO_DRIVER_X11 bool wasrelativemouse = relativemouse; #endif - if(on) - { + if(on) { SDL_ShowCursor(SDL_FALSE); - if(canrelativemouse && userelativemouse) - { - if(SDL_SetRelativeMouseMode(SDL_TRUE) >= 0) - { + if(canrelativemouse && userelativemouse) { + if(SDL_SetRelativeMouseMode(SDL_TRUE) >= 0) { SDL_SetWindowGrab(screen, SDL_TRUE); relativemouse = true; } - else - { + else { SDL_SetWindowGrab(screen, SDL_FALSE); canrelativemouse = false; relativemouse = false; } } } - else - { + else { SDL_ShowCursor(SDL_TRUE); - if(relativemouse) - { + if(relativemouse) { SDL_SetWindowGrab(screen, SDL_FALSE); SDL_SetRelativeMouseMode(SDL_FALSE); relativemouse = false; @@ -475,15 +402,12 @@ void inputgrab(bool on, bool delay = false) shouldgrab = delay; #ifdef SDL_VIDEO_DRIVER_X11 - if((relativemouse || wasrelativemouse) && sdl_xgrab_bug) - { + if((relativemouse || wasrelativemouse) && sdl_xgrab_bug) { // Workaround for buggy SDL X11 pointer grabbing union { SDL_SysWMinfo info; uchar buf[sizeof(SDL_SysWMinfo) + 128]; }; SDL_GetVersion(&info.version); - if(SDL_GetWindowWMInfo(screen, &info) && info.subsystem == SDL_SYSWM_X11) - { - if(relativemouse) - { + if(SDL_GetWindowWMInfo(screen, &info) && info.subsystem == SDL_SYSWM_X11) { + if(relativemouse) { uint mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask; XGrabPointer(info.info.x11.display, info.info.x11.window, True, mask, GrabModeAsync, GrabModeAsync, info.info.x11.window, None, CurrentTime); } @@ -495,17 +419,14 @@ void inputgrab(bool on, bool delay = false) bool initwindowpos = false; -void setfullscreen(bool enable) -{ +void setfullscreen(bool enable) { if(!screen) return; //initwarning(enable ? "fullscreen" : "windowed"); extern int fullscreendesktop; SDL_SetWindowFullscreen(screen, enable ? (fullscreendesktop ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN) : 0); - if(!enable) - { + if(!enable) { SDL_SetWindowSize(screen, scr_w, scr_h); - if(initwindowpos) - { + if(initwindowpos) { int winx = SDL_WINDOWPOS_CENTERED, winy = SDL_WINDOWPOS_CENTERED; SDL_SetWindowPosition(screen, winx, winy); initwindowpos = false; @@ -519,74 +440,62 @@ VARF(fullscreen, 0, 0, 1, setfullscreen(fullscreen!=0)); VARF(fullscreen, 0, 1, 1, setfullscreen(fullscreen!=0)); #endif -void resetfullscreen() -{ +void resetfullscreen() { setfullscreen(false); setfullscreen(true); } VARF(fullscreendesktop, 0, 0, 1, if(fullscreen) resetfullscreen()); -void screenres(int w, int h) -{ +void screenres(int w, int h) { scr_w = clamp(w, SCR_MINW, SCR_MAXW); scr_h = clamp(h, SCR_MINH, SCR_MAXH); - if(screen) - { - if(fullscreendesktop) - { + if(screen) { + if(fullscreendesktop) { scr_w = min(scr_w, desktopw); scr_h = min(scr_h, desktoph); } - if(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN) - { + if(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN) { if(fullscreendesktop) gl_resize(); else resetfullscreen(); initwindowpos = true; } - else - { + else { SDL_SetWindowSize(screen, scr_w, scr_h); SDL_SetWindowPosition(screen, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); initwindowpos = false; } } - else - { + else { initwarning("screen resolution"); } } ICOMMAND(screenres, "ii", (int *w, int *h), screenres(*w, *h)); -static void setgamma(int val) -{ +static void setgamma(int val) { if(screen && SDL_SetWindowBrightness(screen, val/100.0f) < 0) conoutf(CON_ERROR, "Could not set gamma: %s", SDL_GetError()); } static int curgamma = 100; -VARFNP(gamma, reqgamma, 30, 100, 300, -{ +VARFNP(gamma, reqgamma, 30, 100, 300, { if(initing || reqgamma == curgamma) return; curgamma = reqgamma; setgamma(curgamma); }); -void restoregamma() -{ +void restoregamma() { if(initing || reqgamma == 100) return; curgamma = reqgamma; setgamma(curgamma); } -void cleargamma() -{ +void cleargamma() { if(curgamma != 100 && screen) SDL_SetWindowBrightness(screen, 1.0f); } int curvsync = -1; -void restorevsync() -{ +void restorevsync() { if(initing || !glcontext) return; extern int vsync, vsynctear; if(!SDL_GL_SetSwapInterval(vsync ? (vsynctear ? -1 : 1) : 0)) @@ -596,40 +505,31 @@ void restorevsync() VARFP(vsync, 0, 0, 1, restorevsync()); VARFP(vsynctear, 0, 0, 1, { if(vsync) restorevsync(); }); -void setupscreen() -{ - if(glcontext) - { +void setupscreen() { + if(glcontext) { SDL_GL_DeleteContext(glcontext); glcontext = NULL; } - if(screen) - { + if(screen) { SDL_DestroyWindow(screen); screen = NULL; } curvsync = -1; - SDL_Rect desktop; if(SDL_GetDisplayBounds(0, &desktop) < 0) fatal("failed querying desktop bounds: %s", SDL_GetError()); desktopw = desktop.w; desktoph = desktop.h; - if(scr_h < 0) scr_h = fullscreen ? desktoph : SCR_DEFAULTH; if(scr_w < 0) scr_w = (scr_h*desktopw)/desktoph; scr_w = clamp(scr_w, SCR_MINW, SCR_MAXW); scr_h = clamp(scr_h, SCR_MINH, SCR_MAXH); - if(fullscreendesktop) - { + if(fullscreendesktop) { scr_w = min(scr_w, desktopw); scr_h = min(scr_h, desktoph); } - int winx = SDL_WINDOWPOS_UNDEFINED, winy = SDL_WINDOWPOS_UNDEFINED, winw = scr_w, winh = scr_h, flags = SDL_WINDOW_RESIZABLE; - if(fullscreen) - { - if(fullscreendesktop) - { + if(fullscreen) { + if(fullscreendesktop) { winw = desktopw; winh = desktoph; flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; @@ -637,42 +537,35 @@ void setupscreen() else flags |= SDL_WINDOW_FULLSCREEN; initwindowpos = true; } - SDL_GL_ResetAttributes(); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - static const int configs[] = - { + static const int configs[] = { 0x3, /* try everything */ 0x2, 0x1, /* try disabling one at a time */ 0 /* try disabling everything */ }; int config = 0; if(!depthbits) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - if(!fsaa) - { + if(!fsaa) { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); } - loopi(sizeof(configs)/sizeof(configs[0])) - { + loopi(sizeof(configs)/sizeof(configs[0])) { config = configs[i]; if(!depthbits && config&1) continue; if(fsaa<=0 && config&2) continue; if(depthbits) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, config&1 ? depthbits : 24); - if(fsaa>0) - { + if(fsaa>0) { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, config&2 ? 1 : 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, config&2 ? fsaa : 0); } screen = SDL_CreateWindow("Cube 2: Sauerbraten", winx, winy, winw, winh, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS | flags); if(!screen) continue; - static const int glversions[] = { 33, 32, 31, 30, 20 }; - loopj(sizeof(glversions)/sizeof(glversions[0])) - { + loopj(sizeof(glversions)/sizeof(glversions[0])) { glcompat = glversions[j] <= 30 ? 1 : 0; SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, glversions[j] / 10); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, glversions[j] % 10); @@ -684,24 +577,18 @@ void setupscreen() } if(!screen) fatal("failed to create OpenGL window: %s", SDL_GetError()); else if(!glcontext) fatal("failed to create OpenGL context: %s", SDL_GetError()); - else - { + else { if(depthbits && (config&1)==0) conoutf(CON_WARN, "%d bit z-buffer not supported - disabling", depthbits); if(fsaa>0 && (config&2)==0) conoutf(CON_WARN, "%dx anti-aliasing not supported - disabling", fsaa); } - SDL_SetWindowMinimumSize(screen, SCR_MINW, SCR_MINH); SDL_SetWindowMaximumSize(screen, SCR_MAXW, SCR_MAXH); - SDL_GetWindowSize(screen, &screenw, &screenh); } -void resetgl() -{ +void resetgl() { clearchanges(CHANGE_GFX); - renderbackground("resetting OpenGL"); - extern void cleanupva(); extern void cleanupparticles(); extern void cleanupdecals(); @@ -719,11 +606,9 @@ void resetgl() cleanshadowmap(); cleanupshaders(); cleanupgl(); - setupscreen(); inputgrab(grabinput); gl_init(); - inbetweenframes = false; if(!reloadtexture(*notexture) || !reloadtexture("data/logo.png") || @@ -750,13 +635,10 @@ COMMAND(resetgl, ""); static queue events; -static inline bool filterevent(const SDL_Event &event) -{ - switch(event.type) - { +static inline bool filterevent(const SDL_Event &event) { + switch(event.type) { case SDL_MOUSEMOTION: - if(grabinput && !relativemouse && !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) - { + if(grabinput && !relativemouse && !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) { if(event.motion.x == screenw / 2 && event.motion.y == screenh / 2) return false; // ignore any motion events generated by SDL_WarpMouse } @@ -765,10 +647,8 @@ static inline bool filterevent(const SDL_Event &event) return true; } -template static inline bool pumpevents(queue &events) -{ - while(events.empty()) - { +template static inline bool pumpevents(queue &events) { + while(events.empty()) { SDL_PumpEvents(); databuf buf = events.reserve(events.capacity()); int n = SDL_PeepEvents(buf.getbuf(), buf.remaining(), SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT); @@ -781,14 +661,11 @@ template static inline bool pumpevents(queue &events static int interceptkeysym = 0; -static int interceptevents(void *data, SDL_Event *event) -{ - switch(event->type) - { +static int interceptevents(void *data, SDL_Event *event) { + switch(event->type) { case SDL_MOUSEMOTION: return 0; case SDL_KEYDOWN: - if(event->key.keysym.sym == interceptkeysym) - { + if(event->key.keysym.sym == interceptkeysym) { interceptkeysym = -interceptkeysym; return 0; } @@ -797,20 +674,16 @@ static int interceptevents(void *data, SDL_Event *event) return 1; } -static void clearinterceptkey() -{ +static void clearinterceptkey() { SDL_DelEventWatch(interceptevents, NULL); interceptkeysym = 0; } -bool interceptkey(int sym) -{ - if(!interceptkeysym) - { +bool interceptkey(int sym) { + if(!interceptkeysym) { interceptkeysym = sym; SDL_FilterEvents(interceptevents, NULL); - if(interceptkeysym < 0) - { + if(interceptkeysym < 0) { interceptkeysym = 0; return true; } @@ -818,8 +691,7 @@ bool interceptkey(int sym) } else if(abs(interceptkeysym) != sym) interceptkeysym = sym; SDL_PumpEvents(); - if(interceptkeysym < 0) - { + if(interceptkeysym < 0) { clearinterceptkey(); interceptkeysym = sym; SDL_FilterEvents(interceptevents, NULL); @@ -829,24 +701,19 @@ bool interceptkey(int sym) return false; } -static void ignoremousemotion() -{ +static void ignoremousemotion() { SDL_PumpEvents(); SDL_FlushEvent(SDL_MOUSEMOTION); } -static void resetmousemotion() -{ - if(grabinput && !relativemouse && !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) - { +static void resetmousemotion() { + if(grabinput && !relativemouse && !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) { SDL_WarpMouseInWindow(screen, screenw / 2, screenh / 2); } } -static void checkmousemotion(int &dx, int &dy) -{ - while(pumpevents(events)) - { +static void checkmousemotion(int &dx, int &dy) { + while(pumpevents(events)) { SDL_Event &event = events.removing(); if(event.type != SDL_MOUSEMOTION) return; dx += event.motion.xrel; @@ -855,46 +722,35 @@ static void checkmousemotion(int &dx, int &dy) } } -void checkinput() -{ +void checkinput() { if(interceptkeysym) clearinterceptkey(); //int lasttype = 0, lastbut = 0; bool mousemoved = false; int focused = 0; - while(pumpevents(events)) - { + while(pumpevents(events)) { SDL_Event &event = events.remove(); - if(focused && event.type!=SDL_WINDOWEVENT) { if(grabinput != (focused>0)) inputgrab(grabinput = focused>0, shouldgrab); focused = 0; } - - switch(event.type) - { + switch(event.type) { case SDL_QUIT: quit(); return; - case SDL_TEXTINPUT: - if(textinputmask && int(event.text.timestamp-textinputtime) >= textinputfilter) - { + if(textinputmask && int(event.text.timestamp-textinputtime) >= textinputfilter) { uchar buf[SDL_TEXTINPUTEVENT_TEXT_SIZE+1]; size_t len = decodeutf8(buf, sizeof(buf)-1, (const uchar *)event.text.text, strlen(event.text.text)); if(len > 0) { buf[len] = '\0'; processtextinput((const char *)buf, len); } } break; - case SDL_KEYDOWN: case SDL_KEYUP: if(keyrepeatmask || !event.key.repeat) processkey(event.key.keysym.sym, event.key.state==SDL_PRESSED, event.key.keysym.mod | SDL_GetModState()); break; - case SDL_WINDOWEVENT: - switch(event.window.event) - { + switch(event.window.event) { case SDL_WINDOWEVENT_CLOSE: quit(); break; - case SDL_WINDOWEVENT_FOCUS_GAINED: shouldgrab = true; break; @@ -902,30 +758,23 @@ void checkinput() shouldgrab = false; focused = 1; break; - case SDL_WINDOWEVENT_LEAVE: case SDL_WINDOWEVENT_FOCUS_LOST: shouldgrab = false; focused = -1; break; - case SDL_WINDOWEVENT_MINIMIZED: minimized = true; break; - case SDL_WINDOWEVENT_MAXIMIZED: case SDL_WINDOWEVENT_RESTORED: minimized = false; break; - case SDL_WINDOWEVENT_RESIZED: break; - - case SDL_WINDOWEVENT_SIZE_CHANGED: - { + case SDL_WINDOWEVENT_SIZE_CHANGED: { SDL_GetWindowSize(screen, &screenw, &screenh); - if(!fullscreendesktop || !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) - { + if(!fullscreendesktop || !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) { scr_w = clamp(screenw, SCR_MINW, SCR_MAXW); scr_h = clamp(screenh, SCR_MINH, SCR_MAXH); } @@ -934,10 +783,8 @@ void checkinput() } } break; - case SDL_MOUSEMOTION: - if(grabinput) - { + if(grabinput) { int dx = event.motion.xrel, dy = event.motion.yrel; checkmousemotion(dx, dy); if(!g3d_movecursor(dx, dy)) mousemove(dx, dy); @@ -945,12 +792,10 @@ void checkinput() } else if(shouldgrab) inputgrab(grabinput = true); break; - case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: //if(lasttype==event.type && lastbut==event.button.button) break; // why?? get event twice without it - switch(event.button.button) - { + switch(event.button.button) { case SDL_BUTTON_LEFT: processkey(-1, event.button.state==SDL_PRESSED); break; case SDL_BUTTON_MIDDLE: processkey(-2, event.button.state==SDL_PRESSED); break; case SDL_BUTTON_RIGHT: processkey(-3, event.button.state==SDL_PRESSED); break; @@ -960,7 +805,6 @@ void checkinput() //lasttype = event.type; //lastbut = event.button.button; break; - case SDL_MOUSEWHEEL: if(event.wheel.y > 0) { processkey(-4, true); processkey(-4, false); } else if(event.wheel.y < 0) { processkey(-5, true); processkey(-5, false); } @@ -971,8 +815,7 @@ void checkinput() if(mousemoved) resetmousemotion(); } -void swapbuffers(bool overlay) -{ +void swapbuffers(bool overlay) { gle::disable(); SDL_GL_SwapWindow(screen); } @@ -980,23 +823,19 @@ void swapbuffers(bool overlay) VAR(menufps, 0, 60, 1000); VARP(maxfps, 0, 200, 1000); -void limitfps(int &millis, int curmillis) -{ +void limitfps(int &millis, int curmillis) { int limit = (mainmenu || minimized) && menufps ? (maxfps ? min(maxfps, menufps) : menufps) : maxfps; if(!limit) return; static int fpserror = 0; int delay = 1000/limit - (millis-curmillis); if(delay < 0) fpserror = 0; - else - { + else { fpserror += 1000%limit; - if(fpserror >= limit) - { + if(fpserror >= limit) { ++delay; fpserror -= limit; } - if(delay > 0) - { + if(delay > 0) { SDL_Delay(delay); millis += delay; } @@ -1007,36 +846,30 @@ void limitfps(int &millis, int curmillis) int fpspos = 0, fpshistory[MAXFPSHISTORY]; -void resetfpshistory() -{ +void resetfpshistory() { loopi(MAXFPSHISTORY) fpshistory[i] = 1; fpspos = 0; } -void updatefpshistory(int millis) -{ +void updatefpshistory(int millis) { fpshistory[fpspos++] = max(1, min(1000, millis)); if(fpspos>=MAXFPSHISTORY) fpspos = 0; } -void getfps(int &fps, int &bestdiff, int &worstdiff) -{ +void getfps(int &fps, int &bestdiff, int &worstdiff) { int total = fpshistory[MAXFPSHISTORY-1], best = total, worst = total; - loopi(MAXFPSHISTORY-1) - { + loopi(MAXFPSHISTORY-1) { int millis = fpshistory[i]; total += millis; if(millis < best) best = millis; if(millis > worst) worst = millis; } - fps = (1000*MAXFPSHISTORY)/total; bestdiff = 1000/best-fps; worstdiff = fps-1000/worst; } -void getfps_(int *raw) -{ +void getfps_(int *raw) { int fps, bestdiff, worstdiff; if(*raw) fps = 1000/fpshistory[(fpspos+MAXFPSHISTORY-1)%MAXFPSHISTORY]; else getfps(fps, bestdiff, worstdiff); @@ -1047,8 +880,7 @@ COMMANDN(getfps, getfps_, "i"); bool inbetweenframes = false, renderedframe = true; -static bool findarg(int argc, char **argv, const char *str) -{ +static bool findarg(int argc, char **argv, const char *str) { for(int i = 1; i0, dedicated>1); // never returns if dedicated ASSERT(dedicated <= 1); game::initclient(); - logoutf("init: video"); SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, "0"); SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); setupscreen(); SDL_ShowCursor(SDL_FALSE); SDL_StopTextInput(); // workaround for spurious text-input events getting sent on first text input toggle? - logoutf("init: gl"); gl_checkextensions(); gl_init(); notexture = textureload("packages/textures/texture_error.png"); if(!notexture) fatal("could not find core textures"); - logoutf("init: console"); if(!execfile("data/stdlib.cfg", false)) fatal("cannot find data files (you are running from the wrong folder, try .bat file in the main folder)"); // this is the first file we load. if(!execfile("packages/fonts/default.cfg", false)) fatal("cannot find font definitions"); if(!setfont("default")) fatal("no default font specified"); - inbetweenframes = true; renderbackground("initializing..."); - logoutf("init: world"); camera1 = player = game::iterdynents(0); emptymap(0, true, NULL, false); - logoutf("init: sound"); initsound(); - logoutf("init: cfg"); initing = INIT_LOAD; execfile("data/keymap.cfg"); @@ -1189,52 +999,35 @@ int main(int argc, char **argv) execfile("data/game.cfg"); execfile("data/custom_maps_menu.cfg"); if(game::savedservers()) execfile(game::savedservers(), false); - identflags |= IDF_PERSIST; - - if(!execfile(game::savedconfig(), false)) - { + if(!execfile(game::savedconfig(), false)) { execfile(game::defaultconfig()); writecfg(game::restoreconfig()); } execfile(game::autoexec(), false); - identflags &= ~IDF_PERSIST; - initing = INIT_GAME; game::loadconfigs(); - initing = NOT_INITING; - logoutf("init: render"); restoregamma(); restorevsync(); loadshaders(); initparticles(); initdecals(); - identflags |= IDF_PERSIST; - logoutf("init: mainloop"); - if(execfile("once.cfg", false)) remove(findfile("once.cfg", "rb")); - - if(load) - { + if(load) { logoutf("init: localconnect"); //localconnect(); game::changemap(load); } - if(initscript) execute(initscript); - resetfpshistory(); - inputgrab(grabinput = true); ignoremousemotion(); - - for(;;) - { + for(;;) { static int frames = 0; int millis = getclockmillis(); limitfps(millis, totalmillis); @@ -1248,37 +1041,26 @@ int main(int argc, char **argv) lastmillis += curtime; totalmillis = millis; updatetime(); - checkinput(); menuprocess(); tryedit(); - if(lastmillis) game::updateworld(); - checksleep(lastmillis); - serverslice(false, 0); - if(frames) updatefpshistory(elapsedtime); frames++; - // miscellaneous general game effects recomputecamera(); updateparticles(); updatesounds(); - if(minimized) continue; - inbetweenframes = false; - glClearColor(0,0,0,1);///TODO - if(mainmenu) gl_drawmainmenu(); else gl_drawframe(); swapbuffers(); renderedframe = inbetweenframes = true; } - ASSERT(0); return EXIT_FAILURE; } diff --git a/src/engine/master.cpp b/src/engine/master.cpp index 2bf1dba..c1d3e20 100644 --- a/src/engine/master.cpp +++ b/src/engine/master.cpp @@ -22,15 +22,13 @@ FILE *logfile = NULL; -struct userinfo -{ +struct userinfo { char *name; void *pubkey; }; hashnameset users; -void adduser(char *name, char *pubkey) -{ +void adduser(char *name, char *pubkey) { name = newstring(name); userinfo &u = users[name]; u.name = name; @@ -38,8 +36,7 @@ void adduser(char *name, char *pubkey) } COMMAND(adduser, "ss"); -void clearusers() -{ +void clearusers() { enumerate(users, userinfo, u, { delete[] u.name; freepubkey(u.pubkey); }); users.clear(); } @@ -47,16 +44,14 @@ COMMAND(clearusers, ""); vector bans, servbans, gbans; -void clearbans() -{ +void clearbans() { bans.shrink(0); servbans.shrink(0); gbans.shrink(0); } COMMAND(clearbans, ""); -void addban(vector &bans, const char *name) -{ +void addban(vector &bans, const char *name) { ipmask ban; ban.parse(name); bans.add(ban); @@ -65,21 +60,18 @@ ICOMMAND(ban, "s", (char *name), addban(bans, name)); ICOMMAND(servban, "s", (char *name), addban(servbans, name)); ICOMMAND(gban, "s", (char *name), addban(gbans, name)); -bool checkban(vector &bans, enet_uint32 host) -{ +bool checkban(vector &bans, enet_uint32 host) { loopv(bans) if(bans[i].check(host)) return true; return false; } -struct authreq -{ +struct authreq { enet_uint32 reqtime; uint id; void *answer; }; -struct gameserver -{ +struct gameserver { ENetAddress address; string ip; int port, numpings; @@ -87,30 +79,21 @@ struct gameserver }; vector gameservers; -struct messagebuf -{ +struct messagebuf { vector &owner; vector buf; int refs; - messagebuf(vector &owner) : owner(owner), refs(0) {} - const char *getbuf() { return buf.getbuf(); } int length() { return buf.length(); } void purge(); - - bool equals(const messagebuf &m) const - { + bool equals(const messagebuf &m) const { return buf.length() == m.buf.length() && !memcmp(buf.getbuf(), m.buf.getbuf(), buf.length()); } - - bool endswith(const messagebuf &m) const - { + bool endswith(const messagebuf &m) const { return buf.length() >= m.buf.length() && !memcmp(&buf[buf.length() - m.buf.length()], m.buf.getbuf(), m.buf.length()); } - - void concat(const messagebuf &m) - { + void concat(const messagebuf &m) { if(buf.length() && buf.last() == '\0') buf.pop(); buf.put(m.buf.getbuf(), m.buf.length()); } @@ -118,8 +101,7 @@ struct messagebuf vector gameserverlists, gbanlists; bool updateserverlist = true; -struct client -{ +struct client { ENetAddress address; ENetSocket socket; char input[INPUT_LIMIT]; @@ -132,7 +114,6 @@ struct client vector authreqs; bool shouldpurge; bool registeredserver; - client() : message(NULL), inputpos(0), outputpos(0), servport(-1), lastauth(0), shouldpurge(false), registeredserver(false) {} }; vector clients; @@ -142,8 +123,7 @@ ENetSocket serversocket = ENET_SOCKET_NULL; time_t starttime; enet_uint32 servtime = 0; -void fatal(const char *fmt, ...) -{ +void fatal(const char *fmt, ...) { va_list args; va_start(args, fmt); vfprintf(logfile, fmt, args); @@ -152,14 +132,12 @@ void fatal(const char *fmt, ...) exit(EXIT_FAILURE); } -void conoutfv(int type, const char *fmt, va_list args) -{ +void conoutfv(int type, const char *fmt, va_list args) { vfprintf(logfile, fmt, args); fputc('\n', logfile); } -void purgeclient(int n) -{ +void purgeclient(int n) { client &c = *clients[n]; if(c.message) c.message->purge(); enet_socket_destroy(c.socket); @@ -167,27 +145,23 @@ void purgeclient(int n) clients.remove(n); } -void output(client &c, const char *msg, int len = 0) -{ +void output(client &c, const char *msg, int len = 0) { if(!len) len = strlen(msg); c.output.put(msg, len); } -void outputf(client &c, const char *fmt, ...) -{ +void outputf(client &c, const char *fmt, ...) { string msg; va_list args; va_start(args, fmt); vformatstring(msg, fmt, args); va_end(args); - output(c, msg); } ENetSocket pingsocket = ENET_SOCKET_NULL; -bool setuppingsocket(ENetAddress *address) -{ +bool setuppingsocket(ENetAddress *address) { if(pingsocket != ENET_SOCKET_NULL) return true; pingsocket = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); if(pingsocket == ENET_SOCKET_NULL) return false; @@ -196,14 +170,11 @@ bool setuppingsocket(ENetAddress *address) return true; } -void setupserver(int port, const char *ip = NULL) -{ +void setupserver(int port, const char *ip = NULL) { ENetAddress address; address.host = ENET_HOST_ANY; address.port = port; - - if(ip) - { + if(ip) { if(enet_address_set_host(&address, ip)<0) fatal("failed to resolve server address: %s", ip); } @@ -217,23 +188,19 @@ void setupserver(int port, const char *ip = NULL) fatal("failed to make server socket non-blocking"); if(!setuppingsocket(&address)) fatal("failed to create ping socket"); - enet_time_set(0); - starttime = time(NULL); char *ct = ctime(&starttime); if(strchr(ct, '\n')) *strchr(ct, '\n') = '\0'; conoutf("*** Starting master server on %s %d at %s ***", ip ? ip : "localhost", port, ct); } -void genserverlist() -{ +void genserverlist() { if(!updateserverlist) return; while(gameserverlists.length() && gameserverlists.last()->refs<=0) delete gameserverlists.pop(); messagebuf *l = new messagebuf(gameserverlists); - loopv(gameservers) - { + loopv(gameservers) { gameserver &s = *gameservers[i]; if(!s.lastpong) continue; defformatstring(cmd, "addserver %s %d\n", s.ip, s.port); @@ -244,67 +211,56 @@ void genserverlist() updateserverlist = false; } -void gengbanlist() -{ +void gengbanlist() { messagebuf *l = new messagebuf(gbanlists); const char *header = "cleargbans\n"; l->buf.put(header, strlen(header)); string cmd = "addgban "; int cmdlen = strlen(cmd); - loopv(gbans) - { + loopv(gbans) { ipmask &b = gbans[i]; l->buf.put(cmd, cmdlen + b.print(&cmd[cmdlen])); l->buf.add('\n'); } - if(gbanlists.length() && gbanlists.last()->equals(*l)) - { + if(gbanlists.length() && gbanlists.last()->equals(*l)) { delete l; return; } while(gbanlists.length() && gbanlists.last()->refs<=0) delete gbanlists.pop(); - loopv(gbanlists) - { + loopv(gbanlists) { messagebuf *m = gbanlists[i]; if(m->refs > 0 && !m->endswith(*l)) m->concat(*l); } gbanlists.add(l); - loopv(clients) - { + loopv(clients) { client &c = *clients[i]; - if(c.servport >= 0 && !c.message) - { + if(c.servport >= 0 && !c.message) { c.message = l; c.message->refs++; } } } -void addgameserver(client &c) -{ +void addgameserver(client &c) { if(gameservers.length() >= SERVER_LIMIT) return; int dups = 0; - loopv(gameservers) - { + loopv(gameservers) { gameserver &s = *gameservers[i]; if(s.address.host != c.address.host) continue; ++dups; - if(s.port == c.servport) - { + if(s.port == c.servport) { s.lastping = 0; s.numpings = 0; return; } } - if(dups >= SERVER_DUP_LIMIT) - { + if(dups >= SERVER_DUP_LIMIT) { outputf(c, "failreg too many servers on ip\n"); return; } string hostname; - if(enet_address_get_host_ip(&c.address, hostname, sizeof(hostname)) < 0) - { + if(enet_address_get_host_ip(&c.address, hostname, sizeof(hostname)) < 0) { outputf(c, "failreg failed resolving ip\n"); return; } @@ -317,10 +273,8 @@ void addgameserver(client &c) s.lastping = s.lastpong = 0; } -client *findclient(gameserver &s) -{ - loopv(clients) - { +client *findclient(gameserver &s) { + loopv(clients) { client &c = *clients[i]; if(s.address.host == c.address.host && s.port == c.servport) return &c; @@ -328,37 +282,29 @@ client *findclient(gameserver &s) return NULL; } -void servermessage(gameserver &s, const char *msg) -{ +void servermessage(gameserver &s, const char *msg) { client *c = findclient(s); if(c) outputf(*c, msg); } -void checkserverpongs() -{ +void checkserverpongs() { ENetBuffer buf; ENetAddress addr; static uchar pong[MAXTRANS]; - for(;;) - { + for(;;) { buf.data = pong; buf.dataLength = sizeof(pong); int len = enet_socket_receive(pingsocket, &addr, &buf, 1); if(len <= 0) break; - loopv(gameservers) - { + loopv(gameservers) { gameserver &s = *gameservers[i]; - if(s.address.host == addr.host && s.address.port == addr.port) - { - if(s.lastping && (!s.lastpong || ENET_TIME_GREATER(s.lastping, s.lastpong))) - { + if(s.address.host == addr.host && s.address.port == addr.port) { + if(s.lastping && (!s.lastpong || ENET_TIME_GREATER(s.lastping, s.lastpong))) { client *c = findclient(s); - if(c) - { + if(c) { c->registeredserver = true; outputf(*c, "succreg\n"); - if(!c->message && gbanlists.length()) - { + if(!c->message && gbanlists.length()) { c->message = gbanlists.last(); c->message->refs++; } @@ -372,39 +318,30 @@ void checkserverpongs() } } -void bangameservers() -{ - loopvrev(gameservers) if(checkban(servbans, gameservers[i]->address.host)) - { +void bangameservers() { + loopvrev(gameservers) if(checkban(servbans, gameservers[i]->address.host)) { delete gameservers.remove(i); updateserverlist = true; } } -void checkgameservers() -{ +void checkgameservers() { ENetBuffer buf; - loopv(gameservers) - { + loopv(gameservers) { gameserver &s = *gameservers[i]; - if(s.lastping && s.lastpong && ENET_TIME_LESS_EQUAL(s.lastping, s.lastpong)) - { - if(ENET_TIME_DIFFERENCE(servtime, s.lastpong) > KEEPALIVE_TIME) - { + if(s.lastping && s.lastpong && ENET_TIME_LESS_EQUAL(s.lastping, s.lastpong)) { + if(ENET_TIME_DIFFERENCE(servtime, s.lastpong) > KEEPALIVE_TIME) { delete gameservers.remove(i--); updateserverlist = true; } } - else if(!s.lastping || ENET_TIME_DIFFERENCE(servtime, s.lastping) > PING_TIME) - { - if(s.numpings >= PING_RETRY) - { + else if(!s.lastping || ENET_TIME_DIFFERENCE(servtime, s.lastping) > PING_TIME) { + if(s.numpings >= PING_RETRY) { servermessage(s, "failreg failed pinging server\n"); delete gameservers.remove(i--); updateserverlist = true; } - else - { + else { static const uchar ping[] = { 1 }; buf.data = (void *)ping; buf.dataLength = sizeof(ping); @@ -416,23 +353,18 @@ void checkgameservers() } } -void messagebuf::purge() -{ +void messagebuf::purge() { refs = max(refs - 1, 0); - if(refs<=0 && owner.last()!=this) - { + if(refs<=0 && owner.last()!=this) { owner.removeobj(this); delete this; } } -void purgeauths(client &c) -{ +void purgeauths(client &c) { int expired = 0; - loopv(c.authreqs) - { - if(ENET_TIME_DIFFERENCE(servtime, c.authreqs[i].reqtime) >= AUTH_TIME) - { + loopv(c.authreqs) { + if(ENET_TIME_DIFFERENCE(servtime, c.authreqs[i].reqtime) >= AUTH_TIME) { outputf(c, "failauth %u\n", c.authreqs[i].id); freechallenge(c.authreqs[i].answer); expired = i + 1; @@ -442,40 +374,30 @@ void purgeauths(client &c) if(expired > 0) c.authreqs.remove(0, expired); } -void reqauth(client &c, uint id, char *name) -{ +void reqauth(client &c, uint id, char *name) { if(ENET_TIME_DIFFERENCE(servtime, c.lastauth) < AUTH_THROTTLE) return; - c.lastauth = servtime; - purgeauths(c); - time_t t = time(NULL); char *ct = ctime(&t); - if(ct) - { + if(ct) { char *newline = strchr(ct, '\n'); if(newline) *newline = '\0'; } string ip; if(enet_address_get_host_ip(&c.address, ip, sizeof(ip)) < 0) copystring(ip, "-"); conoutf("%s: attempting \"%s\" as %u from %s", ct ? ct : "-", name, id, ip); - userinfo *u = users.access(name); - if(!u) - { + if(!u) { outputf(c, "failauth %u\n", id); return; } - - if(c.authreqs.length() >= AUTH_LIMIT) - { + if(c.authreqs.length() >= AUTH_LIMIT) { outputf(c, "failauth %u\n", c.authreqs[0].id); freechallenge(c.authreqs[0].answer); c.authreqs.remove(0); } - authreq &a = c.authreqs.add(); a.reqtime = servtime; a.id = id; @@ -483,25 +405,19 @@ void reqauth(client &c, uint id, char *name) static vector buf; buf.setsize(0); a.answer = genchallenge(u->pubkey, seed, sizeof(seed), buf); - outputf(c, "chalauth %u %s\n", id, buf.getbuf()); } -void confauth(client &c, uint id, const char *val) -{ +void confauth(client &c, uint id, const char *val) { purgeauths(c); - - loopv(c.authreqs) if(c.authreqs[i].id == id) - { + loopv(c.authreqs) if(c.authreqs[i].id == id) { string ip; if(enet_address_get_host_ip(&c.address, ip, sizeof(ip)) < 0) copystring(ip, "-"); - if(checkchallenge(val, c.authreqs[i].answer)) - { + if(checkchallenge(val, c.authreqs[i].answer)) { outputf(c, "succauth %u\n", id); conoutf("succeeded %u from %s", id, ip); } - else - { + else { outputf(c, "failauth %u\n", id); conoutf("failed %u from %s", id, ip); } @@ -512,20 +428,16 @@ void confauth(client &c, uint id, const char *val) outputf(c, "failauth %u\n", id); } -bool checkclientinput(client &c) -{ +bool checkclientinput(client &c) { if(c.inputpos<0) return true; char *end = (char *)memchr(c.input, '\n', c.inputpos); - while(end) - { + while(end) { *end++ = '\0'; c.lastinput = servtime; - int port; uint id; string user, val; - if(!strncmp(c.input, "list", 4) && (!c.input[4] || c.input[4] == '\n' || c.input[4] == '\r')) - { + if(!strncmp(c.input, "list", 4) && (!c.input[4] || c.input[4] == '\n' || c.input[4] == '\r')) { genserverlist(); if(gameserverlists.empty() || c.message) return false; c.message = gameserverlists.last(); @@ -535,27 +447,22 @@ bool checkclientinput(client &c) c.shouldpurge = true; return true; } - else if(sscanf(c.input, "regserv %d", &port) == 1) - { + else if(sscanf(c.input, "regserv %d", &port) == 1) { if(checkban(servbans, c.address.host)) return false; if(port < 0 || port > 0xFFFF-1 || (c.servport >= 0 && port != c.servport)) outputf(c, "failreg invalid port\n"); - else - { + else { c.servport = port; addgameserver(c); } } - else if(sscanf(c.input, "reqauth %u %100s", &id, user) == 2) - { + else if(sscanf(c.input, "reqauth %u %100s", &id, user) == 2) { reqauth(c, id, user); } - else if(sscanf(c.input, "confauth %u %100s", &id, val) == 2) - { + else if(sscanf(c.input, "confauth %u %100s", &id, val) == 2) { confauth(c, id, val); } c.inputpos = &c.input[c.inputpos] - end; memmove(c.input, end, c.inputpos); - end = (char *)memchr(c.input, '\n', c.inputpos); } return c.inputpos<(int)sizeof(c.input); @@ -563,16 +470,14 @@ bool checkclientinput(client &c) ENetSocketSet readset, writeset; -void checkclients() -{ +void checkclients() { ENetSocketSet readset, writeset; ENetSocket maxsock = max(serversocket, pingsocket); ENET_SOCKETSET_EMPTY(readset); ENET_SOCKETSET_EMPTY(writeset); ENET_SOCKETSET_ADD(readset, serversocket); ENET_SOCKETSET_ADD(readset, pingsocket); - loopv(clients) - { + loopv(clients) { client &c = *clients[i]; if(c.authreqs.length()) purgeauths(c); if(c.message || c.output.length()) ENET_SOCKETSET_ADD(writeset, c.socket); @@ -580,23 +485,18 @@ void checkclients() maxsock = max(maxsock, c.socket); } if(enet_socketset_select(maxsock, &readset, &writeset, 1000)<=0) return; - if(ENET_SOCKETSET_CHECK(readset, pingsocket)) checkserverpongs(); - if(ENET_SOCKETSET_CHECK(readset, serversocket)) - { + if(ENET_SOCKETSET_CHECK(readset, serversocket)) { ENetAddress address; ENetSocket clientsocket = enet_socket_accept(serversocket, &address); if(clients.length()>=CLIENT_LIMIT || checkban(bans, address.host)) enet_socket_destroy(clientsocket); - else if(clientsocket!=ENET_SOCKET_NULL) - { + else if(clientsocket!=ENET_SOCKET_NULL) { int dups = 0, oldest = -1; - loopv(clients) if(clients[i]->address.host == address.host) - { + loopv(clients) if(clients[i]->address.host == address.host) { dups++; if(oldest<0 || clients[i]->connecttime < clients[oldest]->connecttime) oldest = i; } if(dups >= DUP_LIMIT) purgeclient(oldest); - client *c = new client; c->address = address; c->socket = clientsocket; @@ -605,32 +505,25 @@ void checkclients() clients.add(c); } } - - loopv(clients) - { + loopv(clients) { client &c = *clients[i]; - if((c.message || c.output.length()) && ENET_SOCKETSET_CHECK(writeset, c.socket)) - { + if((c.message || c.output.length()) && ENET_SOCKETSET_CHECK(writeset, c.socket)) { const char *data = c.output.length() ? c.output.getbuf() : c.message->getbuf(); int len = c.output.length() ? c.output.length() : c.message->length(); ENetBuffer buf; buf.data = (void *)&data[c.outputpos]; buf.dataLength = len-c.outputpos; int res = enet_socket_send(c.socket, NULL, &buf, 1); - if(res>=0) - { + if(res>=0) { c.outputpos += res; - if(c.outputpos>=len) - { + if(c.outputpos>=len) { if(c.output.length()) c.output.setsize(0); - else - { + else { c.message->purge(); c.message = NULL; } c.outputpos = 0; - if(!c.message && c.output.empty() && c.shouldpurge) - { + if(!c.message && c.output.empty() && c.shouldpurge) { purgeclient(i--); continue; } @@ -638,14 +531,12 @@ void checkclients() } else { purgeclient(i--); continue; } } - if(ENET_SOCKETSET_CHECK(readset, c.socket)) - { + if(ENET_SOCKETSET_CHECK(readset, c.socket)) { ENetBuffer buf; buf.data = &c.input[c.inputpos]; buf.dataLength = sizeof(c.input) - c.inputpos; int res = enet_socket_receive(c.socket, NULL, &buf, 1); - if(res>0) - { + if(res>0) { c.inputpos += res; c.input[min(c.inputpos, (int)sizeof(c.input)-1)] = '\0'; if(!checkclientinput(c)) { purgeclient(i--); continue; } @@ -657,23 +548,19 @@ void checkclients() } } -void banclients() -{ +void banclients() { loopvrev(clients) if(checkban(bans, clients[i]->address.host)) purgeclient(i); } volatile int reloadcfg = 1; -void reloadsignal(int signum) -{ +void reloadsignal(int signum) { reloadcfg = 1; } -int main(int argc, char **argv) -{ +int main(int argc, char **argv) { if(enet_initialize()<0) fatal("Unable to initialise network module"); atexit(enet_deinitialize); - const char *dir = "", *ip = NULL; int port = 28787; if(argc>=2) dir = argv[1]; @@ -688,10 +575,8 @@ int main(int argc, char **argv) setvbuf(logfile, NULL, _IOLBF, BUFSIZ); signal(SIGUSR1, reloadsignal); setupserver(port, ip); - for(;;) - { - if(reloadcfg) - { + for(;;) { + if(reloadcfg) { conoutf("reloading master.cfg"); execfile(cfgname); bangameservers(); @@ -699,12 +584,10 @@ int main(int argc, char **argv) gengbanlist(); reloadcfg = 0; } - servtime = enet_time_get(); checkclients(); checkgameservers(); } - return EXIT_SUCCESS; } diff --git a/src/engine/material.cpp b/src/engine/material.cpp index e29ccf5..55151a1 100644 --- a/src/engine/material.cpp +++ b/src/engine/material.cpp @@ -4,13 +4,9 @@ struct QuadNode { int x, y, size; uint filled; QuadNode *child[4]; - QuadNode(int x, int y, int size) : x(x), y(y), size(size), filled(0) { loopi(4) child[i] = 0; } - void clear() { loopi(4) DELETEP(child[i]); } - ~QuadNode() { clear(); } - void insert(int mx, int my, int msize) { if(size == msize) { filled = 0xF; @@ -25,15 +21,13 @@ struct QuadNode { } if(!child[i]) child[i] = new QuadNode(i&1 ? x+csize : x, i&2 ? y+csize : y, csize); child[i]->insert(mx, my, msize); - loopj(4) if(child[j]) - { + loopj(4) if(child[j]) { if(child[j]->filled == 0xF) { DELETEP(child[j]); filled |= (1 << j); } } } - void genmatsurf(ushort mat, uchar orient, uchar visible, int x, int y, int z, int size, materialsurface *&matbuf) { materialsurface &m = *matbuf++; m.material = mat; @@ -46,11 +40,9 @@ struct QuadNode { m.o[R[dim]] = y; m.o[dim] = z; } - void genmatsurfs(ushort mat, uchar orient, uchar flags, int z, materialsurface *&matbuf) { if(filled == 0xF) genmatsurf(mat, orient, flags, x, y, z, size, matbuf); - else if(filled) - { + else if(filled) { int csize = size>>1; loopi(4) if(filled & (1 << i)) genmatsurf(mat, orient, flags, i&1 ? x+csize : x, i&2 ? y+csize : y, z, csize, matbuf); @@ -68,21 +60,18 @@ static const bvec4 matnormals[6] = { bvec4(0, 0, 0x7F) }; -static void drawmaterial(const materialsurface &m, float offset, const bvec4 &color) -{ - if(gle::attribbuf.empty()) - { +static void drawmaterial(const materialsurface &m, float offset, const bvec4 &color) { + if(gle::attribbuf.empty()) { gle::defvertex(); gle::defcolor(4, GL_UNSIGNED_BYTE); gle::begin(GL_QUADS); } float x = m.o.x, y = m.o.y, z = m.o.z, csize = m.csize, rsize = m.rsize; - switch(m.orient) - { + switch(m.orient) { #define GENFACEORIENT(orient, v0, v1, v2, v3) \ case orient: v0 v1 v2 v3 break; - #define GENFACEVERT(orient, vert, mx,my,mz, sx,sy,sz) \ - { \ + #define GENFACEVERT(orient, vert, mx,my,mz, sx,sy,sz) { \ + \ gle::attribf(mx sx, my sy, mz sz); \ gle::attrib(color); \ } @@ -92,45 +81,38 @@ static void drawmaterial(const materialsurface &m, float offset, const bvec4 &co } } -const struct material -{ +const struct material { const char *name; ushort id; -} materials[] = -{ - {"air", MAT_AIR}, - {"clip", MAT_CLIP}, - {"noclip", MAT_NOCLIP}, - {"gameclip", MAT_GAMECLIP}, - {"death", MAT_DEATH}, - {"alpha", MAT_ALPHA} +} materials[] = { + { + "air", MAT_AIR}, { + "clip", MAT_CLIP}, { + "noclip", MAT_NOCLIP}, { + "gameclip", MAT_GAMECLIP}, { + "death", MAT_DEATH}, { + "alpha", MAT_ALPHA} }; -int findmaterial(const char *name) -{ - loopi(sizeof(materials)/sizeof(material)) - { +int findmaterial(const char *name) { + loopi(sizeof(materials)/sizeof(material)) { if(!strcmp(materials[i].name, name)) return materials[i].id; } return -1; } -const char *findmaterialname(int mat) -{ +const char *findmaterialname(int mat) { loopi(sizeof(materials)/sizeof(materials[0])) if(materials[i].id == mat) return materials[i].name; return NULL; } -const char *getmaterialdesc(int mat, const char *prefix) -{ +const char *getmaterialdesc(int mat, const char *prefix) { static const ushort matmasks[] = { MATF_INDEX, MATF_CLIP, MAT_DEATH, MAT_ALPHA }; static string desc; desc[0] = '\0'; - loopi(sizeof(matmasks)/sizeof(matmasks[0])) if(mat&matmasks[i]) - { + loopi(sizeof(matmasks)/sizeof(matmasks[0])) if(mat&matmasks[i]) { const char *matname = findmaterialname(mat&matmasks[i]); - if(matname) - { + if(matname) { concatstring(desc, desc[0] ? ", " : prefix); concatstring(desc, matname); } @@ -138,14 +120,11 @@ const char *getmaterialdesc(int mat, const char *prefix) return desc; } -int visiblematerial(const cube &c, int orient, const ivec &co, int size, ushort matmask) -{ +int visiblematerial(const cube &c, int orient, const ivec &co, int size, ushort matmask) { ushort mat = c.material&matmask; - switch(mat) - { + switch(mat) { case MAT_AIR: break; - default: if(visibleface(c, orient, co, size, mat, MAT_AIR, matmask)) return MATSURF_EDIT_ONLY; @@ -154,17 +133,13 @@ int visiblematerial(const cube &c, int orient, const ivec &co, int size, ushort return MATSURF_NOT_VISIBLE; } -void genmatsurfs(const cube &c, const ivec &co, int size, vector &matsurfs) -{ - loopi(6) - { +void genmatsurfs(const cube &c, const ivec &co, int size, vector &matsurfs) { + loopi(6) { static const ushort matmasks[] = { MATF_INDEX, MATF_CLIP, MAT_DEATH, MAT_ALPHA }; - loopj(sizeof(matmasks)/sizeof(matmasks[0])) - { + loopj(sizeof(matmasks)/sizeof(matmasks[0])) { int matmask = matmasks[j]; int vis = visiblematerial(c, i, co, size, matmask&~MATF_INDEX); - if(vis != MATSURF_NOT_VISIBLE) - { + if(vis != MATSURF_NOT_VISIBLE) { materialsurface m; m.material = c.material&matmask; m.orient = i; @@ -179,22 +154,18 @@ void genmatsurfs(const cube &c, const ivec &co, int size, vector y.o[r] + y.rsize) return false; return x.o[c] < y.o[c]; } -static int mergematr(materialsurface *m, int sz, materialsurface &n) -{ +static int mergematr(materialsurface *m, int sz, materialsurface &n) { int dim = dimension(n.orient), c = C[dim], r = R[dim]; - for(int i = sz-1; i >= 0; --i) - { + for(int i = sz-1; i >= 0; --i) { if(m[i].o[r] + m[i].rsize < n.o[r]) break; - if(m[i].o[r] + m[i].rsize == n.o[r] && m[i].o[c] == n.o[c] && m[i].csize == n.csize) - { + if(m[i].o[r] + m[i].rsize == n.o[r] && m[i].o[c] == n.o[c] && m[i].csize == n.csize) { n.o[r] = m[i].o[r]; n.rsize += m[i].rsize; memmove(&m[i], &m[i+1], (sz - (i+1)) * sizeof(materialsurface)); @@ -204,11 +175,9 @@ static int mergematr(materialsurface *m, int sz, materialsurface &n) return 0; } -static int mergematc(materialsurface &m, materialsurface &n) -{ +static int mergematc(materialsurface &m, materialsurface &n) { int dim = dimension(n.orient), c = C[dim], r = R[dim]; - if(m.o[r] == n.o[r] && m.rsize == n.rsize && m.o[c] + m.csize == n.o[c]) - { + if(m.o[r] == n.o[r] && m.rsize == n.rsize && m.o[c] + m.csize == n.o[c]) { n.o[c] = m.o[c]; n.csize += m.csize; return 1; @@ -216,10 +185,8 @@ static int mergematc(materialsurface &m, materialsurface &n) return 0; } -static int mergemat(materialsurface *m, int sz, materialsurface &n) -{ - for(bool merged = false; sz; merged = true) - { +static int mergemat(materialsurface *m, int sz, materialsurface &n) { + for(bool merged = false; sz; merged = true) { int rmerged = mergematr(m, sz, n); sz -= rmerged; if(!rmerged && merged) break; @@ -232,17 +199,14 @@ static int mergemat(materialsurface *m, int sz, materialsurface &n) return sz; } -static int mergemats(materialsurface *m, int sz) -{ +static int mergemats(materialsurface *m, int sz) { quicksort(m, sz, mergematcmp); - int nsz = 0; loopi(sz) nsz = mergemat(m, nsz, m[i]); return nsz; } -static inline bool optmatcmp(const materialsurface &x, const materialsurface &y) -{ +static inline bool optmatcmp(const materialsurface &x, const materialsurface &y) { if(x.material < y.material) return true; if(x.material > y.material) return false; if(x.orient > y.orient) return true; @@ -253,13 +217,11 @@ static inline bool optmatcmp(const materialsurface &x, const materialsurface &y) VARF(optmats, 0, 1, 1, allchanged()); -int optimizematsurfs(materialsurface *matbuf, int matsurfs) -{ +int optimizematsurfs(materialsurface *matbuf, int matsurfs) { quicksort(matbuf, matsurfs, optmatcmp); if(!optmats) return matsurfs; materialsurface *cur = matbuf, *end = matbuf+matsurfs; - while(cur < end) - { + while(cur < end) { materialsurface *start = cur++; int dim = dimension(start->orient); while(cur < end && @@ -288,17 +250,14 @@ int optimizematsurfs(materialsurface *matbuf, int matsurfs) return matsurfs - (end-matbuf); } -void setupmaterials(int start, int len) -{ +void setupmaterials(int start, int len) { int hasmat = 0; unionfind uf; if(!len) len = valist.length(); - for(int i = start; i < len; i++) - { + for(int i = start; i < len; i++) { vtxarray *va = valist[i]; materialsurface *skip = NULL; - loopj(va->matsurfs) - { + loopj(va->matsurfs) { materialsurface &m = va->matbuf[j]; int matvol = 0; if(matvol) hasmat |= 1< &vismats) -{ +void sortmaterials(vector &vismats) { sortorigin = ivec(camera1->o); vec dir; vecfromyawpitch(camera1->yaw, camera1->pitch, 1, 0, dir); @@ -355,15 +311,11 @@ void sortmaterials(vector &vismats) if(dir[sortdim[2]] > dir[sortdim[1]]) swap(sortdim[2], sortdim[1]); if(dir[sortdim[1]] > dir[sortdim[0]]) swap(sortdim[1], sortdim[0]); if(dir[sortdim[2]] > dir[sortdim[1]]) swap(sortdim[2], sortdim[1]); - - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(!va->matsurfs || va->occluded >= OCCLUDE_BB) continue; - loopi(va->matsurfs) - { + loopi(va->matsurfs) { materialsurface &m = va->matbuf[i]; - if(!editmode || !showmat || drawtex) - { + if(!editmode || !showmat || drawtex) { if(m.visible == MATSURF_EDIT_ONLY) { i += m.skip; continue; } } vismats.add(&m); @@ -373,19 +325,15 @@ void sortmaterials(vector &vismats) vismats.sort(vismatcmp); } -void rendermatgrid(vector &vismats) -{ +void rendermatgrid(vector &vismats) { enablepolygonoffset(GL_POLYGON_OFFSET_LINE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); int lastmat = -1; bvec4 color(0, 0, 0, 0); - loopvrev(vismats) - { + loopvrev(vismats) { materialsurface &m = *vismats[i]; - if(m.material != lastmat) - { - switch(m.material&~MATF_INDEX) - { + if(m.material != lastmat) { + switch(m.material&~MATF_INDEX) { case MAT_CLIP: color = bvec4(85, 0, 0, 255); break; // red case MAT_NOCLIP: color = bvec4( 0, 85, 0, 255); break; // green case MAT_GAMECLIP: color = bvec4(85, 85, 0, 255); break; // yellow @@ -402,31 +350,22 @@ void rendermatgrid(vector &vismats) disablepolygonoffset(GL_POLYGON_OFFSET_LINE); } -void rendermaterials() -{ +void rendermaterials() { vector vismats; sortmaterials(vismats); if(vismats.empty()) return; - glDisable(GL_CULL_FACE); - int lastorient = -1, lastmat = -1; bool depth = true, blended = false; - GLOBALPARAM(camera, camera1->o); - - if(editmode && showmat && !drawtex) - { + if(editmode && showmat && !drawtex) { glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); glEnable(GL_BLEND); blended = true; bvec4 color(0, 0, 0, 0); - loopv(vismats) - { + loopv(vismats) { const materialsurface &m = *vismats[i]; - if(lastmat!=m.material) - { - switch(m.material&~MATF_INDEX) - { + if(lastmat!=m.material) { + switch(m.material&~MATF_INDEX) { case MAT_CLIP: color = bvec4( 0, 255, 255, 255); break; // red case MAT_NOCLIP: color = bvec4(255, 0, 255, 255); break; // green case MAT_GAMECLIP: color = bvec4( 0, 0, 255, 255); break; // yellow @@ -440,16 +379,13 @@ void rendermaterials() } xtraverts += gle::end(); } - if(lastorient >= 0) if(lastmat&~MATF_INDEX) xtraverts += gle::end(); - if(!depth) glDepthMask(GL_TRUE); if(blended) glDisable(GL_BLEND); extern int wireframe; if(editmode && showmat && !drawtex && !wireframe) rendermatgrid(vismats); - glEnable(GL_CULL_FACE); } diff --git a/src/engine/md3.h b/src/engine/md3.h deleted file mode 100644 index 7296055..0000000 --- a/src/engine/md3.h +++ /dev/null @@ -1,183 +0,0 @@ -struct md3; - -struct md3frame -{ - vec bbmin, bbmax, origin; - float radius; - uchar name[16]; -}; - -struct md3tag -{ - char name[64]; - float translation[3]; - float rotation[3][3]; -}; - -struct md3vertex -{ - short vertex[3]; - short normal; -}; - -struct md3triangle -{ - int vertexindices[3]; -}; - -struct md3header -{ - char id[4]; - int version; - char name[64]; - int flags; - int numframes, numtags, nummeshes, numskins; - int ofs_frames, ofs_tags, ofs_meshes, ofs_eof; // offsets -}; - -struct md3meshheader -{ - char id[4]; - char name[64]; - int flags; - int numframes, numshaders, numvertices, numtriangles; - int ofs_triangles, ofs_shaders, ofs_uv, ofs_vertices, meshsize; // offsets -}; - -struct md3 : vertloader -{ - md3(const char *name) : vertloader(name) {} - - static const char *formatname() { return "md3"; } - bool flipy() const { return true; } - int type() const { return MDL_MD3; } - - struct md3meshgroup : vertmeshgroup - { - bool load(const char *path) - { - stream *f = openfile(path, "rb"); - if(!f) return false; - md3header header; - f->read(&header, sizeof(md3header)); - lilswap(&header.version, 1); - lilswap(&header.flags, 9); - if(strncmp(header.id, "IDP3", 4) != 0 || header.version != 15) // header check - { - delete f; - conoutf(CON_ERROR, "md3: corrupted header"); - return false; - } - - name = newstring(path); - - numframes = header.numframes; - - int mesh_offset = header.ofs_meshes; - loopi(header.nummeshes) - { - vertmesh &m = *new vertmesh; - m.group = this; - meshes.add(&m); - - md3meshheader mheader; - f->seek(mesh_offset, SEEK_SET); - f->read(&mheader, sizeof(md3meshheader)); - lilswap(&mheader.flags, 10); - - m.name = newstring(mheader.name); - - m.numtris = mheader.numtriangles; - m.tris = new tri[m.numtris]; - f->seek(mesh_offset + mheader.ofs_triangles, SEEK_SET); - loopj(m.numtris) - { - md3triangle tri = { 0 }; - f->read(&tri, sizeof(md3triangle)); // read the triangles - lilswap(tri.vertexindices, 3); - loopk(3) m.tris[j].vert[k] = (ushort)tri.vertexindices[k]; - } - - m.numverts = mheader.numvertices; - m.tcverts = new tcvert[m.numverts]; - f->seek(mesh_offset + mheader.ofs_uv , SEEK_SET); - f->read(m.tcverts, m.numverts*2*sizeof(float)); // read the UV data - lilswap(&m.tcverts[0].tc.x, 2*m.numverts); - - m.verts = new vert[numframes*m.numverts]; - f->seek(mesh_offset + mheader.ofs_vertices, SEEK_SET); - loopj(numframes*m.numverts) - { - md3vertex v = { {0}, 0 }; - f->read(&v, sizeof(md3vertex)); // read the vertices - lilswap(v.vertex, 4); - - m.verts[j].pos = vec(v.vertex[0]/64.0f, -v.vertex[1]/64.0f, v.vertex[2]/64.0f); - - float lng = (v.normal&0xFF)*2*M_PI/255.0f; // decode vertex normals - float lat = ((v.normal>>8)&0xFF)*2*M_PI/255.0f; - m.verts[j].norm = vec(cosf(lat)*sinf(lng), -sinf(lat)*sinf(lng), cosf(lng)); - } - - mesh_offset += mheader.meshsize; - } - - numtags = header.numtags; - if(numtags) - { - tags = new tag[numframes*numtags]; - f->seek(header.ofs_tags, SEEK_SET); - md3tag tag; - - loopi(header.numframes*header.numtags) - { - f->read(&tag, sizeof(md3tag)); - lilswap(tag.translation, 12); - if(tag.name[0] && iload(name)) { delete group; return NULL; } - return group; - } - - bool loaddefaultparts() - { - const char *pname = parentdir(name); - part &mdl = addpart(); - defformatstring(name1, "packages/models/%s/tris.md3", name); - mdl.meshes = sharemeshes(path(name1)); - if(!mdl.meshes) - { - defformatstring(name2, "packages/models/%s/tris.md3", pname); // try md3 in parent folder (vert sharing) - mdl.meshes = sharemeshes(path(name2)); - if(!mdl.meshes) return false; - } - Texture *tex, *masks; - loadskin(name, pname, tex, masks); - mdl.initskins(tex, masks); - if(tex==notexture) conoutf(CON_ERROR, "could not load model skin for %s", name1); - return true; - } -}; - -vertcommands md3commands; - diff --git a/src/engine/md5.h b/src/engine/md5.h index d948ccf..e508cb3 100644 --- a/src/engine/md5.h +++ b/src/engine/md5.h @@ -1,66 +1,48 @@ struct md5; -struct md5joint -{ +struct md5joint { vec pos; quat orient; }; -struct md5weight -{ +struct md5weight { int joint; float bias; vec pos; }; -struct md5vert -{ +struct md5vert { vec2 tc; ushort start, count; }; -struct md5hierarchy -{ +struct md5hierarchy { string name; int parent, flags, start; }; -struct md5 : skelloader -{ +struct md5 : skelloader { md5(const char *name) : skelloader(name) {} - static const char *formatname() { return "md5"; } int type() const { return MDL_MD5; } - - struct md5mesh : skelmesh - { + struct md5mesh : skelmesh { md5weight *weightinfo; int numweights; md5vert *vertinfo; - - md5mesh() : weightinfo(NULL), numweights(0), vertinfo(NULL) - { + md5mesh() : weightinfo(NULL), numweights(0), vertinfo(NULL) { } - - ~md5mesh() - { + ~md5mesh() { cleanup(); } - - void cleanup() - { + void cleanup() { DELETEA(weightinfo); DELETEA(vertinfo); } - - void buildverts(vector &joints) - { - loopi(numverts) - { + void buildverts(vector &joints) { + loopi(numverts) { md5vert &v = vertinfo[i]; vec pos(0, 0, 0); - loopk(v.count) - { + loopk(v.count) { md5weight &w = weightinfo[v.start+k]; md5joint &j = joints[w.joint]; vec wpos = j.orient.rotate(w.pos); @@ -71,11 +53,9 @@ struct md5 : skelloader vert &vv = verts[i]; vv.pos = pos; vv.tc = v.tc; - blendcombo c; int sorted = 0; - loopj(v.count) - { + loopj(v.count) { md5weight &w = weightinfo[v.start+j]; sorted = c.addweight(sorted, w.bias, w.joint); } @@ -83,29 +63,22 @@ struct md5 : skelloader vv.blend = addblendcombo(c); } } - - void load(stream *f, char *buf, size_t bufsize) - { + void load(stream *f, char *buf, size_t bufsize) { md5weight w; md5vert v; tri t; int index; - - while(f->getline(buf, bufsize) && buf[0]!='}') - { - if(strstr(buf, "// meshes:")) - { + while(f->getline(buf, bufsize) && buf[0]!='}') { + if(strstr(buf, "// meshes:")) { char *start = strchr(buf, ':')+1; if(*start==' ') start++; char *end = start + strlen(start)-1; while(end >= start && isspace(*end)) end--; name = newstring(start, end+1-start); } - else if(strstr(buf, "shader")) - { + else if(strstr(buf, "shader")) { char *start = strchr(buf, '"'), *end = start ? strchr(start+1, '"') : NULL; - if(start && end) - { + if(start && end) { char *texname = newstring(start+1, end-(start+1)); part *p = loading->parts.last(); p->initskins(notexture, notexture, group->meshes.length()); @@ -114,86 +87,66 @@ struct md5 : skelloader delete[] texname; } } - else if(sscanf(buf, " numverts %d", &numverts)==1) - { + else if(sscanf(buf, " numverts %d", &numverts)==1) { numverts = max(numverts, 0); - if(numverts) - { + if(numverts) { vertinfo = new md5vert[numverts]; verts = new vert[numverts]; } } - else if(sscanf(buf, " numtris %d", &numtris)==1) - { + else if(sscanf(buf, " numtris %d", &numtris)==1) { numtris = max(numtris, 0); if(numtris) tris = new tri[numtris]; } - else if(sscanf(buf, " numweights %d", &numweights)==1) - { + else if(sscanf(buf, " numweights %d", &numweights)==1) { numweights = max(numweights, 0); if(numweights) weightinfo = new md5weight[numweights]; } - else if(sscanf(buf, " vert %d ( %f %f ) %hu %hu", &index, &v.tc.x, &v.tc.y, &v.start, &v.count)==5) - { + else if(sscanf(buf, " vert %d ( %f %f ) %hu %hu", &index, &v.tc.x, &v.tc.y, &v.start, &v.count)==5) { if(index>=0 && index=0 && index=0 && index basejoints; - while(f->getline(buf, sizeof(buf))) - { + while(f->getline(buf, sizeof(buf))) { int tmp; - if(sscanf(buf, " MD5Version %d", &tmp)==1) - { + if(sscanf(buf, " MD5Version %d", &tmp)==1) { if(tmp!=10) { delete f; return false; } } - else if(sscanf(buf, " numJoints %d", &tmp)==1) - { + else if(sscanf(buf, " numJoints %d", &tmp)==1) { if(tmp<1) { delete f; return false; } if(skel->numbones>0) continue; skel->numbones = tmp; skel->bones = new boneinfo[skel->numbones]; } - else if(sscanf(buf, " numMeshes %d", &tmp)==1) - { + else if(sscanf(buf, " numMeshes %d", &tmp)==1) { if(tmp<1) { delete f; return false; } } - else if(strstr(buf, "joints {")) - { + else if(strstr(buf, "joints {")) { string name; int parent; md5joint j; - while(f->getline(buf, sizeof(buf)) && buf[0]!='}') - { + while(f->getline(buf, sizeof(buf)) && buf[0]!='}') { char *curbuf = buf, *curname = name; bool allowspace = false; while(*curbuf && isspace(*curbuf)) curbuf++; if(*curbuf == '"') { curbuf++; allowspace = true; } - while(*curbuf && curname < &name[sizeof(name)-1]) - { + while(*curbuf && curname < &name[sizeof(name)-1]) { char c = *curbuf++; if(c == '"') break; if(isspace(c) && !allowspace) break; @@ -202,8 +155,7 @@ struct md5 : skelloader *curname = '\0'; if(sscanf(curbuf, " %d ( %f %f %f ) ( %f %f %f )", &parent, &j.pos.x, &j.pos.y, &j.pos.z, - &j.orient.x, &j.orient.y, &j.orient.z)==7) - { + &j.orient.x, &j.orient.y, &j.orient.z)==7) { j.pos.y = -j.pos.y; j.orient.x = -j.orient.x; j.orient.z = -j.orient.z; @@ -219,101 +171,77 @@ struct md5 : skelloader } if(basejoints.length()!=skel->numbones) { delete f; return false; } } - else if(strstr(buf, "mesh {")) - { + else if(strstr(buf, "mesh {")) { md5mesh *m = new md5mesh; m->group = this; meshes.add(m); m->load(f, buf, sizeof(buf)); - if(!m->numtris || !m->numverts) - { + if(!m->numtris || !m->numverts) { conoutf(CON_WARN, "empty mesh in %s", filename); meshes.removeobj(m); delete m; } } } - - if(skel->shared <= 1) - { + if(skel->shared <= 1) { skel->linkchildren(); - loopv(basejoints) - { + loopv(basejoints) { boneinfo &b = skel->bones[i]; b.base = dualquat(basejoints[i].orient, basejoints[i].pos); (b.invbase = b.base).invert(); } } - - loopv(meshes) - { + loopv(meshes) { md5mesh &m = *(md5mesh *)meshes[i]; m.buildverts(basejoints); if(smooth <= 1) m.smoothnorms(smooth); else m.buildnorms(); m.cleanup(); } - sortblendcombos(); - delete f; return true; } - - skelanimspec *loadanim(const char *filename) - { + skelanimspec *loadanim(const char *filename) { skelanimspec *sa = skel->findskelanim(filename); if(sa) return sa; - stream *f = openfile(filename, "r"); if(!f) return NULL; - vector hierarchy; vector basejoints; int animdatalen = 0, animframes = 0; float *animdata = NULL; dualquat *animbones = NULL; char buf[512]; - while(f->getline(buf, sizeof(buf))) - { + while(f->getline(buf, sizeof(buf))) { int tmp; - if(sscanf(buf, " MD5Version %d", &tmp)==1) - { + if(sscanf(buf, " MD5Version %d", &tmp)==1) { if(tmp!=10) { delete f; return NULL; } } - else if(sscanf(buf, " numJoints %d", &tmp)==1) - { + else if(sscanf(buf, " numJoints %d", &tmp)==1) { if(tmp!=skel->numbones) { delete f; return NULL; } } - else if(sscanf(buf, " numFrames %d", &animframes)==1) - { + else if(sscanf(buf, " numFrames %d", &animframes)==1) { if(animframes<1) { delete f; return NULL; } } else if(sscanf(buf, " frameRate %d", &tmp)==1); - else if(sscanf(buf, " numAnimatedComponents %d", &animdatalen)==1) - { + else if(sscanf(buf, " numAnimatedComponents %d", &animdatalen)==1) { if(animdatalen>0) animdata = new float[animdatalen]; } - else if(strstr(buf, "bounds {")) - { + else if(strstr(buf, "bounds {")) { while(f->getline(buf, sizeof(buf)) && buf[0]!='}'); } - else if(strstr(buf, "hierarchy {")) - { - while(f->getline(buf, sizeof(buf)) && buf[0]!='}') - { + else if(strstr(buf, "hierarchy {")) { + while(f->getline(buf, sizeof(buf)) && buf[0]!='}') { md5hierarchy h; if(sscanf(buf, " %100s %d %d %d", h.name, &h.parent, &h.flags, &h.start)==4) hierarchy.add(h); } } - else if(strstr(buf, "baseframe {")) - { - while(f->getline(buf, sizeof(buf)) && buf[0]!='}') - { + else if(strstr(buf, "baseframe {")) { + while(f->getline(buf, sizeof(buf)) && buf[0]!='}') { md5joint j; - if(sscanf(buf, " ( %f %f %f ) ( %f %f %f )", &j.pos.x, &j.pos.y, &j.pos.z, &j.orient.x, &j.orient.y, &j.orient.z)==6) - { + if(sscanf(buf, " ( %f %f %f ) ( %f %f %f )", &j.pos.x, &j.pos.y, &j.pos.z, &j.orient.x, &j.orient.y, &j.orient.z)==6) { j.pos.y = -j.pos.y; j.orient.x = -j.orient.x; j.orient.z = -j.orient.z; @@ -323,37 +251,29 @@ struct md5 : skelloader } if(basejoints.length()!=skel->numbones) { delete f; if(animdata) delete[] animdata; return NULL; } animbones = new dualquat[(skel->numframes+animframes)*skel->numbones]; - if(skel->framebones) - { + if(skel->framebones) { memcpy(animbones, skel->framebones, skel->numframes*skel->numbones*sizeof(dualquat)); delete[] skel->framebones; } skel->framebones = animbones; animbones += skel->numframes*skel->numbones; - sa = &skel->addskelanim(filename); sa->frame = skel->numframes; sa->range = animframes; - skel->numframes += animframes; } - else if(sscanf(buf, " frame %d", &tmp)==1) - { - for(int numdata = 0; f->getline(buf, sizeof(buf)) && buf[0]!='}';) - { - for(char *src = buf, *next = src; numdata < animdatalen; numdata++, src = next) - { + else if(sscanf(buf, " frame %d", &tmp)==1) { + for(int numdata = 0; f->getline(buf, sizeof(buf)) && buf[0]!='}';) { + for(char *src = buf, *next = src; numdata < animdatalen; numdata++, src = next) { animdata[numdata] = strtod(src, &next); if(next <= src) break; } } dualquat *frame = &animbones[tmp*skel->numbones]; - loopv(basejoints) - { + loopv(basejoints) { md5hierarchy &h = hierarchy[i]; md5joint j = basejoints[i]; - if(h.start < animdatalen && h.flags) - { + if(h.start < animdatalen && h.flags) { float *jdata = &animdata[h.start]; if(h.flags&1) j.pos.x = *jdata++; if(h.flags&2) j.pos.y = -*jdata++; @@ -371,33 +291,23 @@ struct md5 : skelloader } } } - if(animdata) delete[] animdata; delete f; - return sa; } - - bool load(const char *meshfile, float smooth) - { + bool load(const char *meshfile, float smooth) { name = newstring(meshfile); - if(!loadmesh(meshfile, smooth)) return false; - return true; } }; - - meshgroup *loadmeshes(const char *name, va_list args) - { + meshgroup *loadmeshes(const char *name, va_list args) { md5meshgroup *group = new md5meshgroup; group->shareskeleton(va_arg(args, char *)); if(!group->load(name, va_arg(args, double))) { delete group; return NULL; } return group; } - - bool loaddefaultparts() - { + bool loaddefaultparts() { skelpart &mdl = addpart(); mdl.pitchscale = mdl.pitchoffset = mdl.pitchmin = mdl.pitchmax = 0; adjustments.setsize(0); diff --git a/src/engine/menus.cpp b/src/engine/menus.cpp index 805a79b..e2bd266 100644 --- a/src/engine/menus.cpp +++ b/src/engine/menus.cpp @@ -12,17 +12,13 @@ static g3d_gui *cgui = NULL; VAR(guitabnum, 1, 0, 0); -struct menu : g3d_callback -{ +struct menu : g3d_callback { char *name, *header; uint *contents, *init, *onclear; bool showtab, keeptab; int menutab; - menu() : name(NULL), header(NULL), contents(NULL), init(NULL), onclear(NULL), showtab(true), keeptab(false), menutab(1) {} - - void gui(g3d_gui &g, bool firstpass) - { + void gui(g3d_gui &g, bool firstpass) { cgui = &g; guitabnum = menutab; cgui->start(menustart, 0.03f, showtab ? &menutab : NULL); @@ -32,75 +28,57 @@ struct menu : g3d_callback cgui = NULL; guitabnum = 0; } - - virtual void clear() - { + virtual void clear() { if(onclear) { freecode(onclear); onclear = NULL; } } }; -struct delayedupdate -{ - enum - { +struct delayedupdate { + enum { INT, FLOAT, STRING, ACTION } type; ident *id; - union - { + union { int i; float f; char *s; } val; delayedupdate() : type(ACTION), id(NULL) { val.s = NULL; } ~delayedupdate() { if(type == STRING || type == ACTION) DELETEA(val.s); } - void schedule(const char *s) { type = ACTION; val.s = newstring(s); } void schedule(ident *var, int i) { type = INT; id = var; val.i = i; } void schedule(ident *var, float f) { type = FLOAT; id = var; val.f = f; } void schedule(ident *var, char *s) { type = STRING; id = var; val.s = newstring(s); } - - int getint() const - { - switch(type) - { + int getint() const { + switch(type) { case INT: return val.i; case FLOAT: return int(val.f); case STRING: return int(strtol(val.s, NULL, 0)); default: return 0; } } - - float getfloat() const - { - switch(type) - { + float getfloat() const { + switch(type) { case INT: return float(val.i); case FLOAT: return val.f; case STRING: return float(parsefloat(val.s)); default: return 0; } } - - const char *getstring() const - { - switch(type) - { + const char *getstring() const { + switch(type) { case INT: return intstr(val.i); case FLOAT: return intstr(int(floor(val.f))); case STRING: return val.s; default: return ""; } } - - void run() - { + void run() { if(type == ACTION) { if(val.s) execute(val.s); } - else if(id) switch(id->type) - { + else if(id) switch(id->type) { case ID_VAR: setvarchecked(id, getint()); break; case ID_FVAR: setfvarchecked(id, getfloat()); break; case ID_SVAR: setsvarchecked(id, getstring()); break; @@ -117,8 +95,7 @@ static bool shouldclearmenu = true, clearlater = false; VARP(menudistance, 16, 40, 256); VARP(menuautoclose, 32, 120, 4096); -vec menuinfrontofplayer() -{ +vec menuinfrontofplayer() { vec dir; vecfromyawpitch(camera1->yaw, 0, 1, 0, dir); dir.mul(menudistance).add(camera1->o); @@ -126,48 +103,40 @@ vec menuinfrontofplayer() return dir; } -void popgui() -{ +void popgui() { menu *m = guistack.pop(); m->clear(); } -void removegui(menu *m) -{ - loopv(guistack) if(guistack[i]==m) - { +void removegui(menu *m) { + loopv(guistack) if(guistack[i]==m) { guistack.remove(i); m->clear(); return; } } -void pushgui(menu *m, int pos = -1) -{ - if(guistack.empty()) - { +void pushgui(menu *m, int pos = -1) { + if(guistack.empty()) { menupos = menuinfrontofplayer(); g3d_resetcursor(); } if(pos < 0) guistack.add(m); else guistack.insert(pos, m); - if(pos < 0 || pos==guistack.length()-1) - { + if(pos < 0 || pos==guistack.length()-1) { if(!m->keeptab) m->menutab = 1; menustart = totalmillis; } if(m->init) execute(m->init); } -void restoregui(int pos) -{ +void restoregui(int pos) { int clear = guistack.length()-pos-1; loopi(clear) popgui(); menustart = totalmillis; } -void showgui(const char *name) -{ +void showgui(const char *name) { menu *m = guis.access(name); if(!m) return; int pos = guistack.find(m); @@ -175,17 +144,14 @@ void showgui(const char *name) else restoregui(pos); } -void hidegui(const char *name) -{ +void hidegui(const char *name) { menu *m = guis.access(name); if(m) removegui(m); } -int cleargui(int n) -{ +int cleargui(int n) { int clear = guistack.length(); - if(mainmenu && !isconnected(true) && clear > 0 && guistack[0]->name && !strcmp(guistack[0]->name, "main")) - { + if(mainmenu && !isconnected(true) && clear > 0 && guistack[0]->name && !strcmp(guistack[0]->name, "main")) { clear--; if(!clear) return 1; } @@ -195,14 +161,12 @@ int cleargui(int n) return clear; } -void clearguis(int level = -1) -{ +void clearguis(int level = -1) { if(level < 0) level = guistack.length(); - loopvrev(guistack) - { + loopvrev(guistack) { menu *m = guistack[i]; if(m->onclear) - { + { uint *action = m->onclear; m->onclear = NULL; execute(action); @@ -212,32 +176,28 @@ void clearguis(int level = -1) cleargui(level); } -void guionclear(char *action) -{ +void guionclear(char *action) { if(guistack.empty()) return; menu *m = guistack.last(); if(m->onclear) { freecode(m->onclear); m->onclear = NULL; } if(action[0]) m->onclear = compilecode(action); } -void guistayopen(uint *contents) -{ +void guistayopen(uint *contents) { bool oldclearmenu = shouldclearmenu; shouldclearmenu = false; execute(contents); shouldclearmenu = oldclearmenu; } -void guinoautotab(uint *contents) -{ +void guinoautotab(uint *contents) { if(!cgui) return; bool oldval = cgui->allowautotab(false); execute(contents); cgui->allowautotab(oldval); } -void guimerge(uint *contents) -{ +void guimerge(uint *contents) { if(!cgui) return; bool oldval = cgui->mergehits(true); execute(contents); @@ -245,114 +205,92 @@ void guimerge(uint *contents) } //@DOC name and icon are optional -void guibutton(char *name, char *action, char *icon) -{ +void guibutton(char *name, char *action, char *icon) { if(!cgui) return; bool hideicon = !strcmp(icon, "0"); int ret = cgui->button(name, GUI_BUTTON_COLOR, hideicon ? NULL : (icon[0] ? icon : (strstr(action, "showgui") ? "menu" : "action"))); - if(ret&G3D_UP) - { + if(ret&G3D_UP) { updatelater.add().schedule(action[0] ? action : name); if(shouldclearmenu) clearlater = true; } - else if(ret&G3D_ROLLOVER) - { + else if(ret&G3D_ROLLOVER) { alias("guirollovername", name); alias("guirolloveraction", action); } } -void guiimage(char *path, char *action, float *scale, int *overlaid, char *alt, char *title) -{ +void guiimage(char *path, char *action, float *scale, int *overlaid, char *alt, char *title) { if(!cgui) return; Texture *t = textureload(path, 0, true, false); - if(t==notexture) - { + if(t==notexture) { if(alt[0]) t = textureload(alt, 0, true, false); if(t==notexture) return; } int ret = cgui->image(t, *scale, *overlaid!=0 ? title : NULL); - if(ret&G3D_UP) - { - if(*action) - { + if(ret&G3D_UP) { + if(*action) { updatelater.add().schedule(action); if(shouldclearmenu) clearlater = true; } } - else if(ret&G3D_ROLLOVER) - { + else if(ret&G3D_ROLLOVER) { alias("guirolloverimgpath", path); alias("guirolloverimgaction", action); } } -void guicolor(int *color) -{ - if(cgui) - { +void guicolor(int *color) { + if(cgui) { defformatstring(desc, "0x%06X", *color); cgui->text(desc, *color, NULL); } } -void guitextbox(char *text, int *width, int *height, int *color) -{ +void guitextbox(char *text, int *width, int *height, int *color) { if(cgui && text[0]) cgui->textbox(text, *width ? *width : 12, *height ? *height : 1, *color ? *color : 0xFFFFFF); } -void guitext(char *name, char *icon) -{ +void guitext(char *name, char *icon) { bool hideicon = !strcmp(icon, "0"); if(cgui) cgui->text(name, !hideicon && icon[0] ? GUI_BUTTON_COLOR : GUI_TEXT_COLOR, hideicon ? NULL : (icon[0] ? icon : "info")); } -void guititle(char *name) -{ +void guititle(char *name) { if(cgui) cgui->title(name, GUI_TITLE_COLOR); } -void guitab(char *name) -{ +void guitab(char *name) { if(cgui) cgui->tab(name, GUI_TITLE_COLOR); } -void guibar() -{ +void guibar() { if(cgui) cgui->separator(); } -void guistrut(float *strut, int *alt) -{ - if(cgui) - { +void guistrut(float *strut, int *alt) { + if(cgui) { if(*alt) cgui->strut(*strut); else cgui->space(*strut); } } -void guispring(int *weight) -{ +void guispring(int *weight) { if(cgui) cgui->spring(max(*weight, 1)); } -void guicolumn(int *col) -{ +void guicolumn(int *col) { if(cgui) cgui->column(*col); } -template static void updateval(char *var, T val, char *onchange) -{ +template static void updateval(char *var, T val, char *onchange) { ident *id = writeident(var); updatelater.add().schedule(id, val); if(onchange[0]) updatelater.add().schedule(onchange); } -static int getval(char *var) -{ +static int getval(char *var) { ident *id = readident(var); if(!id) return 0; - switch(id->type) - { + switch(id->type) { case ID_VAR: return *id->storage.i; case ID_FVAR: return int(*id->storage.f); case ID_SVAR: return parseint(*id->storage.s); @@ -361,12 +299,10 @@ static int getval(char *var) } } -static float getfval(char *var) -{ +static float getfval(char *var) { ident *id = readident(var); if(!id) return 0; - switch(id->type) - { + switch(id->type) { case ID_VAR: return *id->storage.i; case ID_FVAR: return *id->storage.f; case ID_SVAR: return parsefloat(*id->storage.s); @@ -375,12 +311,10 @@ static float getfval(char *var) } } -static const char *getsval(char *var) -{ +static const char *getsval(char *var) { ident *id = readident(var); if(!id) return ""; - switch(id->type) - { + switch(id->type) { case ID_VAR: return intstr(*id->storage.i); case ID_FVAR: return floatstr(*id->storage.f); case ID_SVAR: return *id->storage.s; @@ -389,21 +323,18 @@ static const char *getsval(char *var) } } -void guislider(char *var, int *min, int *max, char *onchange) -{ +void guislider(char *var, int *min, int *max, char *onchange) { if(!cgui) return; int oldval = getval(var), val = oldval, vmin = *max > INT_MIN ? *min : getvarmin(var), vmax = *max > INT_MIN ? *max : getvarmax(var); cgui->slider(val, vmin, vmax, GUI_TITLE_COLOR); if(val != oldval) updateval(var, val, onchange); } -void guilistslider(char *var, char *list, char *onchange) -{ +void guilistslider(char *var, char *list, char *onchange) { if(!cgui) return; vector vals; list += strspn(list, "\n\t "); - while(*list) - { + while(*list) { vals.add(parseint(list)); list += strcspn(list, "\n\t \0"); list += strspn(list, "\n\t "); @@ -415,13 +346,11 @@ void guilistslider(char *var, char *list, char *onchange) if(offset != oldoffset) updateval(var, vals[offset], onchange); } -void guinameslider(char *var, char *names, char *list, char *onchange) -{ +void guinameslider(char *var, char *names, char *list, char *onchange) { if(!cgui) return; vector vals; list += strspn(list, "\n\t "); - while(*list) - { + while(*list) { vals.add(parseint(list)); list += strcspn(list, "\n\t \0"); list += strspn(list, "\n\t "); @@ -435,37 +364,30 @@ void guinameslider(char *var, char *names, char *list, char *onchange) delete[] label; } -void guicheckbox(char *name, char *var, float *on, float *off, char *onchange) -{ +void guicheckbox(char *name, char *var, float *on, float *off, char *onchange) { bool enabled = getfval(var)!=*off; - if(cgui && cgui->button(name, GUI_BUTTON_COLOR, enabled ? "checkbox_on" : "checkbox_off")&G3D_UP) - { + if(cgui && cgui->button(name, GUI_BUTTON_COLOR, enabled ? "checkbox_on" : "checkbox_off")&G3D_UP) { updateval(var, enabled ? *off : (*on || *off ? *on : 1.0f), onchange); } } -void guiradio(char *name, char *var, float *n, char *onchange) -{ +void guiradio(char *name, char *var, float *n, char *onchange) { bool enabled = getfval(var)==*n; - if(cgui && cgui->button(name, GUI_BUTTON_COLOR, enabled ? "radio_on" : "radio_off")&G3D_UP) - { + if(cgui && cgui->button(name, GUI_BUTTON_COLOR, enabled ? "radio_on" : "radio_off")&G3D_UP) { if(!enabled) updateval(var, *n, onchange); } } -void guibitfield(char *name, char *var, int *mask, char *onchange) -{ +void guibitfield(char *name, char *var, int *mask, char *onchange) { int val = getval(var); bool enabled = (val & *mask) != 0; - if(cgui && cgui->button(name, GUI_BUTTON_COLOR, enabled ? "checkbox_on" : "checkbox_off")&G3D_UP) - { + if(cgui && cgui->button(name, GUI_BUTTON_COLOR, enabled ? "checkbox_on" : "checkbox_off")&G3D_UP) { updateval(var, enabled ? val & ~*mask : val | *mask, onchange); } } //-ve length indicates a wrapped text field of any (approx 260 chars) length, |length| is the field width -void guifield(char *var, int *maxlength, char *onchange) -{ +void guifield(char *var, int *maxlength, char *onchange) { if(!cgui) return; const char *initval = getsval(var); char *result = cgui->field(var, GUI_BUTTON_COLOR, *maxlength ? *maxlength : 12, 0, initval); @@ -473,16 +395,14 @@ void guifield(char *var, int *maxlength, char *onchange) } //-ve maxlength indicates a wrapped text field of any (approx 260 chars) length, |maxlength| is the field width -void guieditor(char *name, int *maxlength, int *height, int *mode) -{ +void guieditor(char *name, int *maxlength, int *height, int *mode) { if(!cgui) return; cgui->field(name, GUI_BUTTON_COLOR, *maxlength ? *maxlength : 12, *height, NULL, *mode<=0 ? EDITORFOREVER : *mode); //returns a non-NULL pointer (the currentline) when the user commits, could then manipulate via text* commands } //-ve length indicates a wrapped text field of any (approx 260 chars) length, |length| is the field width -void guikeyfield(char *var, int *maxlength, char *onchange) -{ +void guikeyfield(char *var, int *maxlength, char *onchange) { if(!cgui) return; const char *initval = getsval(var); char *result = cgui->keyfield(var, GUI_BUTTON_COLOR, *maxlength ? *maxlength : -8, 0, initval); @@ -492,16 +412,14 @@ void guikeyfield(char *var, int *maxlength, char *onchange) //use text to do more... -void guilist(uint *contents) -{ +void guilist(uint *contents) { if(!cgui) return; cgui->pushlist(); execute(contents); cgui->poplist(); } -void guialign(int *align, uint *contents) -{ +void guialign(int *align, uint *contents) { if(!cgui) return; cgui->pushlist(); if(*align >= 0) cgui->spring(); @@ -510,38 +428,31 @@ void guialign(int *align, uint *contents) cgui->poplist(); } -void newgui(char *name, char *contents, char *header, char *init) -{ +void newgui(char *name, char *contents, char *header, char *init) { menu *m = guis.access(name); - if(!m) - { + if(!m) { name = newstring(name); m = &guis[name]; m->name = name; } - else - { + else { DELETEA(m->header); freecode(m->contents); freecode(m->init); } - if(header && header[0]) - { + if(header && header[0]) { char *end = NULL; int val = strtol(header, &end, 0); - if(end && !*end) - { + if(end && !*end) { m->header = NULL; m->showtab = val != 0; } - else - { + else { m->header = newstring(header); m->showtab = true; } } - else - { + else { m->header = NULL; m->showtab = true; } @@ -551,14 +462,11 @@ void newgui(char *name, char *contents, char *header, char *init) menu *guiserversmenu = NULL; -void guiservers(uint *header, int *pagemin, int *pagemax) -{ +void guiservers(uint *header, int *pagemin, int *pagemax) { extern const char *showservers(g3d_gui *cgui, uint *header, int pagemin, int pagemax); - if(cgui) - { + if(cgui) { const char *command = showservers(cgui, header, *pagemin, *pagemax > 0 ? *pagemax : INT_MAX); - if(command) - { + if(command) { updatelater.add().schedule(command); if(shouldclearmenu) clearlater = true; guiserversmenu = clearlater || guistack.empty() ? NULL : guistack.last(); @@ -566,10 +474,8 @@ void guiservers(uint *header, int *pagemin, int *pagemax) } } -void notifywelcome() -{ - if(guiserversmenu) - { +void notifywelcome() { + if(guiserversmenu) { if(guistack.length() && guistack.last() == guiserversmenu) clearguis(); guiserversmenu = NULL; } @@ -608,14 +514,11 @@ COMMAND(guieditor, "siii"); COMMAND(guicolor, "i"); COMMAND(guitextbox, "siii"); -void guiplayerpreview(int *model, int *team, int *weap, char *action, float *scale, int *overlaid, char *title) -{ +void guiplayerpreview(int *model, int *team, int *weap, char *action, float *scale, int *overlaid, char *title) { if(!cgui) return; int ret = cgui->playerpreview(*model, *team, *weap, *scale, *overlaid!=0 ? title : NULL); - if(ret&G3D_UP) - { - if(*action) - { + if(ret&G3D_UP) { + if(*action) { updatelater.add().schedule(action); if(shouldclearmenu) clearlater = true; } @@ -623,84 +526,68 @@ void guiplayerpreview(int *model, int *team, int *weap, char *action, float *sca } COMMAND(guiplayerpreview, "iiisfis"); -void guimodelpreview(char *model, char *animspec, char *action, float *scale, int *overlaid, char *title, int *throttle) -{ +void guimodelpreview(char *model, char *animspec, char *action, float *scale, int *overlaid, char *title, int *throttle) { if(!cgui) return; int anim = ANIM_ALL; - if(animspec[0]) - { - if(isdigit(animspec[0])) - { + if(animspec[0]) { + if(isdigit(animspec[0])) { anim = parseint(animspec); if(anim >= 0) anim %= ANIM_INDEX; else anim = ANIM_ALL; } - else - { + else { vector anims; findanims(animspec, anims); if(anims.length()) anim = anims[0]; } } int ret = cgui->modelpreview(model, anim|ANIM_LOOP, *scale, *overlaid!=0 ? title : NULL, *throttle!=0); - if(ret&G3D_UP) - { - if(*action) - { + if(ret&G3D_UP) { + if(*action) { updatelater.add().schedule(action); if(shouldclearmenu) clearlater = true; } } - else if(ret&G3D_ROLLOVER) - { + else if(ret&G3D_ROLLOVER) { alias("guirolloverpreviewname", model); alias("guirolloverpreviewaction", action); } } COMMAND(guimodelpreview, "sssfisi"); -void guiprefabpreview(char *prefab, int *color, char *action, float *scale, int *overlaid, char *title, int *throttle) -{ +void guiprefabpreview(char *prefab, int *color, char *action, float *scale, int *overlaid, char *title, int *throttle) { if(!cgui) return; int ret = cgui->prefabpreview(prefab, vec::hexcolor(*color), *scale, *overlaid!=0 ? title : NULL, *throttle!=0); - if(ret&G3D_UP) - { - if(*action) - { + if(ret&G3D_UP) { + if(*action) { updatelater.add().schedule(action); if(shouldclearmenu) clearlater = true; } } - else if(ret&G3D_ROLLOVER) - { + else if(ret&G3D_ROLLOVER) { alias("guirolloverpreviewname", prefab); alias("guirolloverpreviewaction", action); } } COMMAND(guiprefabpreview, "sisfisi"); -struct change -{ +struct change { int type; const char *desc; - change() {} change(int type, const char *desc) : type(type), desc(desc) {} }; static vector needsapply; -static struct applymenu : menu -{ - void gui(g3d_gui &g, bool firstpass) - { +static struct applymenu : menu { + void gui(g3d_gui &g, bool firstpass) { if(guistack.empty()) return; g.start(menustart, 0.03f); g.text("the following settings have changed:", GUI_TEXT_COLOR, "info"); loopv(needsapply) g.text(needsapply[i].desc, GUI_TEXT_COLOR, "info"); g.separator(); g.text("apply changes now?", GUI_TEXT_COLOR, "info"); - if(g.button("yes", GUI_BUTTON_COLOR, "action")&G3D_UP) - { + if(g.button("yes", GUI_BUTTON_COLOR, "action")&G3D_UP) { int changetypes = 0; loopv(needsapply) changetypes |= needsapply[i].type; if(changetypes&CHANGE_GFX) updatelater.add().schedule("resetgl"); @@ -711,9 +598,7 @@ static struct applymenu : menu clearlater = true; g.end(); } - - void clear() - { + void clear() { menu::clear(); needsapply.shrink(0); } @@ -723,8 +608,7 @@ VARP(applydialog, 0, 1, 1); static bool processingmenu = false; -void addchange(const char *desc, int type) -{ +void addchange(const char *desc, int type) { if(!applydialog) return; loopv(needsapply) if(!strcmp(needsapply[i].desc, desc)) return; needsapply.add(change(type, desc)); @@ -732,12 +616,9 @@ void addchange(const char *desc, int type) pushgui(&applymenu, processingmenu ? max(guistack.length()-1, 0) : -1); } -void clearchanges(int type) -{ - loopv(needsapply) - { - if(needsapply[i].type&type) - { +void clearchanges(int type) { + loopv(needsapply) { + if(needsapply[i].type&type) { needsapply[i].type &= ~type; if(!needsapply[i].type) needsapply.remove(i--); } @@ -745,14 +626,12 @@ void clearchanges(int type) if(needsapply.empty()) removegui(&applymenu); } -void menuprocess() -{ +void menuprocess() { processingmenu = true; int wasmain = mainmenu, level = guistack.length(); loopv(updatelater) updatelater[i].run(); updatelater.shrink(0); - if(wasmain > mainmenu || clearlater) - { + if(wasmain > mainmenu || clearlater) { if(wasmain > mainmenu || level==guistack.length()) clearguis(level); clearlater = false; } @@ -762,19 +641,15 @@ void menuprocess() VAR(mainmenu, 1, 1, 0); -void clearmainmenu() -{ - if(mainmenu && isconnected()) - { +void clearmainmenu() { + if(mainmenu && isconnected()) { mainmenu = 0; if(!processingmenu) cleargui(); } } -void g3d_mainmenu() -{ - if(!guistack.empty()) - { +void g3d_mainmenu() { + if(!guistack.empty()) { extern int usegui2d; if(!mainmenu && !usegui2d && camera1->o.dist(menupos) > menuautoclose) cleargui(); else g3d_addgui(guistack.last(), menupos, GUI_2D | GUI_FOLLOW); diff --git a/src/engine/model.h b/src/engine/model.h index 82aea40..16f1629 100644 --- a/src/engine/model.h +++ b/src/engine/model.h @@ -1,7 +1,6 @@ -enum { MDL_MD3, MDL_MD5, MDL_IQM, NUMMODELTYPES }; +enum { MDL_MD5, MDL_IQM, NUMMODELTYPES }; -struct model -{ +struct model { char *name; float spinyaw, spinpitch, offsetyaw, offsetpitch; bool collide, ellipsecollide, shadow, alphadepth, depthoffset; @@ -11,7 +10,6 @@ struct model vec bbcenter, bbradius, bbextend, collidecenter, collideradius; float rejectradius, eyeheight, collidexyradius, collideheight; int batch; - model(const char *name) : name(name ? newstring(name) : NULL), spinyaw(0), spinpitch(0), offsetyaw(0), offsetpitch(0), collide(true), ellipsecollide(false), shadow(true), alphadepth(true), depthoffset(false), scale(1.0f), translate(0, 0, 0), bih(0), bbcenter(0, 0, 0), bbradius(-1, -1, -1), bbextend(0, 0, 0), collidecenter(0, 0, 0), collideradius(-1, -1, -1), rejectradius(-1), eyeheight(0.9f), collidexyradius(0), collideheight(0), batch(-1) {} virtual ~model() { DELETEA(name); DELETEP(bih); } virtual void calcbb(vec ¢er, vec &radius) = 0; @@ -20,46 +18,35 @@ struct model virtual int type() const = 0; virtual BIH *setBIH() { return 0; } virtual bool skeletal() const { return false; } - - virtual void setshader(Shader *shader) {} - virtual void setspec(float spec) {} - virtual void setambient(float ambient) {} - virtual void setalphatest(float alpha) {} - virtual void setalphablend(bool blend) {} - virtual void setfullbright(float fullbright) {} - virtual void setcullface(bool cullface) {} - + virtual void setshader(Shader *) {} + virtual void setspec(float) {} + virtual void setambient(float) {} + virtual void setalphatest(float) {} + virtual void setalphablend(bool) {} + virtual void setfullbright(float) {} + virtual void setcullface(bool) {} virtual void preloadBIH() { if(!bih) setBIH(); } - virtual void preloadshaders(bool force = false) {} + virtual void preloadshaders() {} virtual void preloadmeshes() {} virtual void cleanup() {} - virtual void startrender() {} virtual void endrender() {} - - void boundbox(vec ¢er, vec &radius) - { - if(bbradius.x < 0) - { + void boundbox(vec ¢er, vec &radius) { + if(bbradius.x < 0) { calcbb(bbcenter, bbradius); bbradius.add(bbextend); } center = bbcenter; radius = bbradius; } - - float collisionbox(vec ¢er, vec &radius) - { - if(collideradius.x < 0) - { + float collisionbox(vec ¢er, vec &radius) { + if(collideradius.x < 0) { boundbox(collidecenter, collideradius); - if(collidexyradius) - { + if(collidexyradius) { collidecenter.x = collidecenter.y = 0; collideradius.x = collideradius.y = collidexyradius; } - if(collideheight) - { + if(collideheight) { collidecenter.z = collideradius.z = collideheight/2; } rejectradius = vec(collidecenter).abs().add(collideradius).magnitude(); @@ -68,16 +55,12 @@ struct model radius = collideradius; return rejectradius; } - - float boundsphere(vec ¢er) - { + float boundsphere(vec ¢er) { vec radius; boundbox(center, radius); return radius.magnitude(); } - - float above() - { + float above() { vec center, radius; boundbox(center, radius); return center.z+radius.z; diff --git a/src/engine/mpr.h b/src/engine/mpr.h index 6288e4f..6c20869 100644 --- a/src/engine/mpr.h +++ b/src/engine/mpr.h @@ -1,41 +1,28 @@ // This code is based off the Minkowski Portal Refinement algorithm by Gary Snethen in XenoCollide & Game Programming Gems 7. -namespace mpr -{ - struct CubePlanes - { +namespace mpr { + struct CubePlanes { const clipplanes &p; - CubePlanes(const clipplanes &p) : p(p) {} - vec center() const { return p.o; } - - vec supportpoint(const vec &n) const - { + vec supportpoint(const vec &n) const { int besti = 7; float bestd = n.dot(p.v[7]); - loopi(7) - { + loopi(7) { float d = n.dot(p.v[i]); if(d > bestd) { besti = i; bestd = d; } } return p.v[besti]; } }; - - struct SolidCube - { + struct SolidCube { vec o; int size; - SolidCube(float x, float y, float z, int size) : o(x, y, z), size(size) {} SolidCube(const vec &o, int size) : o(o), size(size) {} SolidCube(const ivec &o, int size) : o(o), size(size) {} - vec center() const { return vec(o).add(size/2); } - - vec supportpoint(const vec &n) const - { + vec supportpoint(const vec &n) const { vec p(o); if(n.x > 0) p.x += size; if(n.y > 0) p.y += size; @@ -43,36 +30,24 @@ namespace mpr return p; } }; - - struct Ent - { + struct Ent { physent *ent; - Ent(physent *ent) : ent(ent) {} - vec center() const { return vec(ent->o.x, ent->o.y, ent->o.z + (ent->aboveeye - ent->eyeheight)/2); } }; - - struct EntOBB : Ent - { + struct EntOBB : Ent { matrix3 orient; float zmargin; - - EntOBB(physent *ent, float zmargin = 0) : Ent(ent), zmargin(zmargin) - { + EntOBB(physent *ent, float zmargin = 0) : Ent(ent), zmargin(zmargin) { orient.setyaw(ent->yaw*RAD); } - vec center() const { return vec(ent->o.x, ent->o.y, ent->o.z + (ent->aboveeye - ent->eyeheight - zmargin)/2); } - - vec contactface(const vec &wn, const vec &wdir) const - { + vec contactface(const vec &wn, const vec &wdir) const { vec n = orient.transform(wn).div(vec(ent->xradius, ent->yradius, (ent->aboveeye + ent->eyeheight + zmargin)/2)), dir = orient.transform(wdir), an(fabs(n.x), fabs(n.y), dir.z ? fabs(n.z) : 0), fn(0, 0, 0); - if(an.x > an.y) - { + if(an.x > an.y) { if(an.x > an.z) fn.x = n.x*dir.x < 0 ? (n.x > 0 ? 1 : -1) : 0; else if(an.z > 0) fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0; } @@ -80,28 +55,20 @@ namespace mpr else if(an.z > 0) fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0; return orient.transposedtransform(fn); } - - vec localsupportpoint(const vec &ln) const - { + vec localsupportpoint(const vec &ln) const { return vec(ln.x > 0 ? ent->xradius : -ent->xradius, ln.y > 0 ? ent->yradius : -ent->yradius, ln.z > 0 ? ent->aboveeye : -ent->eyeheight - zmargin); } - - vec supportpoint(const vec &n) const - { + vec supportpoint(const vec &n) const { return orient.transposedtransform(localsupportpoint(orient.transform(n))).add(ent->o); } - - float supportcoordneg(float a, float b, float c) const - { + float supportcoordneg(float a, float b, float c) const { return localsupportpoint(vec(-a, -b, -c)).dot(vec(a, b, c)); } - float supportcoord(float a, float b, float c) const - { + float supportcoord(float a, float b, float c) const { return localsupportpoint(vec(a, b, c)).dot(vec(a, b, c)); } - float left() const { return supportcoordneg(orient.a.x, orient.b.x, orient.c.x) + ent->o.x; } float right() const { return supportcoord(orient.a.x, orient.b.x, orient.c.x) + ent->o.x; } float back() const { return supportcoordneg(orient.a.y, orient.b.y, orient.c.y) + ent->o.y; } @@ -109,11 +76,8 @@ namespace mpr float bottom() const { return ent->o.z - ent->eyeheight - zmargin; } float top() const { return ent->o.z + ent->aboveeye; } }; - - struct EntFuzzy : Ent - { + struct EntFuzzy : Ent { EntFuzzy(physent *ent) : Ent(ent) {} - float left() const { return ent->o.x - ent->radius; } float right() const { return ent->o.x + ent->radius; } float back() const { return ent->o.y - ent->radius; } @@ -121,38 +85,27 @@ namespace mpr float bottom() const { return ent->o.z - ent->eyeheight; } float top() const { return ent->o.z + ent->aboveeye; } }; - - struct EntCylinder : EntFuzzy - { + struct EntCylinder : EntFuzzy { float zmargin; - EntCylinder(physent *ent, float zmargin = 0) : EntFuzzy(ent), zmargin(zmargin) {} - vec center() const { return vec(ent->o.x, ent->o.y, ent->o.z + (ent->aboveeye - ent->eyeheight - zmargin)/2); } - float bottom() const { return ent->o.z - ent->eyeheight - zmargin; } - - vec contactface(const vec &n, const vec &dir) const - { + vec contactface(const vec &n, const vec &dir) const { float dxy = n.dot2(n)/(ent->radius*ent->radius), dz = n.z*n.z*4/(ent->aboveeye + ent->eyeheight + zmargin); vec fn(0, 0, 0); if(dz > dxy && dir.z) fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0; - else if(n.dot2(dir) < 0) - { + else if(n.dot2(dir) < 0) { fn.x = n.x; fn.y = n.y; fn.normalize(); } return fn; } - - vec supportpoint(const vec &n) const - { + vec supportpoint(const vec &n) const { vec p(ent->o); if(n.z > 0) p.z += ent->aboveeye; else p.z -= ent->eyeheight + zmargin; - if(n.x || n.y) - { + if(n.x || n.y) { float r = ent->radius / n.magnitude2(); p.x += n.x*r; p.y += n.y*r; @@ -160,13 +113,9 @@ namespace mpr return p; } }; - - struct EntCapsule : EntFuzzy - { + struct EntCapsule : EntFuzzy { EntCapsule(physent *ent) : EntFuzzy(ent) {} - - vec supportpoint(const vec &n) const - { + vec supportpoint(const vec &n) const { vec p(ent->o); if(n.z > 0) p.z += ent->aboveeye - ent->radius; else p.z -= ent->eyeheight - ent->radius; @@ -174,13 +123,9 @@ namespace mpr return p; } }; - - struct EntEllipsoid : EntFuzzy - { + struct EntEllipsoid : EntFuzzy { EntEllipsoid(physent *ent) : EntFuzzy(ent) {} - - vec supportpoint(const vec &dir) const - { + vec supportpoint(const vec &dir) const { vec p(ent->o), n = vec(dir).normalize(); p.x += ent->radius*n.x; p.y += ent->radius*n.y; @@ -188,34 +133,24 @@ namespace mpr return p; } }; - - struct Model - { + struct Model { vec o, radius; matrix3 orient; - - Model(const vec &ent, const vec ¢er, const vec &radius, int yaw) : o(ent), radius(radius) - { + Model(const vec &ent, const vec ¢er, const vec &radius, int yaw) : o(ent), radius(radius) { orient.setyaw(yaw*RAD); o.add(orient.transposedtransform(center)); } - vec center() const { return o; } }; - - struct ModelOBB : Model - { + struct ModelOBB : Model { ModelOBB(const vec &ent, const vec ¢er, const vec &radius, int yaw) : - Model(ent, center, radius, yaw) - {} - - vec contactface(const vec &wn, const vec &wdir) const - { + Model(ent, center, radius, yaw) { + } + vec contactface(const vec &wn, const vec &wdir) const { vec n = orient.transform(wn).div(radius), dir = orient.transform(wdir), an(fabs(n.x), fabs(n.y), dir.z ? fabs(n.z) : 0), fn(0, 0, 0); - if(an.x > an.y) - { + if(an.x > an.y) { if(an.x > an.z) fn.x = n.x*dir.x < 0 ? (n.x > 0 ? 1 : -1) : 0; else if(an.z > 0) fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0; } @@ -223,9 +158,7 @@ namespace mpr else if(an.z > 0) fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0; return orient.transposedtransform(fn); } - - vec supportpoint(const vec &n) const - { + vec supportpoint(const vec &n) const { vec ln = orient.transform(n), p(0, 0, 0); if(ln.x > 0) p.x += radius.x; else p.x -= radius.x; @@ -236,35 +169,27 @@ namespace mpr return orient.transposedtransform(p).add(o); } }; - - struct ModelEllipse : Model - { + struct ModelEllipse : Model { ModelEllipse(const vec &ent, const vec ¢er, const vec &radius, int yaw) : - Model(ent, center, radius, yaw) - {} - - vec contactface(const vec &wn, const vec &wdir) const - { + Model(ent, center, radius, yaw) { + } + vec contactface(const vec &wn, const vec &wdir) const { vec n = orient.transform(wn).div(radius), dir = orient.transform(wdir); float dxy = n.dot2(n), dz = n.z*n.z; vec fn(0, 0, 0); if(dz > dxy && dir.z) fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0; - else if(n.dot2(dir) < 0) - { + else if(n.dot2(dir) < 0) { fn.x = n.x*radius.y; fn.y = n.y*radius.x; fn.normalize(); } return orient.transposedtransform(fn); } - - vec supportpoint(const vec &n) const - { + vec supportpoint(const vec &n) const { vec ln = orient.transform(n), p(0, 0, 0); if(ln.z > 0) p.z += radius.z; else p.z -= radius.z; - if(ln.x || ln.y) - { + if(ln.x || ln.y) { float r = ln.magnitude2(); p.x += ln.x*radius.x/r; p.y += ln.y*radius.y/r; @@ -272,83 +197,60 @@ namespace mpr return orient.transposedtransform(p).add(o); } }; - const float boundarytolerance = 1e-3f; - template - bool collide(const T &p1, const U &p2) - { + bool collide(const T &p1, const U &p2) { // v0 = center of Minkowski difference vec v0 = p2.center().sub(p1.center()); if(v0.iszero()) return true; // v0 and origin overlap ==> hit - // v1 = support in direction of origin vec n = vec(v0).neg(); vec v1 = p2.supportpoint(n).sub(p1.supportpoint(vec(n).neg())); if(v1.dot(n) <= 0) return false; // origin outside v1 support plane ==> miss - // v2 = support perpendicular to plane containing origin, v0 and v1 n.cross(v1, v0); if(n.iszero()) return true; // v0, v1 and origin colinear (and origin inside v1 support plane) == > hit vec v2 = p2.supportpoint(n).sub(p1.supportpoint(vec(n).neg())); if(v2.dot(n) <= 0) return false; // origin outside v2 support plane ==> miss - // v3 = support perpendicular to plane containing v0, v1 and v2 n.cross(v0, v1, v2); - // If the origin is on the - side of the plane, reverse the direction of the plane - if(n.dot(v0) > 0) - { + if(n.dot(v0) > 0) { swap(v1, v2); n.neg(); } - /// // Phase One: Find a valid portal - - loopi(100) - { + loopi(100) { // Obtain the next support point vec v3 = p2.supportpoint(n).sub(p1.supportpoint(vec(n).neg())); if(v3.dot(n) <= 0) return false; // origin outside v3 support plane ==> miss - // If origin is outside (v1,v0,v3), then portal is invalid -- eliminate v2 and find new support outside face vec v3xv0; v3xv0.cross(v3, v0); - if(v1.dot(v3xv0) < 0) - { + if(v1.dot(v3xv0) < 0) { v2 = v3; n.cross(v0, v1, v3); continue; } - // If origin is outside (v3,v0,v2), then portal is invalid -- eliminate v1 and find new support outside face - if(v2.dot(v3xv0) > 0) - { + if(v2.dot(v3xv0) > 0) { v1 = v3; n.cross(v0, v3, v2); continue; } - /// // Phase Two: Refine the portal - - for(int j = 0;; j++) - { + for(int j = 0;; j++) { // Compute outward facing normal of the portal n.cross(v1, v2, v3); - // If the origin is inside the portal, we have a hit if(n.dot(v1) >= 0) return true; - n.normalize(); - // Find the support point in the direction of the portal's normal vec v4 = p2.supportpoint(n).sub(p1.supportpoint(vec(n).neg())); - // If the origin is outside the support plane or the boundary is thin enough, we have a miss if(v4.dot(n) <= 0 || vec(v4).sub(v3).dot(n) <= boundarytolerance || j > 100) return false; - // Test origin against the three planes that separate the new portal candidates: (v1,v4,v0) (v2,v4,v0) (v3,v4,v0) // Note: We're taking advantage of the triple product identities here as an optimization // (v1 % v4) * v0 == v1 * (v4 % v0) > 0 if origin inside (v1, v4, v0) @@ -356,13 +258,11 @@ namespace mpr // (v3 % v4) * v0 == v3 * (v4 % v0) > 0 if origin inside (v3, v4, v0) vec v4xv0; v4xv0.cross(v4, v0); - if(v1.dot(v4xv0) > 0) - { + if(v1.dot(v4xv0) > 0) { if(v2.dot(v4xv0) > 0) v1 = v4; // Inside v1 & inside v2 ==> eliminate v1 else v3 = v4; // Inside v1 & outside v2 ==> eliminate v3 } - else - { + else { if(v3.dot(v4xv0) > 0) v2 = v4; // Outside v1 & inside v3 ==> eliminate v2 else v1 = v4; // Outside v1 & outside v3 ==> eliminate v1 } @@ -370,33 +270,26 @@ namespace mpr } return false; } - template - bool collide(const T &p1, const U &p2, vec *contactnormal, vec *contactpoint1, vec *contactpoint2) - { + bool collide(const T &p1, const U &p2, vec *contactnormal, vec *contactpoint1, vec *contactpoint2) { // v0 = center of Minkowski sum vec v01 = p1.center(); vec v02 = p2.center(); vec v0 = vec(v02).sub(v01); - // Avoid case where centers overlap -- any direction is fine in this case if(v0.iszero()) v0 = vec(0, 0, 1e-5f); - // v1 = support in direction of origin vec n = vec(v0).neg(); vec v11 = p1.supportpoint(vec(n).neg()); vec v12 = p2.supportpoint(n); vec v1 = vec(v12).sub(v11); - if(v1.dot(n) <= 0) - { + if(v1.dot(n) <= 0) { if(contactnormal) *contactnormal = n; return false; } - // v2 - support perpendicular to v1,v0 n.cross(v1, v0); - if(n.iszero()) - { + if(n.iszero()) { n = vec(v1).sub(v0); n.normalize(); if(contactnormal) *contactnormal = n; @@ -407,97 +300,74 @@ namespace mpr vec v21 = p1.supportpoint(vec(n).neg()); vec v22 = p2.supportpoint(n); vec v2 = vec(v22).sub(v21); - if(v2.dot(n) <= 0) - { + if(v2.dot(n) <= 0) { if(contactnormal) *contactnormal = n; return false; } - // Determine whether origin is on + or - side of plane (v1,v0,v2) n.cross(v0, v1, v2); ASSERT( !n.iszero() ); // If the origin is on the - side of the plane, reverse the direction of the plane - if(n.dot(v0) > 0) - { + if(n.dot(v0) > 0) { swap(v1, v2); swap(v11, v21); swap(v12, v22); n.neg(); } - /// // Phase One: Identify a portal - - loopi(100) - { + loopi(100) { // Obtain the support point in a direction perpendicular to the existing plane // Note: This point is guaranteed to lie off the plane vec v31 = p1.supportpoint(vec(n).neg()); vec v32 = p2.supportpoint(n); vec v3 = vec(v32).sub(v31); - if(v3.dot(n) <= 0) - { + if(v3.dot(n) <= 0) { if(contactnormal) *contactnormal = n; return false; } - // If origin is outside (v1,v0,v3), then eliminate v2 and loop vec v3xv0; v3xv0.cross(v3, v0); - if(v1.dot(v3xv0) < 0) - { + if(v1.dot(v3xv0) < 0) { v2 = v3; v21 = v31; v22 = v32; n.cross(v0, v1, v3); continue; } - // If origin is outside (v3,v0,v2), then eliminate v1 and loop - if(v2.dot(v3xv0) > 0) - { + if(v2.dot(v3xv0) > 0) { v1 = v3; v11 = v31; v12 = v32; n.cross(v0, v3, v2); continue; } - bool hit = false; - /// // Phase Two: Refine the portal - // We are now inside of a wedge... - for(int j = 0;; j++) - { + for(int j = 0;; j++) { // Compute normal of the wedge face n.cross(v1, v2, v3); - // Can this happen??? Can it be handled more cleanly? - if(n.iszero()) - { + if(n.iszero()) { ASSERT(0); return true; } - n.normalize(); - // If the origin is inside the wedge, we have a hit - if(n.dot(v1) >= 0 && !hit) - { + if(n.dot(v1) >= 0 && !hit) { if(contactnormal) *contactnormal = n; - // Compute the barycentric coordinates of the origin - if(contactpoint1 || contactpoint2) - { + if(contactpoint1 || contactpoint2) { float b0 = v3.scalartriple(v1, v2), b1 = v0.scalartriple(v3, v2), b2 = v3.scalartriple(v0, v1), b3 = v0.scalartriple(v2, v1), sum = b0 + b1 + b2 + b3; - if(sum <= 0) - { + if(sum <= 0) { b0 = 0; b1 = n.scalartriple(v2, v3); b2 = n.scalartriple(v3, v1); @@ -509,23 +379,18 @@ namespace mpr if(contactpoint2) *contactpoint2 = (vec(v02).mul(b0).add(vec(v12).mul(b1)).add(vec(v22).mul(b2)).add(vec(v32).mul(b3))).mul(1.0f/sum); } - // HIT!!! hit = true; } - // Find the support point in the direction of the wedge face vec v41 = p1.supportpoint(vec(n).neg()); vec v42 = p2.supportpoint(n); vec v4 = vec(v42).sub(v41); - // If the boundary is thin enough or the origin is outside the support plane for the newly discovered vertex, then we can terminate - if(v4.dot(n) <= 0 || vec(v4).sub(v3).dot(n) <= boundarytolerance || j > 100) - { + if(v4.dot(n) <= 0 || vec(v4).sub(v3).dot(n) <= boundarytolerance || j > 100) { if(contactnormal) *contactnormal = n; return hit; } - // Test origin against the three planes that separate the new portal candidates: (v1,v4,v0) (v2,v4,v0) (v3,v4,v0) // Note: We're taking advantage of the triple product identities here as an optimization // (v1 % v4) * v0 == v1 * (v4 % v0) > 0 if origin inside (v1, v4, v0) @@ -533,34 +398,28 @@ namespace mpr // (v3 % v4) * v0 == v3 * (v4 % v0) > 0 if origin inside (v3, v4, v0) vec v4xv0; v4xv0.cross(v4, v0); - if(v1.dot(v4xv0) > 0) // Compute the tetrahedron dividing face d1 = (v4,v0,v1) - { - if(v2.dot(v4xv0) > 0) // Compute the tetrahedron dividing face d2 = (v4,v0,v2) - { + if(v1.dot(v4xv0) > 0) { // Compute the tetrahedron dividing face d1 = (v4,v0,v1) { + if(v2.dot(v4xv0) > 0) { // Compute the tetrahedron dividing face d2 = (v4,v0,v2) { // Inside d1 & inside d2 ==> eliminate v1 v1 = v4; v11 = v41; v12 = v42; } - else - { + else { // Inside d1 & outside d2 ==> eliminate v3 v3 = v4; v31 = v41; v32 = v42; } } - else - { - if(v3.dot(v4xv0) > 0) // Compute the tetrahedron dividing face d3 = (v4,v0,v3) - { + else { + if(v3.dot(v4xv0) > 0) { // Compute the tetrahedron dividing face d3 = (v4,v0,v3) { // Outside d1 & inside d3 ==> eliminate v2 v2 = v4; v21 = v41; v22 = v42; } - else - { + else { // Outside d1 & outside d3 ==> eliminate v1 v1 = v4; v11 = v41; @@ -572,4 +431,3 @@ namespace mpr return false; } } - diff --git a/src/engine/normal.cpp b/src/engine/normal.cpp index cba6777..64c21c6 100644 --- a/src/engine/normal.cpp +++ b/src/engine/normal.cpp @@ -1,24 +1,20 @@ #include "engine.h" -struct normalgroup -{ +struct normalgroup { vec pos; int flat, normals, tnormals; - normalgroup() : flat(0), normals(-1), tnormals(-1) {} normalgroup(const vec &pos) : pos(pos), flat(0), normals(-1), tnormals(-1) {} }; static inline bool htcmp(const vec &v, const normalgroup &n) { return v == n.pos; } -struct normal -{ +struct normal { int next; vec surface; }; -struct tnormal -{ +struct tnormal { int next; float offset; int normals[2]; @@ -34,8 +30,7 @@ VARR(lerpangle, 0, 44, 180); static float lerpthreshold = 0; static bool usetnormals = true; -static int addnormal(const vec &key, const vec &surface) -{ +static int addnormal(const vec &key, const vec &surface) { normalgroup &g = normalgroups.access(key, key); normal &n = normals.add(); n.next = g.normals; @@ -43,8 +38,7 @@ static int addnormal(const vec &key, const vec &surface) return g.normals = normals.length()-1; } -static void addtnormal(const vec &key, float offset, int normal1, int normal2, normalgroup *group1, normalgroup *group2) -{ +static void addtnormal(const vec &key, float offset, int normal1, int normal2, normalgroup *group1, normalgroup *group2) { normalgroup &g = normalgroups.access(key, key); tnormal &n = tnormals.add(); n.next = g.tnormals; @@ -56,15 +50,13 @@ static void addtnormal(const vec &key, float offset, int normal1, int normal2, n g.tnormals = tnormals.length()-1; } -static int addnormal(const vec &key, int axis) -{ +static int addnormal(const vec &key, int axis) { normalgroup &g = normalgroups.access(key, key); g.flat += 1<<(4*axis); return axis - 6; } -static inline void findnormal(const normalgroup &g, const vec &surface, vec &v) -{ +static inline void findnormal(const normalgroup &g, const vec &surface, vec &v) { v = vec(0, 0, 0); int total = 0; if(surface.x >= lerpthreshold) { int n = (g.flat>>4)&0xF; v.x += n; total += n; } @@ -73,11 +65,9 @@ static inline void findnormal(const normalgroup &g, const vec &surface, vec &v) else if(surface.y <= -lerpthreshold) { int n = (g.flat>>8)&0xF; v.y -= n; total += n; } if(surface.z >= lerpthreshold) { int n = (g.flat>>20)&0xF; v.z += n; total += n; } else if(surface.z <= -lerpthreshold) { int n = (g.flat>>16)&0xF; v.z -= n; total += n; } - for(int cur = g.normals; cur >= 0;) - { + for(int cur = g.normals; cur >= 0;) { normal &o = normals[cur]; - if(o.surface.dot(surface) >= lerpthreshold) - { + if(o.surface.dot(surface) >= lerpthreshold) { v.add(o.surface); total++; } @@ -87,12 +77,10 @@ static inline void findnormal(const normalgroup &g, const vec &surface, vec &v) else if(!total) v = surface; } -static inline bool findtnormal(const normalgroup &g, const vec &surface, vec &v) -{ +static inline bool findtnormal(const normalgroup &g, const vec &surface, vec &v) { float bestangle = lerpthreshold; tnormal *bestnorm = NULL; - for(int cur = g.tnormals; cur >= 0;) - { + for(int cur = g.tnormals; cur >= 0;) { tnormal &o = tnormals[cur]; static const vec flats[6] = { vec(-1, 0, 0), vec(1, 0, 0), vec(0, -1, 0), vec(0, 1, 0), vec(0, 0, -1), vec(0, 0, 1) }; vec n1 = o.normals[0] < 0 ? flats[o.normals[0]+6] : normals[o.normals[0]].surface, @@ -100,8 +88,7 @@ static inline bool findtnormal(const normalgroup &g, const vec &surface, vec &v) nt; nt.lerp(n1, n2, o.offset).normalize(); float tangle = nt.dot(surface); - if(tangle >= bestangle) - { + if(tangle >= bestangle) { bestangle = tangle; bestnorm = &o; } @@ -115,8 +102,7 @@ static inline bool findtnormal(const normalgroup &g, const vec &surface, vec &v) return true; } -void findnormal(const vec &key, const vec &surface, vec &v) -{ +void findnormal(const vec &key, const vec &surface, vec &v) { const normalgroup *g = normalgroups.access(key); if(!g) v = surface; else if(g->tnormals < 0 || !findtnormal(*g, surface, v)) @@ -128,48 +114,38 @@ VARR(lerpsubdivsize, 4, 4, 128); static uint progress = 0; -void show_addnormals_progress() -{ +void show_addnormals_progress() { float bar1 = float(progress) / float(allocnodes); renderprogress(bar1, "computing normals..."); } -void addnormals(cube &c, const ivec &o, int size) -{ +void addnormals(cube &c, const ivec &o, int size) { CHECK_CALCLIGHT_PROGRESS(return, show_addnormals_progress); - - if(c.children) - { + if(c.children) { progress++; size >>= 1; loopi(8) addnormals(c.children[i], ivec(i, o, size), size); return; } else if(isempty(c)) return; - vec pos[MAXFACEVERTS]; int norms[MAXFACEVERTS]; int tj = usetnormals && c.ext ? c.ext->tjoints : -1, vis; - loopi(6) if((vis = visibletris(c, i, o, size))) - { + loopi(6) if((vis = visibletris(c, i, o, size))) { CHECK_CALCLIGHT_PROGRESS(return, show_addnormals_progress); - vec planes[2]; int numverts = c.ext ? c.ext->surfaces[i].numverts&MAXFACEVERTS : 0, convex = 0, numplanes = 0; - if(numverts) - { + if(numverts) { vertinfo *verts = c.ext->verts() + c.ext->surfaces[i].verts; vec vo(ivec(o).mask(~0xFFF)); - loopj(numverts) - { + loopj(numverts) { vertinfo &v = verts[j]; pos[j] = vec(v.x, v.y, v.z).mul(1.0f/8).add(vo); } if(!(c.merged&(1<= 0 && tjoints[tj].edge < i*(MAXFACEVERTS+1)) tj = tjoints[tj].next; - while(tj >= 0 && tjoints[tj].edge < (i+1)*(MAXFACEVERTS+1)) - { + while(tj >= 0 && tjoints[tj].edge < (i+1)*(MAXFACEVERTS+1)) { int edge = tjoints[tj].edge, e1 = edge%(MAXFACEVERTS+1), e2 = (e1+1)%numverts; const vec &v1 = pos[e1], &v2 = pos[e2]; ivec d(vec(v2).sub(v1).mul(8)); @@ -212,9 +182,7 @@ void addnormals(cube &c, const ivec &o, int size) offset2 = (int(v2[axis]*8) - origin) / d[axis]; vec o = vec(v1).sub(vec(d).mul(offset1/8.0f)), n1, n2; float doffset = 1.0f / (offset2 - offset1); - - while(tj >= 0) - { + while(tj >= 0) { tjoint &t = tjoints[tj]; if(t.edge != edge) break; float offset = (t.offset - offset1) * doffset; @@ -226,8 +194,7 @@ void addnormals(cube &c, const ivec &o, int size) } } -void calcnormals(bool lerptjoints) -{ +void calcnormals(bool lerptjoints) { if(!lerpangle) return; usetnormals = lerptjoints; if(usetnormals) findtjoints(); @@ -236,20 +203,16 @@ void calcnormals(bool lerptjoints) loopi(8) addnormals(worldroot[i], ivec(i, ivec(0, 0, 0), worldsize/2), worldsize/2); } -void clearnormals() -{ +void clearnormals() { normalgroups.clear(); normals.setsize(0); tnormals.setsize(0); } -void calclerpverts(const vec2 *c, const vec *n, lerpvert *lv, int &numv) -{ +void calclerpverts(const vec2 *c, const vec *n, lerpvert *lv, int &numv) { int i = 0; - loopj(numv) - { - if(j) - { + loopj(numv) { + if(j) { if(c[j] == c[j-1] && n[j] == n[j-1]) continue; if(j == numv-1 && c[j] == c[0] && n[j] == n[0]) continue; } @@ -260,14 +223,11 @@ void calclerpverts(const vec2 *c, const vec *n, lerpvert *lv, int &numv) numv = i; } -void setlerpstep(float v, lerpbounds &bounds) -{ - if(bounds.min->tc.y + 1 > bounds.max->tc.y) - { +void setlerpstep(float v, lerpbounds &bounds) { + if(bounds.min->tc.y + 1 > bounds.max->tc.y) { bounds.nstep = vec(0, 0, 0); bounds.normal = bounds.min->normal; - if(bounds.min->normal != bounds.max->normal) - { + if(bounds.min->normal != bounds.max->normal) { bounds.normal.add(bounds.max->normal); bounds.normal.normalize(); } @@ -275,70 +235,55 @@ void setlerpstep(float v, lerpbounds &bounds) bounds.u = bounds.min->tc.x; return; } - bounds.nstep = bounds.max->normal; bounds.nstep.sub(bounds.min->normal); bounds.nstep.div(bounds.max->tc.y-bounds.min->tc.y); - bounds.normal = bounds.nstep; bounds.normal.mul(v - bounds.min->tc.y); bounds.normal.add(bounds.min->normal); - bounds.ustep = (bounds.max->tc.x-bounds.min->tc.x) / (bounds.max->tc.y-bounds.min->tc.y); bounds.u = bounds.ustep * (v-bounds.min->tc.y) + bounds.min->tc.x; } -void initlerpbounds(float u, float v, const lerpvert *lv, int numv, lerpbounds &start, lerpbounds &end) -{ +void initlerpbounds(float u, float v, const lerpvert *lv, int numv, lerpbounds &start, lerpbounds &end) { const lerpvert *first = &lv[0], *second = NULL; - loopi(numv-1) - { + loopi(numv-1) { if(lv[i+1].tc.y < first->tc.y) { second = first; first = &lv[i+1]; } else if(!second || lv[i+1].tc.y < second->tc.y) second = &lv[i+1]; } - if(int(first->tc.y) < int(second->tc.y)) { start.min = end.min = first; } else if(first->tc.x > second->tc.x) { start.min = second; end.min = first; } else { start.min = first; end.min = second; } - - if((lv[1].tc.x - lv->tc.x)*(lv[2].tc.y - lv->tc.y) > (lv[1].tc.y - lv->tc.y)*(lv[2].tc.x - lv->tc.x)) - { + if((lv[1].tc.x - lv->tc.x)*(lv[2].tc.y - lv->tc.y) > (lv[1].tc.y - lv->tc.y)*(lv[2].tc.x - lv->tc.x)) { start.winding = end.winding = 1; start.max = (start.min == lv ? &lv[numv-1] : start.min-1); end.max = (end.min == &lv[numv-1] ? lv : end.min+1); } - else - { + else { start.winding = end.winding = -1; start.max = (start.min == &lv[numv-1] ? lv : start.min+1); end.max = (end.min == lv ? &lv[numv-1] : end.min-1); } - setlerpstep(v, start); setlerpstep(v, end); } -void updatelerpbounds(float v, const lerpvert *lv, int numv, lerpbounds &start, lerpbounds &end) -{ - if(v >= start.max->tc.y) - { +void updatelerpbounds(float v, const lerpvert *lv, int numv, lerpbounds &start, lerpbounds &end) { + if(v >= start.max->tc.y) { const lerpvert *next = start.winding > 0 ? (start.max == lv ? &lv[numv-1] : start.max-1) : (start.max == &lv[numv-1] ? lv : start.max+1); - if(next->tc.y > start.max->tc.y) - { + if(next->tc.y > start.max->tc.y) { start.min = start.max; start.max = next; setlerpstep(v, start); } } - if(v >= end.max->tc.y) - { + if(v >= end.max->tc.y) { const lerpvert *next = end.winding > 0 ? (end.max == &lv[numv-1] ? lv : end.max+1) : (end.max == lv ? &lv[numv-1] : end.max-1); - if(next->tc.y > end.max->tc.y) - { + if(next->tc.y > end.max->tc.y) { end.min = end.max; end.max = next; setlerpstep(v, end); @@ -346,36 +291,28 @@ void updatelerpbounds(float v, const lerpvert *lv, int numv, lerpbounds &start, } } -void lerpnormal(float u, float v, const lerpvert *lv, int numv, lerpbounds &start, lerpbounds &end, vec &normal, vec &nstep) -{ +void lerpnormal(float u, float v, const lerpvert *lv, int numv, lerpbounds &start, lerpbounds &end, vec &normal, vec &nstep) { updatelerpbounds(v, lv, numv, start, end); - - if(start.u + 1 > end.u) - { + if(start.u + 1 > end.u) { nstep = vec(0, 0, 0); normal = start.normal; normal.add(end.normal); normal.normalize(); } - else - { + else { vec nstart(start.normal), nend(end.normal); nstart.normalize(); nend.normalize(); - nstep = nend; nstep.sub(nstart); nstep.div(end.u-start.u); - normal = nstep; normal.mul(u-start.u); normal.add(nstart); normal.normalize(); } - start.normal.add(start.nstep); start.u += start.ustep; - end.normal.add(end.nstep); end.u += end.ustep; } diff --git a/src/engine/octa.cpp b/src/engine/octa.cpp index 3d47cd3..21a3938 100644 --- a/src/engine/octa.cpp +++ b/src/engine/octa.cpp @@ -5,17 +5,14 @@ cube *worldroot = newcubes(F_SOLID); int allocnodes = 0; -cubeext *growcubeext(cubeext *old, int maxverts) -{ +cubeext *growcubeext(cubeext *old, int maxverts) { cubeext *ext = (cubeext *)new uchar[sizeof(cubeext) + maxverts*sizeof(vertinfo)]; - if(old) - { + if(old) { ext->va = old->va; ext->ents = old->ents; ext->tjoints = old->tjoints; } - else - { + else { ext->va = NULL; ext->ents = NULL; ext->tjoints = -1; @@ -24,22 +21,18 @@ cubeext *growcubeext(cubeext *old, int maxverts) return ext; } -void setcubeext(cube &c, cubeext *ext) -{ +void setcubeext(cube &c, cubeext *ext) { cubeext *old = c.ext; if(old == ext) return; c.ext = ext; if(old) delete[] (uchar *)old; } -cubeext *newcubeext(cube &c, int maxverts, bool init) -{ +cubeext *newcubeext(cube &c, int maxverts, bool init) { if(c.ext && c.ext->maxverts >= maxverts) return c.ext; cubeext *ext = growcubeext(c.ext, maxverts); - if(init) - { - if(c.ext) - { + if(init) { + if(c.ext) { memcpy(ext->surfaces, c.ext->surfaces, sizeof(ext->surfaces)); memcpy(ext->verts(), c.ext->verts(), c.ext->maxverts*sizeof(vertinfo)); } @@ -49,11 +42,9 @@ cubeext *newcubeext(cube &c, int maxverts, bool init) return ext; } -cube *newcubes(uint face, int mat) -{ +cube *newcubes(uint face, int mat) { cube *c = new cube[8]; - loopi(8) - { + loopi(8) { c->children = NULL; c->ext = NULL; c->visible = 0; @@ -67,53 +58,44 @@ cube *newcubes(uint face, int mat) return c-8; } -int familysize(const cube &c) -{ +int familysize(const cube &c) { int size = 1; if(c.children) loopi(8) size += familysize(c.children[i]); return size; } -void freeocta(cube *c) -{ +void freeocta(cube *c) { if(!c) return; loopi(8) discardchildren(c[i]); delete[] c; allocnodes--; } -void freecubeext(cube &c) -{ - if(c.ext) - { +void freecubeext(cube &c) { + if(c.ext) { delete[] (uchar *)c.ext; c.ext = NULL; } } -void discardchildren(cube &c, bool fixtex, int depth) -{ +void discardchildren(cube &c, bool fixtex, int depth) { c.material = MAT_AIR; c.visible = 0; c.merged = 0; - if(c.ext) - { + if(c.ext) { if(c.ext->va) destroyva(c.ext->va); c.ext->va = NULL; c.ext->tjoints = -1; freeoctaentities(c); freecubeext(c); } - if(c.children) - { + if(c.children) { uint filled = F_EMPTY; - loopi(8) - { + loopi(8) { discardchildren(c.children[i], fixtex, depth+1); filled |= c.children[i].faces[0]; } - if(fixtex) - { + if(fixtex) { loopi(6) c.texture[i] = getmippedtexture(c, i); if(depth > 0 && filled != F_EMPTY) c.faces[0] = F_SOLID; } @@ -122,44 +104,36 @@ void discardchildren(cube &c, bool fixtex, int depth) } } -void getcubevector(cube &c, int d, int x, int y, int z, ivec &p) -{ +void getcubevector(cube &c, int d, int x, int y, int z, ivec &p) { ivec v(d, x, y, z); - loopi(3) p[i] = edgeget(cubeedge(c, i, v[R[i]], v[C[i]]), v[D[i]]); } -void setcubevector(cube &c, int d, int x, int y, int z, const ivec &p) -{ +void setcubevector(cube &c, int d, int x, int y, int z, const ivec &p) { ivec v(d, x, y, z); - loopi(3) edgeset(cubeedge(c, i, v[R[i]], v[C[i]]), v[D[i]], p[i]); } -static inline void getcubevector(cube &c, int i, ivec &p) -{ +static inline void getcubevector(cube &c, int i, ivec &p) { p.x = edgeget(cubeedge(c, 0, (i>>R[0])&1, (i>>C[0])&1), (i>>D[0])&1); p.y = edgeget(cubeedge(c, 1, (i>>R[1])&1, (i>>C[1])&1), (i>>D[1])&1); p.z = edgeget(cubeedge(c, 2, (i>>R[2])&1, (i>>C[2])&1), (i>>D[2])&1); } -static inline void setcubevector(cube &c, int i, const ivec &p) -{ +static inline void setcubevector(cube &c, int i, const ivec &p) { edgeset(cubeedge(c, 0, (i>>R[0])&1, (i>>C[0])&1), (i>>D[0])&1, p.x); edgeset(cubeedge(c, 1, (i>>R[1])&1, (i>>C[1])&1), (i>>D[1])&1, p.y); edgeset(cubeedge(c, 2, (i>>R[2])&1, (i>>C[2])&1), (i>>D[2])&1, p.z); } -void optiface(uchar *p, cube &c) -{ +void optiface(uchar *p, cube &c) { uint f = *(uint *)p; if(((f>>4)&0x0F0F0F0FU) == (f&0x0F0F0F0FU)) emptyfaces(c); } -void printcube() -{ +void printcube() { cube &c = lookupcube(lu); // assume this is cube being pointed at conoutf(CON_DEBUG, "= %p = (%d, %d, %d) @ %d", (void *)&c, lu.x, lu.y, lu.z, lusize); conoutf(CON_DEBUG, " x %.8x", c.faces[0]); @@ -169,43 +143,33 @@ void printcube() COMMAND(printcube, ""); -bool isvalidcube(const cube &c) -{ +bool isvalidcube(const cube &c) { clipplanes p; genclipplanes(c, ivec(0, 0, 0), 256, p); - loopi(8) // test that cube is convex - { + loopi(8) { // test that cube is convex { vec v = p.v[i]; loopj(p.size) if(p.p[j].dist(v)>1e-3f) return false; } return true; } -void validatec(cube *c, int size) -{ - loopi(8) - { - if(c[i].children) - { - if(size<=1) - { +void validatec(cube *c, int size) { + loopi(8) { + if(c[i].children) { + if(size<=1) { solidfaces(c[i]); discardchildren(c[i], true); } else validatec(c[i].children, size>>1); } - else if(size > 0x1000) - { + else if(size > 0x1000) { subdividecube(c[i], true, false); validatec(c[i].children, size>>1); } - else - { - loopj(3) - { + else { + loopj(3) { uint f = c[i].faces[j], e0 = f&0x0F0F0F0FU, e1 = (f>>4)&0x0F0F0F0FU; - if(e0 == e1 || ((e1+0x07070707U)|(e1-e0))&0xF0F0F0F0U) - { + if(e0 == e1 || ((e1+0x07070707U)|(e1-e0))&0xF0F0F0F0U) { emptyfaces(c[i]); break; } @@ -216,19 +180,15 @@ void validatec(cube *c, int size) ivec lu; int lusize; -cube &lookupcube(const ivec &to, int tsize, ivec &ro, int &rsize) -{ +cube &lookupcube(const ivec &to, int tsize, ivec &ro, int &rsize) { int tx = clamp(to.x, 0, worldsize-1), ty = clamp(to.y, 0, worldsize-1), tz = clamp(to.z, 0, worldsize-1); int scale = worldscale-1, csize = abs(tsize); cube *c = &worldroot[octastep(tx, ty, tz, scale)]; - if(!(csize>>scale)) do - { - if(!c->children) - { - if(tsize > 0) do - { + if(!(csize>>scale)) do { + if(!c->children) { + if(tsize > 0) do { subdividecube(*c); scale--; c = &c->children[octastep(tx, ty, tz, scale)]; @@ -243,14 +203,12 @@ cube &lookupcube(const ivec &to, int tsize, ivec &ro, int &rsize) return *c; } -int lookupmaterial(const vec &v) -{ +int lookupmaterial(const vec &v) { ivec o(v); if(!insideworld(o)) return MAT_AIR; int scale = worldscale-1; cube *c = &worldroot[octastep(o.x, o.y, o.z, scale)]; - while(c->children) - { + while(c->children) { scale--; c = &c->children[octastep(o.x, o.y, o.z, scale)]; } @@ -260,8 +218,7 @@ int lookupmaterial(const vec &v) const cube *neighbourstack[32]; int neighbourdepth = -1; -const cube &neighbourcube(const cube &c, int orient, const ivec &co, int size, ivec &ro, int &rsize) -{ +const cube &neighbourcube(const cube &c, int orient, const ivec &co, int size, ivec &ro, int &rsize) { ivec n = co; int dim = dimension(orient); uint diff = n[dim]; @@ -270,8 +227,7 @@ const cube &neighbourcube(const cube &c, int orient, const ivec &co, int size, i if(diff >= uint(worldsize)) { ro = n; rsize = size; return c; } int scale = worldscale; const cube *nc = worldroot; - if(neighbourdepth >= 0) - { + if(neighbourdepth >= 0) { scale -= neighbourdepth + 1; diff >>= scale; do { scale++; diff >>= 1; } while(diff); @@ -279,8 +235,7 @@ const cube &neighbourcube(const cube &c, int orient, const ivec &co, int size, i } scale--; nc = &nc[octastep(n.x, n.y, n.z, scale)]; - if(!(size>>scale) && nc->children) do - { + if(!(size>>scale) && nc->children) do { scale--; nc = &nc->children[octastep(n.x, n.y, n.z, scale)]; } while(!(size>>scale) && nc->children); @@ -291,15 +246,12 @@ const cube &neighbourcube(const cube &c, int orient, const ivec &co, int size, i ////////// (re)mip ////////// -int getmippedtexture(const cube &p, int orient) -{ +int getmippedtexture(const cube &p, int orient) { cube *c = p.children; int d = dimension(orient), dc = dimcoord(orient), texs[4] = { -1, -1, -1, -1 }, numtexs = 0; - loop(x, 2) loop(y, 2) - { + loop(x, 2) loop(y, 2) { int n = octaindex(d, x, y, dc); - if(isempty(c[n])) - { + if(isempty(c[n])) { n = oppositeocta(d, n); if(isempty(c[n])) continue; @@ -312,16 +264,12 @@ int getmippedtexture(const cube &p, int orient) return DEFAULT_GEOM; } -void forcemip(cube &c, bool fixtex) -{ +void forcemip(cube &c, bool fixtex) { cube *ch = c.children; emptyfaces(c); - - loopi(8) loopj(8) - { + loopi(8) loopj(8) { int n = i^(j==3 ? 4 : (j==4 ? 3 : j)); - if(!isempty(ch[n])) // breadth first search for cube near vert - { + if(!isempty(ch[n])) { // breadth first search for cube near vert { ivec v; getcubevector(ch[n], i, v); // adjust vert to parent size @@ -329,13 +277,11 @@ void forcemip(cube &c, bool fixtex) break; } } - if(fixtex) loopj(6) c.texture[j] = getmippedtexture(c, j); } -static int midedge(const ivec &a, const ivec &b, int xd, int yd, bool &perfect) -{ +static int midedge(const ivec &a, const ivec &b, int xd, int yd, bool &perfect) { int ax = a[xd], ay = a[yd], bx = b[xd], by = b[yd]; if(ay==by) return ay; if(ax==bx) { perfect = false; return ay; } @@ -353,23 +299,19 @@ static int midedge(const ivec &a, const ivec &b, int xd, int yd, bool &perfect) return crossy ? 8 : min(max(y, 0), 16); } -static inline bool crosscenter(const ivec &a, const ivec &b, int xd, int yd) -{ +static inline bool crosscenter(const ivec &a, const ivec &b, int xd, int yd) { int ax = a[xd], ay = a[yd], bx = b[xd], by = b[yd]; return (((ax <= 8 && bx <= 8) || (ax >= 8 && bx >= 8)) && ((ay <= 8 && by <= 8) || (ay >= 8 && by >= 8))) || (ax + bx == 16 && ay + by == 16); } -bool subdividecube(cube &c, bool fullcheck, bool brighten) -{ +bool subdividecube(cube &c, bool fullcheck, bool brighten) { if(c.children) return true; if(c.ext) memset(c.ext->surfaces, 0, sizeof(c.ext->surfaces)); - if(isempty(c) || isentirelysolid(c)) - { + if(isempty(c) || isentirelysolid(c)) { c.children = newcubes(isempty(c) ? F_EMPTY : F_SOLID, c.material); - loopi(8) - { + loopi(8) { loopl(6) c.children[i].texture[l] = c.texture[l]; if(brighten && !isempty(c)) brightencube(c.children[i]); } @@ -378,14 +320,11 @@ bool subdividecube(cube &c, bool fullcheck, bool brighten) cube *ch = c.children = newcubes(F_SOLID, c.material); bool perfect = true; ivec v[8]; - loopi(8) - { + loopi(8) { getcubevector(c, i, v[i]); v[i].mul(2); } - - loopj(6) - { + loopj(6) { int d = dimension(j), z = dimcoord(j); const ivec &v00 = v[octaindex(d, 0, 0, z)], &v10 = v[octaindex(d, 1, 0, z)], @@ -406,19 +345,15 @@ bool subdividecube(cube &c, bool fullcheck, bool brighten) bool p1 = perfect, p2 = perfect; int c1 = midedge(v00, v11, R[d], d, p1); int c2 = midedge(v01, v10, R[d], d, p2); - if(z ? c1 > c2 : c1 < c2) - { + if(z ? c1 > c2 : c1 < c2) { e[1][1] = c1; perfect = p1 && (c1 == c2 || crosscenter(v00, v11, C[d], R[d])); } - else - { + else { e[1][1] = c2; perfect = p2 && (c1 == c2 || crosscenter(v01, v10, C[d], R[d])); } - - loopi(8) - { + loopi(8) { ch[i].texture[j] = c.texture[j]; int rd = (i>>R[d])&1, cd = (i>>C[d])&1, dd = (i>>D[d])&1; edgeset(cubeedge(ch[i], d, 0, 0), z, clamp(e[rd][cd] - dd*8, 0, 8)); @@ -427,10 +362,8 @@ bool subdividecube(cube &c, bool fullcheck, bool brighten) edgeset(cubeedge(ch[i], d, 1, 1), z, clamp(e[1+rd][1+cd] - dd*8, 0, 8)); } } - validatec(ch); - if(fullcheck) loopi(8) if(!isvalidcube(ch[i])) // not so good... - { + if(fullcheck) loopi(8) if(!isvalidcube(ch[i])) { // not so good... { emptyfaces(ch[i]); perfect=false; } @@ -440,14 +373,11 @@ bool subdividecube(cube &c, bool fullcheck, bool brighten) bool crushededge(uchar e, int dc) { return dc ? e==0 : e==0x88; } -int visibleorient(const cube &c, int orient) -{ - loopi(2) - { +int visibleorient(const cube &c, int orient) { + loopi(2) { int a = faceedgesidx[orient][i*2 + 0]; int b = faceedgesidx[orient][i*2 + 1]; - loopj(2) - { + loopj(2) { if(crushededge(c.edges[a],j) && crushededge(c.edges[b],j) && touchingface(c, orient)) return ((a>>2)<<1) + j; @@ -460,85 +390,66 @@ VAR(mipvis, 0, 0, 1); static int remipprogress = 0, remiptotal = 0; -bool remip(cube &c, const ivec &co, int size) -{ +bool remip(cube &c, const ivec &co, int size) { cube *ch = c.children; - if(!ch) - { + if(!ch) { if(size<<1 <= 0x1000) return true; subdividecube(c); ch = c.children; } else if((remipprogress++&0xFFF)==1) renderprogress(float(remipprogress)/remiptotal, "remipping..."); - bool perfect = true; - loopi(8) - { + loopi(8) { ivec o(i, co, size); if(!remip(ch[i], o, size>>1)) perfect = false; } - solidfaces(c); // so texmip is more consistent loopj(6) c.texture[j] = getmippedtexture(c, j); // parents get child texs regardless - if(!perfect) return false; if(size<<1 > 0x1000) return false; - ushort mat = MAT_AIR; - loopi(8) - { + loopi(8) { mat = ch[i].material; - if((mat&MATF_CLIP) == MAT_NOCLIP || mat&MAT_ALPHA) - { + if((mat&MATF_CLIP) == MAT_NOCLIP || mat&MAT_ALPHA) { if(i > 0) return false; while(++i < 8) if(ch[i].material != mat) return false; break; } - else if(!isentirelysolid(ch[i])) - { - while(++i < 8) - { + else if(!isentirelysolid(ch[i])) { + while(++i < 8) { int omat = ch[i].material; if(isentirelysolid(ch[i]) ? (omat&MATF_CLIP) == MAT_NOCLIP || omat&MAT_ALPHA : mat != omat) return false; } break; } } - cube n = c; n.ext = NULL; forcemip(n); n.children = NULL; - if(!subdividecube(n, false, false)) - { freeocta(n.children); return false; } - + if(!subdividecube(n, false, false)) { + freeocta(n.children); return false; } cube *nh = n.children; uchar vis[6] = {0, 0, 0, 0, 0, 0}; - loopi(8) - { + loopi(8) { if(ch[i].faces[0] != nh[i].faces[0] || ch[i].faces[1] != nh[i].faces[1] || - ch[i].faces[2] != nh[i].faces[2]) - { freeocta(nh); return false; } - + ch[i].faces[2] != nh[i].faces[2]) { + freeocta(nh); return false; } if(isempty(ch[i]) && isempty(nh[i])) continue; - ivec o(i, co, size); loop(orient, 6) - if(visibleface(ch[i], orient, o, size, MAT_AIR, (mat&MAT_ALPHA)^MAT_ALPHA, MAT_ALPHA)) - { + if(visibleface(ch[i], orient, o, size, MAT_AIR, (mat&MAT_ALPHA)^MAT_ALPHA, MAT_ALPHA)) { if(ch[i].texture[orient] != n.texture[orient]) { freeocta(nh); return false; } vis[orient] |= 1<>1); remip(worldroot[i], o, worldsize>>2); } @@ -564,36 +473,30 @@ void mpremip(bool local) if(!local) allchanged(); } -void remip_() -{ +void remip_() { mpremip(true); allchanged(); } COMMANDN(remip, remip_, ""); -static inline int edgeval(cube &c, const ivec &p, int dim, int coord) -{ +static inline int edgeval(cube &c, const ivec &p, int dim, int coord) { return edgeget(cubeedge(c, dim, p[R[dim]]>>3, p[C[dim]]>>3), coord); } -void genvertp(cube &c, ivec &p1, ivec &p2, ivec &p3, plane &pl, bool solid = false) -{ +void genvertp(cube &c, ivec &p1, ivec &p2, ivec &p3, plane &pl, bool solid = false) { int dim = 0; if(p1.y==p2.y && p2.y==p3.y) dim = 1; else if(p1.z==p2.z && p2.z==p3.z) dim = 2; - int coord = p1[dim]; ivec v1(p1), v2(p2), v3(p3); v1[dim] = solid ? coord*8 : edgeval(c, p1, dim, coord); v2[dim] = solid ? coord*8 : edgeval(c, p2, dim, coord); v3[dim] = solid ? coord*8 : edgeval(c, p3, dim, coord); - pl.toplane(vec(v1), vec(v2), vec(v3)); } -static bool threeplaneintersect(plane &pl1, plane &pl2, plane &pl3, vec &dest) -{ +static bool threeplaneintersect(plane &pl1, plane &pl2, plane &pl3, vec &dest) { vec &t1 = dest, t2, t3, t4; t1.cross(pl1, pl2); t4 = t1; t1.mul(pl3.offset); t2.cross(pl3, pl1); t2.mul(pl2.offset); @@ -607,12 +510,10 @@ static bool threeplaneintersect(plane &pl1, plane &pl2, plane &pl3, vec &dest) return true; } -static void genedgespanvert(ivec &p, cube &c, vec &v) -{ +static void genedgespanvert(ivec &p, cube &c, vec &v) { ivec p1(8-p.x, p.y, p.z); ivec p2(p.x, 8-p.y, p.z); ivec p3(p.x, p.y, 8-p.z); - plane plane1, plane2, plane3; genvertp(c, p, p1, p2, plane1); genvertp(c, p, p2, p3, plane2); @@ -620,7 +521,6 @@ static void genedgespanvert(ivec &p, cube &c, vec &v) if(plane1==plane2) genvertp(c, p, p1, p2, plane1, true); if(plane1==plane3) genvertp(c, p, p1, p2, plane1, true); if(plane2==plane3) genvertp(c, p, p2, p3, plane2, true); - ASSERT(threeplaneintersect(plane1, plane2, plane3, v)); //ASSERT(v.x>=0 && v.x<=8); //ASSERT(v.y>=0 && v.y<=8); @@ -630,34 +530,28 @@ static void genedgespanvert(ivec &p, cube &c, vec &v) v.z = max(0.0f, min(8.0f, v.z)); } -void edgespan2vectorcube(cube &c) -{ +void edgespan2vectorcube(cube &c) { if(isentirelysolid(c) || isempty(c)) return; cube o = c; - loop(x, 2) loop(y, 2) loop(z, 2) - { + loop(x, 2) loop(y, 2) loop(z, 2) { ivec p(8*x, 8*y, 8*z); vec v; genedgespanvert(p, o, v); - edgeset(cubeedge(c, 0, y, z), x, int(v.x+0.49f)); edgeset(cubeedge(c, 1, z, x), y, int(v.y+0.49f)); edgeset(cubeedge(c, 2, x, y), z, int(v.z+0.49f)); } } -const ivec cubecoords[8] = // verts of bounding cube -{ +const ivec cubecoords[8] = {// verts of bounding cube { #define GENCUBEVERT(n, x, y, z) ivec(x, y, z), GENCUBEVERTS(0, 8, 0, 8, 0, 8) #undef GENCUBEVERT }; template -static inline void gencubevert(const cube &c, int i, T &v) -{ - switch(i) - { +static inline void gencubevert(const cube &c, int i, T &v) { + switch(i) { default: #define GENCUBEVERT(n, x, y, z) \ case n: \ @@ -670,10 +564,8 @@ static inline void gencubevert(const cube &c, int i, T &v) } } -void genfaceverts(const cube &c, int orient, ivec v[4]) -{ - switch(orient) - { +void genfaceverts(const cube &c, int orient, ivec v[4]) { + switch(orient) { default: #define GENFACEORIENT(o, v0, v1, v2, v3) \ case o: v0 v1 v2 v3 break; @@ -687,10 +579,9 @@ void genfaceverts(const cube &c, int orient, ivec v[4]) } } -const ivec facecoords[6][4] = -{ -#define GENFACEORIENT(o, v0, v1, v2, v3) \ - { v0, v1, v2, v3 }, +const ivec facecoords[6][4] = { +#define GENFACEORIENT(o, v0, v1, v2, v3) { \ + v0, v1, v2, v3 }, #define GENFACEVERT(o, n, x,y,z, xv,yv,zv) \ ivec(x,y,z) GENFACEVERTS(0, 8, 0, 8, 0, 8, , , , , , ) @@ -698,8 +589,7 @@ const ivec facecoords[6][4] = #undef GENFACEVERT }; -const uchar fv[6][4] = // indexes for cubecoords, per each vert of a face orientation -{ +const uchar fv[6][4] = { // indexes for cubecoords, per each vert of a face orientation { { 2, 1, 6, 5 }, { 3, 4, 7, 0 }, { 4, 5, 6, 7 }, @@ -708,8 +598,7 @@ const uchar fv[6][4] = // indexes for cubecoords, per each vert of a face orient { 5, 4, 3, 2 }, }; -const uchar fvmasks[64] = // mask of verts used given a mask of visible face orientations -{ +const uchar fvmasks[64] = { // mask of verts used given a mask of visible face orientations { 0x00, 0x66, 0x99, 0xFF, 0xF0, 0xF6, 0xF9, 0xFF, 0x0F, 0x6F, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xE7, 0xDB, 0xFF, 0xF3, 0xF7, 0xFB, 0xFF, @@ -720,8 +609,8 @@ const uchar fvmasks[64] = // mask of verts used given a mask of visible face ori 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; -const uchar faceedgesidx[6][4] = // ordered edges surrounding each orient -{//0..1 = row edges, 2..3 = column edges +const uchar faceedgesidx[6][4] = { // ordered edges surrounding each orient { +//0..1 = row edges, 2..3 = column edges { { 4, 5, 8, 10 }, { 6, 7, 9, 11 }, { 8, 9, 0, 2 }, @@ -730,17 +619,14 @@ const uchar faceedgesidx[6][4] = // ordered edges surrounding each orient { 2, 3, 5, 7 }, }; -bool flataxisface(const cube &c, int orient) -{ +bool flataxisface(const cube &c, int orient) { uint face = c.faces[dimension(orient)]; if(dimcoord(orient)) face >>= 4; return (face&0x0F0F0F0F) == 0x01010101*(face&0x0F); } -bool collideface(const cube &c, int orient) -{ - if(flataxisface(c, orient)) - { +bool collideface(const cube &c, int orient) { + if(flataxisface(c, orient)) { uchar r1 = c.edges[faceedgesidx[orient][0]], r2 = c.edges[faceedgesidx[orient][1]]; if(uchar((r1>>4)|(r2&0xF0)) == uchar((r1&0x0F)|(r2<<4))) return false; uchar c1 = c.edges[faceedgesidx[orient][2]], c2 = c.edges[faceedgesidx[orient][3]]; @@ -749,35 +635,30 @@ bool collideface(const cube &c, int orient) return true; } -bool touchingface(const cube &c, int orient) -{ +bool touchingface(const cube &c, int orient) { uint face = c.faces[dimension(orient)]; return dimcoord(orient) ? (face&0xF0F0F0F0)==0x80808080 : (face&0x0F0F0F0F)==0; } -bool notouchingface(const cube &c, int orient) -{ +bool notouchingface(const cube &c, int orient) { uint face = c.faces[dimension(orient)]; return dimcoord(orient) ? (face&0x80808080)==0 : ((0x88888888-face)&0x08080808) == 0; } -int faceconvexity(const ivec v[4]) -{ +int faceconvexity(const ivec v[4]) { ivec n; n.cross(ivec(v[1]).sub(v[0]), ivec(v[2]).sub(v[0])); return ivec(v[0]).sub(v[3]).dot(n); // 1 if convex, -1 if concave, 0 if flat } -int faceconvexity(const vertinfo *verts, int numverts, int size) -{ +int faceconvexity(const vertinfo *verts, int numverts, int size) { if(numverts < 4) return 0; ivec v0 = verts[0].getxyz(), e1 = verts[1].getxyz().sub(v0), e2 = verts[2].getxyz().sub(v0), n; - if(size >= (8<<5)) - { + if(size >= (8<<5)) { if(size >= (8<<10)) n.cross(e1.shr(10), e2.shr(10)); else n.cross(e1, e2).shr(10); } @@ -785,13 +666,11 @@ int faceconvexity(const vertinfo *verts, int numverts, int size) return verts[3].getxyz().sub(v0).dot(n); } -int faceconvexity(const ivec v[4], int &vis) -{ +int faceconvexity(const ivec v[4], int &vis) { ivec e1, e2, e3, n; n.cross((e1 = v[1]).sub(v[0]), (e2 = v[2]).sub(v[0])); int convex = (e3 = v[0]).sub(v[3]).dot(n); - if(!convex) - { + if(!convex) { if(ivec().cross(e3, e2).iszero()) { if(!n.iszero()) vis = 1; } else if(n.iszero()) { vis = 2; } return 0; @@ -799,46 +678,39 @@ int faceconvexity(const ivec v[4], int &vis) return convex; } -int faceconvexity(const cube &c, int orient) -{ +int faceconvexity(const cube &c, int orient) { if(flataxisface(c, orient)) return 0; ivec v[4]; genfaceverts(c, orient, v); return faceconvexity(v); } -int faceorder(const cube &c, int orient) // gets above 'fv' so that each face is convex -{ +int faceorder(const cube &c, int orient) { // gets above 'fv' so that each face is convex { return faceconvexity(c, orient)<0 ? 1 : 0; } -static inline void faceedges(const cube &c, int orient, uchar edges[4]) -{ +static inline void faceedges(const cube &c, int orient, uchar edges[4]) { loopk(4) edges[k] = c.edges[faceedgesidx[orient][k]]; } -uint faceedges(const cube &c, int orient) -{ +uint faceedges(const cube &c, int orient) { union { uchar edges[4]; uint face; } u; faceedges(c, orient, u.edges); return u.face; } -static inline int genfacevecs(const cube &cu, int orient, const ivec &pos, int size, bool solid, ivec2 *fvecs, const ivec *v = NULL) -{ +static inline int genfacevecs(const cube &cu, int orient, const ivec &pos, int size, bool solid, ivec2 *fvecs, const ivec *v = NULL) { int i = 0; - if(solid) - { - switch(orient) - { + if(solid) { + switch(orient) { #define GENFACEORIENT(orient, v0, v1, v2, v3) \ - case orient: \ - { \ + case orient: { \ + \ if(dimcoord(orient)) { v0 v1 v2 v3 } else { v3 v2 v1 v0 } \ break; \ } - #define GENFACEVERT(orient, vert, xv,yv,zv, x,y,z) \ - { ivec2 &f = fvecs[i]; x ((xv)<<3); y ((yv)<<3); z ((zv)<<3); i++; } + #define GENFACEVERT(orient, vert, xv,yv,zv, x,y,z) { \ + ivec2 &f = fvecs[i]; x ((xv)<<3); y ((yv)<<3); z ((zv)<<3); i++; } GENFACEVERTS(pos.x, pos.x+size, pos.y, pos.y+size, pos.z, pos.z+size, f.x = , f.x = , f.y = , f.y = , (void), (void)) #undef GENFACEVERT } @@ -847,15 +719,14 @@ static inline int genfacevecs(const cube &cu, int orient, const ivec &pos, int s ivec buf[4]; if(!v) { genfaceverts(cu, orient, buf); v = buf; } ivec2 prev(INT_MAX, INT_MAX); - switch(orient) - { - #define GENFACEVERT(orient, vert, sx,sy,sz, dx,dy,dz) \ - { \ + switch(orient) { + #define GENFACEVERT(orient, vert, sx,sy,sz, dx,dy,dz) { \ + \ const ivec &e = v[vert]; \ ivec ef; \ ef.dx = e.sx; ef.dy = e.sy; ef.dz = e.sz; \ - if(ef.z == dimcoord(orient)*8) \ - { \ + if(ef.z == dimcoord(orient)*8) { \ + \ ivec2 &f = fvecs[i]; \ ivec pf; \ pf.dx = pos.sx; pf.dy = pos.sy; pf.dz = pos.sz; \ @@ -871,66 +742,51 @@ static inline int genfacevecs(const cube &cu, int orient, const ivec &pos, int s return i; } -static inline int clipfacevecy(const ivec2 &o, const ivec2 &dir, int cx, int cy, int size, ivec2 &r) -{ - if(dir.x >= 0) - { +static inline int clipfacevecy(const ivec2 &o, const ivec2 &dir, int cx, int cy, int size, ivec2 &r) { + if(dir.x >= 0) { if(cx <= o.x || cx >= o.x+dir.x) return 0; } else if(cx <= o.x+dir.x || cx >= o.x) return 0; - int t = (o.y-cy) + (cx-o.x)*dir.y/dir.x; if(t <= 0 || t >= size) return 0; - r.x = cx; r.y = cy + t; return 1; } -static inline int clipfacevecx(const ivec2 &o, const ivec2 &dir, int cx, int cy, int size, ivec2 &r) -{ - if(dir.y >= 0) - { +static inline int clipfacevecx(const ivec2 &o, const ivec2 &dir, int cx, int cy, int size, ivec2 &r) { + if(dir.y >= 0) { if(cy <= o.y || cy >= o.y+dir.y) return 0; } else if(cy <= o.y+dir.y || cy >= o.y) return 0; - int t = (o.x-cx) + (cy-o.y)*dir.x/dir.y; if(t <= 0 || t >= size) return 0; - r.x = cx + t; r.y = cy; return 1; } -static inline int clipfacevec(const ivec2 &o, const ivec2 &dir, int cx, int cy, int size, ivec2 *rvecs) -{ +static inline int clipfacevec(const ivec2 &o, const ivec2 &dir, int cx, int cy, int size, ivec2 *rvecs) { int r = 0; - if(o.x >= cx && o.x <= cx+size && o.y >= cy && o.y <= cy+size && - ((o.x != cx && o.x != cx+size) || (o.y != cy && o.y != cy+size))) - { + ((o.x != cx && o.x != cx+size) || (o.y != cy && o.y != cy+size))) { rvecs[0].x = o.x; rvecs[0].y = o.y; r++; } - r += clipfacevecx(o, dir, cx, cy, size, rvecs[r]); r += clipfacevecx(o, dir, cx, cy+size, size, rvecs[r]); r += clipfacevecy(o, dir, cx, cy, size, rvecs[r]); r += clipfacevecy(o, dir, cx+size, cy, size, rvecs[r]); - ASSERT(r <= 2); return r; } -static inline bool insideface(const ivec2 *p, int nump, const ivec2 *o, int numo) -{ +static inline bool insideface(const ivec2 *p, int nump, const ivec2 *o, int numo) { int bounds = 0; ivec2 prev = o[numo-1]; - loopi(numo) - { + loopi(numo) { const ivec2 &cur = o[i]; ivec2 dir(cur.x-prev.x, cur.y-prev.y); int offset = dir.x*prev.y - dir.y*prev.x; @@ -941,16 +797,13 @@ static inline bool insideface(const ivec2 *p, int nump, const ivec2 *o, int numo return bounds>=3; } -static inline int clipfacevecs(const ivec2 *o, int numo, int cx, int cy, int size, ivec2 *rvecs) -{ +static inline int clipfacevecs(const ivec2 *o, int numo, int cx, int cy, int size, ivec2 *rvecs) { cx <<= 3; cy <<= 3; size <<= 3; - int r = 0; ivec2 prev = o[numo-1]; - loopi(numo) - { + loopi(numo) { const ivec2 &cur = o[i]; r += clipfacevec(prev, ivec2(cur.x-prev.x, cur.y-prev.y), cx, cy, size, &rvecs[r]); prev = cur; @@ -961,8 +814,7 @@ static inline int clipfacevecs(const ivec2 *o, int numo, int cx, int cy, int siz return r; } -bool collapsedface(const cube &c, int orient) -{ +bool collapsedface(const cube &c, int orient) { int e0 = c.edges[faceedgesidx[orient][0]], e1 = c.edges[faceedgesidx[orient][1]], e2 = c.edges[faceedgesidx[orient][2]], e3 = c.edges[faceedgesidx[orient][3]], face = dimension(orient)*4, @@ -978,11 +830,9 @@ bool collapsedface(const cube &c, int orient) ivec().cross(v2, v3.sub(v0)).iszero(); } -static inline bool occludesface(const cube &c, int orient, const ivec &o, int size, const ivec &vo, int vsize, ushort vmat, ushort nmat, ushort matmask, const ivec2 *vf, int numv) -{ +static inline bool occludesface(const cube &c, int orient, const ivec &o, int size, const ivec &vo, int vsize, ushort vmat, ushort nmat, ushort matmask, const ivec2 *vf, int numv) { int dim = dimension(orient); - if(!c.children) - { + if(!c.children) { if(nmat != MAT_AIR && (c.material&matmask) == nmat) { ivec2 nf[8]; @@ -999,42 +849,32 @@ static inline bool occludesface(const cube &c, int orient, const ivec &o, int si int numo = genfacevecs(c, orient, o, size, false, of); return numo >= 3 && insideface(cf, numc, of, numo); } - size >>= 1; int coord = dimcoord(orient); - loopi(8) if(octacoord(dim, i) == coord) - { + loopi(8) if(octacoord(dim, i) == coord) { if(!occludesface(c.children[i], orient, ivec(i, o, size), size, vo, vsize, vmat, nmat, matmask, vf, numv)) return false; } - return true; } -bool visibleface(const cube &c, int orient, const ivec &co, int size, ushort mat, ushort nmat, ushort matmask) -{ - if(mat != MAT_AIR) - { +bool visibleface(const cube &c, int orient, const ivec &co, int size, ushort mat, ushort nmat, ushort matmask) { + if(mat != MAT_AIR) { if(faceedges(c, orient)==F_SOLID && touchingface(c, orient)) return false; } - else - { + else { if(collapsedface(c, orient)) return false; if(!touchingface(c, orient)) return true; } - ivec no; int nsize; const cube &o = neighbourcube(c, orient, co, size, no, nsize); if(&o==&c) return false; - int opp = opposite(orient); - if(nsize > size || (nsize == size && !o.children)) - { + if(nsize > size || (nsize == size && !o.children)) { if(nmat != MAT_AIR && (o.material&matmask) == nmat) return true; if(isentirelysolid(o)) return false; if(isempty(o) || notouchingface(o, opp)) return true; if(touchingface(o, opp) && faceedges(o, opp) == F_SOLID) return false; - ivec vo = ivec(co).mask(0xFFF); no.mask(0xFFF); ivec2 cf[4], of[4]; @@ -1043,7 +883,6 @@ bool visibleface(const cube &c, int orient, const ivec &co, int size, ushort mat return numo < 3 || !insideface(cf, numc, of, numo); } - ivec vo = ivec(co).mask(0xFFF); no.mask(0xFFF); ivec2 cf[4]; @@ -1051,26 +890,21 @@ bool visibleface(const cube &c, int orient, const ivec &co, int size, ushort mat return !occludesface(o, opp, no, nsize, vo, size, mat, nmat, matmask, cf, numc); } -int classifyface(const cube &c, int orient, const ivec &co, int size) -{ +int classifyface(const cube &c, int orient, const ivec &co, int size) { if(collapsedface(c, orient)) return 0; int vismask = (c.material&MATF_CLIP) == MAT_NOCLIP ? 1 : 3; if(!touchingface(c, orient)) return vismask; - ivec no; int nsize; const cube &o = neighbourcube(c, orient, co, size, no, nsize); if(&o==&c) return 0; - int vis = 0, opp = opposite(orient); - if(nsize > size || (nsize == size && !o.children)) - { + if(nsize > size || (nsize == size && !o.children)) { if((~c.material & o.material) & MAT_ALPHA) vis |= 1; if((o.material&MATF_CLIP) == MAT_NOCLIP) vis |= vismask&2; if(vis == vismask || isentirelysolid(o)) return vis; if(isempty(o) || notouchingface(o, opp)) return vismask; if(touchingface(o, opp) && faceedges(o, opp) == F_SOLID) return vis; - ivec vo = ivec(co).mask(0xFFF); no.mask(0xFFF); ivec2 cf[4], of[4]; @@ -1079,7 +913,6 @@ int classifyface(const cube &c, int orient, const ivec &co, int size) if(numo < 3 || !insideface(cf, numc, of, numo)) return vismask; return vis; } - ivec vo = ivec(co).mask(0xFFF); no.mask(0xFFF); ivec2 cf[4]; @@ -1090,79 +923,67 @@ int classifyface(const cube &c, int orient, const ivec &co, int size) } // more expensive version that checks both triangles of a face independently -int visibletris(const cube &c, int orient, const ivec &co, int size, ushort nmat, ushort matmask) -{ +int visibletris(const cube &c, int orient, const ivec &co, int size, ushort nmat, ushort matmask) { int vis = 3, touching = 0xF; ivec v[4], e1, e2, e3, n; genfaceverts(c, orient, v); n.cross((e1 = v[1]).sub(v[0]), (e2 = v[2]).sub(v[0])); int convex = (e3 = v[0]).sub(v[3]).dot(n); - if(!convex) - { + if(!convex) { if(ivec().cross(e3, e2).iszero() || v[1] == v[3]) { if(n.iszero()) return 0; vis = 1; touching = 0xF&~(1<<3); } else if(n.iszero()) { vis = 2; touching = 0xF&~(1<<1); } } - int dim = dimension(orient), coord = dimcoord(orient); if(v[0][dim] != coord*8) touching &= ~(1<<0); if(v[1][dim] != coord*8) touching &= ~(1<<1); if(v[2][dim] != coord*8) touching &= ~(1<<2); if(v[3][dim] != coord*8) touching &= ~(1<<3); - static const int notouchmasks[2][16] = // mask of triangles not touching - { // order 0: flat or convex - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - { 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 1, 3, 0 }, - // order 1: concave - { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 2, 0 }, + static const int notouchmasks[2][16] = { // mask of triangles not touching { + // order 0: flat or convex + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 { + { 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 1, 3, 0 }, + // order 1: concave { + { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 2, 0 }, }; int order = convex < 0 ? 1 : 0, notouch = notouchmasks[order][touching]; if((vis¬ouch)==vis) return vis; - ivec no; int nsize; const cube &o = neighbourcube(c, orient, co, size, no, nsize); if(&o==&c) return 0; - if((c.material&matmask) == nmat) nmat = MAT_AIR; - ivec vo = ivec(co).mask(0xFFF); no.mask(0xFFF); ivec2 cf[4], of[4]; int opp = opposite(orient), numo = 0, numc; - if(nsize > size || (nsize == size && !o.children)) - { + if(nsize > size || (nsize == size && !o.children)) { if(isempty(o) || notouchingface(o, opp)) return vis; if(nmat != MAT_AIR && (o.material&matmask) == nmat) return vis; if(isentirelysolid(o) || (touchingface(o, opp) && faceedges(o, opp) == F_SOLID)) return vis¬ouch; - numc = genfacevecs(c, orient, vo, size, false, cf, v); numo = genfacevecs(o, opp, no, nsize, false, of); if(numo < 3) return vis; if(insideface(cf, numc, of, numo)) return vis¬ouch; } - else - { + else { numc = genfacevecs(c, orient, vo, size, false, cf, v); if(occludesface(o, opp, no, nsize, vo, size, MAT_AIR, nmat, matmask, cf, numc)) return vis¬ouch; } if(vis != 3 || notouch) return vis; - - static const int triverts[2][2][2][3] = - { // order - { // coord - { { 1, 2, 3 }, { 0, 1, 3 } }, // verts - { { 0, 1, 2 }, { 0, 2, 3 } } - }, - { // coord - { { 0, 1, 2 }, { 3, 0, 2 } }, // verts - { { 1, 2, 3 }, { 1, 3, 0 } } + static const int triverts[2][2][2][3] = { + // order { + // coord { + { + { { 1, 2, 3 }, { 0, 1, 3 } }, // verts { + { { 0, 1, 2 }, { 0, 2, 3 } } + }, { + // coord { + { { 0, 1, 2 }, { 3, 0, 2 } }, // verts { + { { 1, 2, 3 }, { 1, 3, 0 } } } }; - - do - { - loopi(2) - { + do { + loopi(2) { const int *verts = triverts[order][coord][i]; ivec2 tf[3] = { cf[verts[0]], cf[verts[1]], cf[verts[2]] }; if(numo > 0) { if(!insideface(tf, 3, of, numo)) continue; } @@ -1171,12 +992,10 @@ int visibletris(const cube &c, int orient, const ivec &co, int size, ushort nmat } vis |= 4; } while(++order <= 1); - return 3; } -void calcvert(const cube &c, const ivec &co, int size, ivec &v, int i, bool solid) -{ +void calcvert(const cube &c, const ivec &co, int size, ivec &v, int i, bool solid) { if(solid) v = cubecoords[i]; else gencubevert(c, i, v); // avoid overflow if(size>=8) v.mul(size/8); @@ -1184,14 +1003,12 @@ void calcvert(const cube &c, const ivec &co, int size, ivec &v, int i, bool soli v.add(ivec(co).shl(3)); } -void calcvert(const cube &c, const ivec &co, int size, vec &v, int i, bool solid) -{ +void calcvert(const cube &c, const ivec &co, int size, vec &v, int i, bool solid) { if(solid) v = vec(cubecoords[i]); else gencubevert(c, i, v); v.mul(size/8.0f).add(vec(co)); } -int genclipplane(const cube &c, int orient, vec *v, plane *clip) -{ +int genclipplane(const cube &c, int orient, vec *v, plane *clip) { int planes = 0, convex = faceconvexity(c, orient), order = convex < 0 ? 1 : 0; const vec &v0 = v[fv[orient][order]], &v1 = v[fv[orient][order+1]], &v2 = v[fv[orient][order+2]], &v3 = v[fv[orient][(order+3)&3]]; if(v0==v2) return 0; @@ -1200,31 +1017,24 @@ int genclipplane(const cube &c, int orient, vec *v, plane *clip) return planes; } -void genclipplanes(const cube &c, const ivec &co, int size, clipplanes &p, bool collide) -{ +void genclipplanes(const cube &c, const ivec &co, int size, clipplanes &p, bool collide) { // generate tight bounding box calcvert(c, co, size, p.v[0], 0); vec mx = p.v[0], mn = p.v[0]; - for(int i = 1; i < 8; i++) - { + for(int i = 1; i < 8; i++) { calcvert(c, co, size, p.v[i], i); mx.max(p.v[i]); mn.min(p.v[i]); } - p.r = mx.sub(mn).mul(0.5f); p.o = mn.add(p.r); - p.size = 0; p.visible = 0; - if(collide || (c.visible&0xC0) == 0x40) - { - loopi(6) if(c.visible&(1< y.v2) return false; if(x.u1 < y.u1) return true; @@ -1258,13 +1064,10 @@ static inline bool mergefacecmp(const facebounds &x, const facebounds &y) return false; } -static int mergefacev(int orient, facebounds *m, int sz, facebounds &n) -{ - for(int i = sz-1; i >= 0; --i) - { +static int mergefacev(int orient, facebounds *m, int sz, facebounds &n) { + for(int i = sz-1; i >= 0; --i) { if(m[i].v2 < n.v1) break; - if(m[i].v2 == n.v1 && m[i].u1 == n.u1 && m[i].u2 == n.u2) - { + if(m[i].v2 == n.v1 && m[i].u1 == n.u1 && m[i].u2 == n.u2) { n.v1 = m[i].v1; memmove(&m[i], &m[i+1], (sz - (i+1)) * sizeof(facebounds)); return 1; @@ -1273,20 +1076,16 @@ static int mergefacev(int orient, facebounds *m, int sz, facebounds &n) return 0; } -static int mergefaceu(int orient, facebounds &m, facebounds &n) -{ - if(m.v1 == n.v1 && m.v2 == n.v2 && m.u2 == n.u1) - { +static int mergefaceu(int orient, facebounds &m, facebounds &n) { + if(m.v1 == n.v1 && m.v2 == n.v2 && m.u2 == n.u1) { n.u1 = m.u1; return 1; } return 0; } -static int mergeface(int orient, facebounds *m, int sz, facebounds &n) -{ - for(bool merged = false; sz; merged = true) - { +static int mergeface(int orient, facebounds *m, int sz, facebounds &n) { + for(bool merged = false; sz; merged = true) { int vmerged = mergefacev(orient, m, sz, n); sz -= vmerged; if(!vmerged && merged) break; @@ -1299,38 +1098,31 @@ static int mergeface(int orient, facebounds *m, int sz, facebounds &n) return sz; } -int mergefaces(int orient, facebounds *m, int sz) -{ +int mergefaces(int orient, facebounds *m, int sz) { quicksort(m, sz, mergefacecmp); - int nsz = 0; loopi(sz) nsz = mergeface(orient, m, nsz, m[i]); return nsz; } -struct cfkey -{ +struct cfkey { uchar orient; ushort material, tex; ivec n; int offset; }; -static inline bool htcmp(const cfkey &x, const cfkey &y) -{ +static inline bool htcmp(const cfkey &x, const cfkey &y) { return x.orient == y.orient && x.tex == y.tex && x.n == y.n && x.offset == y.offset && x.material==y.material; } -static inline uint hthash(const cfkey &k) -{ +static inline uint hthash(const cfkey &k) { return hthash(k.n)^k.offset^k.tex^k.orient^k.material; } -void mincubeface(const cube &cu, int orient, const ivec &o, int size, const facebounds &orig, facebounds &cf, ushort nmat, ushort matmask) -{ +void mincubeface(const cube &cu, int orient, const ivec &o, int size, const facebounds &orig, facebounds &cf, ushort nmat, ushort matmask) { int dim = dimension(orient); - if(cu.children) - { + if(cu.children) { size >>= 1; int coord = dimcoord(orient); loopi(8) if(octacoord(dim, i) == coord) @@ -1344,8 +1136,7 @@ void mincubeface(const cube &cu, int orient, const ivec &o, int size, const face uc2 = min(uc2, orig.u2); vc1 = max(vc1, orig.v1); vc2 = min(vc2, orig.v2); - if(!isempty(cu) && touchingface(cu, orient) && !(nmat!=MAT_AIR && (cu.material&matmask)==nmat)) - { + if(!isempty(cu) && touchingface(cu, orient) && !(nmat!=MAT_AIR && (cu.material&matmask)==nmat)) { uchar r1 = cu.edges[faceedgesidx[orient][0]], r2 = cu.edges[faceedgesidx[orient][1]], c1 = cu.edges[faceedgesidx[orient][2]], c2 = cu.edges[faceedgesidx[orient][3]]; ushort u1 = max(c1&0xF, c2&0xF)*size+uco, u2 = min(c1>>4, c2>>4)*size+uco, @@ -1354,14 +1145,12 @@ void mincubeface(const cube &cu, int orient, const ivec &o, int size, const face u2 = min(u2, orig.u2); v1 = max(v1, orig.v1); v2 = min(v2, orig.v2); - if(v2-v1==vc2-vc1) - { + if(v2-v1==vc2-vc1) { if(u2-u1==uc2-uc1) return; if(u1==uc1) uc1 = u2; if(u2==uc2) uc2 = u1; } - else if(u2-u1==uc2-uc1) - { + else if(u2-u1==uc2-uc1) { if(v1==vc1) vc1 = v2; if(v2==vc2) vc2 = v1; } @@ -1373,8 +1162,7 @@ void mincubeface(const cube &cu, int orient, const ivec &o, int size, const face cf.v2 = max(cf.v2, vc2); } -bool mincubeface(const cube &cu, int orient, const ivec &co, int size, facebounds &orig) -{ +bool mincubeface(const cube &cu, int orient, const ivec &co, int size, facebounds &orig) { ivec no; int nsize; const cube &nc = neighbourcube(cu, orient, co, size, no, nsize); @@ -1395,24 +1183,18 @@ bool mincubeface(const cube &cu, int orient, const ivec &co, int size, facebound VAR(maxmerge, 0, 6, 12); VAR(minface, 0, 4, 12); -struct pvert -{ +struct pvert { ushort x, y; - pvert() {} pvert(ushort x, ushort y) : x(x), y(y) {} - bool operator==(const pvert &o) const { return x == o.x && y == o.y; } bool operator!=(const pvert &o) const { return x != o.x || y != o.y; } }; -struct pedge -{ +struct pedge { pvert from, to; - pedge() {} pedge(const pvert &from, const pvert &to) : from(from), to(to) {} - bool operator==(const pedge &o) const { return from == o.from && to == o.to; } bool operator!=(const pedge &o) const { return from != o.from || to != o.to; } }; @@ -1420,35 +1202,28 @@ struct pedge static inline uint hthash(const pedge &x) { return uint(x.from.x)^(uint(x.from.y)<<8); } static inline bool htcmp(const pedge &x, const pedge &y) { return x == y; } -struct poly -{ +struct poly { cube *c; int numverts; bool merged; pvert verts[MAXFACEVERTS]; }; -bool clippoly(poly &p, const facebounds &b) -{ +bool clippoly(poly &p, const facebounds &b) { pvert verts1[MAXFACEVERTS+4], verts2[MAXFACEVERTS+4]; int numverts1 = 0, numverts2 = 0, px = p.verts[p.numverts-1].x, py = p.verts[p.numverts-1].y; - loopi(p.numverts) - { + loopi(p.numverts) { int x = p.verts[i].x, y = p.verts[i].y; - if(x < b.u1) - { + if(x < b.u1) { if(px > b.u2) verts1[numverts1++] = pvert(b.u2, y + ((y - py)*(b.u2 - x))/(x - px)); if(px > b.u1) verts1[numverts1++] = pvert(b.u1, y + ((y - py)*(b.u1 - x))/(x - px)); } - else if(x > b.u2) - { + else if(x > b.u2) { if(px < b.u1) verts1[numverts1++] = pvert(b.u1, y + ((y - py)*(b.u1 - x))/(x - px)); if(px < b.u2) verts1[numverts1++] = pvert(b.u2, y + ((y - py)*(b.u2 - x))/(x - px)); } - else - { - if(px < b.u1) - { + else { + if(px < b.u1) { if(x > b.u1) verts1[numverts1++] = pvert(b.u1, y + ((y - py)*(b.u1 - x))/(x - px)); } else if(px > b.u2 && x < b.u2) verts1[numverts1++] = pvert(b.u2, y + ((y - py)*(b.u2 - x))/(x - px)); @@ -1460,23 +1235,18 @@ bool clippoly(poly &p, const facebounds &b) if(numverts1 < 3) return false; px = verts1[numverts1-1].x; py = verts1[numverts1-1].y; - loopi(numverts1) - { + loopi(numverts1) { int x = verts1[i].x, y = verts1[i].y; - if(y < b.v1) - { + if(y < b.v1) { if(py > b.v2) verts2[numverts2++] = pvert(x + ((x - px)*(b.v2 - y))/(y - py), b.v2); if(py > b.v1) verts2[numverts2++] = pvert(x + ((x - px)*(b.v1 - y))/(y - py), b.v1); } - else if(y > b.v2) - { + else if(y > b.v2) { if(py < b.v1) verts2[numverts2++] = pvert(x + ((x - px)*(b.v1 - y))/(y - py), b.v1); if(py < b.v2) verts2[numverts2++] = pvert(x + ((x - px)*(b.v2 - y))/(y - py), b.v2); } - else - { - if(py < b.v1) - { + else { + if(py < b.v1) { if(y > b.v1) verts2[numverts2++] = pvert(x + ((x - px)*(b.v1 - y))/(y - py), b.v1); } else if(py > b.v2 && y < b.v2) verts2[numverts2++] = pvert(x + ((x - px)*(b.v2 - y))/(y - py), b.v2); @@ -1492,47 +1262,38 @@ bool clippoly(poly &p, const facebounds &b) return true; } -bool genpoly(cube &cu, int orient, const ivec &o, int size, int vis, ivec &n, int &offset, poly &p) -{ +bool genpoly(cube &cu, int orient, const ivec &o, int size, int vis, ivec &n, int &offset, poly &p) { int dim = dimension(orient), coord = dimcoord(orient); ivec v[4]; genfaceverts(cu, orient, v); - if(flataxisface(cu, orient)) - { + if(flataxisface(cu, orient)) { n = ivec(0, 0, 0); n[dim] = coord ? 1 : -1; } - else - { + else { if(faceconvexity(v)) return false; n.cross(ivec(v[1]).sub(v[0]), ivec(v[2]).sub(v[0])); if(n.iszero()) n.cross(ivec(v[2]).sub(v[0]), ivec(v[3]).sub(v[0])); reduceslope(n); } - ivec po = ivec(o).mask(0xFFF).shl(3); loopk(4) v[k].mul(size).add(po); offset = -n.dot(v[3]); - int r = R[dim], c = C[dim], order = vis&4 ? 1 : 0; p.numverts = 0; - if(coord) - { + if(coord) { const ivec &v0 = v[order]; p.verts[p.numverts++] = pvert(v0[c], v0[r]); if(vis&1) { const ivec &v1 = v[order+1]; p.verts[p.numverts++] = pvert(v1[c], v1[r]); } const ivec &v2 = v[order+2]; p.verts[p.numverts++] = pvert(v2[c], v2[r]); if(vis&2) { const ivec &v3 = v[(order+3)&3]; p.verts[p.numverts++] = pvert(v3[c], v3[r]); } } - else - { + else { if(vis&2) { const ivec &v3 = v[(order+3)&3]; p.verts[p.numverts++] = pvert(v3[c], v3[r]); } const ivec &v2 = v[order+2]; p.verts[p.numverts++] = pvert(v2[c], v2[r]); if(vis&1) { const ivec &v1 = v[order+1]; p.verts[p.numverts++] = pvert(v1[c], v1[r]); } const ivec &v0 = v[order]; p.verts[p.numverts++] = pvert(v0[c], v0[r]); } - - if(faceedges(cu, orient)!=F_SOLID) - { + if(faceedges(cu, orient)!=F_SOLID) { int px = int(p.verts[p.numverts-2].x) - int(p.verts[p.numverts-3].x), py = int(p.verts[p.numverts-2].y) - int(p.verts[p.numverts-3].y), cx = int(p.verts[p.numverts-1].x) - int(p.verts[p.numverts-2].x), cy = int(p.verts[p.numverts-1].y) - int(p.verts[p.numverts-2].y), dir = px*cy - py*cx; @@ -1554,17 +1315,13 @@ bool genpoly(cube &cu, int orient, const ivec &o, int size, int vis, ivec &n, in if(dir > 0) return false; if(!dir) { if(p.numverts < 4) return false; p.verts[1] = p.verts[2]; p.verts[2] = p.verts[3]; p.numverts--; } } - p.c = &cu; p.merged = false; - - if(minface && size >= 1<= 1< &links, vector &queue, int owner, poly &p, poly &q, const pedge &e) -{ +bool mergepolys(int orient, hashset &links, vector &queue, int owner, poly &p, poly &q, const pedge &e) { int pe = -1, qe = -1; loopi(p.numverts) if(p.verts[i] == e.from) { pe = i; break; } loopi(q.numverts) if(q.verts[i] == e.to) { qe = i; break; } @@ -1604,15 +1356,13 @@ bool mergepolys(int orient, hashset &links, vector &queue, int o */ pvert verts[2*MAXFACEVERTS]; int numverts = 0, index = pe+2; // starts at A = T+1, ends at F = T+p.numverts - loopi(p.numverts-1) - { + loopi(p.numverts-1) { if(index >= p.numverts) index -= p.numverts; verts[numverts++] = p.verts[index++]; } index = qe+2; // starts at C = T+2 = F+1, ends at T = T+q.numverts int px = int(verts[numverts-1].x) - int(verts[numverts-2].x), py = int(verts[numverts-1].y) - int(verts[numverts-2].y); - loopi(q.numverts-1) - { + loopi(q.numverts-1) { if(index >= q.numverts) index -= q.numverts; pvert &src = q.verts[index++]; int cx = int(src.x) - int(verts[numverts-1].x), cy = int(src.y) - int(verts[numverts-1].y), @@ -1627,19 +1377,14 @@ bool mergepolys(int orient, hashset &links, vector &queue, int o dir = px*cy - py*cx; if(dir > 0) return false; if(!dir) numverts--; - if(numverts > MAXFACEVERTS) return false; - q.merged = true; q.numverts = 0; - p.merged = true; p.numverts = numverts; memcpy(p.verts, verts, numverts*sizeof(pvert)); - int prev = p.numverts-1; - loopj(p.numverts) - { + loopj(p.numverts) { pedge e(p.verts[prev], p.verts[j]); int order = e.from.x > e.to.x || (e.from.x == e.to.x && e.from.y > e.to.y) ? 1 : 0; if(order) swap(e.from, e.to); @@ -1649,15 +1394,12 @@ bool mergepolys(int orient, hashset &links, vector &queue, int o if(shouldqueue) queue.add(&l); prev = j; } - return true; } -void addmerge(cube &cu, int orient, const ivec &co, const ivec &n, int offset, poly &p) -{ +void addmerge(cube &cu, int orient, const ivec &co, const ivec &n, int offset, poly &p) { cu.merged |= 1<surfaces[orient] = ambientsurface; return; } @@ -1665,8 +1407,7 @@ void addmerge(cube &cu, int orient, const ivec &co, const ivec &n, int offset, p vertinfo verts[MAXFACEVERTS]; surf.numverts |= p.numverts; int dim = dimension(orient), coord = dimcoord(orient), c = C[dim], r = R[dim]; - loopk(p.numverts) - { + loopk(p.numverts) { pvert &src = p.verts[coord ? k : p.numverts-1-k]; vertinfo &dst = verts[k]; ivec v; @@ -1675,18 +1416,14 @@ void addmerge(cube &cu, int orient, const ivec &co, const ivec &n, int offset, p v[dim] = -(offset + n[c]*src.x + n[r]*src.y)/n[dim]; dst.set(v); } - if(cu.ext) - { + if(cu.ext) { const surfaceinfo &oldsurf = cu.ext->surfaces[orient]; int numverts = oldsurf.numverts&MAXFACEVERTS; - if(numverts == p.numverts) - { + if(numverts == p.numverts) { ivec v0 = verts[0].getxyz(); const vertinfo *oldverts = cu.ext->verts() + oldsurf.verts; - loopj(numverts) if(v0 == oldverts[j].getxyz()) - { - for(int k = 1; k < numverts; k++) - { + loopj(numverts) if(v0 == oldverts[j].getxyz()) { + for(int k = 1; k < numverts; k++) { if(++j >= numverts) j = 0; if(verts[k].getxyz() != oldverts[j].getxyz()) goto nomatch; } @@ -1698,36 +1435,29 @@ void addmerge(cube &cu, int orient, const ivec &co, const ivec &n, int offset, p setsurface(cu, orient, surf, verts, p.numverts); } -static inline void clearmerge(cube &c, int orient) -{ - if(c.merged&(1<surfaces[orient] = brightsurface; } } -void addmerges(int orient, const ivec &co, const ivec &n, int offset, vector &polys) -{ - loopv(polys) - { +void addmerges(int orient, const ivec &co, const ivec &n, int offset, vector &polys) { + loopv(polys) { poly &p = polys[i]; if(p.merged) addmerge(*p.c, orient, co, n, offset, p); else clearmerge(*p.c, orient); } } -void mergepolys(int orient, const ivec &co, const ivec &n, int offset, vector &polys) -{ +void mergepolys(int orient, const ivec &co, const ivec &n, int offset, vector &polys) { if(polys.length() <= 1) { addmerges(orient, co, n, offset, polys); return; } hashset links(polys.length() <= 32 ? 128 : 1024); vector queue; - loopv(polys) - { + loopv(polys) { poly &p = polys[i]; int prev = p.numverts-1; - loopj(p.numverts) - { + loopj(p.numverts) { pedge e(p.verts[prev], p.verts[j]); int order = e.from.x > e.to.x || (e.from.x == e.to.x && e.from.y > e.to.y) ? 1 : 0; if(order) swap(e.from, e.to); @@ -1738,10 +1468,8 @@ void mergepolys(int orient, const ivec &co, const ivec &n, int offset, vector nextqueue; - while(queue.length()) - { - loopv(queue) - { + while(queue.length()) { + loopv(queue) { plink &l = *queue[i]; if(l.polys[0] >= 0 && l.polys[1] >= 0) mergepolys(orient, links, nextqueue, l.polys[0], polys[l.polys[0]], polys[l.polys[1]], l); @@ -1754,30 +1482,24 @@ void mergepolys(int orient, const ivec &co, const ivec &n, int offset, vector polys; }; static hashtable cpolys; -void genmerges(cube *c = worldroot, const ivec &o = ivec(0, 0, 0), int size = worldsize>>1) -{ +void genmerges(cube *c = worldroot, const ivec &o = ivec(0, 0, 0), int size = worldsize>>1) { if((genmergeprogress++&0xFFF)==0) renderprogress(float(genmergeprogress)/allocnodes, "merging faces..."); neighbourstack[++neighbourdepth] = c; - loopi(8) - { + loopi(8) { ivec co(i, o, size); int vis; if(c[i].children) genmerges(c[i].children, co, size>>1); - else if(!isempty(c[i])) loopj(6) if((vis = visibletris(c[i], j, co, size))) - { + else if(!isempty(c[i])) loopj(6) if((vis = visibletris(c[i], j, co, size))) { cfkey k; poly p; - if(size < 1<= 1<= 1<= x2 && mo.y <= y1 && mo.y + (1<= y2 && @@ -1839,17 +1554,13 @@ int calcmergedsize(int orient, const ivec &co, int size, const vertinfo *verts, return bits-3; } -static void invalidatemerges(cube &c) -{ - if(c.merged) - { +static void invalidatemerges(cube &c) { + if(c.merged) { brightencube(c); c.merged = 0; } - if(c.ext) - { - if(c.ext->va) - { + if(c.ext) { + if(c.ext->va) { if(!(c.ext->va->hasmerges&(MERGE_PART | MERGE_ORIGIN))) return; destroyva(c.ext->va); c.ext->va = NULL; @@ -1861,18 +1572,15 @@ static void invalidatemerges(cube &c) static int invalidatedmerges = 0; -void invalidatemerges(cube &c, const ivec &co, int size, bool msg) -{ - if(msg && invalidatedmerges!=totalmillis) - { +void invalidatemerges(cube &c, const ivec &co, int size, bool msg) { + if(msg && invalidatedmerges!=totalmillis) { renderprogress(0, "invalidating merged surfaces..."); invalidatedmerges = totalmillis; } invalidatemerges(c); } -void calcmerges() -{ +void calcmerges() { genmergeprogress = 0; genmerges(); } diff --git a/src/engine/octa.h b/src/engine/octa.h index 9452ad0..d8a2c45 100644 --- a/src/engine/octa.h +++ b/src/engine/octa.h @@ -1,34 +1,28 @@ // 6-directional octree heightfield map format -struct elementset -{ +struct elementset { ushort texture, lmid; uchar dim, layer; ushort length[2], minvert[2], maxvert[2]; }; -struct materialsurface -{ +struct materialsurface { ivec o; ushort csize, rsize; ushort material, skip; uchar orient, visible; - union - { + union { short index; short depth; }; - union - { + union { entity *light; uchar ends; }; }; -struct vertinfo -{ +struct vertinfo { ushort x, y, z, u, v, norm; - void setxyz(ushort a, ushort b, ushort c) { x = a; y = b; z = c; } void setxyz(const ivec &v) { setxyz(v.x, v.y, v.z); } void set(ushort a, ushort b, ushort c, ushort s = 0, ushort t = 0, ushort n = 0) { setxyz(a, b, c); u = s; v = t; norm = n; } @@ -36,24 +30,19 @@ struct vertinfo ivec getxyz() const { return ivec(x, y, z); } }; -enum -{ +enum { LAYER_TOP = (1<<5), LAYER_BOTTOM = (1<<6), LAYER_DUP = (1<<7), - LAYER_BLEND = LAYER_TOP|LAYER_BOTTOM, - MAXFACEVERTS = 15 }; enum { LMID_AMBIENT = 0, LMID_AMBIENT1, LMID_BRIGHT, LMID_BRIGHT1, LMID_DARK, LMID_DARK1, LMID_RESERVED }; -struct surfaceinfo -{ +struct surfaceinfo { uchar lmid[2]; uchar verts, numverts; - int totalverts() const { return numverts&LAYER_DUP ? (numverts&MAXFACEVERTS)*2 : numverts&MAXFACEVERTS; } bool used() const { return lmid[0] != LMID_AMBIENT || lmid[1] != LMID_AMBIENT || numverts&~LAYER_TOP; } void clear() { lmid[0] = LMID_AMBIENT; lmid[1] = LMID_AMBIENT; numverts = (numverts&MAXFACEVERTS) | LAYER_TOP; } @@ -64,8 +53,7 @@ static const surfaceinfo ambientsurface = {{LMID_AMBIENT, LMID_AMBIENT}, 0, LAYE static const surfaceinfo brightsurface = {{LMID_BRIGHT, LMID_AMBIENT}, 0, LAYER_TOP}; static const surfaceinfo brightbottomsurface = {{LMID_AMBIENT, LMID_BRIGHT}, 0, LAYER_BOTTOM}; -struct occludequery -{ +struct occludequery { void *owner; GLuint id; int fragments; @@ -73,8 +61,7 @@ struct occludequery struct vtxarray; -struct octaentities -{ +struct octaentities { vector mapmodels; vector other; occludequery *query; @@ -83,30 +70,25 @@ struct octaentities ivec o; int size; ivec bbmin, bbmax; - - octaentities(const ivec &o, int size) : query(0), o(o), size(size), bbmin(o), bbmax(o) - { + octaentities(const ivec &o, int size) : query(0), o(o), size(size), bbmin(o), bbmax(o) { bbmin.add(size); } }; -enum -{ +enum { OCCLUDE_NOTHING = 0, OCCLUDE_GEOM, OCCLUDE_BB, OCCLUDE_PARENT }; -enum -{ +enum { MERGE_ORIGIN = 1<<0, MERGE_PART = 1<<1, MERGE_USE = 1<<2 }; -struct vtxarray -{ +struct vtxarray { vtxarray *parent; vector children; vtxarray *next, *rnext; // linked list of visible VOBs @@ -134,8 +116,7 @@ struct vtxarray struct cube; -struct clipplanes -{ +struct clipplanes { vec o, r, v[8]; plane p[12]; uchar side[12]; @@ -144,37 +125,30 @@ struct clipplanes int version; }; -struct facebounds -{ +struct facebounds { ushort u1, u2, v1, v2; - bool empty() const { return u1 >= u2 || v1 >= v2; } }; -struct tjoint -{ +struct tjoint { int next; ushort offset; uchar edge; }; -struct cubeext -{ +struct cubeext { vtxarray *va; // vertex array for children, or NULL octaentities *ents; // map entities inside cube surfaceinfo surfaces[6]; // render info for each surface int tjoints; // linked list of t-joints uchar maxverts; // allocated space for verts - vertinfo *verts() { return (vertinfo *)(this+1); } }; -struct cube -{ +struct cube { cube *children; // points to 8 cube structures which are its children, or NULL. -Z first, then -Y, -X cubeext *ext; // extended info for the cube - union - { + union { uchar edges[12]; // edges of the cube, each uchar is 2 4bit values denoting the range. // see documentation jpgs for more info. uint faces[3]; // 4 edges of each dimension together representing 2 perpendicular faces @@ -182,38 +156,32 @@ struct cube ushort texture[6]; // one for each face. same order as orient. ushort material; // empty-space material uchar merged; // merged faces of the cube - union - { + union { uchar escaped; // mask of which children have escaped merges uchar visible; // visibility info for faces }; }; -struct block3 -{ +struct block3 { ivec o, s; int grid, orient; block3() {} block3(const selinfo &sel) : o(sel.o), s(sel.s), grid(sel.grid), orient(sel.orient) {} - cube *c() { return (cube *)(this+1); } + cube *c() { return (cube *)(this+1); } int size() const { return s.x*s.y*s.z; } }; -struct editinfo -{ +struct editinfo { block3 *copy; editinfo() : copy(NULL) {} }; -struct undoent { int i; entity e; }; -struct undoblock // undo header, all data sits in payload -{ +struct undoent { int i; entity e; }; +struct undoblock { // undo header, all data sits in payload { undoblock *prev, *next; int size, timestamp, numents; // if numents is 0, is a cube undo record, otherwise an entity undo record - block3 *block() { return (block3 *)(this + 1); } - uchar *gridmap() - { + uchar *gridmap() { block3 *ub = block(); return (uchar *)(ub->c() + ub->size()); } @@ -245,8 +213,7 @@ const uint F_SOLID = 0x80808080; // all edges in the range (0,8) #define octaindex(d,x,y,z) (((z)<>(scale))&1)<<2) | ((((y)>>(scale))&1)<<1) | (((x)>>(scale))&1)) -static inline uchar octaboxoverlap(const ivec &o, int size, const ivec &bbmin, const ivec &bbmax) -{ +static inline uchar octaboxoverlap(const ivec &o, int size, const ivec &bbmin, const ivec &bbmax) { uchar p = 0xFF; // bitmask of possible collisions with octants. 0 bit = 0 octant, etc ivec mid = ivec(o).add(size); if(mid.z <= bbmin.z) p &= 0xF0; // not in a -ve Z octant @@ -261,8 +228,7 @@ static inline uchar octaboxoverlap(const ivec &o, int size, const ivec &bbmin, c #define loopoctabox(o, size, bbmin, bbmax) uchar possible = octaboxoverlap(o, size, bbmin, bbmax); loopi(8) if(possible&(1<0 ? 0.2f : -0.2f) : 0; o[D[d]] += dc * s[D[d]] + f; - vec r(0, 0, 0), c(0, 0, 0); r[R[d]] = s[R[d]]; c[C[d]] = s[C[d]]; - vec v1 = o, v2 = vec(o).add(r), v3 = vec(o).add(r).add(c), v4 = vec(o).add(c); - r[R[d]] = 0.5f*size; c[C[d]] = 0.5f*size; - gle::defvertex(); gle::begin(GL_TRIANGLE_STRIP); gle::attrib(vec(v1).sub(r).sub(c)); @@ -34,53 +29,43 @@ void boxs(int orient, vec o, const vec &s, float size) xtraverts += gle::end(); } -void boxs(int orient, vec o, const vec &s) -{ +void boxs(int orient, vec o, const vec &s) { int d = dimension(orient), dc = dimcoord(orient); float f = boxoutline ? (dc>0 ? 0.2f : -0.2f) : 0; o[D[d]] += dc * s[D[d]] + f; - gle::defvertex(); gle::begin(GL_LINE_LOOP); - gle::attrib(o); o[R[d]] += s[R[d]]; gle::attrib(o); o[C[d]] += s[C[d]]; gle::attrib(o); o[R[d]] -= s[R[d]]; gle::attrib(o); - xtraverts += gle::end(); } -void boxs3D(const vec &o, vec s, int g) -{ +void boxs3D(const vec &o, vec s, int g) { s.mul(g); loopi(6) boxs(i, o, s); } -void boxsgrid(int orient, vec o, vec s, int g) -{ +void boxsgrid(int orient, vec o, vec s, int g) { int d = dimension(orient), dc = dimcoord(orient); float ox = o[R[d]], oy = o[C[d]], xs = s[R[d]], ys = s[C[d]], f = boxoutline ? (dc>0 ? 0.2f : -0.2f) : 0; - o[D[d]] += dc * s[D[d]]*g + f; - gle::defvertex(); gle::begin(GL_LINES); - loop(x, xs) - { + loop(x, xs) { o[R[d]] += g; gle::attrib(o); o[C[d]] += ys*g; gle::attrib(o); o[C[d]] = oy; } - loop(y, ys) - { + loop(y, ys) { o[C[d]] += g; o[R[d]] = ox; gle::attrib(o); @@ -112,18 +97,15 @@ VARF(dragging, 0, 0, 1, ); int moving = 0; -ICOMMAND(moving, "b", (int *n), -{ - if(*n >= 0) - { +ICOMMAND(moving, "b", (int *n), { + if(*n >= 0) { if(!*n || (moving<=1 && !pointinsel(sel, vec(cur).add(1)))) moving = 0; else if(!moving) moving = 1; } intret(moving); }); -VARF(gridpower, 0, 3, 12, -{ +VARF(gridpower, 0, 3, 12, { if(dragging) return; gridsize = 1<=worldsize) gridsize = worldsize/2; @@ -136,35 +118,29 @@ VAR(selectcorners, 0, 0, 1); void forcenextundo() { lastsel.orient = -1; } -void cubecancel() -{ +void cubecancel() { havesel = false; moving = dragging = passthroughsel = 0; forcenextundo(); } -void cancelsel() -{ +void cancelsel() { cubecancel(); entcancel(); } -void toggleedit(bool force) -{ - if(!force) - { +void toggleedit(bool force) { + if(!force) { if(!isconnected()) return; if(player->state!=CS_ALIVE && player->state!=CS_DEAD && player->state!=CS_EDITING) return; // do not allow dead players to edit to avoid state confusion if(!game::allowedittoggle()) return; // not in most multiplayer modes } - if(!(editmode = !editmode)) - { + if(!(editmode = !editmode)) { player->state = player->editstate; player->o.z -= player->eyeheight; // entinmap wants feet pos entinmap(player); // find spawn closest to current floating pos } - else - { + else { game::resetgamestate(); player->editstate = player->state; player->state = CS_EDITING; @@ -179,8 +155,7 @@ void toggleedit(bool force) VARP(editinview, 0, 1, 1); -bool noedit(bool view, bool msg) -{ +bool noedit(bool view, bool msg) { if(!editmode) { if(msg) conoutf(CON_ERROR, "operation only allowed in edit mode"); return true; } if(view || haveselent()) return false; float r = 1.0f; @@ -194,8 +169,7 @@ bool noedit(bool view, bool msg) return true; } -void reorient() -{ +void reorient() { sel.cx = 0; sel.cy = 0; sel.cxs = sel.s[R[dimension(orient)]]*2; @@ -203,18 +177,14 @@ void reorient() sel.orient = orient; } -void selextend() -{ +void selextend() { if(noedit(true)) return; - loopi(3) - { - if(cur[i]=sel.o[i]+sel.s[i]*sel.grid) - { + else if(cur[i]>=sel.o[i]+sel.s[i]*sel.grid) { sel.s[i] = (cur[i]-sel.o[i])/sel.grid+1; } } @@ -232,23 +202,20 @@ ICOMMAND(selsave, "", (), { if(noedit(true)) return; savedsel = sel; }); ICOMMAND(selrestore, "", (), { if(noedit(true)) return; sel = savedsel; }); ICOMMAND(selswap, "", (), { if(noedit(true)) return; swap(sel, savedsel); }); -ICOMMAND(getselpos, "", (), -{ +ICOMMAND(getselpos, "", (), { if(noedit(true)) return; defformatstring(pos, "%s %s %s", floatstr(sel.o.x), floatstr(sel.o.y), floatstr(sel.o.z)); result(pos); }); -void setselpos(int *x, int *y, int *z) -{ +void setselpos(int *x, int *y, int *z) { if(noedit(moving!=0)) return; havesel = true; sel.o = ivec(*x, *y, *z).mask(~(gridsize-1)); } COMMAND(setselpos, "iii"); -void movesel(int *dir, int *dim) -{ +void movesel(int *dir, int *dim) { if(noedit(moving!=0)) return; if(*dim < 0 || *dim > 2) return; sel.o[*dim] += *dir * sel.grid; @@ -257,8 +224,7 @@ COMMAND(movesel, "ii"); ///////// selection support ///////////// -cube &blockcube(int x, int y, int z, const block3 &b, int rgrid) // looks up a world cube, based on coordinates mapped by the block -{ +cube &blockcube(int x, int y, int z, const block3 &b, int rgrid) { // looks up a world cube, based on coordinates mapped by the block { int dim = dimension(b.orient), dc = dimcoord(b.orient); ivec s(dim, x*b.grid, y*b.grid, dc*(b.s[dim]-1)*b.grid); s.add(b.o); @@ -277,18 +243,14 @@ int selchildcount = 0, selchildmat = -1; ICOMMAND(havesel, "", (), intret(havesel ? selchildcount : 0)); -void countselchild(cube *c, const ivec &cor, int size) -{ +void countselchild(cube *c, const ivec &cor, int size) { ivec ss = ivec(sel.s).mul(sel.grid); - loopoctaboxsize(cor, size, sel.o, ss) - { + loopoctaboxsize(cor, size, sel.o, ss) { ivec o(i, cor, size); if(c[i].children) countselchild(c[i].children, o, size/2); - else - { + else { selchildcount++; - if(c[i].material != MAT_AIR && selchildmat != MAT_AIR) - { + if(c[i].material != MAT_AIR && selchildmat != MAT_AIR) { if(selchildmat < 0) selchildmat = c[i].material; else if(selchildmat != c[i].material) selchildmat = MAT_AIR; } @@ -296,16 +258,13 @@ void countselchild(cube *c, const ivec &cor, int size) } } -void normalizelookupcube(const ivec &o) -{ - if(lusize>gridsize) - { +void normalizelookupcube(const ivec &o) { + if(lusize>gridsize) { lu.x += (o.x-lu.x)/gridsize*gridsize; lu.y += (o.y-lu.y)/gridsize*gridsize; lu.z += (o.z-lu.z)/gridsize*gridsize; } - else if(gridsize>lusize) - { + else if(gridsize>lusize) { lu.x &= ~(gridsize-1); lu.y &= ~(gridsize-1); lu.z &= ~(gridsize-1); @@ -313,8 +272,7 @@ void normalizelookupcube(const ivec &o) lusize = gridsize; } -void updateselection() -{ +void updateselection() { sel.o.x = min(lastcur.x, cur.x); sel.o.y = min(lastcur.y, cur.y); sel.o.z = min(lastcur.z, cur.z); @@ -323,13 +281,11 @@ void updateselection() sel.s.z = abs(lastcur.z-cur.z)/sel.grid+1; } -bool editmoveplane(const vec &o, const vec &ray, int d, float off, vec &handle, vec &dest, bool first) -{ +bool editmoveplane(const vec &o, const vec &ray, int d, float off, vec &handle, vec &dest, bool first) { plane pl(d, off); float dist = 0.0f; if(!pl.rayintersect(player->o, ray, dist)) return false; - dest = vec(ray).mul(dist).add(player->o); if(first) handle = vec(dest).sub(o); dest.sub(handle); @@ -338,7 +294,7 @@ bool editmoveplane(const vec &o, const vec &ray, int d, float off, vec &handle, extern void entdrag(const vec &ray); extern bool hoveringonent(int ent, int orient); -extern void renderentselection(const vec &o, const vec &ray, bool entmoving); +extern void renderentselection(const vec &o, bool entmoving); extern float rayent(const vec &o, const vec &ray, float radius, int mode, int size, int &orient, int &ent); VAR(gridlookup, 0, 0, 1); @@ -346,21 +302,15 @@ VAR(passthroughcube, 0, 1, 1); VAR(passthroughent, 0, 1, 1); VARF(passthrough, 0, 0, 1, { passthroughsel = passthrough; entcancel(); }); -void rendereditcursor() -{ +void rendereditcursor() { int d = dimension(sel.orient), od = dimension(orient), odc = dimcoord(orient); - bool hidecursor = g3d_windowhit(true, false), hovering = false; - - if(moving) - { + if(moving) { static vec dest, handle; - if(editmoveplane(vec(sel.o), camdir, od, sel.o[D[od]]+odc*sel.grid*sel.s[D[od]], handle, dest, moving==1)) - { - if(moving==1) - { + if(editmoveplane(vec(sel.o), camdir, od, sel.o[D[od]]+odc*sel.grid*sel.s[D[od]], handle, dest, moving==1)) { + if(moving==1) { dest.add(handle); handle = vec(ivec(handle).mask(~(sel.grid-1))); dest.sub(handle); @@ -372,50 +322,40 @@ void rendereditcursor() } } else - if(entmoving) - { + if(entmoving) { entdrag(camdir); } - else - { + else { ivec w; float sdist = 0, wdist = 0, t; int entorient = 0, ent = -1; - wdist = rayent(player->o, camdir, 1e16f, (editmode && showmat ? RAY_EDITMAT : 0) // select cubes first | (!dragging && entediting && (!passthrough || !passthroughent) ? RAY_ENTS : 0) | RAY_SKIPFIRST | (passthroughcube || passthrough ? RAY_PASS : 0), gridsize, entorient, ent); - if((havesel || dragging) && !passthroughsel) // now try selecting the selection - if(rayboxintersect(vec(sel.o), vec(sel.s).mul(sel.grid), player->o, camdir, sdist, orient)) - { // and choose the nearest of the two - if(sdist < wdist) - { + if(rayboxintersect(vec(sel.o), vec(sel.s).mul(sel.grid), player->o, camdir, sdist, orient)) { + // and choose the nearest of the two + if(sdist < wdist) { wdist = sdist; ent = -1; } } - - if((hovering = hoveringonent(hidecursor ? -1 : ent, entorient))) - { + if((hovering = hoveringonent(hidecursor ? -1 : ent, entorient))) { if(!havesel) - { + { selchildcount = 0; selchildmat = -1; sel.s = ivec(0, 0, 0); } } - else - { + else { vec w = vec(camdir).mul(wdist+0.05f).add(player->o); - if(!insideworld(w)) - { + if(!insideworld(w)) { loopi(3) wdist = min(wdist, ((camdir[i] > 0 ? worldsize : 0) - player->o[i]) / camdir[i]); w = vec(camdir).mul(wdist-0.05f).add(player->o); - if(!insideworld(w)) - { + if(!insideworld(w)) { wdist = 0; loopi(3) w[i] = clamp(player->o[i], 0.0f, float(worldsize)); } @@ -429,17 +369,13 @@ void rendereditcursor() cor = ivec(vec(w).mul(2).div(gridsize)); od = dimension(orient); d = dimension(sel.orient); - - if(dragging) - { + if(dragging) { updateselection(); sel.cx = min(cor[R[d]], lastcor[R[d]]); sel.cy = min(cor[C[d]], lastcor[C[d]]); sel.cxs = max(cor[R[d]], lastcor[R[d]]); sel.cys = max(cor[C[d]], lastcor[C[d]]); - - if(!selectcorners) - { + if(!selectcorners) { sel.cx &= ~1; sel.cy &= ~1; sel.cxs &= ~1; @@ -447,18 +383,15 @@ void rendereditcursor() sel.cxs -= sel.cx-2; sel.cys -= sel.cy-2; } - else - { + else { sel.cxs -= sel.cx-1; sel.cys -= sel.cy-1; } - sel.cx &= 1; sel.cy &= 1; havesel = true; } - else if(!havesel) - { + else if(!havesel) { sel.o = lu; sel.s.x = sel.s.y = sel.s.z = 1; sel.cx = sel.cy = 0; @@ -467,41 +400,29 @@ void rendereditcursor() sel.orient = orient; d = od; } - sel.corner = (cor[R[d]]-(lu[R[d]]*2)/gridsize)+(cor[C[d]]-(lu[C[d]]*2)/gridsize)*2; selchildcount = 0; selchildmat = -1; countselchild(worldroot, ivec(0, 0, 0), worldsize/2); - if(mag>=1 && selchildcount==1) - { + if(mag>=1 && selchildcount==1) { selchildmat = c->material; if(mag>1) selchildcount = -mag; } } } - glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); - // cursors - notextureshader->set(); - - renderentselection(player->o, camdir, entmoving!=0); - + renderentselection(player->o, entmoving!=0); boxoutline = outline!=0; - enablepolygonoffset(GL_POLYGON_OFFSET_LINE); - - if(!moving && !hovering && !hidecursor) - { + if(!moving && !hovering && !hidecursor) { gle::colorub(120,120,120); boxs(orient, vec(lu), vec(lusize)); } - // selections - if(havesel || moving) - { + if(havesel || moving) { d = dimension(sel.orient); gle::colorub(50,50,50); // grid boxsgrid(sel.orient, vec(sel.o), vec(sel.s), sel.grid); @@ -518,16 +439,12 @@ void rendereditcursor() gle::colorub(0,0,120); boxs3D(vec(sel.o), vec(sel.s), sel.grid); } - disablepolygonoffset(GL_POLYGON_OFFSET_LINE); - boxoutline = false; - glDisable(GL_BLEND); } -void tryedit() -{ +void tryedit() { extern int hidehud; if(!editmode || hidehud || mainmenu) return; } @@ -536,15 +453,11 @@ void tryedit() static bool haschanged = false; -void readychanges(const ivec &bbmin, const ivec &bbmax, cube *c, const ivec &cor, int size) -{ - loopoctabox(cor, size, bbmin, bbmax) - { +void readychanges(const ivec &bbmin, const ivec &bbmax, cube *c, const ivec &cor, int size) { + loopoctabox(cor, size, bbmin, bbmax) { ivec o(i, cor, size); - if(c[i].ext) - { - if(c[i].ext->va) // removes va s so that octarender will recreate - { + if(c[i].ext) { + if(c[i].ext->va) { // removes va s so that octarender will recreate { int hasmerges = c[i].ext->va->hasmerges; destroyva(c[i].ext->va); c[i].ext->va = NULL; @@ -553,10 +466,8 @@ void readychanges(const ivec &bbmin, const ivec &bbmax, cube *c, const ivec &cor freeoctaentities(c[i]); c[i].ext->tjoints = -1; } - if(c[i].children) - { - if(size<=1) - { + if(c[i].children) { + if(size<=1) { solidfaces(c[i]); discardchildren(c[i], true); brightencube(c[i]); @@ -567,11 +478,9 @@ void readychanges(const ivec &bbmin, const ivec &bbmax, cube *c, const ivec &cor } } -void commitchanges(bool force) -{ +void commitchanges(bool force) { if(!force && !haschanged) return; haschanged = false; - int oldlen = valist.length(); resetclipplanes(); entitiesinoctanodes(); @@ -582,44 +491,37 @@ void commitchanges(bool force) updatevabbs(); } -void changed(const block3 &sel, bool commit = true) -{ +void changed(const block3 &sel, bool commit = true) { if(sel.s.iszero()) return; readychanges(ivec(sel.o).sub(1), ivec(sel.s).mul(sel.grid).add(sel.o).add(1), worldroot, ivec(0, 0, 0), worldsize/2); haschanged = true; - if(commit) commitchanges(); } //////////// copy and undo ///////////// -static inline void copycube(const cube &src, cube &dst) -{ +static inline void copycube(const cube &src, cube &dst) { dst = src; dst.visible = 0; dst.merged = 0; dst.ext = NULL; // src cube is responsible for va destruction - if(src.children) - { + if(src.children) { dst.children = newcubes(F_EMPTY); loopi(8) copycube(src.children[i], dst.children[i]); } } -static inline void pastecube(const cube &src, cube &dst) -{ +static inline void pastecube(const cube &src, cube &dst) { discardchildren(dst); copycube(src, dst); } -void blockcopy(const block3 &s, int rgrid, block3 *b) -{ +void blockcopy(const block3 &s, int rgrid, block3 *b) { *b = s; cube *q = b->c(); loopxyz(s, rgrid, copycube(c, *q++)); } -block3 *blockcopy(const block3 &s, int rgrid) -{ +block3 *blockcopy(const block3 &s, int rgrid) { int bsize = sizeof(block3)+sizeof(cube)*s.size(); if(bsize <= 0 || bsize > (100<<20)) return NULL; block3 *b = (block3 *)new (false) uchar[bsize]; @@ -627,41 +529,34 @@ block3 *blockcopy(const block3 &s, int rgrid) return b; } -void freeblock(block3 *b, bool alloced = true) -{ +void freeblock(block3 *b, bool alloced = true) { cube *q = b->c(); loopi(b->size()) discardchildren(*q++); if(alloced) delete[] b; } -void selgridmap(selinfo &sel, uchar *g) // generates a map of the cube sizes at each grid point -{ +void selgridmap(selinfo &sel, uchar *g) { // generates a map of the cube sizes at each grid point { loopxyz(sel, -sel.grid, (*g++ = bitscan(lusize), (void)c)); } -void freeundo(undoblock *u) -{ +void freeundo(undoblock *u) { if(!u->numents) freeblock(u->block(), false); delete[] (uchar *)u; } -void pasteundoblock(block3 *b, uchar *g) -{ +void pasteundoblock(block3 *b, uchar *g) { cube *s = b->c(); loopxyz(*b, 1<numents) pasteundoents(u); else pasteundoblock(u->block(), u->gridmap()); } -static inline int undosize(undoblock *u) -{ +static inline int undosize(undoblock *u) { if(u->numents) return u->numents*sizeof(undoent); - else - { + else { block3 *b = u->block(); cube *q = b->c(); int size = b->size(), total = size; @@ -670,37 +565,27 @@ static inline int undosize(undoblock *u) } } -struct undolist -{ +struct undolist { undoblock *first, *last; - undolist() : first(NULL), last(NULL) {} - bool empty() { return !first; } - - void add(undoblock *u) - { + void add(undoblock *u) { u->next = NULL; u->prev = last; if(!first) first = last = u; - else - { + else { last->next = u; last = u; } } - - undoblock *popfirst() - { + undoblock *popfirst() { undoblock *u = first; first = first->next; if(first) first->prev = NULL; else last = NULL; return u; } - - undoblock *poplast() - { + undoblock *poplast() { undoblock *u = last; last = last->prev; if(last) last->next = NULL; @@ -713,17 +598,14 @@ undolist undos, redos; VARP(undomegs, 0, 8, 100); // bounded by n megs int totalundos = 0; -void pruneundos(int maxremain) // bound memory -{ - while(totalundos > maxremain && !undos.empty()) - { +void pruneundos(int maxremain) { // bound memory { + while(totalundos > maxremain && !undos.empty()) { undoblock *u = undos.popfirst(); totalundos -= u->size; freeundo(u); } //conoutf(CON_DEBUG, "undo: %d of %d(%%%d)", totalundos, undomegs<<20, totalundos*100/(undomegs<<20)); - while(!redos.empty()) - { + while(!redos.empty()) { undoblock *u = redos.popfirst(); totalundos -= u->size; freeundo(u); @@ -734,8 +616,7 @@ void clearundos() { pruneundos(0); } COMMAND(clearundos, ""); -undoblock *newundocube(selinfo &s) -{ +undoblock *newundocube(selinfo &s) { int ssize = s.size(), selgridsize = ssize, blocksize = sizeof(block3)+ssize*sizeof(cube); @@ -750,8 +631,7 @@ undoblock *newundocube(selinfo &s) return u; } -void addundo(undoblock *u) -{ +void addundo(undoblock *u) { u->size = undosize(u); u->timestamp = totalmillis; undos.add(u); @@ -761,21 +641,18 @@ void addundo(undoblock *u) VARP(nompedit, 0, 1, 1); -void makeundo(selinfo &s) -{ +void makeundo(selinfo &s) { undoblock *u = newundocube(s); if(u) addundo(u); } -void makeundo() // stores state of selected cubes before editing -{ +void makeundo() { // stores state of selected cubes before editing { if(lastsel==sel || sel.s.iszero()) return; lastsel=sel; makeundo(sel); } -static inline int countblock(cube *c, int n = 8) -{ +static inline int countblock(cube *c, int n = 8) { int r = 0; loopi(n) if(c[i].children) r += countblock(c[i].children); else ++r; return r; @@ -783,20 +660,16 @@ static inline int countblock(cube *c, int n = 8) static int countblock(block3 *b) { return countblock(b->c(), b->size()); } -void swapundo(undolist &a, undolist &b, int op) -{ +void swapundo(undolist &a, undolist &b, int op) { if(noedit()) return; if(a.empty()) { conoutf(CON_WARN, "nothing more to %s", op == EDIT_REDO ? "redo" : "undo"); return; } int ts = a.last->timestamp; - if(multiplayer(false)) - { + if(multiplayer(false)) { int n = 0, ops = 0; - for(undoblock *u = a.last; u && ts==u->timestamp; u = u->prev) - { + for(undoblock *u = a.last; u && ts==u->timestamp; u = u->prev) { ++ops; n += u->numents ? u->numents : countblock(u->block()); - if(ops > 10 || n > 2500) - { + if(ops > 10 || n > 2500) { conoutf(CON_WARN, "undo too big for multiplayer"); if(nompedit) { multiplayer(); return; } op = -1; @@ -805,13 +678,11 @@ void swapundo(undolist &a, undolist &b, int op) } } selinfo l = sel; - while(!a.empty() && ts==a.last->timestamp) - { + while(!a.empty() && ts==a.last->timestamp) { if(op >= 0) game::edittrigger(sel, op); undoblock *u = a.poplast(), *r; if(u->numents) r = copyundoents(u); - else - { + else { block3 *ub = u->block(); l.o = ub->o; l.s = ub->s; @@ -819,8 +690,7 @@ void swapundo(undolist &a, undolist &b, int op) l.orient = ub->orient; r = newundocube(l); } - if(r) - { + if(r) { r->size = u->size; r->timestamp = totalmillis; b.add(r); @@ -845,15 +715,12 @@ vector editinfos; editinfo *localedit = NULL; template -static void packcube(cube &c, B &buf) -{ - if(c.children) - { +static void packcube(cube &c, B &buf) { + if(c.children) { buf.put(0xFF); loopi(8) packcube(c.children[i], buf); } - else - { + else { cube data = c; lilswap(data.texture, 6); buf.put(c.material&0xFF); @@ -864,8 +731,7 @@ static void packcube(cube &c, B &buf) } template -static bool packblock(block3 &b, B &buf) -{ +static bool packblock(block3 &b, B &buf) { if(b.size() <= 0 || b.size() > (1<<20)) return false; block3 hdr = b; lilswap(hdr.o.v, 3); @@ -878,23 +744,18 @@ static bool packblock(block3 &b, B &buf) return true; } -struct vslothdr -{ +struct vslothdr { ushort index; ushort slot; }; -static void packvslots(cube &c, vector &buf, vector &used) -{ - if(c.children) - { +static void packvslots(cube &c, vector &buf, vector &used) { + if(c.children) { loopi(8) packvslots(c.children[i], buf, used); } - else loopi(6) - { + else loopi(6) { ushort index = c.texture[i]; - if(vslots.inrange(index) && vslots[index]->changed && used.find(index) < 0) - { + if(vslots.inrange(index) && vslots[index]->changed && used.find(index) < 0) { used.add(index); VSlot &vs = *vslots[index]; vslothdr &hdr = *(vslothdr *)buf.pad(sizeof(vslothdr)); @@ -906,8 +767,7 @@ static void packvslots(cube &c, vector &buf, vector &used) } } -static void packvslots(block3 &b, vector &buf) -{ +static void packvslots(block3 &b, vector &buf) { vector used; cube *c = b.c(); loopi(b.size()) packvslots(c[i], buf, used); @@ -915,16 +775,13 @@ static void packvslots(block3 &b, vector &buf) } template -static void unpackcube(cube &c, B &buf) -{ +static void unpackcube(cube &c, B &buf) { int mat = buf.get(); - if(mat == 0xFF) - { + if(mat == 0xFF) { c.children = newcubes(F_EMPTY); loopi(8) unpackcube(c.children[i], buf); } - else - { + else { c.material = mat | (buf.get()<<8); buf.get(c.edges, sizeof(c.edges)); buf.get((uchar *)c.texture, sizeof(c.texture)); @@ -933,8 +790,7 @@ static void unpackcube(cube &c, B &buf) } template -static bool unpackblock(block3 *&b, B &buf) -{ +static bool unpackblock(block3 *&b, B &buf) { if(b) { freeblock(b); b = NULL; } block3 hdr; if(buf.get((uchar *)&hdr, sizeof(hdr)) < int(sizeof(hdr))) return false; @@ -952,33 +808,26 @@ static bool unpackblock(block3 *&b, B &buf) return true; } -struct vslotmap -{ +struct vslotmap { int index; VSlot *vslot; - vslotmap() {} vslotmap(int index, VSlot *vslot) : index(index), vslot(vslot) {} }; static vector unpackingvslots; -static void unpackvslots(cube &c, ucharbuf &buf) -{ - if(c.children) - { +static void unpackvslots(cube &c, ucharbuf &buf) { + if(c.children) { loopi(8) unpackvslots(c.children[i], buf); } - else loopi(6) - { + else loopi(6) { ushort tex = c.texture[i]; loopvj(unpackingvslots) if(unpackingvslots[j].index == tex) { c.texture[i] = unpackingvslots[j].vslot->index; break; } } } -static void unpackvslots(block3 &b, ucharbuf &buf) -{ - while(buf.remaining() >= int(sizeof(vslothdr))) - { +static void unpackvslots(block3 &b, ucharbuf &buf) { + while(buf.remaining() >= int(sizeof(vslothdr))) { vslothdr &hdr = *(vslothdr *)buf.pad(sizeof(vslothdr)); lilswap(&hdr.index, 2); if(!hdr.index) break; @@ -989,20 +838,16 @@ static void unpackvslots(block3 &b, ucharbuf &buf) VSlot *edit = editvslot(vs, ds); unpackingvslots.add(vslotmap(hdr.index, edit ? edit : &vs)); } - cube *c = b.c(); loopi(b.size()) unpackvslots(c[i], buf); - unpackingvslots.setsize(0); } -static bool compresseditinfo(const uchar *inbuf, int inlen, uchar *&outbuf, int &outlen) -{ +static bool compresseditinfo(const uchar *inbuf, int inlen, uchar *&outbuf, int &outlen) { uLongf len = compressBound(inlen); if(len > (1<<20)) return false; outbuf = new (false) uchar[len]; - if(!outbuf || compress2((Bytef *)outbuf, &len, (const Bytef *)inbuf, inlen, Z_BEST_COMPRESSION) != Z_OK || len > (1<<16)) - { + if(!outbuf || compress2((Bytef *)outbuf, &len, (const Bytef *)inbuf, inlen, Z_BEST_COMPRESSION) != Z_OK || len > (1<<16)) { delete[] outbuf; outbuf = NULL; return false; @@ -1011,13 +856,11 @@ static bool compresseditinfo(const uchar *inbuf, int inlen, uchar *&outbuf, int return true; } -static bool uncompresseditinfo(const uchar *inbuf, int inlen, uchar *&outbuf, int &outlen) -{ +static bool uncompresseditinfo(const uchar *inbuf, int inlen, uchar *&outbuf, int &outlen) { if(compressBound(outlen) > (1<<20)) return false; uLongf len = outlen; outbuf = new (false) uchar[len]; - if(!outbuf || uncompress((Bytef *)outbuf, &len, (const Bytef *)inbuf, inlen) != Z_OK) - { + if(!outbuf || uncompress((Bytef *)outbuf, &len, (const Bytef *)inbuf, inlen) != Z_OK) { delete[] outbuf; outbuf = NULL; return false; @@ -1026,8 +869,7 @@ static bool uncompresseditinfo(const uchar *inbuf, int inlen, uchar *&outbuf, in return true; } -bool packeditinfo(editinfo *e, int &inlen, uchar *&outbuf, int &outlen) -{ +bool packeditinfo(editinfo *e, int &inlen, uchar *&outbuf, int &outlen) { vector buf; if(!e || !e->copy || !packblock(*e->copy, buf)) return false; packvslots(*e->copy, buf); @@ -1035,15 +877,13 @@ bool packeditinfo(editinfo *e, int &inlen, uchar *&outbuf, int &outlen) return compresseditinfo(buf.getbuf(), buf.length(), outbuf, outlen); } -bool unpackeditinfo(editinfo *&e, const uchar *inbuf, int inlen, int outlen) -{ +bool unpackeditinfo(editinfo *&e, const uchar *inbuf, int inlen, int outlen) { if(e && e->copy) { freeblock(e->copy); e->copy = NULL; } uchar *outbuf = NULL; if(!uncompresseditinfo(inbuf, inlen, outbuf, outlen)) return false; ucharbuf buf(outbuf, outlen); if(!e) e = editinfos.add(new editinfo); - if(!unpackblock(e->copy, buf)) - { + if(!unpackblock(e->copy, buf)) { delete[] outbuf; return false; } @@ -1052,8 +892,7 @@ bool unpackeditinfo(editinfo *&e, const uchar *inbuf, int inlen, int outlen) return true; } -void freeeditinfo(editinfo *&e) -{ +void freeeditinfo(editinfo *&e) { if(!e) return; editinfos.removeobj(e); if(e->copy) freeblock(e->copy); @@ -1061,16 +900,13 @@ void freeeditinfo(editinfo *&e) e = NULL; } -bool packundo(undoblock *u, int &inlen, uchar *&outbuf, int &outlen) -{ +bool packundo(undoblock *u, int &inlen, uchar *&outbuf, int &outlen) { vector buf; buf.reserve(512); *(ushort *)buf.pad(2) = lilswap(ushort(u->numents)); - if(u->numents) - { + if(u->numents) { undoent *ue = u->ents(); - loopi(u->numents) - { + loopi(u->numents) { *(ushort *)buf.pad(2) = lilswap(ushort(ue[i].i)); entity &e = *(entity *)buf.pad(sizeof(entity)); e = ue[i].e; @@ -1078,8 +914,7 @@ bool packundo(undoblock *u, int &inlen, uchar *&outbuf, int &outlen) lilswap(&e.attr1, 5); } } - else - { + else { block3 &b = *u->block(); if(!packblock(b, buf)) return false; buf.put(u->gridmap(), b.size()); @@ -1089,26 +924,21 @@ bool packundo(undoblock *u, int &inlen, uchar *&outbuf, int &outlen) return compresseditinfo(buf.getbuf(), buf.length(), outbuf, outlen); } -bool unpackundo(const uchar *inbuf, int inlen, int outlen) -{ +bool unpackundo(const uchar *inbuf, int inlen, int outlen) { uchar *outbuf = NULL; if(!uncompresseditinfo(inbuf, inlen, outbuf, outlen)) return false; ucharbuf buf(outbuf, outlen); - if(buf.remaining() < 2) - { + if(buf.remaining() < 2) { delete[] outbuf; return false; } int numents = lilswap(*(const ushort *)buf.pad(2)); - if(numents) - { - if(buf.remaining() < numents*int(2 + sizeof(entity))) - { + if(numents) { + if(buf.remaining() < numents*int(2 + sizeof(entity))) { delete[] outbuf; return false; } - loopi(numents) - { + loopi(numents) { int idx = lilswap(*(const ushort *)buf.pad(2)); entity &e = *(entity *)buf.pad(sizeof(entity)); lilswap(&e.o.x, 3); @@ -1116,11 +946,9 @@ bool unpackundo(const uchar *inbuf, int inlen, int outlen) pasteundoent(idx, e); } } - else - { + else { block3 *b = NULL; - if(!unpackblock(b, buf) || b->grid >= worldsize || buf.remaining() < b->size()) - { + if(!unpackblock(b, buf) || b->grid >= worldsize || buf.remaining() < b->size()) { freeblock(b); delete[] outbuf; return false; @@ -1136,33 +964,26 @@ bool unpackundo(const uchar *inbuf, int inlen, int outlen) return true; } -bool packundo(int op, int &inlen, uchar *&outbuf, int &outlen) -{ - switch(op) - { +bool packundo(int op, int &inlen, uchar *&outbuf, int &outlen) { + switch(op) { case EDIT_UNDO: return !undos.empty() && packundo(undos.last, inlen, outbuf, outlen); case EDIT_REDO: return !redos.empty() && packundo(redos.last, inlen, outbuf, outlen); default: return false; } } -struct prefabheader -{ +struct prefabheader { char magic[4]; int version; }; -struct prefab : editinfo -{ +struct prefab : editinfo { char *name; GLuint ebo, vbo; int numtris, numverts; - prefab() : name(NULL), ebo(0), vbo(0), numtris(0), numverts(0) {} ~prefab() { DELETEA(name); if(copy) freeblock(copy); } - - void cleanup() - { + void cleanup() { if(ebo) { glDeleteBuffers_(1, &ebo); ebo = 0; } if(vbo) { glDeleteBuffers_(1, &vbo); vbo = 0; } numtris = numverts = 0; @@ -1171,16 +992,13 @@ struct prefab : editinfo static hashnameset prefabs; -void cleanupprefabs() -{ +void cleanupprefabs() { enumerate(prefabs, prefab, p, p.cleanup()); } -void delprefab(char *name) -{ +void delprefab(char *name) { prefab *p = prefabs.access(name); - if(p) - { + if(p) { p->cleanup(); prefabs.remove(name); conoutf("deleted prefab %s", name); @@ -1188,12 +1006,10 @@ void delprefab(char *name) } COMMAND(delprefab, "s"); -void saveprefab(char *name) -{ +void saveprefab(char *name) { if(!name[0] || noedit(true) || (nompedit && multiplayer())) return; prefab *b = prefabs.access(name); - if(!b) - { + if(!b) { b = &prefabs[name]; b->name = newstring(name); } @@ -1216,8 +1032,7 @@ void saveprefab(char *name) } COMMAND(saveprefab, "s"); -void pasteblock(block3 &b, selinfo &sel, bool local) -{ +void pasteblock(block3 &b, selinfo &sel, bool local) { sel.s = b.s; int o = sel.orient; sel.orient = b.orient; @@ -1226,13 +1041,11 @@ void pasteblock(block3 &b, selinfo &sel, bool local) sel.orient = o; } -bool prefabloaded(const char *name) -{ +bool prefabloaded(const char *name) { return prefabs.access(name) != NULL; } -prefab *loadprefab(const char *name, bool msg = true) -{ +prefab *loadprefab(const char *name, bool msg = true) { prefab *b = prefabs.access(name); if(b) return b; @@ -1256,31 +1069,24 @@ prefab *loadprefab(const char *name, bool msg = true) return b; } -void pasteprefab(char *name) -{ +void pasteprefab(char *name) { if(!name[0] || noedit() || (nompedit && multiplayer())) return; prefab *b = loadprefab(name, true); if(b) pasteblock(*b->copy, sel, true); } COMMAND(pasteprefab, "s"); -struct prefabmesh -{ +struct prefabmesh { struct vertex { vec pos; bvec4 norm; }; - static const int SIZE = 1<<9; int table[SIZE]; vector verts; vector chain; vector tris; - prefabmesh() { memset(table, -1, sizeof(table)); } - - int addvert(const vertex &v) - { + int addvert(const vertex &v) { uint h = hthash(v.pos)&(SIZE-1); - for(int i = table[h]; i>=0; i = chain[i]) - { + for(int i = table[h]; i>=0; i = chain[i]) { const vertex &c = verts[i]; if(c.pos==v.pos && c.norm==v.norm) return i; } @@ -1289,28 +1095,21 @@ struct prefabmesh chain.add(table[h]); return table[h] = verts.length()-1; } - - int addvert(const vec &pos, const bvec &norm) - { + int addvert(const vec &pos, const bvec &norm) { vertex vtx; vtx.pos = pos; vtx.norm = norm; return addvert(vtx); } - - void setup(prefab &p) - { + void setup(prefab &p) { if(tris.empty()) return; - p.cleanup(); - loopv(verts) verts[i].norm.flip(); if(!p.vbo) glGenBuffers_(1, &p.vbo); gle::bindvbo(p.vbo); glBufferData_(GL_ARRAY_BUFFER, verts.length()*sizeof(vertex), verts.getbuf(), GL_STATIC_DRAW); gle::clearvbo(); p.numverts = verts.length(); - if(!p.ebo) glGenBuffers_(1, &p.ebo); gle::bindebo(p.ebo); glBufferData_(GL_ELEMENT_ARRAY_BUFFER, tris.length()*sizeof(ushort), tris.getbuf(), GL_STATIC_DRAW); @@ -1320,23 +1119,18 @@ struct prefabmesh }; -static void genprefabmesh(prefabmesh &r, cube &c, const ivec &co, int size) -{ - if(c.children) - { +static void genprefabmesh(prefabmesh &r, cube &c, const ivec &co, int size) { + if(c.children) { neighbourstack[++neighbourdepth] = c.children; - loopi(8) - { + loopi(8) { ivec o(i, co, size/2); genprefabmesh(r, c.children[i], o, size/2); } --neighbourdepth; } - else if(!isempty(c)) - { + else if(!isempty(c)) { int vis; - loopi(6) if((vis = visibletris(c, i, co, size))) - { + loopi(6) if((vis = visibletris(c, i, co, size))) { ivec v[4]; genfaceverts(c, i, v); int convex = 0; @@ -1350,8 +1144,7 @@ static void genprefabmesh(prefabmesh &r, cube &c, const ivec &co, int size) guessnormals(pos, numverts, norm); int index[4]; loopj(numverts) index[j] = r.addvert(pos[j], bvec(norm[j])); - loopj(numverts-2) if(index[0]!=index[j+1] && index[j+1]!=index[j+2] && index[j+2]!=index[0]) - { + loopj(numverts-2) if(index[0]!=index[j+1] && index[j+1]!=index[j+2] && index[j+2]!=index[0]) { r.tris.add(index[0]); r.tris.add(index[j+1]); r.tris.add(index[j+2]); @@ -1360,53 +1153,40 @@ static void genprefabmesh(prefabmesh &r, cube &c, const ivec &co, int size) } } -void genprefabmesh(prefab &p) -{ +void genprefabmesh(prefab &p) { block3 b = *p.copy; b.o = ivec(0, 0, 0); - cube *oldworldroot = worldroot; int oldworldscale = worldscale, oldworldsize = worldsize; - worldroot = newcubes(); worldscale = 1; worldsize = 2; - while(worldsize < max(max(b.s.x, b.s.y), b.s.z)*b.grid) - { + while(worldsize < max(max(b.s.x, b.s.y), b.s.z)*b.grid) { worldscale++; worldsize *= 2; } - cube *s = p.copy->c(); loopxyz(b, b.grid, if(!isempty(*s) || s->children) pastecube(*s, c); s++); - prefabmesh r; neighbourstack[++neighbourdepth] = worldroot; loopi(8) genprefabmesh(r, worldroot[i], ivec(i, ivec(0, 0, 0), worldsize/2), worldsize/2); --neighbourdepth; r.setup(p); - freeocta(worldroot); - worldroot = oldworldroot; worldscale = oldworldscale; worldsize = oldworldsize; - useshaderbyname("prefab"); } extern int outlinecolour; -static void renderprefab(prefab &p, const vec &o, float yaw, float pitch, float roll, float size, const vec &color) -{ - if(!p.numtris) - { +static void renderprefab(prefab &p, const vec &o, float yaw, float pitch, float roll, float size, const vec &color) { + if(!p.numtris) { genprefabmesh(p); if(!p.numtris) return; } - block3 &b = *p.copy; - matrix4 m; m.identity(); m.settranslation(o); @@ -1416,7 +1196,6 @@ static void renderprefab(prefab &p, const vec &o, float yaw, float pitch, float matrix3 w(m); if(size > 0 && size != 1) m.scale(size); m.translate(vec(b.s).mul(-b.grid*0.5f)); - gle::bindvbo(p.vbo); gle::bindebo(p.ebo); gle::enablevertex(); @@ -1424,7 +1203,6 @@ static void renderprefab(prefab &p, const vec &o, float yaw, float pitch, float prefabmesh::vertex *v = (prefabmesh::vertex *)0; gle::vertexpointer(sizeof(prefabmesh::vertex), v->pos.v); gle::normalpointer(sizeof(prefabmesh::vertex), v->norm.v, GL_BYTE); - matrix4 pm; pm.mul(camprojmatrix, m); GLOBALPARAM(prefabmatrix, pm); @@ -1432,36 +1210,29 @@ static void renderprefab(prefab &p, const vec &o, float yaw, float pitch, float SETSHADER(prefab); gle::color(color); glDrawRangeElements_(GL_TRIANGLES, 0, p.numverts-1, p.numtris*3, GL_UNSIGNED_SHORT, (ushort *)0); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); enablepolygonoffset(GL_POLYGON_OFFSET_LINE); - pm.mul(camprojmatrix, m); GLOBALPARAM(prefabmatrix, pm); SETSHADER(prefab); gle::color(vec::hexcolor(outlinecolour)); glDrawRangeElements_(GL_TRIANGLES, 0, p.numverts-1, p.numtris*3, GL_UNSIGNED_SHORT, (ushort *)0); - disablepolygonoffset(GL_POLYGON_OFFSET_LINE); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - gle::disablevertex(); gle::disablenormal(); gle::clearebo(); gle::clearvbo(); } -void renderprefab(const char *name, const vec &o, float yaw, float pitch, float roll, float size, const vec &color) -{ +void renderprefab(const char *name, const vec &o, float yaw, float pitch, float roll, float size, const vec &color) { prefab *p = loadprefab(name, false); if(p) renderprefab(*p, o, yaw, pitch, roll, size, color); } -void previewprefab(const char *name, const vec &color) -{ +void previewprefab(const char *name, const vec &color) { prefab *p = loadprefab(name, false); - if(p) - { + if(p) { block3 &b = *p->copy; float yaw; vec o = calcmodelpreviewpos(vec(b.s).mul(b.grid*0.5f), yaw); @@ -1469,8 +1240,7 @@ void previewprefab(const char *name, const vec &color) } } -void mpcopy(editinfo *&e, selinfo &sel, bool local) -{ +void mpcopy(editinfo *&e, selinfo &sel, bool local) { if(local) game::edittrigger(sel, EDIT_COPY); if(e==NULL) e = editinfos.add(new editinfo); if(e->copy) freeblock(e->copy); @@ -1479,29 +1249,25 @@ void mpcopy(editinfo *&e, selinfo &sel, bool local) changed(sel); } -void mppaste(editinfo *&e, selinfo &sel, bool local) -{ +void mppaste(editinfo *&e, selinfo &sel, bool local) { if(e==NULL) return; if(local) game::edittrigger(sel, EDIT_PASTE); if(e->copy) pasteblock(*e->copy, sel, local); } -void copy() -{ +void copy() { if(noedit(true)) return; mpcopy(localedit, sel, true); } -void pastehilite() -{ +void pastehilite() { if(!localedit) return; sel.s = localedit->copy->s; reorient(); havesel = true; } -void paste() -{ +void paste() { if(noedit(true)) return; mppaste(localedit, sel, true); } @@ -1513,19 +1279,16 @@ COMMANDN(undo, editundo, ""); COMMANDN(redo, editredo, ""); static vector editingvslots; -struct vslotref -{ +struct vslotref { vslotref(int &index) { editingvslots.add(&index); } ~vslotref() { editingvslots.pop(); } }; #define editingvslot(...) vslotref vslotrefs[] = { __VA_ARGS__ }; (void)vslotrefs; -void compacteditvslots() -{ +void compacteditvslots() { loopv(editingvslots) if(*editingvslots[i]) compactvslot(*editingvslots[i]); loopv(unpackingvslots) compactvslot(*unpackingvslots[i].vslot); - loopv(editinfos) - { + loopv(editinfos) { editinfo *e = editinfos[i]; compactvslots(e->copy->c(), e->copy->size()); } @@ -1541,31 +1304,25 @@ void compacteditvslots() int bounded(int n) { return n<0 ? 0 : (n>8 ? 8 : n); } -void pushedge(uchar &edge, int dir, int dc) -{ +void pushedge(uchar &edge, int dir, int dc) { int ne = bounded(edgeget(edge, dc)+dir); edgeset(edge, dc, ne); int oe = edgeget(edge, 1-dc); if((dir<0 && dc && oe>ne) || (dir>0 && dc==0 && oe0) == dc && h<=0) || ((dir<0) == dc && h>=worldsize)) return; if(dir<0) sel.o[d] += sel.grid * seldir; } - if(dc) sel.o[d] += sel.us(d)-sel.grid; sel.s[d] = 1; - loopselxyz( if(c.children) solidfaces(c); ushort mat = getmaterial(c); discardchildren(c, true); c.material = mat; - if(mode==1) // fill command - { - if(dir<0) - { + if(mode==1) { // fill command { + if(dir<0) { solidfaces(c); cube &o = blockcube(x, y, 1, sel, -sel.grid); loopi(6) @@ -1612,35 +1361,27 @@ void mpeditface(int dir, int mode, selinfo &sel, bool local) else emptyfaces(c); } - else - { + else { uint bak = c.faces[d]; uchar *p = (uchar *)&c.faces[d]; - if(mode==2) linkedpush(c, d, sel.corner&1, sel.corner>>1, dc, seldir); // corner command - else - { - loop(mx,2) loop(my,2) // pull/push edges command - { + else { + loop(mx,2) loop(my,2) { // pull/push edges command { if(x==0 && mx==0 && sel.cx) continue; if(y==0 && my==0 && sel.cy) continue; if(x==sel.s[R[d]]-1 && mx==1 && (sel.cx+sel.cxs)&1) continue; if(y==sel.s[C[d]]-1 && my==1 && (sel.cy+sel.cys)&1) continue; if(p[mx+my*2] != ((uchar *)&bak)[mx+my*2]) continue; - linkedpush(c, d, mx, my, dc, seldir); } } - optiface(p, c); - if(invalidcubeguard==1 && !isvalidcube(c)) - { + if(invalidcubeguard==1 && !isvalidcube(c)) { uint newbak = c.faces[d]; uchar *m = (uchar *)&bak; uchar *n = (uchar *)&newbak; - loopk(4) if(n[k] != m[k]) // tries to find partial edit that is valid - { + loopk(4) if(n[k] != m[k]) { // tries to find partial edit that is valid { c.faces[d] = bak; c.edges[d*4+k] = n[k]; if(isvalidcube(c)) @@ -1654,35 +1395,30 @@ void mpeditface(int dir, int mode, selinfo &sel, bool local) sel.o[d] += sel.grid * seldir; } -void editface(int *dir, int *mode) -{ +void editface(int *dir, int *mode) { if(noedit(moving!=0)) return; mpeditface(*dir, *mode, sel, true); } VAR(selectionsurf, 0, 0, 1); -void pushsel(int *dir) -{ +void pushsel(int *dir) { if(noedit(moving!=0)) return; int d = dimension(orient); int s = dimcoord(orient) ? -*dir : *dir; sel.o[d] += s*sel.grid; - if(selectionsurf==1) - { + if(selectionsurf==1) { player->o[d] += s*sel.grid; player->resetinterp(); } } -void mpdelcube(selinfo &sel, bool local) -{ +void mpdelcube(selinfo &sel, bool local) { if(local) game::edittrigger(sel, EDIT_DELCUBE); loopselxyz(discardchildren(c, true); emptyfaces(c)); } -void delcube() -{ +void delcube() { if(noedit(true)) return; mpdelcube(sel, true); } @@ -1697,11 +1433,9 @@ int curtexindex = -1, lasttex = 0, lasttexmillis = -1; int texpaneltimer = 0; vector texmru; -void tofronttex() // maintain most recently used of the texture lists when applying texture -{ +void tofronttex() { // maintain most recently used of the texture lists when applying texture { int c = curtexindex; - if(texmru.inrange(c)) - { + if(texmru.inrange(c)) { texmru.insert(0, texmru.remove(c)); curtexindex = -1; } @@ -1714,14 +1448,12 @@ static vector remappedvslots; VAR(usevdelta, 1, 0, 0); -static VSlot *remapvslot(int index, bool delta, const VSlot &ds) -{ +static VSlot *remapvslot(int index, bool delta, const VSlot &ds) { loopv(remappedvslots) if(remappedvslots[i].index == index) return remappedvslots[i].vslot; VSlot &vs = lookupvslot(index, false); if(vs.index < 0) return NULL; VSlot *edit = NULL; - if(delta) - { + if(delta) { VSlot ms; mergevslot(ms, vs, ds); edit = ms.changed ? editvslot(vs, ms) : vs.slot->variants; @@ -1732,31 +1464,24 @@ static VSlot *remapvslot(int index, bool delta, const VSlot &ds) return edit; } -static void remapvslots(cube &c, bool delta, const VSlot &ds, int orient, bool &findrep, VSlot *&findedit) -{ - if(c.children) - { +static void remapvslots(cube &c, bool delta, const VSlot &ds, int orient, bool &findrep, VSlot *&findedit) { + if(c.children) { loopi(8) remapvslots(c.children[i], delta, ds, orient, findrep, findedit); return; } static VSlot ms; - if(orient<0) loopi(6) - { + if(orient<0) loopi(6) { VSlot *edit = remapvslot(c.texture[i], delta, ds); - if(edit) - { + if(edit) { c.texture[i] = edit->index; if(!findedit) findedit = edit; } } - else - { + else { int i = visibleorient(c, orient); VSlot *edit = remapvslot(c.texture[i], delta, ds); - if(edit) - { - if(findrep) - { + if(edit) { + if(findrep) { if(reptex < 0) reptex = c.texture[i]; else if(reptex != c.texture[i]) findrep = false; } @@ -1766,14 +1491,11 @@ static void remapvslots(cube &c, bool delta, const VSlot &ds, int orient, bool & } } -void edittexcube(cube &c, int tex, int orient, bool &findrep) -{ +void edittexcube(cube &c, int tex, int orient, bool &findrep) { if(orient<0) loopi(6) c.texture[i] = tex; - else - { + else { int i = visibleorient(c, orient); - if(findrep) - { + if(findrep) { if(reptex < 0) reptex = c.texture[i]; else if(reptex != c.texture[i]) findrep = false; } @@ -1784,10 +1506,8 @@ void edittexcube(cube &c, int tex, int orient, bool &findrep) VAR(allfaces, 0, 0, 1); -void mpeditvslot(int delta, VSlot &ds, int allfaces, selinfo &sel, bool local) -{ - if(local) - { +void mpeditvslot(int delta, VSlot &ds, int allfaces, selinfo &sel, bool local) { + if(local) { game::edittrigger(sel, EDIT_VSLOT, delta, allfaces, 0, &ds); if(!(lastsel==sel)) tofronttex(); if(allfaces || !(repsel == sel)) reptex = -1; @@ -1797,21 +1517,18 @@ void mpeditvslot(int delta, VSlot &ds, int allfaces, selinfo &sel, bool local) VSlot *findedit = NULL; loopselxyz(remapvslots(c, delta != 0, ds, allfaces ? -1 : sel.orient, findrep, findedit)); remappedvslots.setsize(0); - if(local && findedit) - { + if(local && findedit) { lasttex = findedit->index; lasttexmillis = totalmillis; curtexindex = texmru.find(lasttex); - if(curtexindex < 0) - { + if(curtexindex < 0) { curtexindex = texmru.length(); texmru.add(lasttex); } } } -bool mpeditvslot(int delta, int allfaces, selinfo &sel, ucharbuf &buf) -{ +bool mpeditvslot(int delta, int allfaces, selinfo &sel, ucharbuf &buf) { VSlot ds; if(!unpackvslot(buf, ds, delta != 0)) return false; editingvslot(ds.layer); @@ -1819,8 +1536,7 @@ bool mpeditvslot(int delta, int allfaces, selinfo &sel, ucharbuf &buf) return true; } -void vdelta(char *body) -{ +void vdelta(char *body) { if(noedit()) return; usevdelta++; execute(body); @@ -1828,8 +1544,7 @@ void vdelta(char *body) } COMMAND(vdelta, "s"); -void vrotate(int *n) -{ +void vrotate(int *n) { if(noedit()) return; VSlot ds; ds.changed = 1<changed && nompedit && multiplayer()) return; } @@ -1898,8 +1606,7 @@ void vlayer(int *n) COMMAND(vlayer, "i"); ICOMMAND(getvlayer, "i", (int *tex), intret(lookupvslot(*tex, false).layer)); -void valpha(float *front, float *back) -{ +void valpha(float *front, float *back) { if(noedit()) return; VSlot ds; ds.changed = 1< str; - loopv(vslot.params) - { + loopv(vslot.params) { SlotShaderParam &p = vslot.params[i]; if(i) str.put(' '); str.put(p.name, strlen(p.name)); @@ -1980,10 +1676,8 @@ ICOMMAND(getvshaderparamnames, "i", (int *tex), stringret(newstring(str.getbuf(), str.length()-1)); }); -void mpedittex(int tex, int allfaces, selinfo &sel, bool local) -{ - if(local) - { +void mpedittex(int tex, int allfaces, selinfo &sel, bool local) { + if(local) { game::edittrigger(sel, EDIT_TEX, tex, allfaces); if(allfaces || !(repsel == sel)) reptex = -1; repsel = sel; @@ -1992,8 +1686,7 @@ void mpedittex(int tex, int allfaces, selinfo &sel, bool local) loopselxyz(edittexcube(c, tex, allfaces ? -1 : sel.orient, findrep)); } -static int unpacktex(int &tex, ucharbuf &buf, bool insert = true) -{ +static int unpacktex(int &tex, ucharbuf &buf, bool insert = true) { if(tex < 0x10000) return true; VSlot ds; if(!unpackvslot(buf, ds, false)) return false; @@ -2005,10 +1698,8 @@ static int unpacktex(int &tex, ucharbuf &buf, bool insert = true) return true; } -int shouldpacktex(int index) -{ - if(vslots.inrange(index)) - { +int shouldpacktex(int index) { + if(vslots.inrange(index)) { VSlot &vs = *vslots[index]; if(vs.changed) return 0x10000 + vs.slot->index; } @@ -2016,19 +1707,15 @@ int shouldpacktex(int index) } -bool mpedittex(int tex, int allfaces, selinfo &sel, ucharbuf &buf) -{ +bool mpedittex(int tex, int allfaces, selinfo &sel, ucharbuf &buf) { if(!unpacktex(tex, buf)) return false; mpedittex(tex, allfaces, sel, false); return true; } -void filltexlist() -{ - if(texmru.length()!=vslots.length()) - { - loopvrev(texmru) if(texmru[i]>=vslots.length()) - { +void filltexlist() { + if(texmru.length()!=vslots.length()) { + loopvrev(texmru) if(texmru[i]>=vslots.length()) { if(curtexindex > i) curtexindex--; else if(curtexindex == i) curtexindex = -1; texmru.remove(i); @@ -2037,16 +1724,12 @@ void filltexlist() } } -void compactmruvslots() -{ +void compactmruvslots() { remappedvslots.setsize(0); - loopvrev(texmru) - { - if(vslots.inrange(texmru[i])) - { + loopvrev(texmru) { + if(vslots.inrange(texmru[i])) { VSlot &vs = *vslots[texmru[i]]; - if(vs.index >= 0) - { + if(vs.index >= 0) { texmru[i] = vs.index; continue; } @@ -2055,8 +1738,7 @@ void compactmruvslots() else if(curtexindex == i) curtexindex = -1; texmru.remove(i); } - if(vslots.inrange(lasttex)) - { + if(vslots.inrange(lasttex)) { VSlot &vs = *vslots[lasttex]; lasttex = vs.index >= 0 ? vs.index : 0; } @@ -2064,19 +1746,16 @@ void compactmruvslots() reptex = vslots.inrange(reptex) ? vslots[reptex]->index : -1; } -void edittex(int i, bool save = true) -{ +void edittex(int i, bool save = true) { lasttex = i; lasttexmillis = totalmillis; - if(save) - { + if(save) { loopvj(texmru) if(texmru[j]==lasttex) { curtexindex = j; break; } } mpedittex(i, allfaces, sel, true); } -void edittex_(int *dir) -{ +void edittex_(int *dir) { if(noedit()) return; filltexlist(); if(texmru.empty()) return; @@ -2086,22 +1765,19 @@ void edittex_(int *dir) edittex(texmru[curtexindex], false); } -void gettex() -{ +void gettex() { if(noedit(true)) return; filltexlist(); int tex = -1; loopxyz(sel, sel.grid, tex = c.texture[sel.orient]); - loopv(texmru) if(texmru[i]==tex) - { + loopv(texmru) if(texmru[i]==tex) { curtexindex = i; tofronttex(); return; } } -void getcurtex() -{ +void getcurtex() { if(noedit(true)) return; filltexlist(); int index = curtexindex < 0 ? 0 : curtexindex; @@ -2109,16 +1785,14 @@ void getcurtex() intret(texmru[index]); } -void getseltex() -{ +void getseltex() { if(noedit(true)) return; cube &c = lookupcube(sel.o, -sel.grid); if(c.children || isempty(c)) return; intret(c.texture[sel.orient]); } -void gettexname(int *tex, int *subslot) -{ +void gettexname(int *tex, int *subslot) { if(noedit(true) || *tex<0) return; VSlot &vslot = lookupvslot(*tex, false); Slot &slot = *vslot.slot; @@ -2126,8 +1800,7 @@ void gettexname(int *tex, int *subslot) result(slot.sts[*subslot].name); } -void getslottex(int *idx) -{ +void getslottex(int *idx) { if(*idx < 0 || !slots.inrange(*idx)) { intret(-1); return; } Slot &slot = lookupslot(*idx, false); intret(slot.variants->index); @@ -2144,28 +1817,23 @@ ICOMMAND(numslots, "", (), intret(slots.length())); COMMAND(getslottex, "i"); ICOMMAND(texloaded, "i", (int *tex), intret(slots.inrange(*tex) && slots[*tex]->loaded ? 1 : 0)); -void replacetexcube(cube &c, int oldtex, int newtex) -{ +void replacetexcube(cube &c, int oldtex, int newtex) { loopi(6) if(c.texture[i] == oldtex) c.texture[i] = newtex; if(c.children) loopi(8) replacetexcube(c.children[i], oldtex, newtex); } -void mpreplacetex(int oldtex, int newtex, bool insel, selinfo &sel, bool local) -{ +void mpreplacetex(int oldtex, int newtex, bool insel, selinfo &sel, bool local) { if(local) game::edittrigger(sel, EDIT_REPLACE, oldtex, newtex, insel ? 1 : 0); - if(insel) - { + if(insel) { loopselxyz(replacetexcube(c, oldtex, newtex)); } - else - { + else { loopi(8) replacetexcube(worldroot[i], oldtex, newtex); } allchanged(); } -bool mpreplacetex(int oldtex, int newtex, bool insel, selinfo &sel, ucharbuf &buf) -{ +bool mpreplacetex(int oldtex, int newtex, bool insel, selinfo &sel, ucharbuf &buf) { if(!unpacktex(oldtex, buf, false)) return false; editingvslot(oldtex); if(!unpacktex(newtex, buf)) return false; @@ -2173,8 +1841,7 @@ bool mpreplacetex(int oldtex, int newtex, bool insel, selinfo &sel, ucharbuf &bu return true; } -void replace(bool insel) -{ +void replace(bool insel) { if(noedit()) return; if(reptex < 0) { conoutf(CON_ERROR, "can only replace after a texture edit"); return; } mpreplacetex(reptex, lasttex, insel, sel, true); @@ -2189,37 +1856,30 @@ uint cflip(uint face) { return ((face&0xFF00FF00)>>8) | ((face&0x00FF00FF)<<8); uint rflip(uint face) { return ((face&0xFFFF0000)>>16)| ((face&0x0000FFFF)<<16); } uint mflip(uint face) { return (face&0xFF0000FF) | ((face&0x00FF0000)>>8) | ((face&0x0000FF00)<<8); } -void flipcube(cube &c, int d) -{ +void flipcube(cube &c, int d) { swap(c.texture[d*2], c.texture[d*2+1]); c.faces[D[d]] = dflip(c.faces[D[d]]); c.faces[C[d]] = cflip(c.faces[C[d]]); c.faces[R[d]] = rflip(c.faces[R[d]]); - if(c.children) - { + if(c.children) { loopi(8) if(i&octadim(d)) swap(c.children[i], c.children[i-octadim(d)]); loopi(8) flipcube(c.children[i], d); } } -void rotatequad(cube &a, cube &b, cube &c, cube &d) -{ +void rotatequad(cube &a, cube &b, cube &c, cube &d) { cube t = a; a = b; b = c; c = d; d = t; } -void rotatecube(cube &c, int d) // rotates cube clockwise. see pics in cvs for help. -{ +void rotatecube(cube &c, int d) { // rotates cube clockwise. see pics in cvs for help. { c.faces[D[d]] = cflip (mflip(c.faces[D[d]])); c.faces[C[d]] = dflip (mflip(c.faces[C[d]])); c.faces[R[d]] = rflip (mflip(c.faces[R[d]])); swap(c.faces[R[d]], c.faces[C[d]]); - swap(c.texture[2*R[d]], c.texture[2*C[d]+1]); swap(c.texture[2*C[d]], c.texture[2*R[d]+1]); swap(c.texture[2*C[d]], c.texture[2*C[d]+1]); - - if(c.children) - { + if(c.children) { int row = octadim(R[d]); int col = octadim(C[d]); for(int i=0; i<=octadim(d); i+=octadim(d)) rotatequad @@ -2233,19 +1893,15 @@ void rotatecube(cube &c, int d) // rotates cube clockwise. see pics in cvs for } } -void mpflip(selinfo &sel, bool local) -{ - if(local) - { +void mpflip(selinfo &sel, bool local) { + if(local) { game::edittrigger(sel, EDIT_FLIP); makeundo(); } int zs = sel.s[dimension(sel.orient)]; - loopxy(sel) - { + loopxy(sel) { loop(z,zs) flipcube(selcube(x, y, z), dimension(sel.orient)); - loop(z,zs/2) - { + loop(z,zs/2) { cube &a = selcube(x, y, z); cube &b = selcube(x, y, zs-z-1); swap(a, b); @@ -2254,22 +1910,19 @@ void mpflip(selinfo &sel, bool local) changed(sel); } -void flip() -{ +void flip() { if(noedit()) return; mpflip(sel, true); } -void mprotate(int cw, selinfo &sel, bool local) -{ +void mprotate(int cw, selinfo &sel, bool local) { if(local) game::edittrigger(sel, EDIT_ROTATE, cw); int d = dimension(sel.orient); if(!dimcoord(sel.orient)) cw = -cw; int m = sel.s[C[d]] < sel.s[R[d]] ? C[d] : R[d]; int ss = sel.s[m] = max(sel.s[R[d]], sel.s[C[d]]); if(local) makeundo(); - loop(z,sel.s[D[d]]) loopi(cw>0 ? 1 : 3) - { + loop(z,sel.s[D[d]]) loopi(cw>0 ? 1 : 3) { loopxy(sel) rotatecube(selcube(x,y,z), d); loop(y,ss/2) loop(x,ss-1-y*2) rotatequad ( @@ -2282,8 +1935,7 @@ void mprotate(int cw, selinfo &sel, bool local) changed(sel); } -void rotate(int *cw) -{ +void rotate(int *cw) { if(noedit()) return; mprotate(*cw, sel, true); } @@ -2292,29 +1944,25 @@ COMMAND(flip, ""); COMMAND(rotate, "i"); enum { EDITMATF_EMPTY = 0x10000, EDITMATF_NOTEMPTY = 0x20000, EDITMATF_SOLID = 0x30000, EDITMATF_NOTSOLID = 0x40000 }; -static const struct { const char *name; int filter; } editmatfilters[] = -{ - { "empty", EDITMATF_EMPTY }, - { "notempty", EDITMATF_NOTEMPTY }, - { "solid", EDITMATF_SOLID }, - { "notsolid", EDITMATF_NOTSOLID } +static const struct { const char *name; int filter; } editmatfilters[] = { + { + "empty", EDITMATF_EMPTY }, { + "notempty", EDITMATF_NOTEMPTY }, { + "solid", EDITMATF_SOLID }, { + "notsolid", EDITMATF_NOTSOLID } }; -void setmat(cube &c, ushort mat, ushort matmask, ushort filtermat, ushort filtermask, int filtergeom) -{ +void setmat(cube &c, ushort mat, ushort matmask, ushort filtermat, ushort filtermask, int filtergeom) { if(c.children) loopi(8) setmat(c.children[i], mat, matmask, filtermat, filtermask, filtergeom); - else if((c.material&filtermask) == filtermat) - { - switch(filtergeom) - { + else if((c.material&filtermask) == filtermat) { + switch(filtergeom) { case EDITMATF_EMPTY: if(isempty(c)) break; return; case EDITMATF_NOTEMPTY: if(!isempty(c)) break; return; case EDITMATF_SOLID: if(isentirelysolid(c)) break; return; case EDITMATF_NOTSOLID: if(!isentirelysolid(c)) break; return; } - if(mat!=MAT_AIR) - { + if(mat!=MAT_AIR) { c.material &= matmask; c.material |= mat; } @@ -2322,47 +1970,38 @@ void setmat(cube &c, ushort mat, ushort matmask, ushort filtermat, ushort filter } } -void mpeditmat(int matid, int filter, selinfo &sel, bool local) -{ +void mpeditmat(int matid, int filter, selinfo &sel, bool local) { if(local) game::edittrigger(sel, EDIT_MAT, matid, filter); - ushort filtermat = 0, filtermask = 0, matmask; int filtergeom = 0; - if(filter >= 0) - { + if(filter >= 0) { filtermat = filter&0xFFFF; filtermask = filtermat&(MATF_INDEX) ? (int) MATF_INDEX : (filtermat&MATF_CLIP ? (int) MATF_CLIP : (int) filtermat); filtergeom = filter&~0xFFFF; } - if(matid < 0) - { + if(matid < 0) { matid = 0; matmask = filtermask; } - else - { + else { matmask = matid&MATF_INDEX ? 0 : (matid&MATF_CLIP ? ~MATF_CLIP : ~matid); } loopselxyz(setmat(c, matid, matmask, filtermat, filtermask, filtergeom)); } -void editmat(char *name, char *filtername) -{ +void editmat(char *name, char *filtername) { if(noedit()) return; int filter = -1; - if(filtername[0]) - { + if(filtername[0]) { loopi(sizeof(editmatfilters)/sizeof(editmatfilters[0])) if(!strcmp(editmatfilters[i].name, filtername)) { filter = editmatfilters[i].filter; break; } if(filter < 0) filter = findmaterial(filtername); - if(filter < 0) - { + if(filter < 0) { conoutf(CON_ERROR, "unknown material \"%s\"", filtername); return; } } int id = -1; - if(name[0] || filter < 0) - { + if(name[0] || filter < 0) { id = findmaterial(name); if(id<0) { conoutf(CON_ERROR, "unknown material \"%s\"", name); return; } } @@ -2384,39 +2023,30 @@ static int lastthumbnail = 0; VARP(texgui2d, 0, 1, 1); VAR(texguinum, 1, -1, 0); -struct texturegui : g3d_callback -{ +struct texturegui : g3d_callback { bool menuon; vec menupos; int menustart, menutab; - texturegui() : menustart(-1) {} - - void gui(g3d_gui &g, bool firstpass) - { + void gui(g3d_gui &g, bool firstpass) { int origtab = menutab, numtabs = max((slots.length() + texguiwidth*texguiheight - 1)/(texguiwidth*texguiheight), 1); if(!firstpass) texguinum = -1; g.start(menustart, 0.04f, &menutab); bool oldautotab = g.allowautotab(false); - loopi(numtabs) - { + loopi(numtabs) { g.tab(!i ? "Textures" : NULL, 0xFFDD88); if(i+1 != origtab) continue; //don't load textures on non-visible tabs! Slot *rollover = NULL; - loop(h, texguiheight) - { + loop(h, texguiheight) { g.pushlist(); - loop(w, texguiwidth) - { + loop(w, texguiwidth) { extern VSlot dummyvslot; int ti = (i*texguiheight+h)*texguiwidth+w; - if(tiset(); } } - else - { + else { g.texture(dummyvslot, texguiscale, false); //create an empty space } } g.poplist(); } - if(texguiname) - { - if(rollover) - { + if(texguiname) { + if(rollover) { defformatstring(name, "%d \f7:\fc %s", texguinum, rollover->sts[0].name); g.title(name, 0xFFDD88); } @@ -2453,12 +2079,9 @@ struct texturegui : g3d_callback g.allowautotab(oldautotab); g.end(); } - - void showtextures(bool on) - { + void showtextures(bool on) { if(on == menuon) return; - if((menuon = on)) - { + if((menuon = on)) { if(menustart <= lasttexmillis) menutab = 1+clamp(lookupvslot(lasttex, false).slot->index, 0, slots.length()-1)/(texguiwidth*texguiheight); menupos = menuinfrontofplayer(); @@ -2466,9 +2089,7 @@ struct texturegui : g3d_callback } else texguinum = -1; } - - void show() - { + void show() { if(!menuon) return; filltexlist(); extern int usegui2d; @@ -2477,13 +2098,11 @@ struct texturegui : g3d_callback } } gui; -void g3d_texturemenu() -{ +void g3d_texturemenu() { gui.show(); } -void showtexgui(int *n) -{ +void showtexgui(int *n) { if(!editmode) { conoutf(CON_ERROR, "operation only allowed in edit mode"); return; } gui.showtextures(*n==0 ? !gui.menuon : *n==1); } @@ -2491,47 +2110,36 @@ void showtexgui(int *n) // 0/noargs = toggle, 1 = on, other = off - will autoclose if too far away or exit editmode COMMAND(showtexgui, "i"); -bool cleartexgui() -{ +bool cleartexgui() { if(!gui.menuon) return false; gui.showtextures(false); return true; } ICOMMAND(cleartexgui, "", (), intret(cleartexgui() ? 1 : 0)); -void rendertexturepanel(int w, int h) -{ - if((texpaneltimer -= curtime)>0 && editmode) - { +void rendertexturepanel(int w, int h) { + if((texpaneltimer -= curtime)>0 && editmode) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - pushhudmatrix(); hudmatrix.scale(h/1800.0f, h/1800.0f, 1); flushhudmatrix(false); SETSHADER(hudrgb); - int y = 50, gap = 10; - gle::defvertex(2); gle::deftexcoord0(); - - loopi(7) - { + loopi(7) { int s = (i == 3 ? 285 : 220), ti = curtexindex+i-3; - if(texmru.inrange(ti)) - { - VSlot &vslot = lookupvslot(texmru[ti]), *layer = NULL; + if(texmru.inrange(ti)) { + VSlot &vslot = lookupvslot(texmru[ti]), *layer = NULL; (void) layer; Slot &slot = *vslot.slot; Texture *tex = slot.sts.empty() ? notexture : slot.sts[0].t; - if(vslot.layer) - { + if(vslot.layer) { layer = &lookupvslot(vslot.layer); } float sx = min(1.0f, tex->xs/(float)tex->ys), sy = min(1.0f, tex->ys/(float)tex->xs); vec2 tc[4] = { vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1) }; float xoff = vslot.offset.x, yoff = vslot.offset.y; - if(vslot.rotation) - { + if(vslot.rotation) { const texrotation &r = texrotations[vslot.rotation]; if(r.swapxy) { swap(xoff, yoff); loopk(4) swap(tc[k].x, tc[k].y); } if(r.flipx) { xoff *= -1; loopk(4) tc[k].x *= -1; } @@ -2542,7 +2150,6 @@ void rendertexturepanel(int w, int h) } y += s+gap; } - pophudmatrix(true, false); hudshader->set(); } diff --git a/src/engine/octarender.cpp b/src/engine/octarender.cpp index 6b8a5b5..afbc7b2 100644 --- a/src/engine/octarender.cpp +++ b/src/engine/octarender.cpp @@ -2,8 +2,7 @@ #include "engine.h" -struct vboinfo -{ +struct vboinfo { int uses; }; @@ -12,8 +11,7 @@ hashtable vbos; VAR(printvbo, 0, 0, 1); VARFN(vbosize, maxvbosize, 0, 1<<14, 1<<16, allchanged()); -enum -{ +enum { VBO_VBUF = 0, VBO_EBUF, NUMVBO @@ -23,41 +21,32 @@ static vector vbodata[NUMVBO]; static vector vbovas[NUMVBO]; static int vbosize[NUMVBO]; -void destroyvbo(GLuint vbo) -{ +void destroyvbo(GLuint vbo) { vboinfo *exists = vbos.access(vbo); if(!exists) return; vboinfo &vbi = *exists; if(vbi.uses <= 0) return; vbi.uses--; - if(!vbi.uses) - { + if(!vbi.uses) { glDeleteBuffers_(1, &vbo); vbos.remove(vbo); } } -void genvbo(int type, void *buf, int len, vtxarray **vas, int numva) -{ +void genvbo(int type, void *buf, int len, vtxarray **vas, int numva) { gle::disable(); - GLuint vbo; glGenBuffers_(1, &vbo); GLenum target = type==VBO_VBUF ? GL_ARRAY_BUFFER : GL_ELEMENT_ARRAY_BUFFER; glBindBuffer_(target, vbo); glBufferData_(target, len, buf, GL_STATIC_DRAW); glBindBuffer_(target, 0); - vboinfo &vbi = vbos[vbo]; vbi.uses = numva; - if(printvbo) conoutf(CON_DEBUG, "vbo %d: type %d, size %d, %d uses", vbo, type, len, numva); - - loopi(numva) - { + loopi(numva) { vtxarray *va = vas[i]; - switch(type) - { + switch(type) { case VBO_VBUF: va->vbuf = vbo; break; @@ -68,31 +57,24 @@ void genvbo(int type, void *buf, int len, vtxarray **vas, int numva) } } -bool readva(vtxarray *va, ushort *&edata, vertex *&vdata) -{ +bool readva(vtxarray *va, ushort *&edata, vertex *&vdata) { if(!va->vbuf || !va->ebuf) return false; - edata = new ushort[3*va->tris]; vdata = new vertex[va->verts]; - gle::bindebo(va->ebuf); glGetBufferSubData_(GL_ELEMENT_ARRAY_BUFFER, (size_t)va->edata, 3*va->tris*sizeof(ushort), edata); gle::clearebo(); - gle::bindvbo(va->vbuf); glGetBufferSubData_(GL_ARRAY_BUFFER, va->voffset*sizeof(vertex), va->verts*sizeof(vertex), vdata); gle::clearvbo(); return true; } -void flushvbo(int type = -1) -{ - if(type < 0) - { +void flushvbo(int type = -1) { + if(type < 0) { loopi(NUMVBO) flushvbo(i); return; } - vector &data = vbodata[type]; if(data.empty()) return; vector &vas = vbovas[type]; @@ -102,42 +84,31 @@ void flushvbo(int type = -1) vbosize[type] = 0; } -uchar *addvbo(vtxarray *va, int type, int numelems, int elemsize) -{ +uchar *addvbo(vtxarray *va, int type, int numelems, int elemsize) { vbosize[type] += numelems; - vector &data = vbodata[type]; vector &vas = vbovas[type]; - vas.add(va); - int len = numelems*elemsize; uchar *buf = data.reserve(len).buf; data.advance(len); return buf; } -struct verthash -{ +struct verthash { static const int SIZE = 1<<13; int table[SIZE]; vector verts; vector chain; - verthash() { clearverts(); } - - void clearverts() - { + void clearverts() { memset(table, -1, sizeof(table)); chain.setsize(0); verts.setsize(0); } - - int addvert(const vertex &v) - { + int addvert(const vertex &v) { uint h = hthash(v.pos)&(SIZE-1); - for(int i = table[h]; i>=0; i = chain[i]) - { + for(int i = table[h]; i>=0; i = chain[i]) { const vertex &c = verts[i]; if(c.pos==v.pos && c.tc==v.tc && c.norm==v.norm && c.tangent==v.tangent && (v.lm.iszero() || c.lm==v.lm)) return i; @@ -147,9 +118,7 @@ struct verthash chain.add(table[h]); return table[h] = verts.length()-1; } - - int addvert(const vec &pos, const vec2 &tc = vec2(0, 0), const svec2 &lm = svec2(0, 0), const bvec &norm = bvec(128, 128, 128), const bvec4 &tangent = bvec4(128, 128, 128, 128)) - { + int addvert(const vec &pos, const vec2 &tc = vec2(0, 0), const svec2 &lm = svec2(0, 0), const bvec &norm = bvec(128, 128, 128), const bvec4 &tangent = bvec4(128, 128, 128, 128)) { vertex vtx; vtx.pos = pos; vtx.tc = tc; @@ -160,46 +129,37 @@ struct verthash } }; -enum -{ +enum { NO_ALPHA = 0, ALPHA_BACK, ALPHA_FRONT }; -struct sortkey -{ +struct sortkey { ushort tex, lmid; uchar dim, layer, alpha; - sortkey() {} sortkey(ushort tex, ushort lmid, uchar dim, uchar layer = LAYER_TOP, uchar alpha = NO_ALPHA) : tex(tex), lmid(lmid), dim(dim), layer(layer), alpha(alpha) {} - bool operator==(const sortkey &o) const { return tex==o.tex && lmid==o.lmid && dim==o.dim && layer==o.layer && alpha==o.alpha; } }; -struct sortval -{ +struct sortval { int unlit; vector tris[2]; - sortval() : unlit(0) {} }; -static inline bool htcmp(const sortkey &x, const sortkey &y) -{ +static inline bool htcmp(const sortkey &x, const sortkey &y) { return x == y; } -static inline uint hthash(const sortkey &k) -{ +static inline uint hthash(const sortkey &k) { return k.tex + k.lmid*9741; } -struct vacollect : verthash -{ +struct vacollect : verthash { ivec origin; int size; hashtable indices; @@ -207,9 +167,7 @@ struct vacollect : verthash vector matsurfs; vector mapmodels; int worldtris; - - void clear() - { + void clear() { clearverts(); worldtris = 0; indices.clear(); @@ -217,47 +175,38 @@ struct vacollect : verthash mapmodels.setsize(0); texs.setsize(0); } - - void remapunlit(vector &remap) - { + void remapunlit(vector &remap) { uint lastlmid[8] = { LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT }, firstlmid[8] = { LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT }; int firstlit[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; - loopv(texs) - { + loopv(texs) { sortkey &k = texs[i]; - if(k.lmid>=LMID_RESERVED) - { + if(k.lmid>=LMID_RESERVED) { LightMapTexture &lmtex = lightmaptexs[k.lmid]; int type = lmtex.type&LM_TYPE; if(k.layer==LAYER_BLEND) type += 2; else if(k.alpha) type += 4 + 2*(k.alpha-1); lastlmid[type] = lmtex.unlitx>=0 ? (int) k.lmid : (int) LMID_AMBIENT; - if(firstlmid[type]==LMID_AMBIENT && lastlmid[type]!=LMID_AMBIENT) - { + if(firstlmid[type]==LMID_AMBIENT && lastlmid[type]!=LMID_AMBIENT) { firstlit[type] = i; firstlmid[type] = lastlmid[type]; } } - else if(k.lmid==LMID_AMBIENT) - { + else if(k.lmid==LMID_AMBIENT) { Shader *s = lookupvslot(k.tex, false).slot->shader; int type = s->type&SHADER_NORMALSLMS ? LM_BUMPMAP0 : LM_DIFFUSE; if(k.layer==LAYER_BLEND) type += 2; else if(k.alpha) type += 4 + 2*(k.alpha-1); - if(lastlmid[type]!=LMID_AMBIENT) - { + if(lastlmid[type]!=LMID_AMBIENT) { sortval &t = indices[k]; if(t.unlit<=0) t.unlit = lastlmid[type]; } } } - loopj(2) - { + loopj(2) { int offset = 2*j; if(firstlmid[offset]==LMID_AMBIENT && firstlmid[offset+1]==LMID_AMBIENT) continue; - loopi(max(firstlit[offset], firstlit[offset+1])) - { + loopi(max(firstlit[offset], firstlit[offset+1])) { sortkey &k = texs[i]; if((j ? k.layer!=LAYER_BLEND : k.layer==LAYER_BLEND) || k.alpha) continue; if(k.lmid!=LMID_AMBIENT) continue; @@ -267,12 +216,10 @@ struct vacollect : verthash indices[k].unlit = firstlmid[type]; } } - loopj(2) - { + loopj(2) { int offset = 4 + 2*j; if(firstlmid[offset]==LMID_AMBIENT && firstlmid[offset+1]==LMID_AMBIENT) continue; - loopi(max(firstlit[offset], firstlit[offset+1])) - { + loopi(max(firstlit[offset], firstlit[offset+1])) { sortkey &k = texs[i]; if(k.alpha != j+1) continue; if(k.lmid!=LMID_AMBIENT) continue; @@ -282,20 +229,17 @@ struct vacollect : verthash indices[k].unlit = firstlmid[type]; } } - loopv(remap) - { + loopv(remap) { sortkey &k = remap[i]; sortval &t = indices[k]; if(t.unlit<=0) continue; LightMapTexture &lm = lightmaptexs[t.unlit]; svec2 lmtc(short(ceil((lm.unlitx + 0.5f) * SHRT_MAX/lm.w)), short(ceil((lm.unlity + 0.5f) * SHRT_MAX/lm.h))); - loopl(2) loopvj(t.tris[l]) - { + loopl(2) loopvj(t.tris[l]) { vertex &vtx = verts[t.tris[l][j]]; if(vtx.lm.iszero()) vtx.lm = lmtc; - else if(vtx.lm != lmtc) - { + else if(vtx.lm != lmtc) { vertex vtx2 = vtx; vtx2.lm = lmtc; t.tris[l][j] = addvert(vtx2); @@ -305,26 +249,20 @@ struct vacollect : verthash if(dst) loopl(2) loopvj(t.tris[l]) dst->tris[l].add(t.tris[l][j]); } } - - void optimize() - { + void optimize() { vector remap; enumeratekt(indices, sortkey, k, sortval, t, - loopl(2) if(t.tris[l].length() && t.unlit<=0) - { - if(k.lmid>=LMID_RESERVED && lightmaptexs[k.lmid].unlitx>=0) - { + loopl(2) if(t.tris[l].length() && t.unlit<=0) { + if(k.lmid>=LMID_RESERVED && lightmaptexs[k.lmid].unlitx>=0) { sortkey ukey(k.tex, LMID_AMBIENT, k.dim, k.layer, k.alpha); sortval *uval = indices.access(ukey); - if(uval && uval->unlit<=0) - { + if(uval && uval->unlit<=0) { if(uval->unlit<0) texs.removeobj(ukey); else remap.add(ukey); uval->unlit = k.lmid; } } - else if(k.lmid==LMID_AMBIENT) - { + else if(k.lmid==LMID_AMBIENT) { remap.add(k); t.unlit = -1; } @@ -333,20 +271,15 @@ struct vacollect : verthash } ); texs.sort(texsort); - remapunlit(remap); - matsurfs.shrink(optimizematsurfs(matsurfs.getbuf(), matsurfs.length())); } - - static inline bool texsort(const sortkey &x, const sortkey &y) - { + static inline bool texsort(const sortkey &x, const sortkey &y) { if(x.alpha < y.alpha) return true; if(x.alpha > y.alpha) return false; if(x.layer < y.layer) return true; if(x.layer > y.layer) return false; - if(x.tex == y.tex) - { + if(x.tex == y.tex) { if(x.lmid < y.lmid) return true; if(x.lmid > y.lmid) return false; if(x.dim < y.dim) return true; @@ -362,24 +295,20 @@ struct vacollect : verthash else return false; } -#define GENVERTS(type, ptr, body) do \ - { \ +#define GENVERTS(type, ptr, body) do { \ + \ type *f = (type *)ptr; \ - loopv(verts) \ - { \ + loopv(verts) { \ + \ const vertex &v = verts[i]; \ body; \ f++; \ } \ } while(0) - - void genverts(void *buf) - { + void genverts(void *buf) { GENVERTS(vertex, buf, { *f = v; f->norm.flip(); f->tangent.flip(); }); } - - void setupdata(vtxarray *va) - { + void setupdata(vtxarray *va) { va->verts = verts.length(); va->tris = worldtris/3; va->vbuf = 0; @@ -387,27 +316,22 @@ struct vacollect : verthash va->minvert = 0; va->maxvert = va->verts-1; va->voffset = 0; - if(va->verts) - { + if(va->verts) { if(vbosize[VBO_VBUF] + verts.length() > maxvbosize || vbosize[VBO_EBUF] + worldtris > USHRT_MAX) flushvbo(); - va->voffset = vbosize[VBO_VBUF]; uchar *vdata = addvbo(va, VBO_VBUF, va->verts, sizeof(vertex)); genverts(vdata); va->minvert += va->voffset; va->maxvert += va->voffset; } - va->matbuf = NULL; va->matsurfs = matsurfs.length(); - if(va->matsurfs) - { + if(va->matsurfs) { va->matbuf = new materialsurface[matsurfs.length()]; memcpy(va->matbuf, matsurfs.getbuf(), matsurfs.length()*sizeof(materialsurface)); } - va->eslist = NULL; va->texs = texs.length(); va->blendtris = 0; @@ -419,13 +343,11 @@ struct vacollect : verthash va->ebuf = 0; va->edata = 0; va->texmask = 0; - if(va->texs) - { + if(va->texs) { va->eslist = new elementset[va->texs]; va->edata += vbosize[VBO_EBUF]; ushort *edata = (ushort *)addvbo(va, VBO_EBUF, worldtris, sizeof(ushort)), *curbuf = edata; - loopv(texs) - { + loopv(texs) { const sortkey &k = texs[i]; const sortval &t = indices[k]; elementset &e = va->eslist[i]; @@ -434,22 +356,16 @@ struct vacollect : verthash e.dim = k.dim; e.layer = k.layer; ushort *startbuf = curbuf; - loopl(2) - { + loopl(2) { e.minvert[l] = USHRT_MAX; e.maxvert[l] = 0; - - if(t.tris[l].length()) - { + if(t.tris[l].length()) { memcpy(curbuf, t.tris[l].getbuf(), t.tris[l].length() * sizeof(ushort)); - - loopvj(t.tris[l]) - { + loopvj(t.tris[l]) { curbuf[j] += va->voffset; e.minvert[l] = min(e.minvert[l], curbuf[j]); e.maxvert[l] = max(e.maxvert[l], curbuf[j]); } - curbuf += t.tris[l].length(); } e.length[l] = curbuf-startbuf; @@ -457,19 +373,14 @@ struct vacollect : verthash if(k.layer==LAYER_BLEND) { va->texs--; va->tris -= e.length[1]/3; va->blends++; va->blendtris += e.length[1]/3; } else if(k.alpha==ALPHA_BACK) { va->texs--; va->tris -= e.length[1]/3; va->alphaback++; va->alphabacktris += e.length[1]/3; } else if(k.alpha==ALPHA_FRONT) { va->texs--; va->tris -= e.length[1]/3; va->alphafront++; va->alphafronttris += e.length[1]/3; } - Slot &slot = *lookupvslot(k.tex, false).slot; loopvj(slot.sts) va->texmask |= 1<alphatris = va->alphabacktris + va->alphafronttris; - if(mapmodels.length()) va->mapmodels.put(mapmodels.getbuf(), mapmodels.length()); } - - bool emptyva() - { + bool emptyva() { return verts.empty() && matsurfs.empty() && mapmodels.empty(); } } vc; @@ -481,24 +392,20 @@ vector tjoints; vec shadowmapmin, shadowmapmax; -int calcshadowmask(vec *pos, int numpos) -{ +int calcshadowmask(vec *pos, int numpos) { extern vec shadowdir; int mask = 0, used = 1; vec pe = vec(pos[1]).sub(pos[0]); - loopk(numpos-2) - { + loopk(numpos-2) { vec e = vec(pos[k+2]).sub(pos[0]); - if(vec().cross(pe, e).dot(shadowdir)>0) - { + if(vec().cross(pe, e).dot(shadowdir)>0) { mask |= 1< &idxs = vc.indices[key].tris[(shadowmask>>i)&1]; int left = index[0], mid = index[i+1], right = index[i+2], start = left, i0 = left, i1 = -1; - loopk(4) - { + loopk(4) { int i2 = -1, ctj = -1, cedge = -1; - switch(k) - { + switch(k) { case 1: i1 = i2 = mid; cedge = edge+i+1; break; case 2: if(i1 != mid || i0 == left) { i0 = i1; i1 = right; } i2 = right; if(i+1 == numverts-2) cedge = edge+i+2; break; case 3: if(i0 == start) { i0 = i1; i1 = left; } i2 = left; // fall-through default: if(!i) cedge = edge; break; } - if(i1 != i2) - { + if(i1 != i2) { if(total + 3 > USHRT_MAX) return; total += 3; idxs.add(i0); @@ -575,18 +474,15 @@ void addtris(const sortkey &key, int orient, vertex *verts, int *index, int numv idxs.add(i2); i1 = i2; } - if(cedge >= 0) - { - for(ctj = tj;;) - { + if(cedge >= 0) { + for(ctj = tj;;) { if(ctj < 0) break; if(tjoints[ctj].edge < cedge) { ctj = tjoints[ctj].next; continue; } if(tjoints[ctj].edge != cedge) ctj = -1; break; } } - if(ctj >= 0) - { + if(ctj >= 0) { int e1 = cedge%(MAXFACEVERTS+1), e2 = (e1+1)%numverts; vertex &v1 = verts[e1], &v2 = verts[e2]; ivec d(vec(v2.pos).sub(v1.pos).mul(8)); @@ -598,15 +494,12 @@ void addtris(const sortkey &key, int orient, vertex *verts, int *index, int numv offset2 = (int(v2.pos[axis]*8) - origin) / d[axis]; vec o = vec(v1.pos).sub(vec(d).mul(offset1/8.0f)); float doffset = 1.0f / (offset2 - offset1); - - if(i1 < 0) for(;;) - { + if(i1 < 0) for(;;) { tjoint &t = tjoints[ctj]; if(t.next < 0 || tjoints[t.next].edge != cedge) break; ctj = t.next; } - while(ctj >= 0) - { + while(ctj >= 0) { tjoint &t = tjoints[ctj]; if(t.edge != cedge) break; float offset = (t.offset - offset1) * doffset; @@ -619,8 +512,7 @@ void addtris(const sortkey &key, int orient, vertex *verts, int *index, int numv vt.tangent.lerp(v1.tangent, v2.tangent, offset); int i2 = vc.addvert(vt); if(i2 < 0) return; - if(i1 >= 0) - { + if(i1 >= 0) { if(total + 3 > USHRT_MAX) return; total += 3; idxs.add(i0); @@ -636,8 +528,7 @@ void addtris(const sortkey &key, int orient, vertex *verts, int *index, int numv } } -static inline void calctexgen(VSlot &vslot, int dim, vec4 &sgen, vec4 &tgen) -{ +static inline void calctexgen(VSlot &vslot, int dim, vec4 &sgen, vec4 &tgen) { Texture *tex = vslot.slot->sts.empty() ? notexture : vslot.slot->sts[0].t; const texrotation &r = texrotations[vslot.rotation]; float k = TEX_SCALE/vslot.scale, @@ -650,53 +541,45 @@ static inline void calctexgen(VSlot &vslot, int dim, vec4 &sgen, vec4 &tgen) int sdim = si[dim], tdim = ti[dim]; sgen = vec4(0, 0, 0, soff); tgen = vec4(0, 0, 0, toff); - if(r.swapxy) - { + if(r.swapxy) { sgen[tdim] = (dim <= 1 ? -sk : sk); tgen[sdim] = tk; } - else - { + else { sgen[sdim] = sk; tgen[tdim] = (dim <= 1 ? -tk : tk); } } -ushort encodenormal(const vec &n) -{ +ushort encodenormal(const vec &n) { if(n.iszero()) return 0; int yaw = int(-atan2(n.x, n.y)/RAD), pitch = int(asin(n.z)/RAD); return ushort(clamp(pitch + 90, 0, 180)*360 + (yaw < 0 ? yaw%360 + 360 : yaw%360) + 1); } -vec decodenormal(ushort norm) -{ +vec decodenormal(ushort norm) { if(!norm) return vec(0, 0, 1); norm--; const vec2 &yaw = sincos360[norm%360], &pitch = sincos360[norm/360+270]; return vec(-yaw.y*pitch.x, yaw.x*pitch.x, pitch.y); } -void guessnormals(const vec *pos, int numverts, vec *normals) -{ +void guessnormals(const vec *pos, int numverts, vec *normals) { vec n1, n2; n1.cross(pos[0], pos[1], pos[2]); - if(numverts != 4) - { + if(numverts != 4) { n1.normalize(); loopk(numverts) normals[k] = n1; return; } n2.cross(pos[0], pos[2], pos[3]); - if(n1.iszero()) - { + if(n1.iszero()) { n2.normalize(); loopk(4) normals[k] = n2; return; } else n1.normalize(); - if(n2.iszero()) - { + if(n2.iszero()) { loopk(4) normals[k] = n1; return; } @@ -708,16 +591,13 @@ void guessnormals(const vec *pos, int numverts, vec *normals) normals[3] = n2; } -void addcubeverts(VSlot &vslot, int orient, int size, vec *pos, int convex, ushort texture, ushort lmid, vertinfo *vinfo, int numverts, int tj = -1, int grassy = 0, bool alpha = false, int layer = LAYER_TOP) -{ +void addcubeverts(VSlot &vslot, int orient, int size, vec *pos, int convex, ushort texture, ushort lmid, vertinfo *vinfo, int numverts, int tj = -1, int grassy = 0, bool alpha = false, int layer = LAYER_TOP) { (void) grassy; int dim = dimension(orient); int shadowmask = alpha ? 0 : calcshadowmask(pos, numverts); - LightMap *lm = NULL; LightMapTexture *lmtex = NULL; - if(lightmaps.inrange(lmid-LMID_RESERVED)) - { + if(lightmaps.inrange(lmid-LMID_RESERVED)) { lm = &lightmaps[lmid-LMID_RESERVED]; if((lm->type&LM_TYPE)==LM_DIFFUSE || ((lm->type&LM_TYPE)==LM_BUMPMAP0 && @@ -726,70 +606,58 @@ void addcubeverts(VSlot &vslot, int orient, int size, vec *pos, int convex, usho lmtex = &lightmaptexs[lm->tex]; else lm = NULL; } - vec4 sgen, tgen; calctexgen(vslot, dim, sgen, tgen); vertex verts[MAXFACEVERTS]; int index[MAXFACEVERTS]; - loopk(numverts) - { + loopk(numverts) { vertex &v = verts[k]; v.pos = pos[k]; v.tc = vec2(sgen.dot(v.pos), tgen.dot(v.pos)); - if(lmtex) - { + if(lmtex) { v.lm = svec2(short(ceil((lm->offsetx + vinfo[k].u*(float(LM_PACKW)/float(USHRT_MAX+1)) + 0.5f) * float(SHRT_MAX)/lmtex->w)), short(ceil((lm->offsety + vinfo[k].v*(float(LM_PACKH)/float(USHRT_MAX+1)) + 0.5f) * float(SHRT_MAX)/lmtex->h))); } else v.lm = svec2(0, 0); - if(vinfo && vinfo[k].norm) - { + if(vinfo && vinfo[k].norm) { vec n = decodenormal(vinfo[k].norm), t = orientation_tangent[vslot.rotation][dim]; t.project(n).normalize(); v.norm = bvec(n); v.tangent = bvec4(bvec(t), orientation_bitangent[vslot.rotation][dim].scalartriple(n, t) < 0 ? 0 : 255); } - else - { + else { v.norm = bvec(128, 128, 255); v.tangent = bvec4(255, 128, 128, 255); } index[k] = vc.addvert(v); if(index[k] < 0) return; } - if(lmid >= LMID_RESERVED) lmid = lm ? lm->tex : LMID_AMBIENT; - sortkey key(texture, lmid, !vslot.scroll.iszero() ? dim : 3, layer == LAYER_BLEND ? LAYER_BLEND : LAYER_TOP, alpha ? (vslot.alphaback ? ALPHA_BACK : (vslot.alphafront ? ALPHA_FRONT : NO_ALPHA)) : NO_ALPHA); addtris(key, orient, verts, index, numverts, convex, shadowmask, tj); } -struct edgegroup -{ +struct edgegroup { ivec slope, origin; int axis; }; -static uint hthash(const edgegroup &g) -{ +static uint hthash(const edgegroup &g) { return g.slope.x^(g.slope.y<<2)^(g.slope.z<<4)^g.origin.x^g.origin.y^g.origin.z; } -static bool htcmp(const edgegroup &x, const edgegroup &y) -{ +static bool htcmp(const edgegroup &x, const edgegroup &y) { return x.slope==y.slope && x.origin==y.origin; } -enum -{ +enum { CE_START = 1<<0, CE_END = 1<<1, CE_FLIP = 1<<2, CE_DUP = 1<<3 }; -struct cubeedge -{ +struct cubeedge { cube *c; int next, offset; ushort size; @@ -799,26 +667,21 @@ struct cubeedge vector cubeedges; hashtable edgegroups(1<<13); -void gencubeedges(cube &c, const ivec &co, int size) -{ +void gencubeedges(cube &c, const ivec &co, int size) { ivec pos[MAXFACEVERTS]; int vis; - loopi(6) if((vis = visibletris(c, i, co, size))) - { + loopi(6) if((vis = visibletris(c, i, co, size))) { int numverts = c.ext ? c.ext->surfaces[i].numverts&MAXFACEVERTS : 0; - if(numverts) - { + if(numverts) { vertinfo *verts = c.ext->verts() + c.ext->surfaces[i].verts; ivec vo = ivec(co).mask(~0xFFF).shl(3); - loopj(numverts) - { + loopj(numverts) { vertinfo &v = verts[j]; pos[j] = ivec(v.x, v.y, v.z).add(vo); } } else if(c.merged&(1< abs(d.y) ? (abs(d.x) > abs(d.z) ? 0 : 2) : (abs(d.y) > abs(d.z) ? 1 : 2); - if(d[axis] < 0) - { + if(d[axis] < 0) { d.neg(); swap(e1, e2); } reduceslope(d); - int t1 = pos[e1][axis]/d[axis], t2 = pos[e2][axis]/d[axis]; edgegroup g; @@ -855,22 +715,17 @@ void gencubeedges(cube &c, const ivec &co, int size) ce.index = i*(MAXFACEVERTS+1)+j; ce.flags = CE_START | CE_END | (e1!=j ? CE_FLIP : 0); ce.next = -1; - bool insert = true; int *exists = edgegroups.access(g); - if(exists) - { + if(exists) { int prev = -1, cur = *exists; - while(cur >= 0) - { + while(cur >= 0) { cubeedge &p = cubeedges[cur]; - if(ce.offset <= p.offset+p.size) - { + if(ce.offset <= p.offset+p.size) { if(ce.offset < p.offset) break; if(p.flags&CE_DUP ? ce.offset+ce.size <= p.offset+p.size : - ce.offset==p.offset && ce.size==p.size) - { + ce.offset==p.offset && ce.size==p.size) { p.flags |= CE_DUP; insert = false; break; @@ -880,11 +735,9 @@ void gencubeedges(cube &c, const ivec &co, int size) prev = cur; cur = p.next; } - if(insert) - { + if(insert) { ce.next = cur; - while(cur >= 0) - { + while(cur >= 0) { cubeedge &p = cubeedges[cur]; if(ce.offset+ce.size==p.offset) { ce.flags &= ~CE_END; break; } cur = p.next; @@ -894,18 +747,15 @@ void gencubeedges(cube &c, const ivec &co, int size) } } else edgegroups[g] = cubeedges.length(); - if(insert) cubeedges.add(ce); } } } -void gencubeedges(cube *c = worldroot, const ivec &co = ivec(0, 0, 0), int size = worldsize>>1) -{ +void gencubeedges(cube *c = worldroot, const ivec &co = ivec(0, 0, 0), int size = worldsize>>1) { progress("fixing t-joints..."); neighbourstack[++neighbourdepth] = c; - loopi(8) - { + loopi(8) { ivec o(i, co, size); if(c[i].ext) c[i].ext->tjoints = -1; if(c[i].children) gencubeedges(c[i].children, o, size>>1); @@ -914,29 +764,23 @@ void gencubeedges(cube *c = worldroot, const ivec &co = ivec(0, 0, 0), int size --neighbourdepth; } -void gencubeverts(cube &c, const ivec &co, int size, int csi) -{ +void gencubeverts(cube &c, const ivec &co, int size, int csi) { if(!(c.visible&0xC0)) return; - int vismask = ~c.merged & 0x3F; if(!(c.visible&0x80)) vismask &= c.visible; if(!vismask) return; - int tj = filltjoints && c.ext ? c.ext->tjoints : -1, vis; - loopi(6) if(vismask&(1<surfaces[i].numverts&MAXFACEVERTS : 0, convex = 0; - if(numverts) - { + if(numverts) { verts = c.ext->verts() + c.ext->surfaces[i].verts; vec vo(ivec(co).mask(~0xFFF)); loopj(numverts) pos[j] = vec(verts[j].getxyz()).mul(1.0f/8).add(vo); if(!flataxisface(c, i)) convex = faceconvexity(verts, numverts, size); } - else - { + else { ivec v[4]; genfaceverts(c, i, v); if(!flataxisface(c, i)) convex = faceconvexity(v); @@ -947,15 +791,13 @@ void gencubeverts(cube &c, const ivec &co, int size, int csi) pos[numverts++] = vec(v[order+2]).mul(size/8.0f).add(vo); if(vis&2) pos[numverts++] = vec(v[(order+3)&3]).mul(size/8.0f).add(vo); } - VSlot &vslot = lookupvslot(c.texture[i], true), *layer = vslot.layer && !(c.material&MAT_ALPHA) ? &lookupvslot(vslot.layer, true) : NULL; while(tj >= 0 && tjoints[tj].edge < i*(MAXFACEVERTS+1)) tj = tjoints[tj].next; int hastj = tj >= 0 && tjoints[tj].edge < (i+1)*(MAXFACEVERTS+1) ? tj : -1; if(!c.ext) addcubeverts(vslot, i, size, pos, convex, c.texture[i], LMID_AMBIENT, NULL, numverts, hastj, 0, (c.material&MAT_ALPHA)!=0); - else - { + else { const surfaceinfo &surf = c.ext->surfaces[i]; if(!surf.numverts || surf.numverts&LAYER_TOP) addcubeverts(vslot, i, size, pos, convex, c.texture[i], surf.lmid[0], verts, numverts, hastj, 0, (c.material&MAT_ALPHA)!=0, LAYER_TOP|(surf.numverts&LAYER_BLEND)); @@ -971,10 +813,8 @@ int allocva = 0; int wtris = 0, wverts = 0, vtris = 0, vverts = 0, glde = 0, gbatches = 0; vector valist, varoot; -vtxarray *newva(const ivec &co, int size) -{ +vtxarray *newva(const ivec &co, int size) { vc.optimize(); - vtxarray *va = new vtxarray; va->parent = NULL; va->o = co; @@ -986,29 +826,23 @@ vtxarray *newva(const ivec &co, int size) va->bbmax = ivec(-1, -1, -1); va->hasmerges = 0; va->mergelevel = -1; - vc.setupdata(va); - wverts += va->verts; wtris += va->tris + va->blends + va->alphatris; allocva++; valist.add(va); - return va; } -void destroyva(vtxarray *va, bool reparent) -{ +void destroyva(vtxarray *va, bool reparent) { wverts -= va->verts; wtris -= va->tris + va->blends + va->alphatris; allocva--; valist.removeobj(va); if(!va->parent) varoot.removeobj(va); - if(reparent) - { + if(reparent) { if(va->parent) va->parent->children.removeobj(va); - loopv(va->children) - { + loopv(va->children) { vtxarray *child = va->children[i]; child->parent = va->parent; if(child->parent) child->parent->children.add(child); @@ -1021,12 +855,9 @@ void destroyva(vtxarray *va, bool reparent) delete va; } -void clearvas(cube *c) -{ - loopi(8) - { - if(c[i].ext) - { +void clearvas(cube *c) { + loopi(8) { + if(c[i].ext) { if(c[i].ext->va) destroyva(c[i].ext->va, false); c[i].ext->va = NULL; c[i].ext->tjoints = -1; @@ -1035,23 +866,19 @@ void clearvas(cube *c) } } -void updatevabb(vtxarray *va, bool force) -{ +void updatevabb(vtxarray *va, bool force) { if(!force && va->bbmin.x >= 0) return; - va->bbmin = va->geommin; va->bbmax = va->geommax; va->bbmin.min(va->matmin); va->bbmax.max(va->matmax); - loopv(va->children) - { + loopv(va->children) { vtxarray *child = va->children[i]; updatevabb(child, force); va->bbmin.min(child->bbmin); va->bbmax.max(child->bbmax); } - loopv(va->mapmodels) - { + loopv(va->mapmodels) { octaentities *oe = va->mapmodels[i]; va->bbmin.min(oe->bbmin); va->bbmax.max(oe->bbmax); @@ -1060,13 +887,11 @@ void updatevabb(vtxarray *va, bool force) va->bbmax.min(ivec(va->o).add(va->size)); } -void updatevabbs(bool force) -{ +void updatevabbs(bool force) { loopv(varoot) updatevabb(varoot[i], force); } -struct mergedface -{ +struct mergedface { uchar orient, lmid, numverts; ushort mat, tex; vertinfo *verts; @@ -1077,16 +902,13 @@ struct mergedface static int vahasmerges = 0, vamergemax = 0; static vector vamerges[MAXMERGELEVEL+1]; -int genmergedfaces(cube &c, const ivec &co, int size, int minlevel = -1) -{ +int genmergedfaces(cube &c, const ivec &co, int size, int minlevel = -1) { if(!c.ext || isempty(c)) return -1; int tj = c.ext->tjoints, maxlevel = -1; - loopi(6) if(c.merged&(1<surfaces[i]; int numverts = surf.numverts&MAXFACEVERTS; - if(!numverts) - { + if(!numverts) { if(minlevel < 0) vahasmerges |= MERGE_PART; continue; } @@ -1099,18 +921,13 @@ int genmergedfaces(cube &c, const ivec &co, int size, int minlevel = -1) mf.verts = c.ext->verts() + surf.verts; mf.tjoints = -1; int level = calcmergedsize(i, co, size, mf.verts, mf.numverts&MAXFACEVERTS); - if(level > minlevel) - { + if(level > minlevel) { maxlevel = max(maxlevel, level); - while(tj >= 0 && tjoints[tj].edge < i*(MAXFACEVERTS+1)) tj = tjoints[tj].next; if(tj >= 0 && tjoints[tj].edge < (i+1)*(MAXFACEVERTS+1)) mf.tjoints = tj; - VSlot &vslot = lookupvslot(mf.tex, true); - if(surf.numverts&LAYER_TOP) vamerges[level].add(mf); - if(surf.numverts&LAYER_BOTTOM) - { + if(surf.numverts&LAYER_BOTTOM) { mf.tex = vslot.layer; mf.lmid = surf.lmid[1]; mf.numverts &= ~LAYER_TOP; @@ -1119,22 +936,18 @@ int genmergedfaces(cube &c, const ivec &co, int size, int minlevel = -1) } } } - if(maxlevel >= 0) - { + if(maxlevel >= 0) { vamergemax = max(vamergemax, maxlevel); vahasmerges |= MERGE_ORIGIN; } return maxlevel; } -int findmergedfaces(cube &c, const ivec &co, int size, int csi, int minlevel) -{ +int findmergedfaces(cube &c, const ivec &co, int size, int csi, int minlevel) { if(c.ext && c.ext->va && !(c.ext->va->hasmerges&MERGE_ORIGIN)) return c.ext->va->mergelevel; - else if(c.children) - { + else if(c.children) { int maxlevel = -1; - loopi(8) - { + loopi(8) { ivec o(i, co, size/2); int level = findmergedfaces(c.children[i], o, size/2, csi-1, minlevel); maxlevel = max(maxlevel, level); @@ -1145,18 +958,15 @@ int findmergedfaces(cube &c, const ivec &co, int size, int csi, int minlevel) else return -1; } -void addmergedverts(int level, const ivec &o) -{ +void addmergedverts(int level, const ivec &o) { vector &mfl = vamerges[level]; if(mfl.empty()) return; vec vo(ivec(o).mask(~0xFFF)); vec pos[MAXFACEVERTS]; - loopv(mfl) - { + loopv(mfl) { mergedface &mf = mfl[i]; int numverts = mf.numverts&MAXFACEVERTS; - loopi(numverts) - { + loopi(numverts) { vertinfo &v = mf.verts[i]; pos[i] = vec(v.x, v.y, v.z).mul(1.0f/8).add(vo); } @@ -1167,21 +977,16 @@ void addmergedverts(int level, const ivec &o) mfl.setsize(0); } -void rendercube(cube &c, const ivec &co, int size, int csi, int &maxlevel) // creates vertices and indices ready to be put into a va -{ +void rendercube(cube &c, const ivec &co, int size, int csi, int &maxlevel) { // creates vertices and indices ready to be put into a va { //if(size<=16) return; - if(c.ext && c.ext->va) - { + if(c.ext && c.ext->va) { maxlevel = max(maxlevel, c.ext->va->mergelevel); return; // don't re-render } - - if(c.children) - { + if(c.children) { neighbourstack[++neighbourdepth] = c.children; c.escaped = 0; - loopi(8) - { + loopi(8) { ivec o(i, co, size/2); int level = -1; rendercube(c.children[i], o, size/2, csi-1, level); @@ -1190,91 +995,65 @@ void rendercube(cube &c, const ivec &co, int size, int csi, int &maxlevel) // c maxlevel = max(maxlevel, level); } --neighbourdepth; - if(csi <= MAXMERGELEVEL && vamerges[csi].length()) addmergedverts(csi, co); - - if(c.ext) - { + if(c.ext) { if(c.ext->ents && c.ext->ents->mapmodels.length()) vc.mapmodels.add(c.ext->ents); } return; } - - if(!isempty(c)) - { + if(!isempty(c)) { gencubeverts(c, co, size, csi); if(c.merged) maxlevel = max(maxlevel, genmergedfaces(c, co, size)); } if(c.material != MAT_AIR) genmatsurfs(c, co, size, vc.matsurfs); - - if(c.ext) - { + if(c.ext) { if(c.ext->ents && c.ext->ents->mapmodels.length()) vc.mapmodels.add(c.ext->ents); } - if(csi <= MAXMERGELEVEL && vamerges[csi].length()) addmergedverts(csi, co); } -void calcgeombb(const ivec &co, int size, ivec &bbmin, ivec &bbmax) -{ +void calcgeombb(const ivec &co, int size, ivec &bbmin, ivec &bbmax) { vec vmin(co), vmax = vmin; vmin.add(size); - - loopv(vc.verts) - { + loopv(vc.verts) { const vec &v = vc.verts[i].pos; vmin.min(v); vmax.max(v); } - bbmin = ivec(vmin.mul(8)).shr(3); bbmax = ivec(vmax.mul(8)).add(7).shr(3); } -void calcmatbb(const ivec &co, int size, ivec &bbmin, ivec &bbmax) -{ +void calcmatbb(const ivec &co, int size, ivec &bbmin, ivec &bbmax) { bbmax = co; (bbmin = bbmax).add(size); - loopv(vc.matsurfs) - { + loopv(vc.matsurfs) { materialsurface &m = vc.matsurfs[i]; - int dim = dimension(m.orient), r = R[dim], c = C[dim]; bbmin[dim] = min(bbmin[dim], m.o[dim]); bbmax[dim] = max(bbmax[dim], m.o[dim]); - bbmin[r] = min(bbmin[r], m.o[r]); bbmax[r] = max(bbmax[r], m.o[r] + m.rsize); - bbmin[c] = min(bbmin[c], m.o[c]); bbmax[c] = max(bbmax[c], m.o[c] + m.csize); } } -void setva(cube &c, const ivec &co, int size, int csi) -{ +void setva(cube &c, const ivec &co, int size, int csi) { ASSERT(size <= 0x1000); - int vamergeoffset[MAXMERGELEVEL+1]; loopi(MAXMERGELEVEL+1) vamergeoffset[i] = vamerges[i].length(); - vc.origin = co; vc.size = size; - shadowmapmin = vec(co).add(size); shadowmapmax = vec(co); - int maxlevel = -1; rendercube(c, co, size, csi, maxlevel); - ivec bbmin, bbmax; - calcgeombb(co, size, bbmin, bbmax); - - if(size == min(0x1000, worldsize/2) || !vc.emptyva()) - { + if(size == min(0x1000, worldsize/2) || !vc.emptyva()) { vtxarray *va = newva(co, size); ext(c).va = va; va->geommin = bbmin; @@ -1285,29 +1064,22 @@ void setva(cube &c, const ivec &co, int size, int csi) va->hasmerges = vahasmerges; va->mergelevel = vamergemax; } - else - { + else { loopi(MAXMERGELEVEL+1) vamerges[i].setsize(vamergeoffset[i]); } - vc.clear(); } -static inline int setcubevisibility(cube &c, const ivec &co, int size) -{ +static inline int setcubevisibility(cube &c, const ivec &co, int size) { int numvis = 0, vismask = 0, collidemask = 0, checkmask = 0; - loopi(6) - { + loopi(6) { int facemask = classifyface(c, i, co, size); - if(facemask&1) - { + if(facemask&1) { vismask |= 1<surfaces[i].numverts&MAXFACEVERTS) numvis++; } - else - { + else { numvis++; if(!(c.ext && c.ext->surfaces[i].numverts&MAXFACEVERTS)) checkmask |= 1<va) - { + if(c[i].ext && c[i].ext->va) { varoot.add(c[i].ext->va); if(c[i].ext->va->hasmerges&MERGE_ORIGIN) findmergedfaces(c[i], o, size, csi, csi); } - else - { + else { if(c[i].children) count += updateva(c[i].children, o, size/2, csi-1); - else - { + else { if(!isempty(c[i])) count += setcubevisibility(c[i], o, size); } int tcount = count + (csi <= MAXMERGELEVEL ? vamerges[csi].length() : 0); - if(tcount > vafacemax || (tcount >= vafacemin && size >= vacubesize) || size == min(0x1000, worldsize/2)) - { + if(tcount > vafacemax || (tcount >= vafacemin && size >= vacubesize) || size == min(0x1000, worldsize/2)) { loadprogress = clamp(recalcprogress/float(allocnodes), 0.0f, 1.0f); setva(c[i], o, size, csi); - if(c[i].ext && c[i].ext->va) - { - while(varoot.length() > childpos) - { + if(c[i].ext && c[i].ext->va) { + while(varoot.length() > childpos) { vtxarray *child = varoot.pop(); c[i].ext->va->children.add(child); child->parent = c[i].ext->va; } varoot.add(c[i].ext->va); - if(vamergemax > size) - { + if(vamergemax > size) { cmergemax = max(cmergemax, vamergemax); chasmerges |= vahasmerges&~MERGE_USE; } @@ -1377,58 +1140,46 @@ int updateva(cube *c, const ivec &co, int size, int csi) --neighbourdepth; vamergemax = cmergemax; vahasmerges = chasmerges; - return ccount; } -void addtjoint(const edgegroup &g, const cubeedge &e, int offset) -{ +void addtjoint(const edgegroup &g, const cubeedge &e, int offset) { int vcoord = (g.slope[g.axis]*offset + g.origin[g.axis]) & 0x7FFF; tjoint &tj = tjoints.add(); tj.offset = vcoord / g.slope[g.axis]; tj.edge = e.index; - int prev = -1, cur = ext(*e.c).tjoints; - while(cur >= 0) - { + while(cur >= 0) { tjoint &o = tjoints[cur]; if(tj.edge < o.edge || (tj.edge==o.edge && (e.flags&CE_FLIP ? tj.offset > o.offset : tj.offset < o.offset))) break; prev = cur; cur = o.next; } - tj.next = cur; if(prev < 0) e.c->ext->tjoints = tjoints.length()-1; else tjoints[prev].next = tjoints.length()-1; } -void findtjoints(int cur, const edgegroup &g) -{ +void findtjoints(int cur, const edgegroup &g) { int active = -1; - while(cur >= 0) - { + while(cur >= 0) { cubeedge &e = cubeedges[cur]; int prevactive = -1, curactive = active; - while(curactive >= 0) - { + while(curactive >= 0) { cubeedge &a = cubeedges[curactive]; - if(a.offset+a.size <= e.offset) - { + if(a.offset+a.size <= e.offset) { if(prevactive >= 0) cubeedges[prevactive].next = a.next; else active = a.next; } - else - { + else { prevactive = curactive; - if(!(a.flags&CE_DUP)) - { + if(!(a.flags&CE_DUP)) { if(e.flags&CE_START && e.offset > a.offset && e.offset < a.offset+a.size) addtjoint(g, a, e.offset); if(e.flags&CE_END && e.offset+e.size > a.offset && e.offset+e.size < a.offset+a.size) addtjoint(g, a, e.offset+e.size); } - if(!(e.flags&CE_DUP)) - { + if(!(e.flags&CE_DUP)) { if(a.flags&CE_START && a.offset > e.offset && a.offset < e.offset+e.size) addtjoint(g, e, a.offset); if(a.flags&CE_END && a.offset+a.size > e.offset && a.offset+a.size < e.offset+e.size) @@ -1444,8 +1195,7 @@ void findtjoints(int cur, const edgegroup &g) } } -void findtjoints() -{ +void findtjoints() { recalcprogress = 0; gencubeedges(); tjoints.setsize(0); @@ -1454,38 +1204,31 @@ void findtjoints() edgegroups.clear(); } -void octarender() // creates va s for all leaf cubes that don't already have them -{ +void octarender() { // creates va s for all leaf cubes that don't already have them { int csi = 0; while(1< texs; - loopv(valist) - { + loopv(valist) { vtxarray *va = valist[i]; loopj(va->texs + va->blends) if(texs.find(va->eslist[j].texture) < 0) texs.add(va->eslist[j].texture); } - loopv(texs) - { + loopv(texs) { loadprogress = float(i+1)/texs.length(); lookupvslot(texs[i]); } loadprogress = 0; } -void allchanged(bool load) -{ +void allchanged(bool load) { renderprogress(0, "clearing vertex arrays..."); clearvas(worldroot); resetqueries(); @@ -1499,15 +1242,13 @@ void allchanged(bool load) setupmaterials(); updatevabbs(true); lightents(); - if(load) - { + if(load) { seedparticles(); drawtextures(); } } -void recalc() -{ +void recalc() { allchanged(true); } diff --git a/src/engine/physics.cpp b/src/engine/physics.cpp index b1b800a..a43e8b4 100644 --- a/src/engine/physics.cpp +++ b/src/engine/physics.cpp @@ -10,11 +10,9 @@ const int MAXCLIPPLANES = 1024; static clipplanes clipcache[MAXCLIPPLANES]; static int clipcacheversion = -2; -static inline clipplanes &getclipplanes(const cube &c, const ivec &o, int size, bool collide = true, int offset = 0) -{ +static inline clipplanes &getclipplanes(const cube &c, const ivec &o, int size, bool collide = true, int offset = 0) { clipplanes &p = clipcache[int(&c - worldroot)&(MAXCLIPPLANES-1)]; - if(p.owner != &c || p.version != clipcacheversion+offset) - { + if(p.owner != &c || p.version != clipcacheversion+offset) { p.owner = &c; p.version = clipcacheversion+offset; genclipplanes(c, o, size, p, collide); @@ -22,11 +20,9 @@ static inline clipplanes &getclipplanes(const cube &c, const ivec &o, int size, return p; } -void resetclipplanes() -{ +void resetclipplanes() { clipcacheversion += 2; - if(!clipcacheversion) - { + if(!clipcacheversion) { memclear(clipcache); clipcacheversion = 2; } @@ -36,24 +32,24 @@ void resetclipplanes() #define INTERSECTPLANES(setentry, exit) \ float enterdist = -1e16f, exitdist = 1e16f; \ - loopi(p.size) \ - { \ + loopi(p.size) { \ + \ float pdist = p.p[i].dist(v), facing = ray.dot(p.p[i]); \ - if(facing < 0) \ - { \ + if(facing < 0) { \ + \ pdist /= -facing; \ - if(pdist > enterdist) \ - { \ + if(pdist > enterdist) { \ + \ if(pdist > exitdist) exit; \ enterdist = pdist; \ setentry; \ } \ } \ - else if(facing > 0) \ - { \ + else if(facing > 0) { \ + \ pdist /= -facing; \ - if(pdist < exitdist) \ - { \ + if(pdist < exitdist) { \ + \ if(pdist < enterdist) exit; \ exitdist = pdist; \ } \ @@ -62,19 +58,19 @@ void resetclipplanes() } #define INTERSECTBOX(setentry, exit) \ - loop(i, 3) \ - { \ - if(ray[i]) \ - { \ + loop(i, 3) { \ + \ + if(ray[i]) { \ + \ float prad = fabs(p.r[i] * invray[i]), pdist = (p.o[i] - v[i]) * invray[i], pmin = pdist - prad, pmax = pdist + prad; \ - if(pmin > enterdist) \ - { \ + if(pmin > enterdist) { \ + \ if(pmin > exitdist) exit; \ enterdist = pmin; \ setentry; \ } \ - if(pmax < exitdist) \ - { \ + if(pmax < exitdist) { \ + \ if(pmax < enterdist) exit; \ exitdist = pmax; \ } \ @@ -84,8 +80,7 @@ void resetclipplanes() vec hitsurface; -static inline bool raycubeintersect(const clipplanes &p, const cube &c, const vec &v, const vec &ray, const vec &invray, float &dist) -{ +static inline bool raycubeintersect(const clipplanes &p, const cube &c, const vec &v, const vec &ray, const vec &invray, float &dist) { int entry = -1, bbentry = -1; INTERSECTPLANES(entry = i, return false); INTERSECTBOX(bbentry = i, return false); @@ -100,59 +95,50 @@ extern void entselectionbox(const entity &e, vec &eo, vec &es); float hitentdist; int hitent, hitorient; -static float disttoent(octaentities *oc, const vec &o, const vec &ray, float radius, int mode, extentity *t) -{ +static float disttoent(octaentities *oc, const vec &o, const vec &ray, float radius, int mode, extentity *t) { vec eo, es; int orient = -1; float dist = radius, f = 0.0f; const vector &ents = entities::getents(); - #define entintersect(mask, type, func) {\ - if((mode&(mask))==(mask)) loopv(oc->type) \ - { \ + if((mode&(mask))==(mask)) loopv(oc->type) { \ + \ extentity &e = *ents[oc->type[i]]; \ if(!(e.flags&EF_OCTA) || &e==t) continue; \ func; \ - if(f0 && vec(ray).mul(f).add(o).insidebb(oc->o, oc->size)) \ - { \ + if(f0 && vec(ray).mul(f).add(o).insidebb(oc->o, oc->size)) { \ + \ hitentdist = dist = f; \ hitent = oc->type[i]; \ hitorient = orient; \ } \ } \ } - entintersect(RAY_POLY, mapmodels, if(!mmintersect(e, o, ray, radius, mode, f)) continue; ); - entintersect(RAY_ENTS, other, entselectionbox(e, eo, es); if(!rayboxintersect(eo, es, o, ray, f, orient)) continue; ); - entintersect(RAY_ENTS, mapmodels, entselectionbox(e, eo, es); if(!rayboxintersect(eo, es, o, ray, f, orient)) continue; ); - return dist; } -static float disttooutsideent(const vec &o, const vec &ray, float radius, int mode, extentity *t) -{ +static float disttooutsideent(const vec &o, const vec &ray, float radius, int mode, extentity *t) { vec eo, es; int orient; float dist = radius, f = 0.0f; const vector &ents = entities::getents(); - loopv(outsideents) - { + loopv(outsideents) { extentity &e = *ents[outsideents[i]]; if(!(e.flags&EF_OCTA) || &e==t) continue; entselectionbox(e, eo, es); if(!rayboxintersect(eo, es, o, ray, f, orient)) continue; - if(f0) - { + if(f0) { hitentdist = dist = f; hitent = outsideents[i]; hitorient = orient; @@ -162,12 +148,10 @@ static float disttooutsideent(const vec &o, const vec &ray, float radius, int mo } // optimized shadow version -static float shadowent(octaentities *oc, const vec &o, const vec &ray, float radius, int mode, extentity *t) -{ +static float shadowent(octaentities *oc, const vec &o, const vec &ray, float radius, int mode, extentity *t) { float dist = radius, f = 0.0f; const vector &ents = entities::getents(); - loopv(oc->mapmodels) - { + loopv(oc->mapmodels) { extentity &e = *ents[oc->mapmodels[i]]; if(!(e.flags&EF_OCTA) || &e==t) continue; if(!mmintersect(e, o, ray, radius, mode, f)) continue; @@ -185,14 +169,14 @@ static float shadowent(octaentities *oc, const vec &o, const vec &ray, float rad ivec lsizemask(invray.x>0 ? 1 : 0, invray.y>0 ? 1 : 0, invray.z>0 ? 1 : 0); \ #define CHECKINSIDEWORLD \ - if(!insideworld(o)) \ - { \ + if(!insideworld(o)) { \ + \ float disttoworld = 0, exitworld = 1e16f; \ - loopi(3) \ - { \ + loopi(3) { \ + \ float c = v[i]; \ - if(c<0 || c>=worldsize) \ - { \ + if(c<0 || c>=worldsize) { \ + \ float d = ((invray[i]>0?0:worldsize)-c)*invray[i]; \ if(d<0) return (radius>0?radius:-1); \ disttoworld = max(disttoworld, 0.1f + d); \ @@ -207,15 +191,15 @@ static float shadowent(octaentities *oc, const vec &o, const vec &ray, float rad #define DOWNOCTREE(disttoent, earlyexit) \ cube *lc = levels[lshift]; \ - for(;;) \ - { \ + for(;;) { \ + \ lshift--; \ lc += octastep(x, y, z, lshift); \ - if(lc->ext && lc->ext->ents && lshift < elvl) \ - { \ + if(lc->ext && lc->ext->ents && lshift < elvl) { \ + \ float edist = disttoent(lc->ext->ents, o, ray, dent, mode, t); \ - if(edist < dent) \ - { \ + if(edist < dent) { \ + \ earlyexit return min(edist, dist); \ elvl = lshift; \ dent = min(dent, edist); \ @@ -246,103 +230,76 @@ static float shadowent(octaentities *oc, const vec &o, const vec &ray, float rad if(diff >= uint(worldsize)) exitworld; \ diff >>= lshift; \ if(!diff) exitworld; \ - do \ - { \ + do { \ + \ lshift++; \ diff >>= 1; \ } while(diff); -float raycube(const vec &o, const vec &ray, float radius, int mode, int size, extentity *t) -{ +float raycube(const vec &o, const vec &ray, float radius, int mode, int size, extentity *t) { if(ray.iszero()) return 0; - INITRAYCUBE; CHECKINSIDEWORLD; - int closest = -1, x = int(v.x), y = int(v.y), z = int(v.z); - for(;;) - { + for(;;) { DOWNOCTREE(disttoent, if(mode&RAY_SHADOW)); - int lsize = 1<0 || !(mode&RAY_SKIPFIRST)) && (((mode&RAY_EDITMAT) && c.material != MAT_AIR) || (!(mode&RAY_PASS) && lsize==size && !isempty(c)) || isentirelysolid(c) || - dent < dist)) - { + dent < dist)) { if(closest >= 0) { hitsurface = vec(0, 0, 0); hitsurface[closest] = ray[closest]>0 ? -1 : 1; } return min(dent, dist); } - ivec lo(x&(~0U<0 || !(mode&RAY_SKIPFIRST))) return min(dent, dist+f); } - FINDCLOSEST(closest = 0, closest = 1, closest = 2); - if(radius>0 && dist>=radius) return min(dent, dist); - UPOCTREE(return min(dent, radius>0 ? radius : dist)); } } // optimized version for lightmap shadowing... every cycle here counts!!! -float shadowray(const vec &o, const vec &ray, float radius, int mode, extentity *t) -{ +float shadowray(const vec &o, const vec &ray, float radius, int mode, extentity *t) { INITRAYCUBE; CHECKINSIDEWORLD; - - int side = O_BOTTOM, x = int(v.x), y = int(v.y), z = int(v.z); - for(;;) - { + int side = O_BOTTOM, x = int(v.x), y = int(v.y), z = int(v.z); (void) side; + for(;;) { DOWNOCTREE(shadowent, ); - cube &c = *lc; ivec lo(x&(~0U<= 0) - { + if(exitdist >= 0) { return dist+max(enterdist+0.1f, 0.0f); } } } - nextcube: FINDCLOSEST(side = O_RIGHT - lsizemask.x, side = O_FRONT - lsizemask.y, side = O_TOP - lsizemask.z); - if(dist>=radius) return dist; - UPOCTREE(return radius); } } // thread safe version -struct ShadowRayCache -{ +struct ShadowRayCache { clipplanes clipcache[MAXCLIPPLANES]; int version; - ShadowRayCache() : version(-1) {} }; @@ -350,65 +307,49 @@ ShadowRayCache *newshadowraycache() { return new ShadowRayCache; } void freeshadowraycache(ShadowRayCache *&cache) { delete cache; cache = NULL; } -void resetshadowraycache(ShadowRayCache *cache) -{ +void resetshadowraycache(ShadowRayCache *cache) { cache->version++; - if(!cache->version) - { + if(!cache->version) { memclear(cache->clipcache); cache->version = 1; } } -float shadowray(ShadowRayCache *cache, const vec &o, const vec &ray, float radius, int mode, extentity *t) -{ +float shadowray(ShadowRayCache *cache, const vec &o, const vec &ray, float radius, int mode, extentity *t) { INITRAYCUBE; CHECKINSIDEWORLD; - - int side = O_BOTTOM, x = int(v.x), y = int(v.y), z = int(v.z); - for(;;) - { + int side = O_BOTTOM, x = int(v.x), y = int(v.y), z = int(v.z); (void) side; + for(;;) { DOWNOCTREE(shadowent, ); - cube &c = *lc; ivec lo(x&(~0U<clipcache[int(&c - worldroot)&(MAXCLIPPLANES-1)]; if(p.owner != &c || p.version != cache->version) { p.owner = &c; p.version = cache->version; genclipplanes(c, lo, 1<= 0) - { + if(exitdist >= 0) { return dist+max(enterdist+0.1f, 0.0f); } } } - nextcube: FINDCLOSEST(side = O_RIGHT - lsizemask.x, side = O_FRONT - lsizemask.y, side = O_TOP - lsizemask.z); - if(dist>=radius) return dist; - UPOCTREE(return radius); } } -float rayent(const vec &o, const vec &ray, float radius, int mode, int size, int &orient, int &ent) -{ +float rayent(const vec &o, const vec &ray, float radius, int mode, int size, int &orient, int &ent) { hitent = -1; hitentdist = radius; hitorient = -1; float dist = raycube(o, ray, radius, mode, size); - if((mode&RAY_ENTS) == RAY_ENTS) - { + if((mode&RAY_ENTS) == RAY_ENTS) { float dent = disttooutsideent(o, ray, dist < 0 ? 1e16f : dist, mode, NULL); if(dent < 1e15f && (dist < 0 || dent < dist)) dist = dent; } @@ -417,8 +358,7 @@ float rayent(const vec &o, const vec &ray, float radius, int mode, int size, int return dist; } -float raycubepos(const vec &o, const vec &ray, vec &hitpos, float radius, int mode, int size) -{ +float raycubepos(const vec &o, const vec &ray, vec &hitpos, float radius, int mode, int size) { hitpos = ray; float dist = raycube(o, ray, radius, mode, size); if(radius>0 && dist>=radius) dist = radius; @@ -426,8 +366,7 @@ float raycubepos(const vec &o, const vec &ray, vec &hitpos, float radius, int mo return dist; } -bool raycubelos(const vec &o, const vec &dest, vec &hitpos) -{ +bool raycubelos(const vec &o, const vec &dest, vec &hitpos) { vec ray(dest); ray.sub(o); float mag = ray.magnitude(); @@ -436,8 +375,7 @@ bool raycubelos(const vec &o, const vec &dest, vec &hitpos) return distance >= mag; } -float rayfloor(const vec &o, vec &floor, int mode, float radius) -{ +float rayfloor(const vec &o, vec &floor, int mode, float radius) { if(o.z<=0) return -1; hitsurface = vec(0, 0, 1); float dist = raycube(o, vec(0, 0, -1), radius, mode); @@ -460,53 +398,42 @@ const float WALLZ = 0.2f; extern const float JUMPVEL = 125.0f; extern const float GRAVITY = 200.0f; -bool ellipseboxcollide(physent *d, const vec &dir, const vec &o, const vec ¢er, float yaw, float xr, float yr, float hi, float lo) -{ +bool ellipseboxcollide(physent *d, const vec &dir, const vec &o, const vec ¢er, float yaw, float xr, float yr, float hi, float lo) { float below = (o.z+center.z-lo) - (d->o.z+d->aboveeye), above = (d->o.z-d->eyeheight) - (o.z+center.z+hi); if(below>=0 || above>=0) return false; - vec yo(d->o); yo.sub(o); yo.rotate_around_z(-yaw*RAD); yo.sub(center); - float dx = clamp(yo.x, -xr, xr) - yo.x, dy = clamp(yo.y, -yr, yr) - yo.y, dist = sqrtf(dx*dx + dy*dy) - d->radius; - if(dist < 0) - { + if(dist < 0) { int sx = yo.x <= -xr ? -1 : (yo.x >= xr ? 1 : 0), sy = yo.y <= -yr ? -1 : (yo.y >= yr ? 1 : 0); - if(dist > (yo.z < 0 ? below : above) && (sx || sy)) - { + if(dist > (yo.z < 0 ? below : above) && (sx || sy)) { vec ydir(dir); ydir.rotate_around_z(-yaw*RAD); - if(sx*yo.x - xr > sy*yo.y - yr) - { - if(dir.iszero() || sx*ydir.x < -1e-6f) - { + if(sx*yo.x - xr > sy*yo.y - yr) { + if(dir.iszero() || sx*ydir.x < -1e-6f) { collidewall = vec(sx, 0, 0); collidewall.rotate_around_z(yaw*RAD); return true; } } - else if(dir.iszero() || sy*ydir.y < -1e-6f) - { + else if(dir.iszero() || sy*ydir.y < -1e-6f) { collidewall = vec(0, sy, 0); collidewall.rotate_around_z(yaw*RAD); return true; } } - if(yo.z < 0) - { - if(dir.iszero() || (dir.z > 0 && (d->type>=ENT_INANIMATE || below >= d->zmargin-(d->eyeheight+d->aboveeye)/4.0f))) - { + if(yo.z < 0) { + if(dir.iszero() || (dir.z > 0 && (d->type>=ENT_INANIMATE || below >= d->zmargin-(d->eyeheight+d->aboveeye)/4.0f))) { collidewall = vec(0, 0, -1); return true; } } - else if(dir.iszero() || (dir.z < 0 && (d->type>=ENT_INANIMATE || above >= d->zmargin-(d->eyeheight+d->aboveeye)/3.0f))) - { + else if(dir.iszero() || (dir.z < 0 && (d->type>=ENT_INANIMATE || above >= d->zmargin-(d->eyeheight+d->aboveeye)/3.0f))) { collidewall = vec(0, 0, 1); return true; } @@ -515,8 +442,7 @@ bool ellipseboxcollide(physent *d, const vec &dir, const vec &o, const vec ¢ return false; } -bool ellipsecollide(physent *d, const vec &dir, const vec &o, const vec ¢er, float yaw, float xr, float yr, float hi, float lo) -{ +bool ellipsecollide(physent *d, const vec &dir, const vec &o, const vec ¢er, float yaw, float xr, float yr, float hi, float lo) { float below = (o.z+center.z-lo) - (d->o.z+d->aboveeye), above = (d->o.z-d->eyeheight) - (o.z+center.z+hi); if(below>=0 || above>=0) return false; @@ -528,24 +454,19 @@ bool ellipsecollide(physent *d, const vec &dir, const vec &o, const vec ¢er, float dx = d->xradius*cosf(dangle), dy = d->yradius*sinf(dangle); float ex = xr*cosf(eangle), ey = yr*sinf(eangle); float dist = sqrtf(x*x + y*y) - sqrtf(dx*dx + dy*dy) - sqrtf(ex*ex + ey*ey); - if(dist < 0) - { - if(dist > (d->o.z < yo.z ? below : above) && (dir.iszero() || x*dir.x + y*dir.y > 0)) - { + if(dist < 0) { + if(dist > (d->o.z < yo.z ? below : above) && (dir.iszero() || x*dir.x + y*dir.y > 0)) { collidewall = vec(-x, -y, 0); if(!collidewall.iszero()) collidewall.normalize(); return true; } - if(d->o.z < yo.z) - { - if(dir.iszero() || (dir.z > 0 && (d->type>=ENT_INANIMATE || below >= d->zmargin-(d->eyeheight+d->aboveeye)/4.0f))) - { + if(d->o.z < yo.z) { + if(dir.iszero() || (dir.z > 0 && (d->type>=ENT_INANIMATE || below >= d->zmargin-(d->eyeheight+d->aboveeye)/4.0f))) { collidewall = vec(0, 0, -1); return true; } } - else if(dir.iszero() || (dir.z < 0 && (d->type>=ENT_INANIMATE || above >= d->zmargin-(d->eyeheight+d->aboveeye)/3.0f))) - { + else if(dir.iszero() || (dir.z < 0 && (d->type>=ENT_INANIMATE || above >= d->zmargin-(d->eyeheight+d->aboveeye)/3.0f))) { collidewall = vec(0, 0, 1); return true; } @@ -558,15 +479,13 @@ bool ellipsecollide(physent *d, const vec &dir, const vec &o, const vec ¢er, static uint dynentframe = 0; -static struct dynentcacheentry -{ +static struct dynentcacheentry { int x, y; uint frame; vector dynents; } dynentcache[DYNENTCACHESIZE]; -void cleardynentcache() -{ +void cleardynentcache() { dynentframe++; if(!dynentframe || dynentframe == 1) loopi(DYNENTCACHESIZE) dynentcache[i].frame = 0; if(!dynentframe) dynentframe = 1; @@ -576,8 +495,7 @@ VARF(dynentsize, 4, 7, 12, cleardynentcache()); #define DYNENTHASH(x, y) (((((x)^(y))<<5) + (((x)^(y))>>5)) & (DYNENTCACHESIZE - 1)) -const vector &checkdynentcache(int x, int y) -{ +const vector &checkdynentcache(int x, int y) { dynentcacheentry &dec = dynentcache[DYNENTHASH(x, y)]; if(dec.x == x && dec.y == y && dec.frame == dynentframe) return dec.dynents; dec.x = x; @@ -585,8 +503,7 @@ const vector &checkdynentcache(int x, int y) dec.frame = dynentframe; dec.dynents.shrink(0); int numdyns = game::numdynents(), dsize = 1<state != CS_ALIVE || d->o.x+d->radius <= dx || d->o.x-d->radius >= dx+dsize || @@ -601,23 +518,18 @@ const vector &checkdynentcache(int x, int y) for(int curx = max(int(o.x-radius), 0)>>dynentsize, endx = min(int(o.x+radius), worldsize-1)>>dynentsize; curx <= endx; curx++) \ for(int cury = max(int(o.y-radius), 0)>>dynentsize, endy = min(int(o.y+radius), worldsize-1)>>dynentsize; cury <= endy; cury++) -void updatedynentcache(physent *d) -{ - loopdynentcache(x, y, d->o, d->radius) - { +void updatedynentcache(physent *d) { + loopdynentcache(x, y, d->o, d->radius) { dynentcacheentry &dec = dynentcache[DYNENTHASH(x, y)]; if(dec.x != x || dec.y != y || dec.frame != dynentframe || dec.dynents.find(d) >= 0) continue; dec.dynents.add(d); } } -bool overlapsdynent(const vec &o, float radius) -{ - loopdynentcache(x, y, o, radius) - { +bool overlapsdynent(const vec &o, float radius) { + loopdynentcache(x, y, o, radius) { const vector &dynents = checkdynentcache(x, y); - loopv(dynents) - { + loopv(dynents) { physent *d = dynents[i]; if(o.dist(d->o)-d->radius < radius) return true; } @@ -626,13 +538,11 @@ bool overlapsdynent(const vec &o, float radius) } template -static inline bool plcollide(physent *d, const vec &dir, physent *o) -{ +static inline bool plcollide(physent *d, const vec &dir, physent *o) { E entvol(d); O obvol(o); vec cp; - if(mpr::collide(entvol, obvol, NULL, NULL, &cp)) - { + if(mpr::collide(entvol, obvol, NULL, NULL, &cp)) { vec wn = vec(cp).sub(obvol.center()); collidewall = obvol.contactface(wn, dir.iszero() ? vec(wn).neg() : dir); if(!collidewall.iszero()) return true; @@ -641,10 +551,8 @@ static inline bool plcollide(physent *d, const vec &dir, physent *o) return false; } -static inline bool plcollide(physent *d, const vec &dir, physent *o) -{ - switch(d->collidetype) - { +static inline bool plcollide(physent *d, const vec &dir, physent *o) { + switch(d->collidetype) { case COLLIDE_ELLIPSE: case COLLIDE_ELLIPSE_PRECISE: if(o->collidetype == COLLIDE_OBB) return ellipseboxcollide(d, dir, o->o, vec(0, 0, 0), o->yaw, o->xradius, o->yradius, o->aboveeye, o->eyeheight); @@ -656,33 +564,27 @@ static inline bool plcollide(physent *d, const vec &dir, physent *o) } } -bool plcollide(physent *d, const vec &dir, bool insideplayercol) // collide with player or monster -{ +bool plcollide(physent *d, const vec &dir, bool insideplayercol) { // collide with player or monster { if(d->type==ENT_CAMERA || d->state!=CS_ALIVE) return false; int lastinside = collideinside; physent *insideplayer = NULL; - loopdynentcache(x, y, d->o, d->radius) - { + loopdynentcache(x, y, d->o, d->radius) { const vector &dynents = checkdynentcache(x, y); - loopv(dynents) - { + loopv(dynents) { physent *o = dynents[i]; if(o==d || d->o.reject(o->o, d->radius+o->radius)) continue; - if(plcollide(d, dir, o)) - { + if(plcollide(d, dir, o)) { collideplayer = o; game::dynentcollide(d, o, collidewall); return true; } - if(collideinside > lastinside) - { + if(collideinside > lastinside) { lastinside = collideinside; insideplayer = o; } } } - if(insideplayer && insideplayercol) - { + if(insideplayer && insideplayercol) { collideplayer = insideplayer; game::dynentcollide(d, insideplayer, vec(0, 0, 0)); return true; @@ -690,8 +592,7 @@ bool plcollide(physent *d, const vec &dir, bool insideplayercol) // collide with return false; } -void rotatebb(vec ¢er, vec &radius, int yaw) -{ +void rotatebb(vec ¢er, vec &radius, int yaw) { if(yaw < 0) yaw = 360 + yaw%360; else if(yaw >= 360) yaw %= 360; const vec2 &rot = sincos360[yaw]; @@ -703,13 +604,11 @@ void rotatebb(vec ¢er, vec &radius, int yaw) } template -static inline bool mmcollide(physent *d, const vec &dir, const extentity &e, const vec ¢er, const vec &radius, float yaw) -{ +static inline bool mmcollide(physent *d, const vec &dir, const extentity &e, const vec ¢er, const vec &radius, float yaw) { E entvol(d); M mdlvol(e.o, center, radius, yaw); vec cp; - if(mpr::collide(entvol, mdlvol, NULL, NULL, &cp)) - { + if(mpr::collide(entvol, mdlvol, NULL, NULL, &cp)) { vec wn = vec(cp).sub(mdlvol.center()); collidewall = mdlvol.contactface(wn, dir.iszero() ? vec(wn).neg() : dir); if(!collidewall.iszero()) return true; @@ -718,34 +617,27 @@ static inline bool mmcollide(physent *d, const vec &dir, const extentity &e, con return false; } -bool mmcollide(physent *d, const vec &dir, octaentities &oc) // collide with a mapmodel -{ +bool mmcollide(physent *d, const vec &dir, octaentities &oc) { // collide with a mapmodel { const vector &ents = entities::getents(); - loopv(oc.mapmodels) - { + loopv(oc.mapmodels) { extentity &e = *ents[oc.mapmodels[i]]; if(e.flags&EF_NOCOLLIDE) continue; model *m = loadmapmodel(e.attr2); if(!m || !m->collide) continue; - vec center, radius; float rejectradius = m->collisionbox(center, radius); if(d->o.reject(e.o, d->radius + rejectradius)) continue; - float yaw = e.attr1; - switch(d->collidetype) - { + switch(d->collidetype) { case COLLIDE_ELLIPSE: case COLLIDE_ELLIPSE_PRECISE: - if(m->ellipsecollide) - { + if(m->ellipsecollide) { if(ellipsecollide(d, dir, e.o, center, yaw, radius.x, radius.y, radius.z, radius.z)) return true; } else if(ellipseboxcollide(d, dir, e.o, center, yaw, radius.x, radius.y, radius.z, radius.z)) return true; break; case COLLIDE_OBB: - if(m->ellipsecollide) - { + if(m->ellipsecollide) { if(mmcollide(d, dir, e, center, radius, yaw)) return true; } else if(mmcollide(d, dir, e, center, radius, yaw)) return true; @@ -757,24 +649,22 @@ bool mmcollide(physent *d, const vec &dir, octaentities &oc) // collide wit } template -static bool fuzzycollidesolid(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size) // collide with solid cube geometry -{ +static bool fuzzycollidesolid(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size) { // collide with solid cube geometry { int crad = size/2; if(fabs(d->o.x - co.x - crad) > d->radius + crad || fabs(d->o.y - co.y - crad) > d->radius + crad || d->o.z + d->aboveeye < co.z || d->o.z - d->eyeheight > co.z + size) return false; - E entvol(d); collidewall = vec(0, 0, 0); float bestdist = -1e10f; int visible = isentirelysolid(c) ? c.visible : 0xFF; - #define CHECKSIDE(side, distval, dotval, margin, normal) if(visible&(1< 0) return false; \ if(dist <= bestdist) continue; \ - if(!dir.iszero()) \ - { \ + if(!dir.iszero()) { \ + \ if(dotval >= -cutoff*dir.magnitude()) continue; \ if(d->typeo.y - d->radius - (co.y + size), dir.y, -d->radius, vec(0, 1, 0)); CHECKSIDE(O_BOTTOM, co.z - (d->o.z + d->aboveeye), -dir.z, d->zmargin-(d->eyeheight+d->aboveeye)/4.0f, vec(0, 0, -1)); CHECKSIDE(O_TOP, d->o.z - d->eyeheight - (co.z + size), dir.z, d->zmargin-(d->eyeheight+d->aboveeye)/3.0f, vec(0, 0, 1)); - - if(collidewall.iszero()) - { + if(collidewall.iszero()) { collideinside++; return false; } @@ -797,24 +685,20 @@ static bool fuzzycollidesolid(physent *d, const vec &dir, float cutoff, const cu } template -static inline bool clampcollide(const clipplanes &p, const E &entvol, const plane &w, const vec &pw) -{ - if(w.x && (w.y || w.z) && fabs(pw.x - p.o.x) > p.r.x) - { +static inline bool clampcollide(const clipplanes &p, const E &entvol, const plane &w, const vec &pw) { + if(w.x && (w.y || w.z) && fabs(pw.x - p.o.x) > p.r.x) { vec c = entvol.center(); float fv = pw.x < p.o.x ? p.o.x-p.r.x : p.o.x+p.r.x, fdist = (w.x*fv + w.y*c.y + w.z*c.z + w.offset) / (w.y*w.y + w.z*w.z); vec fdir(fv - c.x, -w.y*fdist, -w.z*fdist); if((pw.y-c.y-fdir.y)*w.y + (pw.z-c.z-fdir.z)*w.z >= 0 && entvol.supportpoint(fdir).squaredist(c) < fdir.squaredlen()) return true; } - if(w.y && (w.x || w.z) && fabs(pw.y - p.o.y) > p.r.y) - { + if(w.y && (w.x || w.z) && fabs(pw.y - p.o.y) > p.r.y) { vec c = entvol.center(); float fv = pw.y < p.o.y ? p.o.y-p.r.y : p.o.y+p.r.y, fdist = (w.x*c.x + w.y*fv + w.z*c.z + w.offset) / (w.x*w.x + w.z*w.z); vec fdir(-w.x*fdist, fv - c.y, -w.z*fdist); if((pw.x-c.x-fdir.x)*w.x + (pw.z-c.z-fdir.z)*w.z >= 0 && entvol.supportpoint(fdir).squaredist(c) < fdir.squaredlen()) return true; } - if(w.z && (w.x || w.y) && fabs(pw.z - p.o.z) > p.r.z) - { + if(w.z && (w.x || w.y) && fabs(pw.z - p.o.z) > p.r.z) { vec c = entvol.center(); float fv = pw.z < p.o.z ? p.o.z-p.r.z : p.o.z+p.r.z, fdist = (w.x*c.x + w.y*c.y + w.z*fv + w.offset) / (w.x*w.x + w.y*w.y); vec fdir(-w.x*fdist, -w.y*fdist, fv - c.z); @@ -824,14 +708,11 @@ static inline bool clampcollide(const clipplanes &p, const E &entvol, const plan } template -static bool fuzzycollideplanes(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size) // collide with deformed cube geometry -{ +static bool fuzzycollideplanes(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size) { // collide with deformed cube geometry { const clipplanes &p = getclipplanes(c, co, size); - if(fabs(d->o.x - p.o.x) > p.r.x + d->radius || fabs(d->o.y - p.o.y) > p.r.y + d->radius || d->o.z + d->aboveeye < p.o.z - p.r.z || d->o.z - d->eyeheight > p.o.z + p.r.z) return false; - collidewall = vec(0, 0, 0); float bestdist = -1e10f; int visible = p.visible; @@ -841,11 +722,9 @@ static bool fuzzycollideplanes(physent *d, const vec &dir, float cutoff, const c CHECKSIDE(O_FRONT, d->o.y - d->radius - (p.o.y + p.r.y), dir.y, -d->radius, vec(0, 1, 0)); CHECKSIDE(O_BOTTOM, p.o.z - p.r.z - (d->o.z + d->aboveeye), -dir.z, d->zmargin-(d->eyeheight+d->aboveeye)/4.0f, vec(0, 0, -1)); CHECKSIDE(O_TOP, d->o.z - d->eyeheight - (p.o.z + p.r.z), dir.z, d->zmargin-(d->eyeheight+d->aboveeye)/3.0f, vec(0, 0, 1)); - E entvol(d); int bestplane = -1; - loopi(p.size) - { + loopi(p.size) { const plane &w = p.p[i]; vec pw = entvol.supportpoint(vec(w).neg()); float dist = w.dist(pw); @@ -853,8 +732,7 @@ static bool fuzzycollideplanes(physent *d, const vec &dir, float cutoff, const c if(dist <= bestdist) continue; bestplane = -1; bestdist = dist; - if(!dir.iszero()) - { + if(!dir.iszero()) { if(w.dot(dir) >= -cutoff*dir.magnitude()) continue; if(d->type= 0) collidewall = p.p[bestplane]; - else if(collidewall.iszero()) - { + else if(collidewall.iszero()) { collideinside++; return false; } @@ -875,17 +752,14 @@ static bool fuzzycollideplanes(physent *d, const vec &dir, float cutoff, const c } template -static bool cubecollidesolid(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size) // collide with solid cube geometry -{ +static bool cubecollidesolid(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size) { // collide with solid cube geometry { int crad = size/2; if(fabs(d->o.x - co.x - crad) > d->radius + crad || fabs(d->o.y - co.y - crad) > d->radius + crad || d->o.z + d->aboveeye < co.z || d->o.z - d->eyeheight > co.z + size) return false; - E entvol(d); bool collided = mpr::collide(mpr::SolidCube(co, size), entvol); if(!collided) return false; - collidewall = vec(0, 0, 0); float bestdist = -1e10f; int visible = isentirelysolid(c) ? c.visible : 0xFF; @@ -895,9 +769,7 @@ static bool cubecollidesolid(physent *d, const vec &dir, float cutoff, const cub CHECKSIDE(O_FRONT, entvol.back() - (co.y + size), dir.y, -d->radius, vec(0, 1, 0)); CHECKSIDE(O_BOTTOM, co.z - entvol.top(), -dir.z, d->zmargin-(d->eyeheight+d->aboveeye)/4.0f, vec(0, 0, -1)); CHECKSIDE(O_TOP, entvol.bottom() - (co.z + size), dir.z, d->zmargin-(d->eyeheight+d->aboveeye)/3.0f, vec(0, 0, 1)); - - if(collidewall.iszero()) - { + if(collidewall.iszero()) { collideinside++; return false; } @@ -905,18 +777,14 @@ static bool cubecollidesolid(physent *d, const vec &dir, float cutoff, const cub } template -static bool cubecollideplanes(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size) // collide with deformed cube geometry -{ +static bool cubecollideplanes(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size) { // collide with deformed cube geometry { const clipplanes &p = getclipplanes(c, co, size); - if(fabs(d->o.x - p.o.x) > p.r.x + d->radius || fabs(d->o.y - p.o.y) > p.r.y + d->radius || d->o.z + d->aboveeye < p.o.z - p.r.z || d->o.z - d->eyeheight > p.o.z + p.r.z) return false; - E entvol(d); bool collided = mpr::collide(mpr::CubePlanes(p), entvol); if(!collided) return false; - collidewall = vec(0, 0, 0); float bestdist = -1e10f; int visible = p.visible; @@ -926,18 +794,15 @@ static bool cubecollideplanes(physent *d, const vec &dir, float cutoff, const cu CHECKSIDE(O_FRONT, entvol.back() - (p.o.y + p.r.y), dir.y, -d->radius, vec(0, 1, 0)); CHECKSIDE(O_BOTTOM, p.o.z - p.r.z - entvol.top(), -dir.z, d->zmargin-(d->eyeheight+d->aboveeye)/4.0f, vec(0, 0, -1)); CHECKSIDE(O_TOP, entvol.bottom() - (p.o.z + p.r.z), dir.z, d->zmargin-(d->eyeheight+d->aboveeye)/3.0f, vec(0, 0, 1)); - int bestplane = -1; - loopi(p.size) - { + loopi(p.size) { const plane &w = p.p[i]; vec pw = entvol.supportpoint(vec(w).neg()); float dist = w.dist(pw); if(dist <= bestdist) continue; bestplane = -1; bestdist = dist; - if(!dir.iszero()) - { + if(!dir.iszero()) { if(w.dot(dir) >= -cutoff*dir.magnitude()) continue; if(d->type= 0) collidewall = p.p[bestplane]; - else if(collidewall.iszero()) - { + else if(collidewall.iszero()) { collideinside++; return false; } return true; } -static inline bool cubecollide(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size, bool solid) -{ - switch(d->collidetype) - { +static inline bool cubecollide(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size, bool solid) { + switch(d->collidetype) { case COLLIDE_OBB: if(isentirelysolid(c) || solid) return cubecollidesolid(d, dir, cutoff, c, co, size); else return cubecollideplanes(d, dir, cutoff, c, co, size); @@ -974,21 +836,16 @@ static inline bool cubecollide(physent *d, const vec &dir, float cutoff, const c } } -static inline bool octacollide(physent *d, const vec &dir, float cutoff, const ivec &bo, const ivec &bs, const cube *c, const ivec &cor, int size) // collide with octants -{ - loopoctabox(cor, size, bo, bs) - { +static inline bool octacollide(physent *d, const vec &dir, float cutoff, const ivec &bo, const ivec &bs, const cube *c, const ivec &cor, int size) { // collide with octants { + loopoctabox(cor, size, bo, bs) { if(c[i].ext && c[i].ext->ents) if(mmcollide(d, dir, *c[i].ext->ents)) return true; ivec o(i, cor, size); - if(c[i].children) - { + if(c[i].children) { if(octacollide(d, dir, cutoff, bo, bs, c[i].children, o, size>>1)) return true; } - else - { + else { bool solid = false; - switch(c[i].material&MATF_CLIP) - { + switch(c[i].material&MATF_CLIP) { case MAT_NOCLIP: continue; case MAT_GAMECLIP: if(d->type==ENT_AI) solid = true; break; case MAT_CLIP: if(d->type= uint(worldsize)) @@ -1009,16 +865,14 @@ static inline bool octacollide(physent *d, const vec &dir, float cutoff, const i const cube *c = &worldroot[octastep(bo.x, bo.y, bo.z, scale)]; if(c->ext && c->ext->ents && mmcollide(d, dir, *c->ext->ents)) return true; scale--; - while(c->children && !(diff&(1<children && !(diff&(1<children[octastep(bo.x, bo.y, bo.z, scale)]; if(c->ext && c->ext->ents && mmcollide(d, dir, *c->ext->ents)) return true; scale--; } if(c->children) return octacollide(d, dir, cutoff, bo, bs, c->children, ivec(bo).mask(~((2<material&MATF_CLIP) - { + switch(c->material&MATF_CLIP) { case MAT_NOCLIP: return false; case MAT_GAMECLIP: if(d->type==ENT_AI) solid = true; break; case MAT_CLIP: if(d->type 1e-6f) - { + if(speed > 1e-6f) { float step = dir.magnitude(); dir = d->vel; dir.add(d->falling); @@ -1052,11 +903,9 @@ void recalcdir(physent *d, const vec &oldvel, vec &dir) } } -void slideagainst(physent *d, vec &dir, const vec &obstacle, bool foundfloor, bool slidecollide) -{ +void slideagainst(physent *d, vec &dir, const vec &obstacle, bool foundfloor, bool slidecollide) { vec wall(obstacle); - if(foundfloor ? wall.z > 0 : slidecollide) - { + if(foundfloor ? wall.z > 0 : slidecollide) { wall.z = 0; if(!wall.iszero()) wall.normalize(); } @@ -1067,14 +916,11 @@ void slideagainst(physent *d, vec &dir, const vec &obstacle, bool foundfloor, bo recalcdir(d, oldvel, dir); } -void switchfloor(physent *d, vec &dir, const vec &floor) -{ +void switchfloor(physent *d, vec &dir, const vec &floor) { if(floor.z >= FLOORZ) d->falling = vec(0, 0, 0); - vec oldvel(d->vel); oldvel.add(d->falling); - if(dir.dot(floor) >= 0) - { + if(dir.dot(floor) >= 0) { if(d->physstate < PHYS_SLIDE || fabs(dir.dot(d->floor)) > 0.01f*dir.magnitude()) return; d->vel.projectxy(floor, 0.0f); } @@ -1083,57 +929,46 @@ void switchfloor(physent *d, vec &dir, const vec &floor) recalcdir(d, oldvel, dir); } -bool trystepup(physent *d, vec &dir, const vec &obstacle, float maxstep, const vec &floor) -{ +bool trystepup(physent *d, vec &dir, const vec &obstacle, float maxstep, const vec &floor) { vec old(d->o), stairdir = (obstacle.z >= 0 && obstacle.z < SLOPEZ ? vec(-obstacle.x, -obstacle.y, 0) : vec(dir.x, dir.y, 0)).rescale(1); bool cansmooth = true; /* check if there is space atop the stair to move to */ - if(d->physstate != PHYS_STEP_UP) - { + if(d->physstate != PHYS_STEP_UP) { vec checkdir = stairdir; checkdir.mul(0.1f); checkdir.z += maxstep + 0.1f; d->o.add(checkdir); - if(collide(d)) - { + if(collide(d)) { d->o = old; if(!collide(d, vec(0, 0, -1), SLOPEZ)) return false; cansmooth = false; } } - - if(cansmooth) - { + if(cansmooth) { vec checkdir = stairdir; checkdir.z += 1; checkdir.mul(maxstep); d->o = old; d->o.add(checkdir); int scale = 2; - if(collide(d, checkdir)) - { - if(!collide(d, vec(0, 0, -1), SLOPEZ)) - { + if(collide(d, checkdir)) { + if(!collide(d, vec(0, 0, -1), SLOPEZ)) { d->o = old; return false; } d->o.add(checkdir); if(collide(d, vec(0, 0, -1), SLOPEZ)) scale = 1; } - if(scale != 1) - { + if(scale != 1) { d->o = old; d->o.sub(checkdir.mul(vec(2, 2, 1))); if(!collide(d, vec(0, 0, -1), SLOPEZ)) scale = 1; } - d->o = old; vec smoothdir(dir.x, dir.y, 0); float magxy = smoothdir.magnitude(); - if(magxy > 1e-9f) - { - if(magxy > scale*dir.z) - { + if(magxy > 1e-9f) { + if(magxy > scale*dir.z) { smoothdir.mul(1/magxy); smoothdir.z = 1.0f/scale; smoothdir.mul(dir.magnitude()/smoothdir.magnitude()); @@ -1141,11 +976,9 @@ bool trystepup(physent *d, vec &dir, const vec &obstacle, float maxstep, const v else smoothdir.z = dir.z; d->o.add(smoothdir); d->o.z += maxstep + 0.1f; - if(!collide(d, smoothdir)) - { + if(!collide(d, smoothdir)) { d->o.z -= maxstep + 0.1f; - if(d->physstate == PHYS_FALL || d->floor != floor) - { + if(d->physstate == PHYS_FALL || d->floor != floor) { d->timeinair = 0; d->floor = floor; switchfloor(d, dir, d->floor); @@ -1155,14 +988,11 @@ bool trystepup(physent *d, vec &dir, const vec &obstacle, float maxstep, const v } } } - /* try stepping up */ d->o = old; d->o.z += dir.magnitude(); - if(!collide(d, vec(0, 0, 1))) - { - if(d->physstate == PHYS_FALL || d->floor != floor) - { + if(!collide(d, vec(0, 0, 1))) { + if(d->physstate == PHYS_FALL || d->floor != floor) { d->timeinair = 0; d->floor = floor; switchfloor(d, dir, d->floor); @@ -1174,34 +1004,28 @@ bool trystepup(physent *d, vec &dir, const vec &obstacle, float maxstep, const v return false; } -bool trystepdown(physent *d, vec &dir, float step, float xy, float z, bool init = false) -{ +bool trystepdown(physent *d, vec &dir, float step, float xy, float z, bool init = false) { vec stepdir(dir.x, dir.y, 0); stepdir.z = -stepdir.magnitude2()*z/xy; if(!stepdir.z) return false; stepdir.normalize(); - vec old(d->o); d->o.add(vec(stepdir).mul(STAIRHEIGHT/fabs(stepdir.z))).z -= STAIRHEIGHT; d->zmargin = -STAIRHEIGHT; - if(collide(d, vec(0, 0, -1), SLOPEZ)) - { + if(collide(d, vec(0, 0, -1), SLOPEZ)) { d->o = old; d->o.add(vec(stepdir).mul(step)); d->zmargin = 0; - if(!collide(d, vec(0, 0, -1))) - { + if(!collide(d, vec(0, 0, -1))) { vec stepfloor(stepdir); stepfloor.mul(-stepfloor.z).z += 1; stepfloor.normalize(); - if(d->physstate >= PHYS_SLOPE && d->floor != stepfloor) - { + if(d->physstate >= PHYS_SLOPE && d->floor != stepfloor) { // prevent alternating step-down/step-up states if player would keep bumping into the same floor vec stepped(d->o); d->o.z -= 0.5f; d->zmargin = -0.5f; - if(collide(d, stepdir) && collidewall == d->floor) - { + if(collide(d, stepdir) && collidewall == d->floor) { d->o = old; if(!init) { d->o.x += dir.x; d->o.y += dir.y; if(dir.z <= 0 || collide(d, dir)) d->o.z += dir.z; } d->zmargin = 0; @@ -1225,14 +1049,12 @@ bool trystepdown(physent *d, vec &dir, float step, float xy, float z, bool init return false; } -bool trystepdown(physent *d, vec &dir, bool init = false) -{ +bool trystepdown(physent *d, vec &dir, bool init = false) { if((!d->move && !d->strafe) || !game::allowmove(d)) return false; vec old(d->o); d->o.z -= STAIRHEIGHT; d->zmargin = -STAIRHEIGHT; - if(!collide(d, vec(0, 0, -1), SLOPEZ)) - { + if(!collide(d, vec(0, 0, -1), SLOPEZ)) { d->o = old; d->zmargin = 0; return false; @@ -1251,10 +1073,8 @@ bool trystepdown(physent *d, vec &dir, bool init = false) return false; } -void falling(physent *d, vec &dir, const vec &floor) -{ - if(floor.z > 0.0f && floor.z < SLOPEZ) - { +void falling(physent *d, vec &dir, const vec &floor) { + if(floor.z > 0.0f && floor.z < SLOPEZ) { if(floor.z >= WALLZ) switchfloor(d, dir, floor); d->timeinair = 0; d->physstate = PHYS_SLIDE; @@ -1264,11 +1084,9 @@ void falling(physent *d, vec &dir, const vec &floor) d->physstate = PHYS_FALL; } -void landing(physent *d, vec &dir, const vec &floor, bool collided) -{ +void landing(physent *d, vec &dir, const vec &floor, bool collided) { #if 0 - if(d->physstate == PHYS_FALL) - { + if(d->physstate == PHYS_FALL) { d->timeinair = 0; if(dir.z < 0.0f) dir.z = d->vel.z = 0.0f; } @@ -1280,40 +1098,32 @@ void landing(physent *d, vec &dir, const vec &floor, bool collided) d->floor = floor; } -bool findfloor(physent *d, bool collided, const vec &obstacle, bool &slide, vec &floor) -{ +bool findfloor(physent *d, bool collided, const vec &obstacle, bool &slide, vec &floor) { bool found = false; vec moved(d->o); d->o.z -= 0.1f; - if(collide(d, vec(0, 0, -1), d->physstate == PHYS_SLOPE || d->physstate == PHYS_STEP_DOWN ? SLOPEZ : FLOORZ)) - { + if(collide(d, vec(0, 0, -1), d->physstate == PHYS_SLOPE || d->physstate == PHYS_STEP_DOWN ? SLOPEZ : FLOORZ)) { floor = collidewall; found = true; } - else if(collided && obstacle.z >= SLOPEZ) - { + else if(collided && obstacle.z >= SLOPEZ) { floor = obstacle; found = true; slide = false; } - else if(d->physstate == PHYS_STEP_UP || d->physstate == PHYS_SLIDE) - { - if(collide(d, vec(0, 0, -1)) && collidewall.z > 0.0f) - { + else if(d->physstate == PHYS_STEP_UP || d->physstate == PHYS_SLIDE) { + if(collide(d, vec(0, 0, -1)) && collidewall.z > 0.0f) { floor = collidewall; if(floor.z >= SLOPEZ) found = true; } } - else if(d->physstate >= PHYS_SLOPE && d->floor.z < 1.0f) - { - if(collide(d, vec(d->floor).neg(), 0.95f) || collide(d, vec(0, 0, -1))) - { + else if(d->physstate >= PHYS_SLOPE && d->floor.z < 1.0f) { + if(collide(d, vec(d->floor).neg(), 0.95f) || collide(d, vec(0, 0, -1))) { floor = collidewall; if(floor.z >= SLOPEZ && floor.z < 1.0f) found = true; } } - if(collided && (!found || obstacle.z > floor.z)) - { + if(collided && (!found || obstacle.z > floor.z)) { floor = obstacle; slide = !found && (floor.z < WALLZ || floor.z >= SLOPEZ); } @@ -1321,49 +1131,41 @@ bool findfloor(physent *d, bool collided, const vec &obstacle, bool &slide, vec return found; } -bool move(physent *d, vec &dir) -{ +bool move(physent *d, vec &dir) { vec old(d->o); bool collided = false, slidecollide = false; vec obstacle = vec(0, 0, 0); d->o.add(dir); - if(collide(d, dir) || ((d->type==ENT_AI || d->type==ENT_INANIMATE) && collide(d, vec(0, 0, 0), 0, false))) - { + if(collide(d, dir) || ((d->type==ENT_AI || d->type==ENT_INANIMATE) && collide(d, vec(0, 0, 0), 0, false))) { obstacle = collidewall; /* check to see if there is an obstacle that would prevent this one from being used as a floor (or ceiling bump) */ - if(d->type==ENT_PLAYER && ((collidewall.z>=SLOPEZ && dir.z<0) || (collidewall.z<=-SLOPEZ && dir.z>0)) && (dir.x || dir.y) && collide(d, vec(dir.x, dir.y, 0))) - { + if(d->type==ENT_PLAYER && ((collidewall.z>=SLOPEZ && dir.z<0) || (collidewall.z<=-SLOPEZ && dir.z>0)) && (dir.x || dir.y) && collide(d, vec(dir.x, dir.y, 0))) { if(collidewall.dot(dir) >= 0) slidecollide = true; obstacle = collidewall; } d->o = old; d->o.z -= STAIRHEIGHT; d->zmargin = -STAIRHEIGHT; - if(d->physstate == PHYS_SLOPE || d->physstate == PHYS_FLOOR || (collide(d, vec(0, 0, -1), SLOPEZ) && (d->physstate==PHYS_STEP_UP || d->physstate==PHYS_STEP_DOWN || collidewall.z>=FLOORZ))) - { + if(d->physstate == PHYS_SLOPE || d->physstate == PHYS_FLOOR || (collide(d, vec(0, 0, -1), SLOPEZ) && (d->physstate==PHYS_STEP_UP || d->physstate==PHYS_STEP_DOWN || collidewall.z>=FLOORZ))) { d->o = old; d->zmargin = 0; if(trystepup(d, dir, obstacle, STAIRHEIGHT, d->physstate == PHYS_SLOPE || d->physstate == PHYS_FLOOR ? d->floor : vec(collidewall))) return true; } - else - { + else { d->o = old; d->zmargin = 0; } /* can't step over the obstacle, so just slide against it */ collided = true; } - else if(d->physstate == PHYS_STEP_UP) - { - if(collide(d, vec(0, 0, -1), SLOPEZ)) - { + else if(d->physstate == PHYS_STEP_UP) { + if(collide(d, vec(0, 0, -1), SLOPEZ)) { d->o = old; if(trystepup(d, dir, vec(0, 0, 1), STAIRHEIGHT, vec(collidewall))) return true; d->o.add(dir); } } - else if(d->physstate == PHYS_STEP_DOWN && dir.dot(d->floor) <= 1e-6f) - { + else if(d->physstate == PHYS_STEP_DOWN && dir.dot(d->floor) <= 1e-6f) { vec moved(d->o); d->o = old; if(trystepdown(d, dir)) return true; @@ -1372,8 +1174,7 @@ bool move(physent *d, vec &dir) vec floor(0, 0, 0); bool slide = collided, found = findfloor(d, collided, obstacle, slide, floor); - if(slide || (!collided && floor.z > 0 && floor.z < WALLZ)) - { + if(slide || (!collided && floor.z > 0 && floor.z < WALLZ)) { slideagainst(d, dir, slide ? obstacle : floor, found, slidecollide); //if(d->type == ENT_AI || d->type == ENT_INANIMATE) d->blocked = true; @@ -1383,21 +1184,17 @@ bool move(physent *d, vec &dir) return !collided; } -bool bounce(physent *d, float secs, float elasticity, float grav) -{ +bool bounce(physent *d, float secs, float elasticity, float grav) { // make sure bouncers don't start inside geometry if(d->physstate!=PHYS_BOUNCE && collide(d, vec(0, 0, 0), 0, false)) return true; d->vel.z -= grav*GRAVITY*secs; vec old(d->o); - loopi(2) - { + loopi(2) { vec dir(d->vel); dir.mul(secs); d->o.add(dir); - if(!collide(d, dir, 0, true, true)) - { - if(collideinside) - { + if(!collide(d, dir, 0, true, true)) { + if(collideinside) { d->o = old; d->vel.mul(-elasticity); } @@ -1411,8 +1208,7 @@ bool bounce(physent *d, float secs, float elasticity, float grav) d->vel.mul(k); d->vel.sub(vec(collidewall).mul(elasticity*2.0f*c)); } - if(d->physstate!=PHYS_BOUNCE) - { + if(d->physstate!=PHYS_BOUNCE) { // make sure bouncers don't start inside geometry if(d->o == old) return !collideplayer; d->physstate = PHYS_BOUNCE; @@ -1420,8 +1216,7 @@ bool bounce(physent *d, float secs, float elasticity, float grav) return collideplayer!=NULL; } -void avoidcollision(physent *d, const vec &dir, physent *obstacle, float space) -{ +void avoidcollision(physent *d, const vec &dir, physent *obstacle, float space) { float rad = obstacle->radius+d->radius; vec bbmin(obstacle->o); bbmin.x -= rad; @@ -1433,31 +1228,24 @@ void avoidcollision(physent *d, const vec &dir, physent *obstacle, float space) bbmax.y += rad; bbmax.z += obstacle->aboveeye+d->eyeheight; bbmax.add(space); - loopi(3) if(d->o[i] <= bbmin[i] || d->o[i] >= bbmax[i]) return; - float mindist = 1e16f; - loopi(3) if(dir[i] != 0) - { + loopi(3) if(dir[i] != 0) { float dist = ((dir[i] > 0 ? bbmax[i] : bbmin[i]) - d->o[i]) / dir[i]; mindist = min(mindist, dist); } if(mindist >= 0.0f && mindist < 1e15f) d->o.add(vec(dir).mul(mindist)); } -bool movecamera(physent *pl, const vec &dir, float dist, float stepdist) -{ +bool movecamera(physent *pl, const vec &dir, float dist, float stepdist) { int steps = (int)ceil(dist/stepdist); if(steps <= 0) return true; - vec d(dir); d.mul(dist/steps); - loopi(steps) - { + loopi(steps) { vec oldpos(pl->o); pl->o.add(d); - if(collide(pl, vec(0, 0, 0), 0, false)) - { + if(collide(pl, vec(0, 0, 0), 0, false)) { pl->o = oldpos; return false; } @@ -1465,22 +1253,18 @@ bool movecamera(physent *pl, const vec &dir, float dist, float stepdist) return true; } -void dropenttofloor(entity *e) -{ +void dropenttofloor(entity *e) { float radius = 1.0f; float height = 4.0f; vec o = e->o; - static struct dropent : physent - { - dropent() - { + static struct dropent : physent { + dropent() { type = ENT_BOUNCE; vel = vec(0, 0, -1); } } d; d.o = o; - if(!insideworld(d.o)) - { + if(!insideworld(d.o)) { if(d.o.z < worldsize) return; d.o.z = worldsize - 1e-3f; if(!insideworld(d.o)) return; @@ -1495,35 +1279,27 @@ void dropenttofloor(entity *e) o = d.o; } -void vecfromyawpitch(float yaw, float pitch, int move, int strafe, vec &m) -{ - if(move) - { +void vecfromyawpitch(float yaw, float pitch, int move, int strafe, vec &m) { + if(move) { m.x = move*-sinf(RAD*yaw); m.y = move*cosf(RAD*yaw); } else m.x = m.y = 0; - - if(pitch) - { + if(pitch) { m.x *= cosf(RAD*pitch); m.y *= cosf(RAD*pitch); m.z = move*sinf(RAD*pitch); } else m.z = 0; - - if(strafe) - { + if(strafe) { m.x += strafe*cosf(RAD*yaw); m.y += strafe*sinf(RAD*yaw); } } -void vectoyawpitch(const vec &v, float &yaw, float &pitch) -{ +void vectoyawpitch(const vec &v, float &yaw, float &pitch) { if(v.iszero()) yaw = pitch = 0; - else - { + else { yaw = -atan2(v.x, v.y)/RAD; pitch = asin(v.z/v.magnitude())/RAD; } @@ -1536,51 +1312,36 @@ FVAR(straferoll, 0, 0.033f, 90); FVAR(faderoll, 0, 0.95f, 1); VAR(floatspeed, 1, 100, 10000); -void modifyvelocity(physent *pl, bool local, bool floating, int curtime) -{ +void modifyvelocity(physent *pl, bool local, bool floating, int curtime) { bool allowmove = game::allowmove(pl); - if(floating) - { - if(pl->jumping && allowmove) - { + if(floating) { + if(pl->jumping && allowmove) { pl->jumping = false; pl->vel.z = max(pl->vel.z, JUMPVEL); } } - else if(pl->physstate >= PHYS_SLOPE) - { + else if(pl->physstate >= PHYS_SLOPE) { if(!pl->inwater) pl->vel.div(8); - if(pl->jumping && allowmove) - { + if(pl->jumping && allowmove) { pl->jumping = false; - pl->vel.z = max(pl->vel.z, JUMPVEL); // physics impulse upwards - game::physicstrigger(pl, local, 1); } } if(!floating && pl->physstate == PHYS_FALL) pl->timeinair = min(pl->timeinair + curtime, 1000); - vec m(0.0f, 0.0f, 0.0f); - if((pl->move || pl->strafe) && allowmove) - { + if((pl->move || pl->strafe) && allowmove) { vecfromyawpitch(pl->yaw, floating || pl->type==ENT_CAMERA ? pl->pitch : 0, pl->move, pl->strafe, m); - if(!floating && pl->physstate >= PHYS_SLOPE) m.z = -(m.x*pl->floor.x + m.y*pl->floor.y)/pl->floor.z; // move up or down slopes in air - m.normalize(); } - vec d(m); speedmodifier*=(pl->physstate!=PHYS_FLOOR)*(speedmodifier>0); speedmodifier=(speedmodifier>100.0f)?100.0f:speedmodifier; d.mul(pl->maxspeed + speedmodifier); - - if(pl->type==ENT_PLAYER) - { - if(floating) - { + if(pl->type==ENT_PLAYER) { + if(floating) { if(pl==player) d.mul(floatspeed/100.0f); } else if(allowmove) d.mul((pl->move && !pl->strafe ? 1.3f : 1.0f) * (pl->physstate < PHYS_SLOPE ? 1.3f : 1.0f)); @@ -1589,22 +1350,18 @@ void modifyvelocity(physent *pl, bool local, bool floating, int curtime) pl->vel.lerp(d, pl->vel, pow(1 - 1/fric, curtime/20.0f)); } -void modifygravity(physent *pl, int curtime) -{ +void modifygravity(physent *pl, int curtime) { float secs = curtime/1000.0f; vec g(0, 0, 0); if(pl->physstate == PHYS_FALL) g.z -= GRAVITY*secs; - else if(pl->floor.z > 0 && pl->floor.z < FLOORZ) - { + else if(pl->floor.z > 0 && pl->floor.z < FLOORZ) { g.z = -1; g.project(pl->floor); g.normalize(); g.mul(GRAVITY*secs); } if(!game::allowmove(pl) || (!pl->move && !pl->strafe)) pl->falling.add(g); - - if(pl->physstate >= PHYS_SLOPE) - { + if(pl->physstate >= PHYS_SLOPE) { float fric = 6.0f, c = clamp((pl->floor.z - SLOPEZ)/(FLOORZ-SLOPEZ), 0.0f, 1.0f); pl->falling.mul(pow(1 - c/fric, curtime/20.0f)); @@ -1615,71 +1372,53 @@ void modifygravity(physent *pl, int curtime) // moveres indicated the physics precision (which is lower for monsters and multiplayer prediction) // local is false for multiplayer prediction -bool moveplayer(physent *pl, int moveres, bool local, int curtime) -{ +bool moveplayer(physent *pl, int moveres, bool local, int curtime) { int material = lookupmaterial(vec(pl->o.x, pl->o.y, pl->o.z + (3*pl->aboveeye - pl->eyeheight)/4)); bool floating = pl->type==ENT_PLAYER && (pl->state==CS_EDITING || pl->state==CS_SPECTATOR); float secs = curtime/1000.f; - // apply gravity if(!floating) modifygravity(pl, curtime); // apply any player generated changes in velocity modifyvelocity(pl, local, floating, curtime); - vec d(pl->vel); if(!floating) d.mul(0.5f); d.add(pl->falling); d.mul(secs); - pl->blocked = false; - - if(floating) // just apply velocity - { - if(pl->physstate != PHYS_FLOAT) - { + if(floating) { // just apply velocity { + if(pl->physstate != PHYS_FLOAT) { pl->physstate = PHYS_FLOAT; pl->timeinair = 0; pl->falling = vec(0, 0, 0); } pl->o.add(d); } - else // apply velocity with collision - { + else { // apply velocity with collision { const float f = 1.0f/moveres; const int timeinair = pl->timeinair; int collisions = 0; - d.mul(f); loopi(moveres) if(!move(pl, d) && ++collisions<5) i--; // discrete steps collision detection & sliding - if(timeinair > 800 && !pl->timeinair) // if we land after long time must have been a high jump, make thud sound - { + if(timeinair > 800 && !pl->timeinair) { // if we land after long time must have been a high jump, make thud sound { game::physicstrigger(pl, local, -1); } } - if(pl->state==CS_ALIVE) updatedynentcache(pl); - // automatically apply smooth roll when strafing - if(pl->strafe && maxroll) pl->roll = clamp(pl->roll - pow(clamp(1.0f + pl->strafe*pl->roll/maxroll, 0.0f, 1.0f), 0.33f)*pl->strafe*curtime*straferoll, -maxroll, maxroll); else pl->roll *= curtime == PHYSFRAMETIME ? faderoll : pow(faderoll, curtime/float(PHYSFRAMETIME)); - if(pl->inwater) game::physicstrigger(pl, local, 0, pl->inwater); pl->inwater = MAT_AIR; - if(pl->state==CS_ALIVE && (pl->o.z < 0 || material&MAT_DEATH)) game::suicide(pl); - return true; } int physsteps = 0, physframetime = PHYSFRAMETIME, lastphysframe = 0; -void physicsframe() // optimally schedule physics frames inside the graphics frames -{ +void physicsframe() { // optimally schedule physics frames inside the graphics frames { int diff = lastmillis - lastphysframe; if(diff <= 0) physsteps = 0; - else - { + else { physframetime = clamp(game::scaletime(PHYSFRAMETIME)/100, 1, PHYSFRAMETIME); physsteps = (diff + physframetime - 1)/physframetime; lastphysframe += physsteps * physframetime; @@ -1689,50 +1428,39 @@ void physicsframe() // optimally schedule physics frames inside the graphics VAR(physinterp, 0, 1, 1); -void interppos(physent *pl) -{ +void interppos(physent *pl) { pl->o = pl->newpos; - int diff = lastphysframe - lastmillis; if(diff <= 0 || !physinterp) return; - vec deltapos(pl->deltapos); deltapos.mul(min(diff, physframetime)/float(physframetime)); pl->o.add(deltapos); } -void moveplayer(physent *pl, int moveres, bool local) -{ - if(physsteps <= 0) - { +void moveplayer(physent *pl, int moveres, bool local) { + if(physsteps <= 0) { if(local) interppos(pl); return; } - if(local) pl->o = pl->newpos; loopi(physsteps-1) moveplayer(pl, moveres, local, physframetime); if(local) pl->deltapos = pl->o; moveplayer(pl, moveres, local, physframetime); - if(local) - { + if(local) { pl->newpos = pl->o; pl->deltapos.sub(pl->newpos); interppos(pl); } } -bool bounce(physent *d, float elasticity, float grav) -{ - if(physsteps <= 0) - { +bool bounce(physent *d, float elasticity, float grav) { + if(physsteps <= 0) { interppos(d); return false; } - d->o = d->newpos; bool hitplayer = false; - loopi(physsteps-1) - { + loopi(physsteps-1) { if(bounce(d, physframetime/1000.0f, elasticity, grav)) hitplayer = true; } d->deltapos = d->o; @@ -1743,8 +1471,7 @@ bool bounce(physent *d, float elasticity, float grav) return hitplayer; } -void updatephysstate(physent *d) -{ +void updatephysstate(physent *d) { if(d->physstate == PHYS_FALL) return; d->timeinair = 0; vec old(d->o); @@ -1752,8 +1479,7 @@ void updatephysstate(physent *d) * May be inaccurate since movement collisions are not considered. * If good floor is not found, just keep the old floor and hope it's correct enough. */ - switch(d->physstate) - { + switch(d->physstate) { case PHYS_SLOPE: case PHYS_FLOOR: case PHYS_STEP_DOWN: @@ -1761,13 +1487,11 @@ void updatephysstate(physent *d) if(collide(d, vec(0, 0, -1), d->physstate == PHYS_SLOPE || d->physstate == PHYS_STEP_DOWN ? SLOPEZ : FLOORZ)) d->floor = collidewall; break; - case PHYS_STEP_UP: d->o.z -= STAIRHEIGHT+0.15f; if(collide(d, vec(0, 0, -1), SLOPEZ)) d->floor = collidewall; break; - case PHYS_SLIDE: d->o.z -= 0.15f; if(collide(d, vec(0, 0, -1)) && collidewall.z < SLOPEZ) @@ -1788,30 +1512,23 @@ dir(right, strafe, -1, k_right, k_left); ICOMMAND(jump, "D", (int *down), { if(!*down || game::canjump()) player->jumping = *down!=0; }); ICOMMAND(attack, "D", (int *down), { game::doattack(*down!=0); }); -bool entinmap(dynent *d, bool avoidplayers) // brute force but effective way to find a free spawn spot in the map -{ +bool entinmap(dynent *d, bool avoidplayers) { // brute force but effective way to find a free spawn spot in the map { d->o.z += d->eyeheight; // pos specified is at feet vec orig = d->o; - loopi(100) // try max 100 times - { - if(i) - { + loopi(100) { // try max 100 times { + if(i) { d->o = orig; d->o.x += (rnd(21)-10)*i/5; // increasing distance d->o.y += (rnd(21)-10)*i/5; d->o.z += (rnd(21)-10)*i/5; } - - if(!collide(d) && !collideinside) - { - if(collideplayer) - { + if(!collide(d) && !collideinside) { + if(collideplayer) { if(!avoidplayers) continue; d->o = orig; d->resetinterp(); return false; } - d->resetinterp(); return true; } diff --git a/src/engine/ragdoll.h b/src/engine/ragdoll.h index 4dac48c..915076e 100644 --- a/src/engine/ragdoll.h +++ b/src/engine/ragdoll.h @@ -1,53 +1,36 @@ -struct ragdollskel -{ - struct vert - { +struct ragdollskel { + struct vert { vec pos; float radius, weight; }; - - struct tri - { + struct tri { int vert[3]; - - bool shareverts(const tri &t) const - { + bool shareverts(const tri &t) const { loopi(3) loopj(3) if(vert[i] == t.vert[j]) return true; return false; } }; - - struct distlimit - { + struct distlimit { int vert[2]; float mindist, maxdist; }; - - struct rotlimit - { + struct rotlimit { int tri[2]; float maxangle; matrix3 middle; }; - - struct rotfriction - { + struct rotfriction { int tri[2]; matrix3 middle; }; - - struct joint - { + struct joint { int bone, tri, vert[3]; float weight; matrix4x3 orient; }; - - struct reljoint - { + struct reljoint { int bone, parent; }; - bool loaded, animjoints; int eye; vector verts; @@ -57,26 +40,20 @@ struct ragdollskel vector rotfrictions; vector joints; vector reljoints; - ragdollskel() : loaded(false), animjoints(false), eye(-1) {} - - void setupjoints() - { + void setupjoints() { loopv(verts) verts[i].weight = 0; - loopv(joints) - { + loopv(joints) { joint &j = joints[i]; j.weight = 0; vec pos(0, 0, 0); - loopk(3) if(j.vert[k]>=0) - { + loopk(3) if(j.vert[k]>=0) { pos.add(verts[j.vert[k]].pos); j.weight++; verts[j.vert[k]].weight++; } if(j.weight) j.weight = 1/j.weight; pos.mul(j.weight); - tri &t = tris[j.tri]; matrix4x3 &m = j.orient; const vec &v1 = verts[t.vert[0]].pos, @@ -91,45 +68,33 @@ struct ragdollskel loopv(verts) if(verts[i].weight) verts[i].weight = 1/verts[i].weight; reljoints.shrink(0); } - - void setuprotfrictions() - { + void setuprotfrictions() { rotfrictions.shrink(0); - loopv(tris) for(int j = i+1; j < tris.length(); j++) if(tris[i].shareverts(tris[j])) - { + loopv(tris) for(int j = i+1; j < tris.length(); j++) if(tris[i].shareverts(tris[j])) { rotfriction &r = rotfrictions.add(); r.tri[0] = i; r.tri[1] = j; } } - - void setup() - { + void setup() { setupjoints(); setuprotfrictions(); - loaded = true; } - - void addreljoint(int bone, int parent) - { + void addreljoint(int bone, int parent) { reljoint &r = reljoints.add(); r.bone = bone; r.parent = parent; } }; -struct ragdolldata -{ - struct vert - { +struct ragdolldata { + struct vert { vec oldpos, pos, newpos; float weight; bool collided, stuck; - vert() : pos(0, 0, 0), newpos(0, 0, 0), weight(0), collided(false), stuck(true) {} }; - ragdollskel *skel; int millis, collidemillis, collisions, floating, lastmove, unsticks; vec offset, center; @@ -138,7 +103,6 @@ struct ragdolldata matrix3 *tris; matrix4x3 *animjoints; dualquat *reljoints; - ragdolldata(ragdollskel *skel, float scale = 1) : skel(skel), millis(lastmillis), @@ -153,26 +117,20 @@ struct ragdolldata verts(new vert[skel->verts.length()]), tris(new matrix3[skel->tris.length()]), animjoints(!skel->animjoints || skel->joints.empty() ? NULL : new matrix4x3[skel->joints.length()]), - reljoints(skel->reljoints.empty() ? NULL : new dualquat[skel->reljoints.length()]) - { + reljoints(skel->reljoints.empty() ? NULL : new dualquat[skel->reljoints.length()]) { } - - ~ragdolldata() - { + ~ragdolldata() { delete[] verts; delete[] tris; if(animjoints) delete[] animjoints; if(reljoints) delete[] reljoints; } - - void calcanimjoint(int i, const matrix4x3 &anim) - { + void calcanimjoint(int i, const matrix4x3 &anim) { if(!animjoints) return; ragdollskel::joint &j = skel->joints[i]; vec pos(0, 0, 0); loopk(3) if(j.vert[k]>=0) pos.add(verts[j.vert[k]].pos); pos.mul(j.weight); - ragdollskel::tri &t = skel->tris[j.tri]; matrix4x3 m; const vec &v1 = verts[t.vert[0]].pos, @@ -184,11 +142,8 @@ struct ragdolldata m.d = pos; animjoints[i].transposemul(m, anim); } - - void calctris() - { - loopv(skel->tris) - { + void calctris() { + loopv(skel->tris) { ragdollskel::tri &t = skel->tris[i]; matrix3 &m = tris[i]; const vec &v1 = verts[t.vert[0]].pos, @@ -199,30 +154,24 @@ struct ragdolldata m.b.cross(m.c, m.a); } } - - void calcboundsphere() - { + void calcboundsphere() { center = vec(0, 0, 0); loopv(skel->verts) center.add(verts[i].pos); center.div(skel->verts.length()); radius = 0; loopv(skel->verts) radius = max(radius, verts[i].pos.dist(center)); } - - void init(dynent *d) - { + void init(dynent *d) { extern int ragdolltimestepmin; float ts = ragdolltimestepmin/1000.0f; loopv(skel->verts) (verts[i].oldpos = verts[i].pos).sub(vec(d->vel).add(d->falling).mul(ts)); timestep = ts; - calctris(); calcboundsphere(); offset = d->o; offset.sub(skel->eye >= 0 ? verts[skel->eye].pos : center); offset.z += (d->eyeheight + d->aboveeye)/2; } - void move(dynent *pl, float ts); void updatepos(); void constrain(); @@ -232,13 +181,9 @@ struct ragdolldata void calcrotfriction(); void applyrotfriction(float ts); void tryunstick(float speed); - - static inline bool collidevert(const vec &pos, const vec &dir, float radius) - { - static struct vertent : physent - { - vertent() - { + static inline bool collidevert(const vec &pos, const vec &dir, float radius) { + static struct vertent : physent { + vertent() { type = ENT_BOUNCE; radius = xradius = yradius = eyeheight = aboveeye = 1; } @@ -255,11 +200,9 @@ struct ragdolldata parented transform = parent{invert(curtri) * origtrig} * (invert(parent{base2anim}) * base2anim) */ -void ragdolldata::constraindist() -{ +void ragdolldata::constraindist() { float invscale = 1.0f/scale; - loopv(skel->distlimits) - { + loopv(skel->distlimits) { ragdollskel::distlimit &d = skel->distlimits[i]; vert &v1 = verts[d.vert[0]], &v2 = verts[d.vert[1]]; vec dir = vec(v2.pos).sub(v1.pos); @@ -277,8 +220,7 @@ void ragdolldata::constraindist() } } -inline void ragdolldata::applyrotlimit(ragdollskel::tri &t1, ragdollskel::tri &t2, float angle, const vec &axis) -{ +inline void ragdolldata::applyrotlimit(ragdollskel::tri &t1, ragdollskel::tri &t2, float angle, const vec &axis) { vert &v1a = verts[t1.vert[0]], &v1b = verts[t1.vert[1]], &v1c = verts[t1.vert[2]], &v2a = verts[t2.vert[0]], &v2b = verts[t2.vert[1]], &v2c = verts[t2.vert[2]]; vec m1 = vec(v1a.pos).add(v1b.pos).add(v1c.pos).div(3), @@ -308,22 +250,18 @@ inline void ragdolldata::applyrotlimit(ragdollskel::tri &t1, ragdollskel::tri &t v2c.weight++; } -void ragdolldata::constrainrot() -{ - loopv(skel->rotlimits) - { +void ragdolldata::constrainrot() { + loopv(skel->rotlimits) { ragdollskel::rotlimit &r = skel->rotlimits[i]; matrix3 rot; rot.mul(tris[r.tri[0]], r.middle); rot.multranspose(tris[r.tri[1]]); - vec axis; float angle; if(!rot.calcangleaxis(angle, axis)) continue; angle = r.maxangle - fabs(angle); if(angle >= 0) continue; angle += 1e-3f; - applyrotlimit(skel->tris[r.tri[0]], skel->tris[r.tri[1]], angle, axis); } } @@ -333,36 +271,29 @@ VAR(ragdolltimestepmax, 1, 10, 50); FVAR(ragdollrotfric, 0, 0.85f, 1); FVAR(ragdollrotfricstop, 0, 0.1f, 1); -void ragdolldata::calcrotfriction() -{ - loopv(skel->rotfrictions) - { +void ragdolldata::calcrotfriction() { + loopv(skel->rotfrictions) { ragdollskel::rotfriction &r = skel->rotfrictions[i]; r.middle.transposemul(tris[r.tri[0]], tris[r.tri[1]]); } } -void ragdolldata::applyrotfriction(float ts) -{ +void ragdolldata::applyrotfriction(float ts) { calctris(); float stopangle = 2*M_PI*ts*ragdollrotfricstop, rotfric = 1.0f - pow(ragdollrotfric, ts*1000.0f/ragdolltimestepmin); - loopv(skel->rotfrictions) - { + loopv(skel->rotfrictions) { ragdollskel::rotfriction &r = skel->rotfrictions[i]; matrix3 rot; rot.mul(tris[r.tri[0]], r.middle); rot.multranspose(tris[r.tri[1]]); - vec axis; float angle; - if(rot.calcangleaxis(angle, axis)) - { + if(rot.calcangleaxis(angle, axis)) { angle *= -(fabs(angle) >= stopangle ? rotfric : 1.0f); applyrotlimit(skel->tris[r.tri[0]], skel->tris[r.tri[1]], angle, axis); } } - loopv(skel->verts) - { + loopv(skel->verts) { vert &v = verts[i]; if(v.weight) v.pos = v.newpos.div(v.weight); v.newpos = vec(0, 0, 0); @@ -370,15 +301,12 @@ void ragdolldata::applyrotfriction(float ts) } } -void ragdolldata::tryunstick(float speed) -{ +void ragdolldata::tryunstick(float speed) { vec unstuck(0, 0, 0); int stuck = 0; - loopv(skel->verts) - { + loopv(skel->verts) { vert &v = verts[i]; - if(v.stuck) - { + if(v.stuck) { if(collidevert(v.pos, vec(0, 0, 0), skel->verts[i].radius)) { stuck++; continue; } v.stuck = false; } @@ -387,28 +315,22 @@ void ragdolldata::tryunstick(float speed) unsticks = 0; if(!stuck || stuck >= skel->verts.length()) return; unstuck.div(skel->verts.length() - stuck); - loopv(skel->verts) - { + loopv(skel->verts) { vert &v = verts[i]; - if(v.stuck) - { + if(v.stuck) { v.pos.add(vec(unstuck).sub(v.pos).rescale(speed)); unsticks++; } } } -void ragdolldata::updatepos() -{ - loopv(skel->verts) - { +void ragdolldata::updatepos() { + loopv(skel->verts) { vert &v = verts[i]; - if(v.weight) - { + if(v.weight) { v.newpos.div(v.weight); if(!collidevert(v.newpos, vec(v.newpos).sub(v.pos), skel->verts[i].radius)) v.pos = v.newpos; - else - { + else { vec dir = vec(v.newpos).sub(v.oldpos); if(dir.dot(collidewall) < 0) v.oldpos = vec(v.pos).sub(dir.reflect(collidewall)); v.collided = true; @@ -421,13 +343,10 @@ void ragdolldata::updatepos() VAR(ragdollconstrain, 1, 5, 100); -void ragdolldata::constrain() -{ - loopi(ragdollconstrain) - { +void ragdolldata::constrain() { + loopi(ragdollconstrain) { constraindist(); updatepos(); - calctris(); constrainrot(); updatepos(); @@ -441,19 +360,15 @@ FVAR(ragdollairfric, 0, 0.996f, 1); FVAR(ragdollunstick, 0, 10, 1e3f); VAR(ragdollexpireoffset, 0, 1500, 30000); -void ragdolldata::move(dynent *pl, float ts) -{ +void ragdolldata::move(dynent *pl, float ts) { extern const float GRAVITY; if(collidemillis && lastmillis > collidemillis) return; - pl->inwater = MAT_AIR; - calcrotfriction(); float tsfric = timestep ? ts/timestep : 1, airfric = ragdollairfric + min((ragdollbodyfricscale*collisions)/skel->verts.length(), 1.0f)*(ragdollbodyfric - ragdollairfric); collisions = 0; - loopv(skel->verts) - { + loopv(skel->verts) { vert &v = verts[i]; vec dpos = vec(v.pos).sub(v.oldpos); dpos.z -= GRAVITY*ts*ts; @@ -462,30 +377,24 @@ void ragdolldata::move(dynent *pl, float ts) v.pos.add(dpos); } applyrotfriction(ts); - loopv(skel->verts) - { + loopv(skel->verts) { vert &v = verts[i]; if(v.pos.z < 0) { v.pos.z = 0; v.oldpos = v.pos; collisions++; } vec dir = vec(v.pos).sub(v.oldpos); v.collided = collidevert(v.pos, dir, skel->verts[i].radius); - if(v.collided) - { + if(v.collided) { v.pos = v.oldpos; v.oldpos.sub(dir.reflect(collidewall)); collisions++; } } - if(unsticks && ragdollunstick) tryunstick(ts*ragdollunstick); - timestep = ts; - if(collisions) - { + if(collisions) { floating = 0; if(!collidemillis) collidemillis = lastmillis + ragdollexpireoffset; } else if(++floating > 1 && lastmillis < collidemillis) collidemillis = 0; - constrain(); calctris(); calcboundsphere(); @@ -494,28 +403,22 @@ void ragdolldata::move(dynent *pl, float ts) FVAR(ragdolleyesmooth, 0, 0.5f, 1); VAR(ragdolleyesmoothmillis, 1, 250, 10000); -void moveragdoll(dynent *d) -{ +void moveragdoll(dynent *d) { if(!curtime || !d->ragdoll) return; - - if(!d->ragdoll->collidemillis || lastmillis < d->ragdoll->collidemillis) - { + if(!d->ragdoll->collidemillis || lastmillis < d->ragdoll->collidemillis) { int lastmove = d->ragdoll->lastmove; - while(d->ragdoll->lastmove + (lastmove == d->ragdoll->lastmove ? ragdolltimestepmin : ragdolltimestepmax) <= lastmillis) - { + while(d->ragdoll->lastmove + (lastmove == d->ragdoll->lastmove ? ragdolltimestepmin : ragdolltimestepmax) <= lastmillis) { int timestep = min(ragdolltimestepmax, lastmillis - d->ragdoll->lastmove); d->ragdoll->move(d, timestep/1000.0f); d->ragdoll->lastmove += timestep; } } - vec eye = d->ragdoll->skel->eye >= 0 ? d->ragdoll->verts[d->ragdoll->skel->eye].pos : d->ragdoll->center; eye.add(d->ragdoll->offset); float k = pow(ragdolleyesmooth, float(curtime)/ragdolleyesmoothmillis); d->o.mul(k).add(eye.mul(1-k)); } -void cleanragdoll(dynent *d) -{ +void cleanragdoll(dynent *d) { DELETEP(d->ragdoll); } diff --git a/src/engine/rendergl.cpp b/src/engine/rendergl.cpp index 7489ff5..b8b28c5 100644 --- a/src/engine/rendergl.cpp +++ b/src/engine/rendergl.cpp @@ -143,8 +143,7 @@ PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays_ = NULL; PFNGLGENVERTEXARRAYSPROC glGenVertexArrays_ = NULL; PFNGLISVERTEXARRAYPROC glIsVertexArray_ = NULL; -void *getprocaddress(const char *name) -{ +void *getprocaddress(const char *name) { return SDL_GL_GetProcAddress(name); } @@ -162,23 +161,18 @@ VAR(rtsharefb, 0, 1, 1); hashset glexts; -void parseglexts() -{ - if(glversion >= 300) - { +void parseglexts() { + if(glversion >= 300) { GLint numexts = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &numexts); - loopi(numexts) - { + loopi(numexts) { const char *ext = (const char *)glGetStringi_(GL_EXTENSIONS, i); glexts.add(newstring(ext)); } } - else - { + else { const char *exts = (const char *)glGetString(GL_EXTENSIONS); - for(;;) - { + for(;;) { while(*exts == ' ') exts++; if(!*exts) break; const char *ext = exts; @@ -188,47 +182,35 @@ void parseglexts() } } -bool hasext(const char *ext) -{ +bool hasext(const char *ext) { return glexts.access(ext)!=NULL; } -void gl_checkextensions() -{ +void gl_checkextensions() { const char *vendor = (const char *)glGetString(GL_VENDOR); const char *renderer = (const char *)glGetString(GL_RENDERER); const char *version = (const char *)glGetString(GL_VERSION); conoutf(CON_INIT, "Renderer: %s (%s)", renderer, vendor); conoutf(CON_INIT, "Driver: %s", version); - - bool mesa = false, intel = false, ati = false, nvidia = false; - if(strstr(renderer, "Mesa") || strstr(version, "Mesa")) - { + bool mesa = false, ati = false, nvidia = false; + if(strstr(renderer, "Mesa") || strstr(version, "Mesa")) { mesa = true; - if(strstr(renderer, "Intel")) intel = true; } else if(strstr(vendor, "NVIDIA")) nvidia = true; else if(strstr(vendor, "ATI") || strstr(vendor, "Advanced Micro Devices")) ati = true; - else if(strstr(vendor, "Intel")) - intel = true; - uint glmajorversion, glminorversion; if(sscanf(version, " %u.%u", &glmajorversion, &glminorversion) != 2) glversion = 100; else glversion = glmajorversion*100 + glminorversion*10; - if(glversion < 200) fatal("OpenGL 2.0 or greater is required!"); - glMultiDrawArrays_ = (PFNGLMULTIDRAWARRAYSPROC) getprocaddress("glMultiDrawArrays"); glMultiDrawElements_ = (PFNGLMULTIDRAWELEMENTSPROC) getprocaddress("glMultiDrawElements"); - glBlendFuncSeparate_ = (PFNGLBLENDFUNCSEPARATEPROC) getprocaddress("glBlendFuncSeparate"); glBlendEquationSeparate_ = (PFNGLBLENDEQUATIONSEPARATEPROC) getprocaddress("glBlendEquationSeparate"); glStencilOpSeparate_ = (PFNGLSTENCILOPSEPARATEPROC) getprocaddress("glStencilOpSeparate"); glStencilFuncSeparate_ = (PFNGLSTENCILFUNCSEPARATEPROC) getprocaddress("glStencilFuncSeparate"); glStencilMaskSeparate_ = (PFNGLSTENCILMASKSEPARATEPROC) getprocaddress("glStencilMaskSeparate"); - glGenBuffers_ = (PFNGLGENBUFFERSPROC) getprocaddress("glGenBuffers"); glBindBuffer_ = (PFNGLBINDBUFFERPROC) getprocaddress("glBindBuffer"); glMapBuffer_ = (PFNGLMAPBUFFERPROC) getprocaddress("glMapBuffer"); @@ -237,7 +219,6 @@ void gl_checkextensions() glBufferSubData_ = (PFNGLBUFFERSUBDATAPROC) getprocaddress("glBufferSubData"); glDeleteBuffers_ = (PFNGLDELETEBUFFERSPROC) getprocaddress("glDeleteBuffers"); glGetBufferSubData_ = (PFNGLGETBUFFERSUBDATAPROC) getprocaddress("glGetBufferSubData"); - glGetQueryiv_ = (PFNGLGETQUERYIVPROC) getprocaddress("glGetQueryiv"); glGenQueries_ = (PFNGLGENQUERIESPROC) getprocaddress("glGenQueries"); glDeleteQueries_ = (PFNGLDELETEQUERIESPROC) getprocaddress("glDeleteQueries"); @@ -245,7 +226,6 @@ void gl_checkextensions() glEndQuery_ = (PFNGLENDQUERYPROC) getprocaddress("glEndQuery"); glGetQueryObjectiv_ = (PFNGLGETQUERYOBJECTIVPROC) getprocaddress("glGetQueryObjectiv"); glGetQueryObjectuiv_ = (PFNGLGETQUERYOBJECTUIVPROC) getprocaddress("glGetQueryObjectuiv"); - glCreateProgram_ = (PFNGLCREATEPROGRAMPROC) getprocaddress("glCreateProgram"); glDeleteProgram_ = (PFNGLDELETEPROGRAMPROC) getprocaddress("glDeleteProgram"); glUseProgram_ = (PFNGLUSEPROGRAMPROC) getprocaddress("glUseProgram"); @@ -283,7 +263,6 @@ void gl_checkextensions() glGetActiveUniform_ = (PFNGLGETACTIVEUNIFORMPROC) getprocaddress("glGetActiveUniform"); glEnableVertexAttribArray_ = (PFNGLENABLEVERTEXATTRIBARRAYPROC) getprocaddress("glEnableVertexAttribArray"); glDisableVertexAttribArray_ = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) getprocaddress("glDisableVertexAttribArray"); - glVertexAttrib1f_ = (PFNGLVERTEXATTRIB1FPROC) getprocaddress("glVertexAttrib1f"); glVertexAttrib1fv_ = (PFNGLVERTEXATTRIB1FVPROC) getprocaddress("glVertexAttrib1fv"); glVertexAttrib1s_ = (PFNGLVERTEXATTRIB1SPROC) getprocaddress("glVertexAttrib1s"); @@ -312,44 +291,31 @@ void gl_checkextensions() glVertexAttrib4Nuiv_ = (PFNGLVERTEXATTRIB4NUIVPROC) getprocaddress("glVertexAttrib4Nuiv"); glVertexAttrib4Nusv_ = (PFNGLVERTEXATTRIB4NUSVPROC) getprocaddress("glVertexAttrib4Nusv"); glVertexAttribPointer_ = (PFNGLVERTEXATTRIBPOINTERPROC) getprocaddress("glVertexAttribPointer"); - glDrawBuffers_ = (PFNGLDRAWBUFFERSPROC) getprocaddress("glDrawBuffers"); - - if(glversion >= 300) - { + if(glversion >= 300) { glGetStringi_ = (PFNGLGETSTRINGIPROC) getprocaddress("glGetStringi"); glBindFragDataLocation_ = (PFNGLBINDFRAGDATALOCATIONPROC)getprocaddress("glBindFragDataLocation"); } - const char *glslstr = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION); uint glslmajorversion, glslminorversion; if(glslstr && sscanf(glslstr, " %u.%u", &glslmajorversion, &glslminorversion) == 2) glslversion = glslmajorversion*100 + glslminorversion; - if(glslversion < 120) fatal("GLSL 1.20 or greater is required!"); - parseglexts(); - GLint val; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &val); hwtexsize = val; glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &val); hwcubetexsize = val; - - if(glversion >= 300 || hasext("GL_ARB_texture_float") || hasext("GL_ATI_texture_float")) - { + if(glversion >= 300 || hasext("GL_ARB_texture_float") || hasext("GL_ATI_texture_float")) { hasTF = true; shadowmap = 1; extern int smoothshadowmappeel; smoothshadowmappeel = 1; } - - if(glversion >= 300 || hasext("GL_ARB_texture_rg")) - { + if(glversion >= 300 || hasext("GL_ARB_texture_rg")) { hasTRG = true; } - - if(glversion >= 300 || hasext("GL_ARB_framebuffer_object")) - { + if(glversion >= 300 || hasext("GL_ARB_framebuffer_object")) { glBindRenderbuffer_ = (PFNGLBINDRENDERBUFFERPROC) getprocaddress("glBindRenderbuffer"); glDeleteRenderbuffers_ = (PFNGLDELETERENDERBUFFERSPROC) getprocaddress("glDeleteRenderbuffers"); glGenRenderbuffers_ = (PFNGLGENFRAMEBUFFERSPROC) getprocaddress("glGenRenderbuffers"); @@ -364,8 +330,7 @@ void gl_checkextensions() glBlitFramebuffer_ = (PFNGLBLITFRAMEBUFFERPROC) getprocaddress("glBlitFramebuffer"); hasAFBO = hasFBO = hasFBB = hasDS = true; } - else if(hasext("GL_EXT_framebuffer_object")) - { + else if(hasext("GL_EXT_framebuffer_object")) { glBindRenderbuffer_ = (PFNGLBINDRENDERBUFFERPROC) getprocaddress("glBindRenderbufferEXT"); glDeleteRenderbuffers_ = (PFNGLDELETERENDERBUFFERSPROC) getprocaddress("glDeleteRenderbuffersEXT"); glGenRenderbuffers_ = (PFNGLGENFRAMEBUFFERSPROC) getprocaddress("glGenRenderbuffersEXT"); @@ -378,49 +343,36 @@ void gl_checkextensions() glFramebufferRenderbuffer_ = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)getprocaddress("glFramebufferRenderbufferEXT"); glGenerateMipmap_ = (PFNGLGENERATEMIPMAPPROC) getprocaddress("glGenerateMipmapEXT"); hasFBO = true; - - if(hasext("GL_EXT_framebuffer_blit")) - { + if(hasext("GL_EXT_framebuffer_blit")) { glBlitFramebuffer_ = (PFNGLBLITFRAMEBUFFERPROC) getprocaddress("glBlitFramebufferEXT"); hasFBB = true; } - - if(hasext("GL_EXT_packed_depth_stencil") || hasext("GL_NV_packed_depth_stencil")) - { + if(hasext("GL_EXT_packed_depth_stencil") || hasext("GL_NV_packed_depth_stencil")) { hasDS = true; } } else fatal("Framebuffer object support is required!"); - - if(ati) - { + if(ati) { minimizetcusage = 1; // On Catalyst 10.2, issuing an occlusion query on the first draw using a given cubemap texture causes a nasty crash ati_cubemap_bug = 1; } - else if(nvidia) - { + else if(nvidia) { reservevpparams = 10; rtsharefb = 0; // work-around for strange driver stalls involving when using many FBOs extern int filltjoints; if(glversion < 300 && !hasext("GL_EXT_gpu_shader4")) filltjoints = 0; // DX9 or less NV cards seem to not cause many sparklies } - else - { + else { reservevpparams = 20; - if(mesa) mesa_swap_bug = 1; } - - if(glversion >= 300 || hasext("GL_ARB_map_buffer_range")) - { + if(glversion >= 300 || hasext("GL_ARB_map_buffer_range")) { glMapBufferRange_ = (PFNGLMAPBUFFERRANGEPROC) getprocaddress("glMapBufferRange"); glFlushMappedBufferRange_ = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC)getprocaddress("glFlushMappedBufferRange"); hasMBR = true; } - - if(glversion >= 310 || hasext("GL_ARB_uniform_buffer_object")) - { + if(glversion >= 310 || hasext("GL_ARB_uniform_buffer_object")) { glGetUniformIndices_ = (PFNGLGETUNIFORMINDICESPROC) getprocaddress("glGetUniformIndices"); glGetActiveUniformsiv_ = (PFNGLGETACTIVEUNIFORMSIVPROC) getprocaddress("glGetActiveUniformsiv"); glGetUniformBlockIndex_ = (PFNGLGETUNIFORMBLOCKINDEXPROC) getprocaddress("glGetUniformBlockIndex"); @@ -428,66 +380,50 @@ void gl_checkextensions() glUniformBlockBinding_ = (PFNGLUNIFORMBLOCKBINDINGPROC) getprocaddress("glUniformBlockBinding"); glBindBufferBase_ = (PFNGLBINDBUFFERBASEPROC) getprocaddress("glBindBufferBase"); glBindBufferRange_ = (PFNGLBINDBUFFERRANGEPROC) getprocaddress("glBindBufferRange"); - useubo = 1; hasUBO = true; } - - if(glversion >= 300 || hasext("GL_ARB_vertex_array_object")) - { + if(glversion >= 300 || hasext("GL_ARB_vertex_array_object")) { glBindVertexArray_ = (PFNGLBINDVERTEXARRAYPROC) getprocaddress("glBindVertexArray"); glDeleteVertexArrays_ = (PFNGLDELETEVERTEXARRAYSPROC)getprocaddress("glDeleteVertexArrays"); glGenVertexArrays_ = (PFNGLGENVERTEXARRAYSPROC) getprocaddress("glGenVertexArrays"); glIsVertexArray_ = (PFNGLISVERTEXARRAYPROC) getprocaddress("glIsVertexArray"); hasVAO = true; } - else if(hasext("GL_APPLE_vertex_array_object")) - { + else if(hasext("GL_APPLE_vertex_array_object")) { glBindVertexArray_ = (PFNGLBINDVERTEXARRAYPROC) getprocaddress("glBindVertexArrayAPPLE"); glDeleteVertexArrays_ = (PFNGLDELETEVERTEXARRAYSPROC)getprocaddress("glDeleteVertexArraysAPPLE"); glGenVertexArrays_ = (PFNGLGENVERTEXARRAYSPROC) getprocaddress("glGenVertexArraysAPPLE"); glIsVertexArray_ = (PFNGLISVERTEXARRAYPROC) getprocaddress("glIsVertexArrayAPPLE"); hasVAO = true; } - - if(glversion >= 330 || hasext("GL_ARB_texture_swizzle") || hasext("GL_EXT_texture_swizzle")) - { + if(glversion >= 330 || hasext("GL_ARB_texture_swizzle") || hasext("GL_EXT_texture_swizzle")) { hasTSW = true; } - - if(hasext("GL_EXT_texture_compression_s3tc")) - { + if(hasext("GL_EXT_texture_compression_s3tc")) { hasS3TC = true; if(!mesa) usetexcompress = 2; } - else if(hasext("GL_EXT_texture_compression_dxt1") && hasext("GL_ANGLE_texture_compression_dxt3") && hasext("GL_ANGLE_texture_compression_dxt5")) - { + else if(hasext("GL_EXT_texture_compression_dxt1") && hasext("GL_ANGLE_texture_compression_dxt3") && hasext("GL_ANGLE_texture_compression_dxt5")) { hasS3TC = true; } - if(hasext("GL_3DFX_texture_compression_FXT1")) - { + if(hasext("GL_3DFX_texture_compression_FXT1")) { hasFXT1 = true; if(mesa) usetexcompress = max(usetexcompress, 1); } - if(hasext("GL_EXT_texture_compression_latc")) - { + if(hasext("GL_EXT_texture_compression_latc")) { hasLATC = true; } - if(glversion >= 300 || hasext("GL_ARB_texture_compression_rgtc") || hasext("GL_EXT_texture_compression_rgtc")) - { + if(glversion >= 300 || hasext("GL_ARB_texture_compression_rgtc") || hasext("GL_EXT_texture_compression_rgtc")) { hasRGTC = true; } - - if(hasext("GL_EXT_texture_filter_anisotropic")) - { + if(hasext("GL_EXT_texture_filter_anisotropic")) { GLint val; glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &val); hwmaxaniso = val; hasAF = true; } - - if(glversion >= 300 || hasext("GL_EXT_gpu_shader4")) - { + if(glversion >= 300 || hasext("GL_EXT_gpu_shader4")) { // on DX10 or above class cards (i.e. GF8 or RadeonHD) enable expensive features extern int maxdynlights, texcompress; maxdynlights = MAXDYNLIGHTS; @@ -495,37 +431,28 @@ void gl_checkextensions() } } -void glext(char *ext) -{ +void glext(char *ext) { intret(hasext(ext) ? 1 : 0); } COMMAND(glext, "s"); -void gl_resize() -{ +void gl_resize() { glViewport(0, 0, screenw, screenh); } -void gl_init() -{ +void gl_init() { glClearColor(0, 0, 0, 0); glClearDepth(1); glDepthFunc(GL_LESS); glDisable(GL_DEPTH_TEST); - glEnable(GL_LINE_SMOOTH); //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glFrontFace(GL_CW); glCullFace(GL_BACK); glDisable(GL_CULL_FACE); - gle::setup(); - setupshaders(); - setuptexcompress(); - gl_resize(); } @@ -534,95 +461,76 @@ VAR(wireframe, 0, 0, 1); ICOMMAND(getcamyaw, "", (), floatret(camera1->yaw)); ICOMMAND(getcampitch, "", (), floatret(camera1->pitch)); ICOMMAND(getcamroll, "", (), floatret(camera1->roll)); -ICOMMAND(getcampos, "", (), -{ +ICOMMAND(getcampos, "", (), { defformatstring(pos, "%s %s %s", floatstr(camera1->o.x), floatstr(camera1->o.y), floatstr(camera1->o.z)); result(pos); }); vec worldpos, camdir, camright, camup; -void setcammatrix() -{ +void setcammatrix() { // move from RH to Z-up LH quake style worldspace cammatrix = viewmatrix; cammatrix.rotate_around_y(camera1->roll*RAD); cammatrix.rotate_around_x(camera1->pitch*-RAD); cammatrix.rotate_around_z(camera1->yaw*-RAD); cammatrix.translate(vec(camera1->o).neg()); - cammatrix.transposedtransformnormal(vec(viewmatrix.b), camdir); cammatrix.transposedtransformnormal(vec(viewmatrix.a).neg(), camright); cammatrix.transposedtransformnormal(vec(viewmatrix.c), camup); - - if(!drawtex) - { + if(!drawtex) { if(raycubepos(camera1->o, camdir, worldpos, 0, RAY_CLIPMAT|RAY_SKIPFIRST) == -1) worldpos = vec(camdir).mul(2*worldsize).add(camera1->o); // if nothing is hit, just far away in the view direction } } -void setcamprojmatrix(bool init = true, bool flush = false) -{ - if(init) - { +void setcamprojmatrix(bool init = true, bool flush = false) { + if(init) { setcammatrix(); } - camprojmatrix.muld(projmatrix, cammatrix); - - if(init) - { + if(init) { invcammatrix.invert(cammatrix); invcamprojmatrix.invert(camprojmatrix); } - GLOBALPARAM(camprojmatrix, camprojmatrix); - if(flush && Shader::lastshader) Shader::lastshader->flushparams(); } matrix4 hudmatrix, hudmatrixstack[64]; int hudmatrixpos = 0; -void resethudmatrix() -{ +void resethudmatrix() { hudmatrixpos = 0; GLOBALPARAM(hudmatrix, hudmatrix); } -void pushhudmatrix() -{ +void pushhudmatrix() { if(hudmatrixpos >= 0 && hudmatrixpos < int(sizeof(hudmatrixstack)/sizeof(hudmatrixstack[0]))) hudmatrixstack[hudmatrixpos] = hudmatrix; ++hudmatrixpos; } -void flushhudmatrix(bool flushparams) -{ +void flushhudmatrix(bool flushparams) { GLOBALPARAM(hudmatrix, hudmatrix); if(flushparams && Shader::lastshader) Shader::lastshader->flushparams(); } -void pophudmatrix(bool flush, bool flushparams) -{ +void pophudmatrix(bool flush, bool flushparams) { --hudmatrixpos; - if(hudmatrixpos >= 0 && hudmatrixpos < int(sizeof(hudmatrixstack)/sizeof(hudmatrixstack[0]))) - { + if(hudmatrixpos >= 0 && hudmatrixpos < int(sizeof(hudmatrixstack)/sizeof(hudmatrixstack[0]))) { hudmatrix = hudmatrixstack[hudmatrixpos]; if(flush) flushhudmatrix(flushparams); } } -void pushhudscale(float sx, float sy) -{ +void pushhudscale(float sx, float sy) { if(!sy) sy = sx; pushhudmatrix(); hudmatrix.scale(sx, sy, 1); flushhudmatrix(); } -void pushhudtranslate(float tx, float ty, float sx, float sy) -{ +void pushhudtranslate(float tx, float ty, float sx, float sy) { if(!sy) sy = sx; pushhudmatrix(); hudmatrix.translate(tx, ty, 0); @@ -644,18 +552,15 @@ FVARNP(aspect, forceaspect, 0, 0, 1e3f); static float zoomprogress = 0; VAR(zoom, -1, 0, 1); -void disablezoom() -{ +void disablezoom() { zoom = 0; zoomprogress = 0; } -void computezoom() -{ +void computezoom() { if(!zoom) { zoomprogress = 0; curfov = fov; curavatarfov = avatarfov; return; } if(zoom > 0) zoomprogress = zoominvel ? min(zoomprogress + float(elapsedtime) / zoominvel, 1.0f) : 1; - else - { + else { zoomprogress = zoomoutvel ? max(zoomprogress - float(elapsedtime) / zoomoutvel, 0.0f) : 0; if(zoomprogress <= 0) zoom = 0; } @@ -679,8 +584,7 @@ physent *camera1 = NULL; bool detachedcamera = false; bool isthirdperson() { return player!=camera1 || detachedcamera; } -void fixcamerarange() -{ +void fixcamerarange() { const float MAXPITCH = 90.0f; if(camera1->pitch>MAXPITCH) camera1->pitch = MAXPITCH; if(camera1->pitch<-MAXPITCH) camera1->pitch = -MAXPITCH; @@ -688,19 +592,15 @@ void fixcamerarange() while(camera1->yaw>=360.0f) camera1->yaw -= 360.0f; } -void mousemove(int dx, int dy) -{ +void mousemove(int dx, int dy) { if(!game::allowmouselook()) return; float cursens = sensitivity, curaccel = mouseaccel; - if(zoom) - { - if(zoomautosens) - { + if(zoom) { + if(zoomautosens) { cursens = float(sensitivity*zoomfov)/fov; curaccel = float(mouseaccel*zoomfov)/fov; } - else - { + else { cursens = zoomsens; curaccel = zoomaccel; } @@ -710,33 +610,27 @@ void mousemove(int dx, int dy) camera1->yaw += dx*cursens; camera1->pitch -= dy*cursens*(invmouse ? -1 : 1); fixcamerarange(); - if(camera1!=player && !detachedcamera) - { + if(camera1!=player && !detachedcamera) { player->yaw = camera1->yaw; player->pitch = camera1->pitch; } speedmodifier += abs(dx)-abs(dy); } -void recomputecamera() -{ +void recomputecamera() { game::setupcamera(); computezoom(); - bool allowthirdperson = game::allowthirdperson(); bool shoulddetach = (allowthirdperson && thirdperson > 1) || game::detachcamera(); - if((!allowthirdperson || !thirdperson) && !shoulddetach) - { + if((!allowthirdperson || !thirdperson) && !shoulddetach) { camera1 = player; detachedcamera = false; } - else - { + else { static physent tempcamera; camera1 = &tempcamera; if(detachedcamera && shoulddetach) camera1->o = player->o; - else - { + else { *camera1 = *player; detachedcamera = shoulddetach; } @@ -744,28 +638,23 @@ void recomputecamera() camera1->type = ENT_CAMERA; camera1->move = -1; camera1->eyeheight = camera1->aboveeye = camera1->radius = camera1->xradius = camera1->yradius = 2; - matrix3 orient; orient.identity(); orient.rotate_around_z(camera1->yaw*RAD); orient.rotate_around_x(camera1->pitch*RAD); orient.rotate_around_y(camera1->roll*-RAD); vec dir = vec(orient.b).neg(), side = vec(orient.a).neg(), up = orient.c; - - if(game::collidecamera()) - { + if(game::collidecamera()) { movecamera(camera1, dir, thirdpersondistance, 1); movecamera(camera1, dir, clamp(thirdpersondistance - camera1->o.dist(player->o), 0.0f, 1.0f), 0.1f); - if(thirdpersonup) - { + if(thirdpersonup) { vec pos = camera1->o; float dist = fabs(thirdpersonup); if(thirdpersonup < 0) up.neg(); movecamera(camera1, up, dist, 1); movecamera(camera1, up, clamp(dist - camera1->o.dist(pos), 0.0f, 1.0f), 0.1f); } - if(thirdpersonside) - { + if(thirdpersonside) { vec pos = camera1->o; float dist = fabs(thirdpersonside); if(thirdpersonside < 0) side.neg(); @@ -773,8 +662,7 @@ void recomputecamera() movecamera(camera1, side, clamp(dist - camera1->o.dist(pos), 0.0f, 1.0f), 0.1f); } } - else - { + else { camera1->o.add(vec(dir).mul(thirdpersondistance)); if(thirdpersonup) camera1->o.add(vec(up).mul(thirdpersonup)); if(thirdpersonside) camera1->o.add(vec(side).mul(thirdpersonside)); @@ -787,8 +675,7 @@ matrix4 cammatrix, projmatrix, camprojmatrix, invcammatrix, invcamprojmatrix; FVAR(nearplane, 0.01f, 0.54f, 2.0f); -vec calcavatarpos(const vec &pos, float dist) -{ +vec calcavatarpos(const vec &pos, float dist) { vec eyepos; cammatrix.transform(pos, eyepos); GLdouble ydist = nearplane * tan(curavatarfov/2*RAD), xdist = ydist * aspect; @@ -797,7 +684,6 @@ vec calcavatarpos(const vec &pos, float dist) scrpos.y = eyepos.y*nearplane/ydist; scrpos.z = (eyepos.z*(farplane + nearplane) - 2*nearplane*farplane) / (farplane - nearplane); scrpos.w = -eyepos.z; - vec worldpos = invcamprojmatrix.perspectivetransform(scrpos); vec dir = vec(worldpos).sub(camera1->o).rescale(dist); return dir.add(camera1->o); @@ -805,17 +691,13 @@ vec calcavatarpos(const vec &pos, float dist) matrix4 clipmatrix, noclipmatrix; -void renderavatar() -{ +void renderavatar() { if(isthirdperson()) return; - matrix4 oldprojmatrix = projmatrix; projmatrix.perspective(curavatarfov, aspect, nearplane, farplane); projmatrix.scalez(avatardepth); setcamprojmatrix(false); - game::renderavatar(); - projmatrix = oldprojmatrix; setcamprojmatrix(false); } @@ -826,36 +708,28 @@ FVAR(depthoffset, -1e4f, 0.01f, 1e4f); matrix4 nooffsetmatrix; -void enablepolygonoffset(GLenum type) -{ - if(!depthoffset) - { +void enablepolygonoffset(GLenum type) { + if(!depthoffset) { glPolygonOffset(polygonoffsetfactor, polygonoffsetunits); glEnable(type); return; } - bool clipped = false; - nooffsetmatrix = projmatrix; projmatrix.d.z += depthoffset * (clipped ? noclipmatrix.c.z : projmatrix.c.z); setcamprojmatrix(false, true); } -void disablepolygonoffset(GLenum type) -{ - if(!depthoffset) - { +void disablepolygonoffset(GLenum type) { + if(!depthoffset) { glDisable(type); return; } - projmatrix = nooffsetmatrix; setcamprojmatrix(false, true); } -void calcspherescissor(const vec ¢er, float size, float &sx1, float &sy1, float &sx2, float &sy2) -{ +void calcspherescissor(const vec ¢er, float size, float &sx1, float &sy1, float &sx2, float &sy2) { vec worldpos(center), e; cammatrix.transform(worldpos, e); if(e.z > 2*size) { sx1 = sy1 = 1; sx2 = sy2 = -1; return; } @@ -868,22 +742,20 @@ void calcspherescissor(const vec ¢er, float size, float &sx1, float &sy1, fl do { \ float nzc = (cz*cz + 1) / (cz dir drt) - cz, \ pz = (d##c)/(nzc*e.c - e.z); \ - if(pz > 0) \ - { \ + if(pz > 0) { \ + \ float c = (focaldist)*nzc, \ pc = pz*nzc; \ if(pc < e.c) low = c; \ else if(pc > e.c) high = c; \ } \ } while(0) - if(dx > 0) - { + if(dx > 0) { float cz = e.x/e.z, drt = sqrtf(dx)/size; CHECKPLANE(x, -, focaldist/aspect, sx1, sx2); CHECKPLANE(x, +, focaldist/aspect, sx1, sx2); } - if(dy > 0) - { + if(dy > 0) { float cz = e.y/e.z, drt = sqrtf(dy)/size; CHECKPLANE(y, -, focaldist, sy1, sy2); CHECKPLANE(y, +, focaldist, sy1, sy2); @@ -893,17 +765,13 @@ void calcspherescissor(const vec ¢er, float size, float &sx1, float &sy1, fl static int scissoring = 0; static GLint oldscissor[4]; -int pushscissor(float sx1, float sy1, float sx2, float sy2) -{ +int pushscissor(float sx1, float sy1, float sx2, float sy2) { scissoring = 0; - if(sx1 <= -1 && sy1 <= -1 && sx2 >= 1 && sy2 >= 1) return 0; - sx1 = max(sx1, -1.0f); sy1 = max(sy1, -1.0f); sx2 = min(sx2, 1.0f); sy2 = min(sy2, 1.0f); - GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); int sx = viewport[0] + int(floor((sx1+1)*0.5f*viewport[2])), @@ -911,9 +779,7 @@ int pushscissor(float sx1, float sy1, float sx2, float sy2) sw = viewport[0] + int(ceil((sx2+1)*0.5f*viewport[2])) - sx, sh = viewport[1] + int(ceil((sy2+1)*0.5f*viewport[3])) - sy; if(sw <= 0 || sh <= 0) return 0; - - if(glIsEnabled(GL_SCISSOR_TEST)) - { + if(glIsEnabled(GL_SCISSOR_TEST)) { glGetIntegerv(GL_SCISSOR_BOX, oldscissor); sw += sx; sh += sy; @@ -925,15 +791,12 @@ int pushscissor(float sx1, float sy1, float sx2, float sy2) scissoring = 2; } else scissoring = 1; - glScissor(sx, sy, sw, sh); if(scissoring<=1) glEnable(GL_SCISSOR_TEST); - return scissoring; } -void popscissor() -{ +void popscissor() { if(scissoring>1) glScissor(oldscissor[0], oldscissor[1], oldscissor[2], oldscissor[3]); else if(scissoring) glDisable(GL_SCISSOR_TEST); scissoring = 0; @@ -941,10 +804,8 @@ void popscissor() static GLuint screenquadvbo = 0; -static void setupscreenquad() -{ - if(!screenquadvbo) - { +static void setupscreenquad() { + if(!screenquadvbo) { glGenBuffers_(1, &screenquadvbo); gle::bindvbo(screenquadvbo); vec2 verts[4] = { vec2(1, -1), vec2(-1, -1), vec2(1, 1), vec2(-1, 1) }; @@ -953,13 +814,11 @@ static void setupscreenquad() } } -static void cleanupscreenquad() -{ +static void cleanupscreenquad() { if(screenquadvbo) { glDeleteBuffers_(1, &screenquadvbo); screenquadvbo = 0; } } -void screenquad() -{ +void screenquad() { setupscreenquad(); gle::bindvbo(screenquadvbo); gle::enablevertex(); @@ -971,38 +830,32 @@ void screenquad() static LocalShaderParam screentexcoord[2] = { LocalShaderParam("screentexcoord0"), LocalShaderParam("screentexcoord1") }; -static inline void setscreentexcoord(int i, float w, float h, float x = 0, float y = 0) -{ +static inline void setscreentexcoord(int i, float w, float h, float x = 0, float y = 0) { screentexcoord[i].setf(w*0.5f, h*0.5f, x + w*0.5f, y + fabs(h)*0.5f); } -void screenquad(float sw, float sh) -{ +void screenquad(float sw, float sh) { setscreentexcoord(0, sw, sh); screenquad(); } -void screenquadflipped(float sw, float sh) -{ +void screenquadflipped(float sw, float sh) { setscreentexcoord(0, sw, -sh); screenquad(); } -void screenquad(float sw, float sh, float sw2, float sh2) -{ +void screenquad(float sw, float sh, float sw2, float sh2) { setscreentexcoord(0, sw, sh); setscreentexcoord(1, sw2, sh2); screenquad(); } -void screenquadoffset(float x, float y, float w, float h) -{ +void screenquadoffset(float x, float y, float w, float h) { setscreentexcoord(0, w, h, x, y); screenquad(); } -void screenquadoffset(float x, float y, float w, float h, float x2, float y2, float w2, float h2) -{ +void screenquadoffset(float x, float y, float w, float h, float x2, float y2, float w2, float h2) { setscreentexcoord(0, w, h, x, y); setscreentexcoord(1, w2, h2, x2, y2); screenquad(); @@ -1019,15 +872,13 @@ void screenquadoffset(float x, float y, float w, float h, float x2, float y2, fl gle::end(); \ } -void hudquad(float x, float y, float w, float h, float tx, float ty, float tw, float th) -{ +void hudquad(float x, float y, float w, float h, float tx, float ty, float tw, float th) { HUDQUAD(x, y, x+w, y+h, tx, ty, tx+tw, ty+th); } bool renderedgame = false; -void rendergame(bool mainpass) -{ +void rendergame(bool mainpass) { game::rendergame(mainpass); if(!shadowmapping) renderedgame = true; } @@ -1037,23 +888,17 @@ int drawtex = 0; VAR(modelpreviewfov, 10, 20, 100); VAR(modelpreviewpitch, -90, -15, 90); -namespace modelpreview -{ +namespace modelpreview { physent *oldcamera; physent camera; - float oldaspect, oldfovy, oldfov; int oldfarplane; matrix4 oldprojmatrix; - - void start(int x, int y, int w, int h, bool background) - { + void start(int x, int y, int w, int h, bool background) { drawtex = DRAWTEX_MODELPREVIEW; - glViewport(x, y, w, h); glScissor(x, y, w, h); glEnable(GL_SCISSOR_TEST); - oldcamera = camera1; camera = *camera1; camera.reset(); @@ -1063,52 +908,39 @@ namespace modelpreview camera.pitch = modelpreviewpitch; camera.roll = 0; camera1 = &camera; - oldaspect = aspect; oldfovy = fovy; oldfov = curfov; oldfarplane = farplane; oldprojmatrix = projmatrix; - aspect = w/float(h); fovy = modelpreviewfov; curfov = 2*atan2(tan(fovy/2*RAD), 1/aspect)/RAD; farplane = 1024; - glClearColor(0, 0, 0, 1); - glClear((background ? GL_COLOR_BUFFER_BIT : 0) | GL_DEPTH_BUFFER_BIT); - projmatrix.perspective(fovy, aspect, nearplane, farplane); setcamprojmatrix(); - glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); } - - void end() - { + void end() { glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); - aspect = oldaspect; fovy = oldfovy; curfov = oldfov; farplane = oldfarplane; - camera1 = oldcamera; drawtex = 0; - glDisable(GL_SCISSOR_TEST); glViewport(0, 0, screenw, screenh); - projmatrix = oldprojmatrix; setcamprojmatrix(); } } -vec calcmodelpreviewpos(const vec &radius, float &yaw) -{ +vec calcmodelpreviewpos(const vec &radius, float &yaw) { yaw = fmod(lastmillis/10000.0f*360.0f, 360.0f); float dist = 1.15f*max(radius.magnitude2()/aspect, radius.magnitude())/sinf(fovy/2*RAD); return vec(0, dist, 0).rotate_around_x(camera1->pitch*RAD); @@ -1116,70 +948,47 @@ vec calcmodelpreviewpos(const vec &radius, float &yaw) bool deferdrawtextures = false; -void drawtextures() -{ +void drawtextures() { if(minimized) { deferdrawtextures = true; return; } deferdrawtextures = false; } int xtraverts, xtravertsva; -void gl_drawframe() -{ +void gl_drawframe() { if(deferdrawtextures) drawtextures(); - updatedynlights(); - int w = screenw, h = screenh; aspect = forceaspect ? forceaspect : w/float(h); fovy = 2*atan2(tan(curfov/2*RAD), aspect)/RAD; - farplane = worldsize*2; - projmatrix.perspective(fovy, aspect, nearplane, farplane); setcamprojmatrix(); - glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); - xtravertsva = xtraverts = glde = gbatches = 0; - visiblecubes(); - glClear(GL_DEPTH_BUFFER_BIT|(wireframe && editmode ? GL_COLOR_BUFFER_BIT : 0)); - if(wireframe && editmode) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - rendergeom(); - extern int outline; if(!wireframe && editmode && outline) renderoutline(); - renderdecals(true); - rendermapmodels(); rendergame(true); renderavatar(); - if(wireframe && editmode) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - rendermaterials(); renderalphageom(); - if(wireframe && editmode) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - renderparticles(true); - glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); - gl_drawhud(); - renderedgame = false; } -void gl_drawmainmenu() -{ +void gl_drawmainmenu() { xtravertsva = xtraverts = glde = gbatches = 0; renderbackground(NULL, NULL, NULL, NULL, true, true); gl_drawhud(); @@ -1194,14 +1003,12 @@ VARP(damagecompassmax, 1, 200, 1000); float damagedirs[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -void damagecompass(int n, const vec &loc) -{ +void damagecompass(int n, const vec &loc) { if(!usedamagecompass || minimized) return; vec delta(loc); delta.sub(camera1->o); float yaw = 0, pitch; - if(delta.magnitude() > 4) - { + if(delta.magnitude() > 4) { vectoyawpitch(delta, yaw, pitch); yaw -= camera1->yaw; } @@ -1212,23 +1019,18 @@ void damagecompass(int n, const vec &loc) if(damagedirs[dir]>1) damagedirs[dir] = 1; } -void drawdamagecompass(int w, int h) -{ +void drawdamagecompass(int w, int h) { hudnotextureshader->set(); - int dirs = 0; float size = damagecompasssize/100.0f*min(h, w)/2.0f; - loopi(8) if(damagedirs[i]>0) - { - if(!dirs) - { + loopi(8) if(damagedirs[i]>0) { + if(!dirs) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gle::colorf(1, 0, 0, damagecompassalpha/100.0f); gle::defvertex(); gle::begin(GL_TRIANGLES); } dirs++; - float logscale = 32, scale = log(1 + (logscale - 1)*damagedirs[i]) / log(logscale), offset = -size/2.0f-min(h, w)/4.0f; @@ -1238,11 +1040,9 @@ void drawdamagecompass(int w, int h) m.rotate_around_z(i*45*RAD); m.translate(0, offset, 0); m.scale(size*scale); - gle::attrib(m.transform(vec2(1, 1))); gle::attrib(m.transform(vec2(-1, 1))); gle::attrib(m.transform(vec2(0, 0))); - // fade in log space so short blips don't disappear too quickly scale -= float(curtime)/damagecompassfade; damagedirs[i] = scale > 0 ? (pow(logscale, scale) - 1) / (logscale - 1) : 0; @@ -1261,68 +1061,57 @@ VARP(crosshaircolors, 0, 1, 1); #define MAXCROSSHAIRS 4 static Texture *crosshairs[MAXCROSSHAIRS] = { NULL, NULL, NULL, NULL }; -void loadcrosshair(const char *name, int i) -{ +void loadcrosshair(const char *name, int i) { if(i < 0 || i >= MAXCROSSHAIRS) return; crosshairs[i] = name ? textureload(name, 3, true) : notexture; - if(crosshairs[i] == notexture) - { + if(crosshairs[i] == notexture) { name = game::defaultcrosshair(i); if(!name) name = "data/crosshair.png"; crosshairs[i] = textureload(name, 3, true); } } -void loadcrosshair_(const char *name, int *i) -{ +void loadcrosshair_(const char *name, int *i) { loadcrosshair(name, *i); } COMMANDN(loadcrosshair, loadcrosshair_, "si"); -ICOMMAND(getcrosshair, "i", (int *i), -{ +ICOMMAND(getcrosshair, "i", (int *i), { const char *name = ""; - if(*i >= 0 && *i < MAXCROSSHAIRS) - { + if(*i >= 0 && *i < MAXCROSSHAIRS) { name = crosshairs[*i] ? crosshairs[*i]->name : game::defaultcrosshair(*i); if(!name) name = "data/crosshair.png"; } result(name); }); -void writecrosshairs(stream *f) -{ +void writecrosshairs(stream *f) { loopi(MAXCROSSHAIRS) if(crosshairs[i] && crosshairs[i]!=notexture) f->printf("loadcrosshair %s %d\n", escapestring(crosshairs[i]->name), i); f->printf("\n"); } -void drawcrosshair(int w, int h) -{ +void drawcrosshair(int w, int h) { bool windowhit = g3d_windowhit(true, false); if(!windowhit && (hidehud || mainmenu)) return; //(hidehud || player->state==CS_SPECTATOR || player->state==CS_DEAD)) return; - vec color(1, 1, 1); float cx = 0.5f, cy = 0.5f, chsize; Texture *crosshair; - if(windowhit) - { + if(windowhit) { static Texture *cursor = NULL; if(!cursor) cursor = textureload("data/guicursor.png", 3, true); crosshair = cursor; chsize = cursorsize*w/900.0f; g3d_cursorpos(cx, cy); } - else - { + else { int index = game::selectcrosshair(color); if(index < 0) return; if(!crosshairfx) index = 0; if(!crosshairfx || !crosshaircolors) color = vec(1, 1, 1); crosshair = crosshairs[index]; - if(!crosshair) - { + if(!crosshair) { loadcrosshair(NULL, index); crosshair = crosshairs[index]; } @@ -1333,7 +1122,6 @@ void drawcrosshair(int w, int h) float x = cx*w - (windowhit ? 0 : chsize/2.0f); float y = cy*h - (windowhit ? 0 : chsize/2.0f); glBindTexture(GL_TEXTURE_2D, crosshair->id); - hudshader->set(); gle::color(color); hudquad(x, y, chsize, chsize); @@ -1346,55 +1134,36 @@ VAR(statrate, 1, 200, 1000); FVARP(conscale, 1e-3f, 0.33f, 1e3f); -void gl_drawhud() -{ +void gl_drawhud() { g3d_render(); - int w = screenw, h = screenh; if(forceaspect) w = int(ceil(h*forceaspect)); - - if(editmode && !hidehud && !mainmenu) - { + if(editmode && !hidehud && !mainmenu) { glEnable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); - rendereditcursor(); - glDepthMask(GL_TRUE); glDisable(GL_DEPTH_TEST); } - gettextres(w, h); - hudmatrix.ortho(0, w, h, 0, -1, 1); resethudmatrix(); - gle::colorf(1, 1, 1); - glEnable(GL_BLEND); - - if(!mainmenu) - { + if(!mainmenu) { drawdamagecompass(w, h); } - hudshader->set(); - int conw = int(w/conscale), conh = int(h/conscale), abovehud = conh - FONTH, limitgui = abovehud; - if(!hidehud && !mainmenu) - { - if(!hidestats) - { + if(!hidehud && !mainmenu) { + if(!hidestats) { pushhudmatrix(); hudmatrix.scale(conscale, conscale, 1); flushhudmatrix(); - int roffset = 0; - if(showfps) - { + if(showfps) { static int lastfps = 0, prevfps[3] = { 0, 0, 0 }, curfps[3] = { 0, 0, 0 }; - if(totalmillis - lastfps >= statrate) - { + if(totalmillis - lastfps >= statrate) { memcpy(prevfps, curfps, sizeof(prevfps)); lastfps = totalmillis - (totalmillis%statrate); } @@ -1405,17 +1174,13 @@ void gl_drawhud() else draw_textf("fps %d", conw-5*FONTH, conh-FONTH*3/2, curfps[0]); roffset += FONTH; } - - if(editmode || showeditstats) - { + if(editmode || showeditstats) { static int laststats = 0, prevstats[8] = { 0, 0, 0, 0, 0, 0, 0 }, curstats[8] = { 0, 0, 0, 0, 0, 0, 0 }; - if(totalmillis - laststats >= statrate) - { + if(totalmillis - laststats >= statrate) { memcpy(prevstats, curstats, sizeof(prevstats)); laststats = totalmillis - (totalmillis%statrate); } - int nextstats[8] = - { + int nextstats[8] = { vtris*100/max(wtris, 1), vverts*100/max(wverts, 1), xtraverts/1024, @@ -1425,22 +1190,16 @@ void gl_drawhud() getnumqueries() }; loopi(8) if(prevstats[i]==curstats[i]) curstats[i] = nextstats[i]; - abovehud -= 2*FONTH; draw_textf("wtr:%dk(%d%%) wvt:%dk(%d%%) evt:%dk eva:%dk", FONTH/2, abovehud, wtris/1024, curstats[0], wverts/1024, curstats[1], curstats[2], curstats[3]); draw_textf("ond:%d va:%d gl:%d(%d) oq:%d lm:%d rp:%d", FONTH/2, abovehud+FONTH, allocnodes*8, allocva, curstats[4], curstats[5], curstats[6], lightmaps.length(), curstats[7]); limitgui = abovehud; } - - if(editmode) - { + if(editmode) { abovehud -= FONTH; draw_textf("cube %s%d%s", FONTH/2, abovehud, selchildcount<0 ? "1/" : "", abs(selchildcount), showmat && selchildmat > 0 ? getmaterialdesc(selchildmat, ": ") : ""); - - if(char *editinfo = execidentstr("edithud")) - { - if(editinfo[0]) - { + if(char *editinfo = execidentstr("edithud")) { + if(editinfo[0]) { int tw, th; text_bounds(editinfo, tw, th); th += FONTH-1; th -= th%FONTH; @@ -1450,10 +1209,8 @@ void gl_drawhud() DELETEA(editinfo); } } - else if(char *gameinfo = execidentstr("gamehud")) - { - if(gameinfo[0]) - { + else if(char *gameinfo = execidentstr("gamehud")) { + if(gameinfo[0]) { int tw, th; text_bounds(gameinfo, tw, th); th += FONTH-1; th -= th%FONTH; @@ -1462,30 +1219,21 @@ void gl_drawhud() } DELETEA(gameinfo); } - pophudmatrix(); } - - if(hidestats || (!editmode && !showeditstats)) - { + if(hidestats || (!editmode && !showeditstats)) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); game::gameplayhud(w, h); limitgui = abovehud = min(abovehud, int(conh*game::abovegameplayhud(w, h))); } - rendertexturepanel(w, h); } - glDisable(GL_BLEND); - g3d_limitscale((2*limitgui - conh) / float(conh)); g3d_render2d(); - glEnable(GL_BLEND); - hudmatrix.ortho(0, w, h, 0, -1, 1); resethudmatrix(); - pushhudmatrix(); hudmatrix.scale(conscale, conscale, 1); flushhudmatrix(); @@ -1493,16 +1241,12 @@ void gl_drawhud() extern int fullconsole; if(!hidehud || fullconsole) renderconsole(conw, conh, abovehud - FONTH/2); pophudmatrix(); - drawcrosshair(w, h); - glDisable(GL_BLEND); } -void cleanupgl() -{ +void cleanupgl() { cleanupscreenquad(); - gle::cleanup(); } diff --git a/src/engine/rendermodel.cpp b/src/engine/rendermodel.cpp index 9f2aba9..bc93caa 100644 --- a/src/engine/rendermodel.cpp +++ b/src/engine/rendermodel.cpp @@ -7,60 +7,52 @@ model *loadingmodel = NULL; #include "ragdoll.h" #include "animmodel.h" -#include "vertmodel.h" #include "skelmodel.h" static model *(__cdecl *modeltypes[NUMMODELTYPES])(const char *); -static int addmodeltype(int type, model *(__cdecl *loader)(const char *)) -{ +static int addmodeltype(int type, model *(__cdecl *loader)(const char *)) { modeltypes[type] = loader; return type; } #define MODELTYPE(modeltype, modelclass) \ -static model *__loadmodel__##modelclass(const char *filename) \ -{ \ +static model *__loadmodel__##modelclass(const char *filename) { \ + \ return new modelclass(filename); \ } \ UNUSED static int __dummy__##modelclass = addmodeltype((modeltype), __loadmodel__##modelclass); -#include "md3.h" #include "md5.h" #include "iqm.h" -MODELTYPE(MDL_MD3, md3); MODELTYPE(MDL_MD5, md5); MODELTYPE(MDL_IQM, iqm); #define checkmdl if(!loadingmodel) { conoutf(CON_ERROR, "not loading a model"); return; } -void mdlcullface(int *cullface) -{ +void mdlcullface(int *cullface) { checkmdl; loadingmodel->setcullface(*cullface!=0); } COMMAND(mdlcullface, "i"); -void mdlcollide(int *collide) -{ +void mdlcollide(int *collide) { checkmdl; loadingmodel->collide = *collide!=0; } COMMAND(mdlcollide, "i"); -void mdlellipsecollide(int *collide) -{ +void mdlellipsecollide(int *collide) { checkmdl; loadingmodel->ellipsecollide = *collide!=0; } COMMAND(mdlellipsecollide, "i"); -void mdlspec(int *percent) -{ +void mdlspec(int *percent) { checkmdl; float spec = 1.0f; if(*percent>0) spec = *percent/100.0f; @@ -70,8 +62,7 @@ void mdlspec(int *percent) COMMAND(mdlspec, "i"); -void mdlambient(int *percent) -{ +void mdlambient(int *percent) { checkmdl; float ambient = 0.3f; if(*percent>0) ambient = *percent/100.0f; @@ -81,56 +72,49 @@ void mdlambient(int *percent) COMMAND(mdlambient, "i"); -void mdlalphatest(float *cutoff) -{ +void mdlalphatest(float *cutoff) { checkmdl; loadingmodel->setalphatest(max(0.0f, min(1.0f, *cutoff))); } COMMAND(mdlalphatest, "f"); -void mdlalphablend(int *blend) -{ +void mdlalphablend(int *blend) { checkmdl; loadingmodel->setalphablend(*blend!=0); } COMMAND(mdlalphablend, "i"); -void mdlalphadepth(int *depth) -{ +void mdlalphadepth(int *depth) { checkmdl; loadingmodel->alphadepth = *depth!=0; } COMMAND(mdlalphadepth, "i"); -void mdldepthoffset(int *offset) -{ +void mdldepthoffset(int *offset) { checkmdl; loadingmodel->depthoffset = *offset!=0; } COMMAND(mdldepthoffset, "i"); -void mdlfullbright(float *fullbright) -{ +void mdlfullbright(float *fullbright) { checkmdl; loadingmodel->setfullbright(*fullbright); } COMMAND(mdlfullbright, "f"); -void mdlshader(char *shader) -{ +void mdlshader(char *shader) { checkmdl; loadingmodel->setshader(lookupshaderbyname(shader)); } COMMAND(mdlshader, "s"); -void mdlspin(float *yaw, float *pitch) -{ +void mdlspin(float *yaw, float *pitch) { checkmdl; loadingmodel->spinyaw = *yaw; loadingmodel->spinpitch = *pitch; @@ -138,8 +122,7 @@ void mdlspin(float *yaw, float *pitch) COMMAND(mdlspin, "ff"); -void mdlscale(int *percent) -{ +void mdlscale(int *percent) { checkmdl; float scale = 1.0f; if(*percent>0) scale = *percent/100.0f; @@ -148,40 +131,35 @@ void mdlscale(int *percent) COMMAND(mdlscale, "i"); -void mdltrans(float *x, float *y, float *z) -{ +void mdltrans(float *x, float *y, float *z) { checkmdl; loadingmodel->translate = vec(*x, *y, *z); } COMMAND(mdltrans, "fff"); -void mdlyaw(float *angle) -{ +void mdlyaw(float *angle) { checkmdl; loadingmodel->offsetyaw = *angle; } COMMAND(mdlyaw, "f"); -void mdlpitch(float *angle) -{ +void mdlpitch(float *angle) { checkmdl; loadingmodel->offsetpitch = *angle; } COMMAND(mdlpitch, "f"); -void mdlshadow(int *shadow) -{ +void mdlshadow(int *shadow) { checkmdl; loadingmodel->shadow = *shadow!=0; } COMMAND(mdlshadow, "i"); -void mdlbb(float *rad, float *h, float *eyeheight) -{ +void mdlbb(float *rad, float *h, float *eyeheight) { checkmdl; loadingmodel->collidexyradius = *rad; loadingmodel->collideheight = *h; @@ -190,16 +168,14 @@ void mdlbb(float *rad, float *h, float *eyeheight) COMMAND(mdlbb, "fff"); -void mdlextendbb(float *x, float *y, float *z) -{ +void mdlextendbb(float *x, float *y, float *z) { checkmdl; loadingmodel->bbextend = vec(*x, *y, *z); } COMMAND(mdlextendbb, "fff"); -void mdlname() -{ +void mdlname() { checkmdl; result(loadingmodel->name); } @@ -219,8 +195,7 @@ COMMAND(mdlname, ""); if(ragdoll->loaded) return; -void rdvert(float *x, float *y, float *z, float *radius) -{ +void rdvert(float *x, float *y, float *z, float *radius) { checkragdoll; ragdollskel::vert &v = ragdoll->verts.add(); v.pos = vec(*x, *y, *z); @@ -228,15 +203,13 @@ void rdvert(float *x, float *y, float *z, float *radius) } COMMAND(rdvert, "ffff"); -void rdeye(int *v) -{ +void rdeye(int *v) { checkragdoll; ragdoll->eye = *v; } COMMAND(rdeye, "i"); -void rdtri(int *v1, int *v2, int *v3) -{ +void rdtri(int *v1, int *v2, int *v3) { checkragdoll; ragdollskel::tri &t = ragdoll->tris.add(); t.vert[0] = *v1; @@ -245,8 +218,7 @@ void rdtri(int *v1, int *v2, int *v3) } COMMAND(rdtri, "iii"); -void rdjoint(int *n, int *t, int *v1, int *v2, int *v3) -{ +void rdjoint(int *n, int *t, int *v1, int *v2, int *v3) { checkragdoll; if(*n < 0 || *n >= skel->numbones) return; ragdollskel::joint &j = ragdoll->joints.add(); @@ -258,8 +230,7 @@ void rdjoint(int *n, int *t, int *v1, int *v2, int *v3) } COMMAND(rdjoint, "iibbb"); -void rdlimitdist(int *v1, int *v2, float *mindist, float *maxdist) -{ +void rdlimitdist(int *v1, int *v2, float *mindist, float *maxdist) { checkragdoll; ragdollskel::distlimit &d = ragdoll->distlimits.add(); d.vert[0] = *v1; @@ -269,8 +240,7 @@ void rdlimitdist(int *v1, int *v2, float *mindist, float *maxdist) } COMMAND(rdlimitdist, "iiff"); -void rdlimitrot(int *t1, int *t2, float *maxangle, float *qx, float *qy, float *qz, float *qw) -{ +void rdlimitrot(int *t1, int *t2, float *maxangle, float *qx, float *qy, float *qz, float *qw) { checkragdoll; ragdollskel::rotlimit &r = ragdoll->rotlimits.add(); r.tri[0] = *t1; @@ -280,8 +250,7 @@ void rdlimitrot(int *t1, int *t2, float *maxangle, float *qx, float *qy, float * } COMMAND(rdlimitrot, "iifffff"); -void rdanimjoints(int *on) -{ +void rdanimjoints(int *on) { checkragdoll; ragdoll->animjoints = *on!=0; } @@ -291,20 +260,17 @@ COMMAND(rdanimjoints, "i"); vector mapmodels; -void mmodel(char *name) -{ +void mmodel(char *name) { mapmodelinfo &mmi = mapmodels.add(); copystring(mmi.name, name); mmi.m = NULL; } -void mapmodelcompat(int *rad, int *h, int *tex, char *name, char *shadow) -{ +void mapmodelcompat(int *rad, int *h, int *tex, char *name, char *shadow) { mmodel(name); } -void mapmodelreset(int *n) -{ +void mapmodelreset(int *n) { if(!(identflags&IDF_OVERRIDDEN) && !game::allowedittoggle()) return; mapmodels.shrink(clamp(*n, 0, mapmodels.length())); } @@ -325,21 +291,17 @@ ICOMMAND(mapmodelfind, "s", (char *name), { int found = -1; loopv(mapmodels) if( hashnameset models; vector preloadmodels; -void preloadmodel(const char *name) -{ +void preloadmodel(const char *name) { if(!name || !name[0] || models.access(name)) return; preloadmodels.add(newstring(name)); } -void flushpreloadedmodels(bool msg) -{ - loopv(preloadmodels) - { +void flushpreloadedmodels(bool msg) { + loopv(preloadmodels) { loadprogress = float(i+1)/preloadmodels.length(); model *m = loadmodel(preloadmodels[i], -1, msg); if(!m) { if(msg) conoutf(CON_WARN, "could not load model: %s", preloadmodels[i]); } - else - { + else { m->preloadmeshes(); } } @@ -347,25 +309,20 @@ void flushpreloadedmodels(bool msg) loadprogress = 0; } -void preloadusedmapmodels(bool msg, bool bih) -{ +void preloadusedmapmodels(bool msg, bool bih) { vector &ents = entities::getents(); vector mapmodels; - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; if(e.type==ET_MAPMODEL && e.attr2 >= 0 && mapmodels.find(e.attr2) < 0) mapmodels.add(e.attr2); } - - loopv(mapmodels) - { + loopv(mapmodels) { loadprogress = float(i+1)/mapmodels.length(); int mmindex = mapmodels[i]; mapmodelinfo *mmi = getmminfo(mmindex); if(!mmi) { if(msg) conoutf(CON_WARN, "could not find map model: %d", mmindex); } else if(mmi->name[0] && !loadmodel(NULL, mmindex, msg)) { if(msg) conoutf(CON_WARN, "could not load model: %s", mmi->name); } - else if(mmi->m) - { + else if(mmi->m) { if(bih) mmi->m->preloadBIH(); mmi->m->preloadmeshes(); } @@ -373,15 +330,12 @@ void preloadusedmapmodels(bool msg, bool bih) loadprogress = 0; } -bool modelloaded(const char *name) -{ +bool modelloaded(const char *name) { return models.find(name, NULL) != NULL; } -model *loadmodel(const char *name, int i, bool msg) -{ - if(!name) - { +model *loadmodel(const char *name, int i, bool msg) { + if(!name) { if(!mapmodels.inrange(i)) return NULL; mapmodelinfo &mmi = mapmodels[i]; if(mmi.m) return mmi.m; @@ -390,16 +344,13 @@ model *loadmodel(const char *name, int i, bool msg) model **mm = models.access(name); model *m; if(mm) m = *mm; - else - { + else { if(!name[0] || loadingmodel || lightmapping > 1) return NULL; - if(msg) - { + if(msg) { defformatstring(filename, "packages/models/%s", name); renderprogress(loadprogress, filename); } - loopi(NUMMODELTYPES) - { + loopi(NUMMODELTYPES) { m = modeltypes[i](name); if(!m) continue; loadingmodel = m; @@ -415,24 +366,20 @@ model *loadmodel(const char *name, int i, bool msg) return m; } -void preloadmodelshaders(bool force) -{ +void preloadmodelshaders() { if(initing) return; - enumerate(models, model *, m, m->preloadshaders(force)); + enumerate(models, model *, m, m->preloadshaders()); } -void clear_mdls() -{ +void clear_mdls() { enumerate(models, model *, m, delete m); } -void cleanupmodels() -{ +void cleanupmodels() { enumerate(models, model *, m, m->cleanup()); } -void clearmodel(char *name) -{ +void clearmodel(char *name) { model **m = models.access(name); if(!m) { conoutf(CON_WARN, "model %s is not loaded", name); return; } loopv(mapmodels) if(mapmodels[i].m==*m) mapmodels[i].m = NULL; @@ -444,16 +391,14 @@ void clearmodel(char *name) COMMAND(clearmodel, "s"); -bool modeloccluded(const vec ¢er, float radius) -{ +bool modeloccluded(const vec ¢er, float radius) { ivec bbmin(vec(center).sub(radius)), bbmax(ivec(center).add(radius+1)); return bboccluded(bbmin, bbmax); } VAR(showboundingbox, 0, 0, 2); -void render2dbox(vec &o, float x, float y, float z) -{ +void render2dbox(vec &o, float x, float y, float z) { gle::begin(GL_LINE_LOOP); gle::attribf(o.x, o.y, o.z); gle::attribf(o.x, o.y, o.z+z); @@ -462,8 +407,7 @@ void render2dbox(vec &o, float x, float y, float z) xtraverts += gle::end(); } -void render3dbox(vec &o, float tofloor, float toceil, float xradius, float yradius) -{ +void render3dbox(vec &o, float tofloor, float toceil, float xradius, float yradius) { if(yradius<=0) yradius = xradius; vec c = o; c.sub(vec(xradius, yradius, tofloor)); @@ -478,21 +422,18 @@ void render3dbox(vec &o, float tofloor, float toceil, float xradius, float yradi render2dbox(c, 0, -ysz, h); } -void renderellipse(vec &o, float xradius, float yradius, float yaw) -{ +void renderellipse(vec &o, float xradius, float yradius, float yaw) { gle::colorf(0.5f, 0.5f, 0.5f); gle::defvertex(); gle::begin(GL_LINE_LOOP); - loopi(15) - { + loopi(15) { const vec2 &sc = sincos360[i*(360/15)]; gle::attrib(vec(xradius*sc.x, yradius*sc.y, 0).rotate_around_z((yaw+90)*RAD).add(o)); } xtraverts += gle::end(); } -struct batchedmodel -{ +struct batchedmodel { vec pos, color, dir; int anim; float yaw, pitch, transparent; @@ -501,8 +442,7 @@ struct batchedmodel int attached; occludequery *query; }; -struct modelbatch -{ +struct modelbatch { model *m; int flags; vector batched; @@ -512,20 +452,16 @@ static vector modelattached; static int numbatches = -1; static occludequery *modelquery = NULL; -void startmodelbatches() -{ +void startmodelbatches() { numbatches = 0; modelattached.setsize(0); } -modelbatch &addbatchedmodel(model *m) -{ +modelbatch &addbatchedmodel(model *m) { modelbatch *b = NULL; if(m->batch>=0 && m->batchbatch]->m==m) b = batches[m->batch]; - else - { - if(numbatchesbatched.setsize(0); } @@ -537,75 +473,59 @@ modelbatch &addbatchedmodel(model *m) return *b; } -void renderbatchedmodel(model *m, batchedmodel &b) -{ +void renderbatchedmodel(model *m, batchedmodel &b) { modelattach *a = NULL; if(b.attached>=0) a = &modelattached[b.attached]; - int anim = b.anim; - if(shadowmapping) - { + if(shadowmapping) { anim |= ANIM_NOSKIN; GLOBALPARAMF(shadowintensity, b.transparent); } - else - { + else { if(b.flags&MDL_FULLBRIGHT) anim |= ANIM_FULLBRIGHT; if(b.flags&MDL_GHOST) anim |= ANIM_GHOST; } - m->render(anim, b.basetime, b.basetime2, b.pos, b.yaw, b.pitch, b.d, a, b.color, b.dir, b.transparent); } -struct transparentmodel -{ +struct transparentmodel { model *m; batchedmodel *batched; float dist; }; -static inline bool sorttransparentmodels(const transparentmodel &x, const transparentmodel &y) -{ +static inline bool sorttransparentmodels(const transparentmodel &x, const transparentmodel &y) { return x.dist < y.dist; } -void endmodelbatches() -{ +void endmodelbatches() { vector transparent; - loopi(numbatches) - { + loopi(numbatches) { modelbatch &b = *batches[i]; if(b.batched.empty()) continue; - bool rendered = false; occludequery *query = NULL; - if(b.flags&MDL_GHOST) - { - loopvj(b.batched) - { + if(b.flags&MDL_GHOST) { + loopvj(b.batched) { batchedmodel &bm = b.batched[j]; if((bm.flags&(MDL_CULL_VFC|MDL_GHOST))!=MDL_GHOST || bm.query) continue; if(!rendered) { b.m->startrender(); rendered = true; } renderbatchedmodel(b.m, bm); } - if(rendered) - { + if(rendered) { b.m->endrender(); rendered = false; } } - loopvj(b.batched) - { + loopvj(b.batched) { batchedmodel &bm = b.batched[j]; if(bm.flags&(MDL_CULL_VFC|MDL_GHOST)) continue; - if(bm.query!=query) - { + if(bm.query!=query) { if(query) endquery(query); query = bm.query; if(query) startquery(query); } - if(bm.transparent < 1 && (!query || query->owner==bm.d) && !shadowmapping) - { + if(bm.transparent < 1 && (!query || query->owner==bm.d) && !shadowmapping) { transparentmodel &tm = transparent.add(); tm.m = b.m; tm.batched = &bm; @@ -618,21 +538,17 @@ void endmodelbatches() if(query) endquery(query); if(rendered) b.m->endrender(); } - if(transparent.length()) - { + if(transparent.length()) { transparent.sort(sorttransparentmodels); model *lastmodel = NULL; occludequery *query = NULL; - loopv(transparent) - { + loopv(transparent) { transparentmodel &tm = transparent[i]; - if(lastmodel!=tm.m) - { + if(lastmodel!=tm.m) { if(lastmodel) lastmodel->endrender(); (lastmodel = tm.m)->startrender(); } - if(query!=tm.batched->query) - { + if(query!=tm.batched->query) { if(query) endquery(query); query = tm.batched->query; if(query) startquery(query); @@ -645,35 +561,29 @@ void endmodelbatches() numbatches = -1; } -void startmodelquery(occludequery *query) -{ +void startmodelquery(occludequery *query) { modelquery = query; } -void endmodelquery() -{ +void endmodelquery() { int querybatches = 0; - loopi(numbatches) - { + loopi(numbatches) { modelbatch &b = *batches[i]; if(b.batched.empty() || b.batched.last().query!=modelquery) continue; querybatches++; } - if(querybatches<=1) - { + if(querybatches<=1) { if(!querybatches) modelquery->fragments = 0; modelquery = NULL; return; } int minattached = modelattached.length(); startquery(modelquery); - loopi(numbatches) - { + loopi(numbatches) { modelbatch &b = *batches[i]; if(b.batched.empty() || b.batched.last().query!=modelquery) continue; b.m->startrender(); - do - { + do { batchedmodel &bm = b.batched.pop(); if(bm.attached>=0) minattached = min(minattached, bm.attached); renderbatchedmodel(b.m, bm); @@ -688,17 +598,14 @@ void endmodelquery() VAR(maxmodelradiusdistance, 10, 200, 1000); -static inline void enablecullmodelquery() -{ +static inline void enablecullmodelquery() { startbb(); } -static inline void rendercullmodelquery(model *m, dynent *d, const vec ¢er, float radius) -{ +static inline void rendercullmodelquery(model *m, dynent *d, const vec ¢er, float radius) { if(fabs(camera1->o.x-center.x) < radius+1 && fabs(camera1->o.y-center.y) < radius+1 && - fabs(camera1->o.z-center.z) < radius+1) - { + fabs(camera1->o.z-center.z) < radius+1) { d->query = NULL; return; } @@ -710,95 +617,73 @@ static inline void rendercullmodelquery(model *m, dynent *d, const vec ¢er, endquery(d->query); } -static inline void disablecullmodelquery() -{ +static inline void disablecullmodelquery() { endbb(); } -static inline int cullmodel(model *m, const vec ¢er, float radius, int flags, dynent *d = NULL, bool shadow = false) -{ +static inline int cullmodel(model *m, const vec ¢er, float radius, int flags, dynent *d = NULL, bool shadow = false) { if(flags&MDL_CULL_DIST && center.dist(camera1->o)/radius>maxmodelradiusdistance) return MDL_CULL_DIST; - if(flags&MDL_CULL_VFC) - { + if(flags&MDL_CULL_VFC) { if(shadowmapping && !isshadowmapcaster(center, radius)) return MDL_CULL_VFC; } - if(shadowmapping) - { - if(d) - { + if(shadowmapping) { + if(d) { if(flags&MDL_CULL_OCCLUDED && d->occluded>=OCCLUDE_PARENT) return MDL_CULL_OCCLUDED; if(flags&MDL_CULL_QUERY && d->occluded+1>=OCCLUDE_BB && d->query && d->query->owner==d && checkquery(d->query)) return MDL_CULL_QUERY; } if(!addshadowmapcaster(center, radius, radius)) return MDL_CULL_VFC; } - else if(flags&MDL_CULL_OCCLUDED && modeloccluded(center, radius)) - { + else if(flags&MDL_CULL_OCCLUDED && modeloccluded(center, radius)) { if(d) d->occluded = OCCLUDE_PARENT; return MDL_CULL_OCCLUDED; } - else if(flags&MDL_CULL_QUERY && d->query && d->query->owner==d && checkquery(d->query)) - { + else if(flags&MDL_CULL_QUERY && d->query && d->query->owner==d && checkquery(d->query)) { if(d->occludedoccluded++; return MDL_CULL_QUERY; } return 0; } -void rendermodel(entitylight *light, const char *mdl, int anim, const vec &o, float yaw, float pitch, int flags, dynent *d, modelattach *a, int basetime, int basetime2, float trans) -{ +void rendermodel(entitylight *light, const char *mdl, int anim, const vec &o, float yaw, float pitch, int flags, dynent *d, modelattach *a, int basetime, int basetime2, float trans) { if(shadowmapping && !(flags&(MDL_SHADOW|MDL_DYNSHADOW))) return; model *m = loadmodel(mdl); if(!m) return; vec center(0, 0, 0), bbradius(0, 0, 0); float radius = 0; bool shadow = !shadowmap && (flags&(MDL_SHADOW|MDL_DYNSHADOW)); - - if(flags&(MDL_CULL_VFC|MDL_CULL_DIST|MDL_CULL_OCCLUDED|MDL_CULL_QUERY|MDL_SHADOW|MDL_DYNSHADOW)) - { - if(flags&MDL_CULL_QUERY) - { + if(flags&(MDL_CULL_VFC|MDL_CULL_DIST|MDL_CULL_OCCLUDED|MDL_CULL_QUERY|MDL_SHADOW|MDL_DYNSHADOW)) { + if(flags&MDL_CULL_QUERY) { if(!oqfrags || !oqdynent || !d) flags &= ~MDL_CULL_QUERY; } - m->boundbox(center, bbradius); radius = bbradius.magnitude(); - if(d && d->ragdoll) - { + if(d && d->ragdoll) { radius = max(radius, d->ragdoll->radius); center = d->ragdoll->center; } - else - { + else { center.rotate_around_z(yaw*RAD); center.add(o); } - int culled = cullmodel(m, center, radius, flags, d, shadow); - if(culled) - { - if(culled&(MDL_CULL_OCCLUDED|MDL_CULL_QUERY) && flags&MDL_CULL_QUERY) - { + if(culled) { + if(culled&(MDL_CULL_OCCLUDED|MDL_CULL_QUERY) && flags&MDL_CULL_QUERY) { enablecullmodelquery(); rendercullmodelquery(m, d, center, radius); disablecullmodelquery(); } return; } - if(shadowmapping) flags &= ~MDL_CULL_QUERY; } - if(flags&MDL_NORENDER) anim |= ANIM_NORENDER; - else if(showboundingbox && !shadowmapping && editmode) - { + else if(showboundingbox && !shadowmapping && editmode) { notextureshader->set(); - if(d && showboundingbox==1) - { + if(d && showboundingbox==1) { render3dbox(d->o, d->eyeheight, d->aboveeye, d->radius); renderellipse(d->o, d->xradius, d->yradius, d->yaw); } - else - { + else { vec center, radius; if(showboundingbox==1) m->collisionbox(center, radius); else m->boundbox(center, radius); @@ -807,19 +692,14 @@ void rendermodel(entitylight *light, const char *mdl, int anim, const vec &o, fl render3dbox(center, radius.z, radius.z, radius.x, radius.y); } } - vec lightcolor(1, 1, 1), lightdir(0, 0, 1); - if(!shadowmapping) - { + if(!shadowmapping) { vec pos = o; - if(d) - { + if(d) { d->occluded = OCCLUDE_NOTHING; if(!light) light = &d->light; - if(flags&MDL_LIGHT && light->millis!=lastmillis) - { - if(d->ragdoll) - { + if(flags&MDL_LIGHT && light->millis!=lastmillis) { + if(d->ragdoll) { pos = d->ragdoll->center; pos.z += radius/2; } @@ -830,15 +710,12 @@ void rendermodel(entitylight *light, const char *mdl, int anim, const vec &o, fl light->millis = lastmillis; } } - else if(flags&MDL_LIGHT) - { - if(!light) - { + else if(flags&MDL_LIGHT) { + if(!light) { lightreaching(pos, lightcolor, lightdir, (flags&MDL_LIGHT_FAST)!=0); dynlightreaching(pos, lightcolor, lightdir, (flags&MDL_HUD)!=0); } - else if(light->millis!=lastmillis) - { + else if(light->millis!=lastmillis) { lightreaching(pos, light->color, light->dir, (flags&MDL_LIGHT_FAST)!=0); dynlightreaching(pos, light->color, light->dir, (flags&MDL_HUD)!=0); light->millis = lastmillis; @@ -847,15 +724,11 @@ void rendermodel(entitylight *light, const char *mdl, int anim, const vec &o, fl if(light) { lightcolor = light->color; lightdir = light->dir; } if(flags&MDL_DYNLIGHT) dynlightreaching(pos, lightcolor, lightdir, (flags&MDL_HUD)!=0); } - - if(a) for(int i = 0; a[i].tag; i++) - { + if(a) for(int i = 0; a[i].tag; i++) { if(a[i].name) a[i].m = loadmodel(a[i].name); //if(a[i].m && a[i].m->type()!=m->type()) a[i].m = NULL; } - - if(numbatches>=0) - { + if(numbatches>=0) { modelbatch &mb = addbatchedmodel(m); batchedmodel &b = mb.batched.add(); b.query = modelquery; @@ -869,8 +742,7 @@ void rendermodel(entitylight *light, const char *mdl, int anim, const vec &o, fl b.basetime2 = basetime2; b.transparent = trans; b.flags = flags & ~(MDL_CULL_VFC | MDL_CULL_DIST | MDL_CULL_OCCLUDED); - if(!shadow) - { + if(!shadow) { b.flags &= ~(MDL_SHADOW|MDL_DYNSHADOW); if(flags&MDL_CULL_VFC) b.flags |= MDL_CULL_VFC; } @@ -881,52 +753,38 @@ void rendermodel(entitylight *light, const char *mdl, int anim, const vec &o, fl if(flags&MDL_CULL_QUERY) d->query = b.query = newquery(d); return; } - m->startrender(); - - if(shadowmapping) - { + if(shadowmapping) { anim |= ANIM_NOSKIN; GLOBALPARAMF(shadowintensity, trans); } - else - { + else { if(flags&MDL_FULLBRIGHT) anim |= ANIM_FULLBRIGHT; if(flags&MDL_GHOST) anim |= ANIM_GHOST; } - - if(flags&MDL_CULL_QUERY) - { + if(flags&MDL_CULL_QUERY) { d->query = newquery(d); if(d->query) startquery(d->query); } - m->render(anim, basetime, basetime2, o, yaw, pitch, d, a, lightcolor, lightdir, trans); - if(flags&MDL_CULL_QUERY && d->query) endquery(d->query); - m->endrender(); } -void abovemodel(vec &o, const char *mdl) -{ +void abovemodel(vec &o, const char *mdl) { model *m = loadmodel(mdl); if(!m) return; o.z += m->above(); } -bool matchanim(const char *name, const char *pattern) -{ - for(;; pattern++) - { +bool matchanim(const char *name, const char *pattern) { + for(;; pattern++) { const char *s = name; char c; - for(;; pattern++) - { + for(;; pattern++) { c = *pattern; if(!c || c=='|') break; - else if(c=='*') - { + else if(c=='*') { if(!*s || iscubespace(*s)) break; do s++; while(*s && !iscubespace(*s)); } @@ -940,19 +798,16 @@ bool matchanim(const char *name, const char *pattern) return false; } -void findanims(const char *pattern, vector &anims) -{ +void findanims(const char *pattern, vector &anims) { loopi(sizeof(animnames)/sizeof(animnames[0])) if(matchanim(animnames[i], pattern)) anims.add(i); } -ICOMMAND(findanims, "s", (char *name), -{ +ICOMMAND(findanims, "s", (char *name), { vector anims; findanims(name, anims); vector buf; string num; - loopv(anims) - { + loopv(anims) { formatstring(num, "%d", anims[i]); if(i > 0) buf.add(' '); buf.put(num, strlen(num)); @@ -961,21 +816,19 @@ ICOMMAND(findanims, "s", (char *name), result(buf.getbuf()); }); -void loadskin(const char *dir, const char *altdir, Texture *&skin, Texture *&masks) // model skin sharing -{ +void loadskin(const char *dir, const char *altdir, Texture *&skin, Texture *&masks) { // model skin sharing { #define ifnoload(tex, path) if((tex = textureload(path, 0, true, false))==notexture) #define tryload(tex, prefix, cmd, name) \ - ifnoload(tex, makerelpath(mdir, name ".jpg", prefix, cmd)) \ - { \ - ifnoload(tex, makerelpath(mdir, name ".png", prefix, cmd)) \ - { \ - ifnoload(tex, makerelpath(maltdir, name ".jpg", prefix, cmd)) \ - { \ + ifnoload(tex, makerelpath(mdir, name ".jpg", prefix, cmd)) { \ + \ + ifnoload(tex, makerelpath(mdir, name ".png", prefix, cmd)) { \ + \ + ifnoload(tex, makerelpath(maltdir, name ".jpg", prefix, cmd)) { \ + \ ifnoload(tex, makerelpath(maltdir, name ".png", prefix, cmd)) return; \ } \ } \ } - defformatstring(mdir, "packages/models/%s", dir); defformatstring(maltdir, "packages/models/%s", altdir); masks = notexture; @@ -989,22 +842,18 @@ VAR(animoverride, -1, 0, NUMANIMS-1); VAR(testanims, 0, 0, 1); VAR(testpitch, -90, 0, 90); -void renderclient(dynent *d, const char *mdlname, modelattach *attachments, int hold, int attack, int attackdelay, int lastaction, int lastpain, float fade, bool ragdoll) -{ +void renderclient(dynent *d, const char *mdlname, modelattach *attachments, int hold, int attack, int attackdelay, int lastaction, int lastpain, float fade, bool ragdoll) { int anim = hold ? hold : ANIM_IDLE|ANIM_LOOP; float yaw = testanims && d==player ? 0 : d->yaw+90, pitch = testpitch && d==player ? testpitch : d->pitch; vec o = d->feetpos(); int basetime = 0; if(animoverride) anim = (animoverride<0 ? ANIM_ALL : animoverride)|ANIM_LOOP; - else if(d->state==CS_DEAD) - { + else if(d->state==CS_DEAD) { anim = ANIM_DYING|ANIM_NOPITCH; basetime = lastpain; - if(ragdoll) - { - if(!d->ragdoll || d->ragdoll->millis < basetime) - { + if(ragdoll) { + if(!d->ragdoll || d->ragdoll->millis < basetime) { DELETEP(d->ragdoll); anim |= ANIM_RAGDOLL; } @@ -1013,32 +862,25 @@ void renderclient(dynent *d, const char *mdlname, modelattach *attachments, int } else if(d->state==CS_EDITING || d->state==CS_SPECTATOR) anim = ANIM_EDIT|ANIM_LOOP; else if(d->state==CS_LAGGED) anim = ANIM_LAG|ANIM_LOOP; - else - { - if(lastmillis-lastpain < 300) - { + else { + if(lastmillis-lastpain < 300) { anim = ANIM_PAIN; basetime = lastpain; } - else if(lastpain < lastaction && (attack < 0 || (d->type != ENT_AI && lastmillis-lastaction < attackdelay))) - { + else if(lastpain < lastaction && (attack < 0 || (d->type != ENT_AI && lastmillis-lastaction < attackdelay))) { anim = attack < 0 ? -attack : attack; basetime = lastaction; } - if(d->inwater && d->physstate<=PHYS_FALL) anim |= (((game::allowmove(d) && (d->move || d->strafe)) || d->vel.z+d->falling.z>0 ? ANIM_SWIM : ANIM_SINK)|ANIM_LOOP)<timeinair>100) anim |= (ANIM_JUMP|ANIM_END)<move || d->strafe)) - { + else if(game::allowmove(d) && (d->move || d->strafe)) { if(d->move>0) anim |= (ANIM_FORWARD|ANIM_LOOP)<strafe) - { + else if(d->strafe) { if(d->move<0) anim |= ((d->strafe>0 ? ANIM_RIGHT : ANIM_LEFT)|ANIM_REVERSE|ANIM_LOOP)<strafe>0 ? ANIM_LEFT : ANIM_RIGHT)|ANIM_LOOP)<move<0) anim |= (ANIM_BACKWARD|ANIM_LOOP)<>ANIM_SECONDARY)&ANIM_INDEX) anim >>= ANIM_SECONDARY; } if(d->ragdoll && (!ragdoll || (anim&ANIM_INDEX)!=ANIM_DYING)) DELETEP(d->ragdoll); @@ -1053,8 +895,7 @@ void renderclient(dynent *d, const char *mdlname, modelattach *attachments, int rendermodel(NULL, mdlname, anim, o, yaw, pitch, flags, d, attachments, basetime, 0, fade); } -void setbbfrommodel(dynent *d, const char *mdl) -{ +void setbbfrommodel(dynent *d, const char *mdl) { model *m = loadmodel(mdl); if(!m) return; vec center, radius; @@ -1066,8 +907,7 @@ void setbbfrommodel(dynent *d, const char *mdl) d->radius = d->collidetype==COLLIDE_OBB ? sqrtf(d->xradius*d->xradius + d->yradius*d->yradius) : max(d->xradius, d->yradius); d->eyeheight = (center.z-radius.z) + radius.z*2*m->eyeheight; d->aboveeye = radius.z*2*(1.0f-m->eyeheight); - if (d->aboveeye + d->eyeheight <= 0.5f) - { + if (d->aboveeye + d->eyeheight <= 0.5f) { float zrad = (0.5f - (d->aboveeye + d->eyeheight)) / 2; d->aboveeye += zrad; d->eyeheight += zrad; diff --git a/src/engine/renderparticles.cpp b/src/engine/renderparticles.cpp index 392e943..dbdf855 100644 --- a/src/engine/renderparticles.cpp +++ b/src/engine/renderparticles.cpp @@ -11,8 +11,7 @@ VARP(emitmillis, 1, 17, 1000); static int lastemitframe = 0, emitoffset = 0; static bool canemit = false, regenemitters = false, canstep = false; -static bool canemitparticles() -{ +static bool canemitparticles() { return canemit || emitoffset; } @@ -21,29 +20,23 @@ VAR(cullparticles, 0, 1, 1); VAR(replayparticles, 0, 1, 1); VARN(seedparticles, seedmillis, 0, 3000, 10000); -struct particleemitter -{ +struct particleemitter { extentity *ent; vec bbmin, bbmax; vec center; float radius; ivec cullmin, cullmax; int maxfade, lastemit, lastcull; - particleemitter(extentity *ent) - : ent(ent), bbmin(ent->o), bbmax(ent->o), maxfade(-1), lastemit(0), lastcull(0) - {} - - void finalize() - { + : ent(ent), bbmin(ent->o), bbmax(ent->o), maxfade(-1), lastemit(0), lastcull(0) { + } + void finalize() { center = vec(bbmin).add(bbmax).mul(0.5f); radius = bbmin.dist(bbmax)/2; cullmin = ivec(int(floor(bbmin.x)), int(floor(bbmin.y)), int(floor(bbmin.z))); cullmax = ivec(int(ceil(bbmax.x)), int(ceil(bbmax.y)), int(ceil(bbmax.z))); } - - void extendbb(const vec &o, float size = 0) - { + void extendbb(const vec &o, float size = 0) { bbmin.x = min(bbmin.x, o.x - size); bbmin.y = min(bbmin.y, o.y - size); bbmin.z = min(bbmin.z, o.z - size); @@ -51,9 +44,7 @@ struct particleemitter bbmax.y = max(bbmax.y, o.y + size); bbmax.z = max(bbmax.z, o.z + size); } - - void extendbb(float z, float size = 0) - { + void extendbb(float z, float size = 0) { bbmin.z = min(bbmin.z, z - size); bbmax.z = max(bbmax.z, z + size); } @@ -62,18 +53,15 @@ struct particleemitter static vector emitters; static particleemitter *seedemitter = NULL; -void clearparticleemitters() -{ +void clearparticleemitters() { emitters.setsize(0); regenemitters = true; } -void addparticleemitters() -{ +void addparticleemitters() { emitters.setsize(0); const vector &ents = entities::getents(); - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; if(e.type != ET_PARTICLES) continue; emitters.add(particleemitter(&e)); @@ -81,8 +69,7 @@ void addparticleemitters() regenemitters = false; } -enum -{ +enum { PT_PART = 0, PT_TAPE, PT_TRAIL, @@ -90,10 +77,7 @@ enum PT_TEXTICON, PT_METER, PT_METERVS, - PT_FIREBALL, - PT_LIGHTNING, PT_FLARE, - PT_MOD = 1<<8, PT_RND4 = 1<<9, PT_LERP = 1<<10, // use very sparingly - order of blending issues @@ -111,30 +95,26 @@ enum PT_FLIP = PT_HFLIP | PT_VFLIP | PT_ROT }; -const char *partnames[] = { "part", "tape", "trail", "text", "texticon", "meter", "metervs", "fireball", "lightning", "flare" }; +const char *partnames[] = { "part", "tape", "trail", "text", "texticon", "meter", "metervs", "flare" }; -struct particle -{ +struct particle { vec o, d; int gravity, fade, millis; bvec color; uchar flags; float size; - union - { + union { const char *text; float val; physent *owner; - struct - { + struct { uchar color2[3]; uchar progress; }; }; }; -struct partvert -{ +struct partvert { vec pos; bvec4 color; vec2 tc; @@ -143,27 +123,21 @@ struct partvert #define COLLIDERADIUS 8.0f #define COLLIDEERROR 1.0f -struct partrenderer -{ +struct partrenderer { Texture *tex; const char *texname; int texclamp; uint type; int collide; string info; - partrenderer(const char *texname, int texclamp, int type, int collide = 0) - : tex(NULL), texname(texname), texclamp(texclamp), type(type), collide(collide) - { + : tex(NULL), texname(texname), texclamp(texclamp), type(type), collide(collide) { } partrenderer(int type, int collide = 0) - : tex(NULL), texname(NULL), texclamp(0), type(type), collide(collide) - { + : tex(NULL), texname(NULL), texclamp(0), type(type), collide(collide) { } - virtual ~partrenderer() - { + virtual ~partrenderer() { } - virtual void init(int n) { } virtual void reset() = 0; virtual void resettracked(physent *owner) { } @@ -172,44 +146,34 @@ struct partrenderer virtual void render() = 0; virtual bool haswork() = 0; virtual void cleanup() {} - - virtual void seedemitter(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int gravity) - { + virtual void seedemitter(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int gravity) { } - //blend = 0 => remove it - void calc(particle *p, int &blend, int &ts, vec &o, vec &d, bool step = true) - { + void calc(particle *p, int &blend, int &ts, vec &o, vec &d, bool step = true) { o = p->o; d = p->d; if(type&PT_TRACK && p->owner) game::particletrack(p->owner, o, d); - if(p->fade <= 5) - { + if(p->fade <= 5) { ts = 1; blend = 255; } - else - { + else { ts = lastmillis-p->millis; blend = max(255 - (ts<<8)/p->fade, 0); - if(p->gravity) - { + if(p->gravity) { if(ts > p->fade) ts = p->fade; float t = ts; o.add(vec(d).mul(t/5000.0f)); o.z -= t*t/(2.0f * 5000.0f * p->gravity); } - if(collide && o.z < p->val && step) - { - if(collide >= 0) - { + if(collide && o.z < p->val && step) { + if(collide >= 0) { vec surface; float floorz = rayfloor(vec(o.x, o.y, p->val), surface, RAY_CLIPMAT, COLLIDERADIUS); float collidez = floorz<0 ? o.z-COLLIDERADIUS : p->val - floorz; if(o.z >= collidez+COLLIDEERROR) p->val = collidez+COLLIDEERROR; - else - { + else { adddecal(collide, vec(o.x, o.y, collidez), vec(p->o).sub(o).normalize(), 2*p->size, p->color, type&PT_RND4 ? (p->flags>>5)&3 : 0); blend = 0; } @@ -220,41 +184,29 @@ struct partrenderer } }; -struct listparticle : particle -{ +struct listparticle : particle { listparticle *next; }; VARP(outlinemeters, 0, 0, 1); -struct listrenderer : partrenderer -{ +struct listrenderer : partrenderer { static listparticle *parempty; listparticle *list; - listrenderer(const char *texname, int texclamp, int type, int collide = 0) - : partrenderer(texname, texclamp, type, collide), list(NULL) - { + : partrenderer(texname, texclamp, type, collide), list(NULL) { } listrenderer(int type, int collide = 0) - : partrenderer(type, collide), list(NULL) - { + : partrenderer(type, collide), list(NULL) { } - - virtual ~listrenderer() - { + virtual ~listrenderer() { } - - virtual void killpart(listparticle *p) - { + virtual void killpart(listparticle *p) { } - - void reset() - { + void reset() { if(!list) return; listparticle *p = list; - for(;;) - { + for(;;) { killpart(p); if(p->next) p = p->next; else break; @@ -263,14 +215,10 @@ struct listrenderer : partrenderer parempty = list; list = NULL; } - - void resettracked(physent *owner) - { + void resettracked(physent *owner) { if(!(type&PT_TRACK)) return; - for(listparticle **prev = &list, *cur = list; cur; cur = *prev) - { - if(!owner || cur->owner==owner) - { + for(listparticle **prev = &list, *cur = list; cur; cur = *prev) { + if(!owner || cur->owner==owner) { *prev = cur->next; cur->next = parempty; parempty = cur; @@ -278,11 +226,8 @@ struct listrenderer : partrenderer else prev = &cur->next; } } - - particle *addpart(const vec &o, const vec &d, int fade, int color, float size, int gravity) - { - if(!parempty) - { + particle *addpart(const vec &o, const vec &d, int fade, int color, float size, int gravity) { + if(!parempty) { listparticle *ps = new listparticle[256]; loopi(255) ps[i].next = &ps[i+1]; ps[255].next = parempty; @@ -303,44 +248,31 @@ struct listrenderer : partrenderer p->flags = 0; return p; } - - int count() - { + int count() { int num = 0; listparticle *lp; for(lp = list; lp; lp = lp->next) num++; return num; } - - bool haswork() - { + bool haswork() { return (list != NULL); } - virtual void startrender() = 0; virtual void endrender() = 0; virtual void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) = 0; - - void render() - { + void render() { startrender(); - if(texname) - { + if(texname) { if(!tex) tex = textureload(texname, texclamp); glBindTexture(GL_TEXTURE_2D, tex->id); } - - for(listparticle **prev = &list, *p = list; p; p = *prev) - { + for(listparticle **prev = &list, *p = list; p; p = *prev) { vec o, d; int blend, ts; calc(p, blend, ts, o, d, canstep); - if(blend > 0) - { + if(blend > 0) { renderpart(p, o, d, blend, ts); - - if(p->fade > 5 || !canstep) - { + if(p->fade > 5 || !canstep) { prev = &p->next; continue; } @@ -351,44 +283,33 @@ struct listrenderer : partrenderer killpart(p); parempty = p; } - endrender(); } }; listparticle *listrenderer::parempty = NULL; -struct meterrenderer : listrenderer -{ +struct meterrenderer : listrenderer { meterrenderer(int type) - : listrenderer(type|PT_NOTEX|PT_LERP) - {} - - void startrender() - { + : listrenderer(type|PT_NOTEX|PT_LERP) { + } + void startrender() { glDisable(GL_BLEND); gle::defvertex(); } - - void endrender() - { + void endrender() { glEnable(GL_BLEND); } - - void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) - { + void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) { int basetype = type&0xFF; float scale = FONTH*p->size/80.0f, right = 8, left = p->progress/100.0f*right; matrix4x3 m(camright, vec(camup).neg(), vec(camdir).neg(), o); m.scale(scale); m.translate(-right/2.0f, 0, 0); - - if(outlinemeters) - { + if(outlinemeters) { gle::colorf(0, 0.8f, 0); gle::begin(GL_TRIANGLE_STRIP); - loopk(10) - { + loopk(10) { const vec2 &sc = sincos360[k*(180/(10-1))]; float c = (0.5f + 0.1f)*sc.y, s = 0.5f - (0.5f + 0.1f)*sc.x; gle::attrib(m.transform(vec2(-c, s))); @@ -396,36 +317,29 @@ struct meterrenderer : listrenderer } gle::end(); } - if(basetype==PT_METERVS) gle::colorub(p->color2[0], p->color2[1], p->color2[2]); else gle::colorf(0, 0, 0); gle::begin(GL_TRIANGLE_STRIP); - loopk(10) - { + loopk(10) { const vec2 &sc = sincos360[k*(180/(10-1))]; float c = 0.5f*sc.y, s = 0.5f - 0.5f*sc.x; gle::attrib(m.transform(vec2(left + c, s))); gle::attrib(m.transform(vec2(right + c, s))); } gle::end(); - - if(outlinemeters) - { + if(outlinemeters) { gle::colorf(0, 0.8f, 0); gle::begin(GL_TRIANGLE_FAN); - loopk(10) - { + loopk(10) { const vec2 &sc = sincos360[k*(180/(10-1))]; float c = (0.5f + 0.1f)*sc.y, s = 0.5f - (0.5f + 0.1f)*sc.x; gle::attrib(m.transform(vec2(left + c, s))); } gle::end(); } - gle::color(p->color); gle::begin(GL_TRIANGLE_STRIP); - loopk(10) - { + loopk(10) { const vec2 &sc = sincos360[k*(180/(10-1))]; float c = 0.5f*sc.y, s = 0.5f - 0.5f*sc.x; gle::attrib(m.transform(vec2(-c, s))); @@ -436,33 +350,22 @@ struct meterrenderer : listrenderer }; static meterrenderer meters(PT_METER), metervs(PT_METERVS); -struct textrenderer : listrenderer -{ +struct textrenderer : listrenderer { textrenderer(int type) - : listrenderer(type) - {} - - void startrender() - { + : listrenderer(type) { } - - void endrender() - { + void startrender() { } - - void killpart(listparticle *p) - { + void endrender() { + } + void killpart(listparticle *p) { if(p->text && p->flags&1) delete[] p->text; } - - void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) - { + void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) { float scale = p->size/80.0f, xoff = -(text_width(p->text) + ((p->flags>>1)&7)*FONTH)/2, yoff = 0; - matrix4x3 m(camright, vec(camup).neg(), vec(camdir).neg(), o); m.scale(scale); m.translate(xoff, yoff, 50); - textmatrix = &m; draw_text(p->text, 0, 0, p->color.r, p->color.g, p->color.b, blend); textmatrix = NULL; @@ -470,35 +373,25 @@ struct textrenderer : listrenderer }; static textrenderer texts(PT_TEXT|PT_LERP); -struct texticonrenderer : listrenderer -{ +struct texticonrenderer : listrenderer { texticonrenderer(const char *texname, int type) - : listrenderer(texname, 3, type) - {} - - void startrender() - { + : listrenderer(texname, 3, type) { + } + void startrender() { gle::defvertex(); gle::deftexcoord0(); gle::defcolor(4, GL_UNSIGNED_BYTE); gle::begin(GL_QUADS); } - - void endrender() - { + void endrender() { gle::end(); } - - void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) - { + void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) { float scale = p->size/80.0f, xoff = p->val, yoff = 0; - matrix4x3 m(camright, vec(camup).neg(), vec(camdir).neg(), o); m.scale(scale); m.translate(xoff, yoff, 50); - float tx = 0.25f*(p->flags&3), ty = 0.25f*((p->flags>>2)&3); - gle::attrib(m.transform(vec2(0, 0))); gle::attrib(tx, ty); gle::attrib(p->color, blend); @@ -516,19 +409,16 @@ struct texticonrenderer : listrenderer static texticonrenderer texticons("packages/hud/items.png", PT_TEXTICON|PT_LERP); template -static inline void modifyblend(const vec &o, int &blend) -{ +static inline void modifyblend(const vec &o, int &blend) { blend = min(blend<<2, 255); } template<> -inline void modifyblend(const vec &o, int &blend) -{ +inline void modifyblend(const vec &o, int &blend) { } template -static inline void genpos(const vec &o, const vec &d, float size, int grav, int ts, partvert *vs) -{ +static inline void genpos(const vec &o, const vec &d, float size, int grav, int ts, partvert *vs) { vec udir = vec(camup).sub(camright).mul(size); vec vdir = vec(camup).add(camright).mul(size); vs[0].pos = vec(o.x + udir.x, o.y + udir.y, o.z + udir.z); @@ -538,8 +428,7 @@ static inline void genpos(const vec &o, const vec &d, float size, int grav, int } template<> -inline void genpos(const vec &o, const vec &d, float size, int ts, int grav, partvert *vs) -{ +inline void genpos(const vec &o, const vec &d, float size, int ts, int grav, partvert *vs) { vec dir1 = d, dir2 = d, c; dir1.sub(o); dir2.sub(camera1->o); @@ -551,8 +440,7 @@ inline void genpos(const vec &o, const vec &d, float size, int ts, int } template<> -inline void genpos(const vec &o, const vec &d, float size, int ts, int grav, partvert *vs) -{ +inline void genpos(const vec &o, const vec &d, float size, int ts, int grav, partvert *vs) { vec e = d; if(grav) e.z -= float(ts)/grav; e.div(-75.0f).add(o); @@ -560,8 +448,7 @@ inline void genpos(const vec &o, const vec &d, float size, int ts, int } template -static inline void genrotpos(const vec &o, const vec &d, float size, int grav, int ts, partvert *vs, int rot) -{ +static inline void genrotpos(const vec &o, const vec &d, float size, int grav, int ts, partvert *vs, int rot) { genpos(o, d, size, grav, ts, vs); } @@ -571,8 +458,7 @@ static inline void genrotpos(const vec &o, const vec &d, float size, int grav, i vec( 1, -1, 0).rotate_around_z(n*2*M_PI/32.0f), \ vec(-1, -1, 0).rotate_around_z(n*2*M_PI/32.0f) \ } -static const vec rotcoeffs[32][4] = -{ +static const vec rotcoeffs[32][4] = { ROTCOEFFS(0), ROTCOEFFS(1), ROTCOEFFS(2), ROTCOEFFS(3), ROTCOEFFS(4), ROTCOEFFS(5), ROTCOEFFS(6), ROTCOEFFS(7), ROTCOEFFS(8), ROTCOEFFS(9), ROTCOEFFS(10), ROTCOEFFS(11), ROTCOEFFS(12), ROTCOEFFS(13), ROTCOEFFS(14), ROTCOEFFS(15), ROTCOEFFS(16), ROTCOEFFS(17), ROTCOEFFS(18), ROTCOEFFS(19), ROTCOEFFS(20), ROTCOEFFS(21), ROTCOEFFS(22), ROTCOEFFS(7), @@ -580,8 +466,7 @@ static const vec rotcoeffs[32][4] = }; template<> -inline void genrotpos(const vec &o, const vec &d, float size, int grav, int ts, partvert *vs, int rot) -{ +inline void genrotpos(const vec &o, const vec &d, float size, int grav, int ts, partvert *vs, int rot) { const vec *coeffs = rotcoeffs[rot]; (vs[0].pos = o).add(vec(camright).mul(coeffs[0].x*size)).add(vec(camup).mul(coeffs[0].y*size)); (vs[1].pos = o).add(vec(camright).mul(coeffs[1].x*size)).add(vec(camup).mul(coeffs[1].y*size)); @@ -590,30 +475,25 @@ inline void genrotpos(const vec &o, const vec &d, float size, int grav, } template -static inline void seedpos(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int grav) -{ - if(grav) - { +static inline void seedpos(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int grav) { + if(grav) { vec end(o); float t = fade; end.add(vec(d).mul(t/5000.0f)); end.z -= t*t/(2.0f * 5000.0f * grav); pe.extendbb(end, size); - float tpeak = d.z*grav; if(tpeak > 0 && tpeak < fade) pe.extendbb(o.z + 1.5f*d.z*tpeak/5000.0f, size); } } template<> -inline void seedpos(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int grav) -{ +inline void seedpos(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int grav) { pe.extendbb(d, size); } template<> -inline void seedpos(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int grav) -{ +inline void seedpos(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int grav) { vec e = d; if(grav) e.z -= float(fade)/grav; e.div(-75.0f).add(o); @@ -621,30 +501,23 @@ inline void seedpos(particleemitter &pe, const vec &o, const vec &d, i } template -struct varenderer : partrenderer -{ +struct varenderer : partrenderer { partvert *verts; particle *parts; int maxparts, numparts, lastupdate, rndmask; GLuint vbo; - varenderer(const char *texname, int type, int collide = 0) : partrenderer(texname, 3, type, collide), - verts(NULL), parts(NULL), maxparts(0), numparts(0), lastupdate(-1), rndmask(0), vbo(0) - { + verts(NULL), parts(NULL), maxparts(0), numparts(0), lastupdate(-1), rndmask(0), vbo(0) { if(type & PT_HFLIP) rndmask |= 0x01; if(type & PT_VFLIP) rndmask |= 0x02; if(type & PT_ROT) rndmask |= 0x1F<<2; if(type & PT_RND4) rndmask |= 0x03<<5; } - - void cleanup() - { + void cleanup() { if(vbo) { glDeleteBuffers_(1, &vbo); vbo = 0; } } - - void init(int n) - { + void init(int n) { DELETEA(parts); DELETEA(verts); parts = new particle[n]; @@ -653,36 +526,25 @@ struct varenderer : partrenderer numparts = 0; lastupdate = -1; } - - void reset() - { + void reset() { numparts = 0; lastupdate = -1; } - - void resettracked(physent *owner) - { + void resettracked(physent *owner) { if(!(type&PT_TRACK)) return; - loopi(numparts) - { + loopi(numparts) { particle *p = parts+i; if(!owner || (p->owner == owner)) p->fade = -1; } lastupdate = -1; } - - int count() - { + int count() { return numparts; } - - bool haswork() - { + bool haswork() { return (numparts > 0); } - - particle *addpart(const vec &o, const vec &d, int fade, int color, float size, int gravity) - { + particle *addpart(const vec &o, const vec &d, int fade, int color, float size, int gravity) { particle *p = parts + (numparts < maxparts ? numparts++ : rnd(maxparts)); //next free slot, or kill a random kitten p->o = o; p->d = d; @@ -696,42 +558,30 @@ struct varenderer : partrenderer lastupdate = -1; return p; } - - void seedemitter(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int gravity) - { + void seedemitter(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int gravity) { pe.maxfade = max(pe.maxfade, fade); size *= SQRT2; pe.extendbb(o, size); - seedpos(pe, o, d, fade, size, gravity); if(!gravity) return; - vec end(o); float t = fade; end.add(vec(d).mul(t/5000.0f)); end.z -= t*t/(2.0f * 5000.0f * gravity); pe.extendbb(end, size); - float tpeak = d.z*gravity; if(tpeak > 0 && tpeak < fade) pe.extendbb(o.z + 1.5f*d.z*tpeak/5000.0f, size); } - - void genverts(particle *p, partvert *vs, bool regen) - { + void genverts(particle *p, partvert *vs, bool regen) { vec o, d; int blend, ts; - calc(p, blend, ts, o, d); if(blend <= 1 || p->fade <= 5) p->fade = -1; //mark to remove on next pass (i.e. after render) - modifyblend(o, blend); - - if(regen) - { + if(regen) { p->flags &= ~0x80; - - #define SETTEXCOORDS(u1c, u2c, v1c, v2c, body) \ - { \ + #define SETTEXCOORDS(u1c, u2c, v1c, v2c, body) { \ + \ float u1 = u1c, u2 = u2c, v1 = v1c, v2 = v2c; \ body; \ vs[0].tc = vec2(u1, v1); \ @@ -739,22 +589,18 @@ struct varenderer : partrenderer vs[2].tc = vec2(u2, v2); \ vs[3].tc = vec2(u1, v2); \ } - if(type&PT_RND4) - { + if(type&PT_RND4) { float tx = 0.5f*((p->flags>>5)&1), ty = 0.5f*((p->flags>>6)&1); - SETTEXCOORDS(tx, tx + 0.5f, ty, ty + 0.5f, - { + SETTEXCOORDS(tx, tx + 0.5f, ty, ty + 0.5f, { if(p->flags&0x01) swap(u1, u2); if(p->flags&0x02) swap(v1, v2); }); } - else if(type&PT_ICON) - { + else if(type&PT_ICON) { float tx = 0.25f*(p->flags&3), ty = 0.25f*((p->flags>>2)&3); SETTEXCOORDS(tx, tx + 0.25f, ty, ty + 0.25f, {}); } else SETTEXCOORDS(0, 1, 0, 1, {}); - #define SETCOLOR(r, g, b, a) \ do { \ bvec4 col(r, g, b, a); \ @@ -766,21 +612,15 @@ struct varenderer : partrenderer } else if(type&PT_MOD) SETMODCOLOR; else loopi(4) vs[i].color.a = blend; - if(type&PT_ROT) genrotpos(o, d, p->size, ts, p->gravity, vs, (p->flags>>2)&0x1F); else genpos(o, d, p->size, ts, p->gravity, vs); } - - void genverts() - { - loopi(numparts) - { + void genverts() { + loopi(numparts) { particle *p = &parts[i]; partvert *vs = &verts[i*4]; - if(p->fade < 0) - { - do - { + if(p->fade < 0) { + do { --numparts; if(numparts <= i) return; } @@ -791,26 +631,19 @@ struct varenderer : partrenderer else genverts(p, vs, (p->flags&0x80)!=0); } } - - void update() - { + void update() { if(lastmillis == lastupdate && vbo) return; lastupdate = lastmillis; - genverts(); - if(!vbo) glGenBuffers_(1, &vbo); gle::bindvbo(vbo); glBufferData_(GL_ARRAY_BUFFER, maxparts*4*sizeof(partvert), NULL, GL_STREAM_DRAW); glBufferSubData_(GL_ARRAY_BUFFER, 0, numparts*4*sizeof(partvert), verts); gle::clearvbo(); } - - void render() - { + void render() { if(!tex) tex = textureload(texname, texclamp); glBindTexture(GL_TEXTURE_2D, tex->id); - gle::bindvbo(vbo); const partvert *ptr = 0; gle::vertexpointer(sizeof(partvert), ptr->pos.v); @@ -820,9 +653,7 @@ struct varenderer : partrenderer gle::enabletexcoord0(); gle::enablecolor(); gle::enablequads(); - gle::drawquads(0, numparts); - gle::disablequads(); gle::disablevertex(); gle::disabletexcoord0(); @@ -830,35 +661,24 @@ struct varenderer : partrenderer gle::clearvbo(); } }; + typedef varenderer quadrenderer; typedef varenderer taperenderer; typedef varenderer trailrenderer; -#include "explosion.h" -#include "lightning.h" - -struct softquadrenderer : quadrenderer -{ +struct softquadrenderer : quadrenderer { softquadrenderer(const char *texname, int type, int collide = 0) - : quadrenderer(texname, type|PT_SOFT, collide) - { + : quadrenderer(texname, type|PT_SOFT, collide) { } }; -static partrenderer *parts[] = -{ +static partrenderer *parts[] = { new quadrenderer("packages/particles/blood.png", PT_PART|PT_FLIP|PT_MOD|PT_RND4, DECAL_BLOOD), // blood spats (note: rgb is inverted) new trailrenderer("packages/particles/base.png", PT_TRAIL|PT_LERP), // water, entity new quadrenderer("packages/particles/smoke.png", PT_PART|PT_FLIP|PT_LERP), // smoke new quadrenderer("packages/particles/steam.png", PT_PART|PT_FLIP), // steam new quadrenderer("packages/particles/flames.png", PT_PART|PT_HFLIP|PT_RND4|PT_GLARE), // flame on - no flipping please, they have orientation - new quadrenderer("packages/particles/ball1.png", PT_PART|PT_FEW|PT_GLARE), // fireball1 - new quadrenderer("packages/particles/ball2.png", PT_PART|PT_FEW|PT_GLARE), // fireball2 - new quadrenderer("packages/particles/ball3.png", PT_PART|PT_FEW|PT_GLARE), // fireball3 new taperenderer("packages/particles/flare.png", PT_TAPE|PT_GLARE), // streak - &lightnings, // lightning - &fireballs, // explosion fireball - &bluefireballs, // bluish explosion fireball new quadrenderer("packages/particles/spark.png", PT_PART|PT_FLIP|PT_GLARE), // sparks new quadrenderer("packages/particles/base.png", PT_PART|PT_FLIP|PT_GLARE), // edit mode entities new quadrenderer("packages/particles/snow.png", PT_PART|PT_FLIP|PT_RND4, -1), // colliding snow @@ -876,73 +696,54 @@ static partrenderer *parts[] = VARFP(maxparticles, 10, 4000, 40000, initparticles()); VARFP(fewparticles, 10, 100, 40000, initparticles()); -void initparticles() -{ +void initparticles() { if(!particleshader) particleshader = lookupshaderbyname("particle"); if(!particlenotextureshader) particlenotextureshader = lookupshaderbyname("particlenotexture"); loopi(sizeof(parts)/sizeof(parts[0])) parts[i]->init(parts[i]->type&PT_FEW ? min(fewparticles, maxparticles) : maxparticles); } -void clearparticles() -{ +void clearparticles() { loopi(sizeof(parts)/sizeof(parts[0])) parts[i]->reset(); clearparticleemitters(); } -void cleanupparticles() -{ +void cleanupparticles() { loopi(sizeof(parts)/sizeof(parts[0])) parts[i]->cleanup(); } -void removetrackedparticles(physent *owner) -{ +void removetrackedparticles(physent *owner) { loopi(sizeof(parts)/sizeof(parts[0])) parts[i]->resettracked(owner); } -void renderparticles(bool mainpass) -{ +void renderparticles(bool mainpass) { canstep = mainpass; - - loopi(sizeof(parts)/sizeof(parts[0])) - { + loopi(sizeof(parts)/sizeof(parts[0])) { parts[i]->update(); } - bool rendered = false; uint lastflags = PT_LERP|PT_SHADER, flagmask = PT_LERP|PT_MOD|PT_SHADER|PT_NOTEX; - - loopi(sizeof(parts)/sizeof(parts[0])) - { + loopi(sizeof(parts)/sizeof(parts[0])) { partrenderer *p = parts[i]; if(!(p->type&PT_GLARE)) continue; if(!p->haswork()) continue; - - if(!rendered) - { + if(!rendered) { rendered = true; glDepthMask(GL_FALSE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - GLOBALPARAMF(colorscale, 1, 1, 1, 1); } - uint flags = p->type & flagmask, changedbits = (flags ^ lastflags); - if(changedbits) - { - if(changedbits&(PT_LERP|PT_MOD)) - { + if(changedbits) { + if(changedbits&(PT_LERP|PT_MOD)) { if(flags&PT_LERP) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); else if(flags&PT_MOD) glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); else glBlendFunc(GL_SRC_ALPHA, GL_ONE); } - if(!(flags&PT_SHADER)) - { - if(changedbits&(PT_SOFT|PT_SHADER|PT_NOTEX|PT_LERP)) - { - if(flags&PT_SOFT) - { + if(!(flags&PT_SHADER)) { + if(changedbits&(PT_SOFT|PT_SHADER|PT_NOTEX|PT_LERP)) { + if(flags&PT_SOFT) { SETSHADER(particlesoft); } else if(flags&PT_NOTEX) particlenotextureshader->set(); @@ -953,9 +754,7 @@ void renderparticles(bool mainpass) } p->render(); } - - if(rendered) - { + if(rendered) { if(lastflags&(PT_LERP|PT_MOD)) glBlendFunc(GL_SRC_ALPHA, GL_ONE); glDisable(GL_BLEND); glDepthMask(GL_TRUE); @@ -964,11 +763,9 @@ void renderparticles(bool mainpass) static int addedparticles = 0; -static inline particle *newparticle(const vec &o, const vec &d, int fade, int type, int color, float size, int gravity = 0) -{ +static inline particle *newparticle(const vec &o, const vec &d, int fade, int type, int color, float size, int gravity = 0) { static particle dummy; - if(seedemitter) - { + if(seedemitter) { parts[type]->seedemitter(*seedemitter, o, d, fade, size, gravity); return &dummy; } @@ -979,17 +776,14 @@ static inline particle *newparticle(const vec &o, const vec &d, int fade, int ty VARP(maxparticledistance, 256, 1024, 4096); -static void splash(int type, int color, int radius, int num, int fade, const vec &p, float size, int gravity) -{ +static void splash(int type, int color, int radius, int num, int fade, const vec &p, float size, int gravity) { if(camera1->o.dist(p) > maxparticledistance && !seedemitter) return; float collidez = parts[type]->collide ? p.z - raycube(p, vec(0, 0, -1), COLLIDERADIUS, RAY_CLIPMAT) + (parts[type]->collide >= 0 ? COLLIDEERROR : 0) : -1; int fmin = 1; int fmax = fade*3; - loopi(num) - { + loopi(num) { int x, y, z; - do - { + do { x = rnd(radius*2)-radius; y = rnd(radius*2)-radius; z = rnd(radius*2)-radius; @@ -1001,41 +795,35 @@ static void splash(int type, int color, int radius, int num, int fade, const vec } } -static void regularsplash(int type, int color, int radius, int num, int fade, const vec &p, float size, int gravity, int delay = 0) -{ +static void regularsplash(int type, int color, int radius, int num, int fade, const vec &p, float size, int gravity, int delay = 0) { if(!canemitparticles() || (delay > 0 && rnd(delay) != 0)) return; splash(type, color, radius, num, fade, p, size, gravity); } -bool canaddparticles() -{ +bool canaddparticles() { return !renderedgame && !shadowmapping && !minimized; } -void regular_particle_splash(int type, int num, int fade, const vec &p, int color, float size, int radius, int gravity, int delay) -{ +void regular_particle_splash(int type, int num, int fade, const vec &p, int color, float size, int radius, int gravity, int delay) { if(!canaddparticles()) return; regularsplash(type, color, radius, num, fade, p, size, gravity, delay); } -void particle_splash(int type, int num, int fade, const vec &p, int color, float size, int radius, int gravity) -{ +void particle_splash(int type, int num, int fade, const vec &p, int color, float size, int radius, int gravity) { if(!canaddparticles()) return; splash(type, color, radius, num, fade, p, size, gravity); } VARP(maxtrail, 1, 500, 10000); -void particle_trail(int type, int fade, const vec &s, const vec &e, int color, float size, int gravity) -{ +void particle_trail(int type, int fade, const vec &s, const vec &e, int color, float size, int gravity) { if(!canaddparticles()) return; vec v; float d = e.dist(s, v); int steps = clamp(int(d*2), 1, maxtrail); v.div(steps); vec p = s; - loopi(steps) - { + loopi(steps) { p.add(v); vec tmp = vec(float(rnd(11)-5), float(rnd(11)-5), float(rnd(11)-5)); newparticle(p, tmp, rnd(fade)+fade, type, color, size, gravity); @@ -1045,8 +833,7 @@ void particle_trail(int type, int fade, const vec &s, const vec &e, int color, f VARP(particletext, 0, 1, 1); VARP(maxparticletextdistance, 0, 128, 10000); -void particle_text(const vec &s, const char *t, int type, int fade, int color, float size, int gravity, int icons) -{ +void particle_text(const vec &s, const char *t, int type, int fade, int color, float size, int gravity, int icons) { if(!canaddparticles()) return; if(!particletext || camera1->o.dist(s) > maxparticletextdistance) return; particle *p = newparticle(s, vec(0, 0, 1), fade, type, color, size, gravity); @@ -1054,8 +841,7 @@ void particle_text(const vec &s, const char *t, int type, int fade, int color, f p->flags = icons<<1; } -void particle_textcopy(const vec &s, const char *t, int type, int fade, int color, float size, int gravity) -{ +void particle_textcopy(const vec &s, const char *t, int type, int fade, int color, float size, int gravity) { if(!canaddparticles()) return; if(!particletext || camera1->o.dist(s) > maxparticletextdistance) return; particle *p = newparticle(s, vec(0, 0, 1), fade, type, color, size, gravity); @@ -1063,8 +849,7 @@ void particle_textcopy(const vec &s, const char *t, int type, int fade, int colo p->flags = 1; } -void particle_texticon(const vec &s, int ix, int iy, float offset, int type, int fade, int color, float size, int gravity) -{ +void particle_texticon(const vec &s, int ix, int iy, float offset, int type, int fade, int color, float size, int gravity) { if(!canaddparticles()) return; if(!particletext || camera1->o.dist(s) > maxparticletextdistance) return; particle *p = newparticle(s, vec(0, 0, 1), fade, type, color, size, gravity); @@ -1072,15 +857,13 @@ void particle_texticon(const vec &s, int ix, int iy, float offset, int type, int p->val = offset; } -void particle_icon(const vec &s, int ix, int iy, int type, int fade, int color, float size, int gravity) -{ +void particle_icon(const vec &s, int ix, int iy, int type, int fade, int color, float size, int gravity) { if(!canaddparticles()) return; particle *p = newparticle(s, vec(0, 0, 1), fade, type, color, size, gravity); p->flags |= ix | (iy<<2); } -void particle_meter(const vec &s, float val, int type, int fade, int color, int color2, float size) -{ +void particle_meter(const vec &s, float val, int type, int fade, int color, int color2, float size) { if(!canaddparticles()) return; particle *p = newparticle(s, vec(0, 0, 1), fade, type, color, size); p->color2[0] = color2>>16; @@ -1089,31 +872,20 @@ void particle_meter(const vec &s, float val, int type, int fade, int color, int p->progress = clamp(int(val*100), 0, 100); } -void particle_flare(const vec &p, const vec &dest, int fade, int type, int color, float size, physent *owner) -{ +void particle_flare(const vec &p, const vec &dest, int fade, int type, int color, float size, physent *owner) { if(!canaddparticles()) return; newparticle(p, dest, fade, type, color, size)->owner = owner; } -void particle_fireball(const vec &dest, float maxsize, int type, int fade, int color, float size) -{ - if(!canaddparticles()) return; - float growth = maxsize - size; - if(fade < 0) fade = int(growth*20); - newparticle(dest, vec(0, 0, 1), fade, type, color, size)->val = growth; -} - //dir = 0..6 where 0=up -static inline vec offsetvec(vec o, int dir, int dist) -{ +static inline vec offsetvec(vec o, int dir, int dist) { vec v = vec(o); v[(2+dir)%3] += (dir>2)?(-dist):dist; return v; } //converts a 16bit color to 24bit -static inline int colorfromattr(int attr) -{ +static inline int colour_from_attribute(int attr) { return (((attr&0xF)<<4) | ((attr&0xF0)<<8) | ((attr&0xF00)<<12)) + 0x0F0F0F; } @@ -1128,19 +900,15 @@ static inline int colorfromattr(int attr) * 24..26 flat plane * +32 to inverse direction */ -void regularshape(int type, int radius, int color, int dir, int num, int fade, const vec &p, float size, int gravity, int vel = 200) -{ +void regularshape(int type, int radius, int color, int dir, int num, int fade, const vec &p, float size, int gravity, int vel = 200) { if(!canemitparticles()) return; - int basetype = parts[type]->type&0xFF; - bool flare = (basetype == PT_TAPE) || (basetype == PT_LIGHTNING), + bool flare = (basetype == PT_TAPE), inv = (dir&0x20)!=0, taper = (dir&0x40)!=0 && !seedemitter; dir &= 0x1F; - loopi(num) - { + loopi(num) { vec to, from; - if(dir < 12) - { + if(dir < 12) { const vec2 &sc = sincos360[rnd(360)]; to[dir%3] = sc.y*radius; to[(dir+1)%3] = sc.x*radius; @@ -1148,20 +916,17 @@ void regularshape(int type, int radius, int color, int dir, int num, int fade, c to.add(p); if(dir < 3) //circle from = p; - else if(dir < 6) //cylinder - { + else if(dir < 6) { //cylinder { from = to; to[(dir+2)%3] += radius; from[(dir+2)%3] -= radius; } - else //cone - { + else { //cone { from = p; to[(dir+2)%3] += (dir < 9)?radius:(-radius); } } - else if(dir < 15) //plane - { + else if(dir < 15) { //plane { to[dir%3] = float(rnd(radius<<4)-(radius<<3))/8.0; to[(dir+1)%3] = float(rnd(radius<<4)-(radius<<3))/8.0; to[(dir+2)%3] = radius; @@ -1169,15 +934,12 @@ void regularshape(int type, int radius, int color, int dir, int num, int fade, c from = to; from[(dir+2)%3] -= 2*radius; } - else if(dir < 21) //line - { - if(dir < 18) - { + else if(dir < 21) { //line { + if(dir < 18) { to[dir%3] = float(rnd(radius<<4)-(radius<<3))/8.0; to[(dir+1)%3] = 0.0; } - else - { + else { to[dir%3] = 0.0; to[(dir+1)%3] = float(rnd(radius<<4)-(radius<<3))/8.0; } @@ -1186,14 +948,12 @@ void regularshape(int type, int radius, int color, int dir, int num, int fade, c from = to; to[(dir+2)%3] += radius; } - else if(dir < 24) //sphere - { + else if(dir < 24) { //sphere { to = vec(2*M_PI*float(rnd(1000))/1000.0, M_PI*float(rnd(1000)-500)/1000.0).mul(radius); to.add(p); from = p; } - else if(dir < 27) // flat plane - { + else if(dir < 27) { // flat plane { to[dir%3] = float(rndscale(2*radius)-radius); to[(dir+1)%3] = float(rndscale(2*radius)-radius); to[(dir+2)%3] = 0.0; @@ -1201,23 +961,17 @@ void regularshape(int type, int radius, int color, int dir, int num, int fade, c from = to; } else from = to = p; - if(inv) swap(from, to); - - if(taper) - { + if(taper) { float dist = clamp(from.dist2(camera1->o)/maxparticledistance, 0.0f, 1.0f); - if(dist > 0.2f) - { + if(dist > 0.2f) { dist = 1 - (dist - 0.2f)/0.8f; if(rnd(0x10000) > dist*dist*0xFFFF) continue; } } - if(flare) newparticle(from, to, rnd(fade*3)+1, type, color, size, gravity); - else - { + else { vec d = vec(to).sub(from).rescale(vel); //velocity particle *n = newparticle(from, d, rnd(fade*3)+1, type, color, size, gravity); if(parts[type]->collide) @@ -1226,14 +980,11 @@ void regularshape(int type, int radius, int color, int dir, int num, int fade, c } } -static void regularflame(int type, const vec &p, float radius, float height, int color, int density = 3, float scale = 2.0f, float speed = 200.0f, float fade = 600.0f, int gravity = -15) -{ +static void regularflame(int type, const vec &p, float radius, float height, int color, int density = 3, float scale = 2.0f, float speed = 200.0f, float fade = 600.0f, int gravity = -15) { if(!canemitparticles()) return; - float size = scale * min(radius, height); vec v(0, 0, min(1.0f, height)*speed); - loopi(density) - { + loopi(density) { vec s = p; s.x += rndscale(radius*2.0f)-radius; s.y += rndscale(radius*2.0f)-radius; @@ -1241,65 +992,48 @@ static void regularflame(int type, const vec &p, float radius, float height, int } } -void regular_particle_flame(int type, const vec &p, float radius, float height, int color, int density, float scale, float speed, float fade, int gravity) -{ +void regular_particle_flame(int type, const vec &p, float radius, float height, int color, int density, float scale, float speed, float fade, int gravity) { if(!canaddparticles()) return; regularflame(type, p, radius, height, color, density, scale, speed, fade, gravity); } -static void makeparticles(entity &e) -{ - switch(e.attr1) - { - case 0: //fire and smoke - - 0 values default to compat for old maps - { - //regularsplash(PART_FIREBALL1, 0xFFC8C8, 150, 1, 40, e.o, 4.8f); - //regularsplash(PART_SMOKE, 0x897661, 50, 1, 200, vec(e.o.x, e.o.y, e.o.z+3.0f), 2.4f, -20, 3); +static void makeparticles(entity &e) { + switch(e.attr1) { + case 0: { //fire and smoke - - 0 values default to compat for old maps { float radius = e.attr2 ? float(e.attr2)/100.0f : 1.5f, height = e.attr3 ? float(e.attr3)/100.0f : radius/3; - regularflame(PART_FLAME, e.o, radius, height, e.attr4 ? colorfromattr(e.attr4) : 0x903020, 3, 2.0f); + regularflame(PART_FLAME, e.o, radius, height, e.attr4 ? colour_from_attribute(e.attr4) : 0x903020, 3, 2.0f); regularflame(PART_SMOKE, vec(e.o.x, e.o.y, e.o.z + 4.0f*min(radius, height)), radius, height, 0x303020, 1, 4.0f, 100.0f, 2000.0f, -20); break; } case 1: //steam vent - regularsplash(PART_STEAM, 0x897661, 50, 1, 200, offsetvec(e.o, e.attr2, rnd(10)), 2.4f, -20); break; - case 2: //water fountain - - { + case 2: { //water fountain - { int color; - if(e.attr3 > 0) color = colorfromattr(e.attr3); - else - { - int mat = clamp(-e.attr3, 0, 3); - color = 0xff7700; - } + if(e.attr3 > 0) color = colour_from_attribute(e.attr3); + else color = 0xff7700; regularsplash(PART_WATER, color, 150, 4, 200, offsetvec(e.o, e.attr2, rnd(10)), 0.6f, 2); break; } - case 3: //fire ball - - newparticle(e.o, vec(0, 0, 1), 1, PART_EXPLOSION, colorfromattr(e.attr3), 4.0f)->val = 1+e.attr2; - break; - case 4: //tape - - case 7: //lightning case 9: //steam + case 4: //tape - case 10: //water - case 13: //snow - { - static const int typemap[] = { PART_STREAK, -1, -1, PART_LIGHTNING, -1, PART_STEAM, PART_WATER, -1, -1, PART_SNOW }; - static const float sizemap[] = { 0.28f, 0.0f, 0.0f, 1.0f, 0.0f, 2.4f, 0.60f, 0.0f, 0.0f, 0.5f }; + case 13: { //snow { + static const int typemap[] = { PART_STREAK, -1, -1, -1, -1, PART_STEAM, PART_WATER, -1, -1, PART_SNOW }; + static const float sizemap[] = { 0.28f, 0.0f, 0.0f, 0.0f, 0.0f, 2.4f, 0.60f, 0.0f, 0.0f, 0.5f }; static const int gravmap[] = { 0, 0, 0, 0, 0, -20, 2, 0, 0, 20 }; int type = typemap[e.attr1-4]; float size = sizemap[e.attr1-4]; int gravity = gravmap[e.attr1-4]; - if(e.attr2 >= 256) regularshape(type, max(1+e.attr3, 1), colorfromattr(e.attr4), e.attr2-256, 5, e.attr5 > 0 ? min(int(e.attr5), 10000) : 200, e.o, size, gravity); - else newparticle(e.o, offsetvec(e.o, e.attr2, max(1+e.attr3, 0)), 1, type, colorfromattr(e.attr4), size, gravity); + if(e.attr2 >= 256) regularshape(type, max(1+e.attr3, 1), colour_from_attribute(e.attr4), e.attr2-256, 5, e.attr5 > 0 ? min(int(e.attr5), 10000) : 200, e.o, size, gravity); + else newparticle(e.o, offsetvec(e.o, e.attr2, max(1+e.attr3, 0)), 1, type, colour_from_attribute(e.attr4), size, gravity); break; } case 5: //meter, metervs - - case 6: - { - particle *p = newparticle(e.o, vec(0, 0, 1), 1, e.attr1==5 ? PART_METER : PART_METER_VS, colorfromattr(e.attr3), 2.0f); - int color2 = colorfromattr(e.attr4); + case 6: { + particle *p = newparticle(e.o, vec(0, 0, 1), 1, e.attr1==5 ? PART_METER : PART_METER_VS, colour_from_attribute(e.attr3), 2.0f); + int color2 = colour_from_attribute(e.attr4); p->color2[0] = color2>>16; p->color2[1] = (color2>>8)&0xFF; p->color2[2] = color2&0xFF; @@ -1307,10 +1041,10 @@ static void makeparticles(entity &e) break; } case 11: // flame - radius=100, height=100 is the classic size - regularflame(PART_FLAME, e.o, float(e.attr2)/100.0f, float(e.attr3)/100.0f, colorfromattr(e.attr4), 3, 2.0f); + regularflame(PART_FLAME, e.o, float(e.attr2)/100.0f, float(e.attr3)/100.0f, colour_from_attribute(e.attr4), 3, 2.0f); break; case 12: // smoke plume - regularflame(PART_SMOKE, e.o, float(e.attr2)/100.0f, float(e.attr3)/100.0f, colorfromattr(e.attr4), 1, 4.0f, 100.0f, 2000.0f, -20); + regularflame(PART_SMOKE, e.o, float(e.attr2)/100.0f, float(e.attr3)/100.0f, colour_from_attribute(e.attr4), 1, 4.0f, 100.0f, 2000.0f, -20); break; case 32: //lens flares - plain/sparkle/sun/sparklesun case 33: @@ -1318,8 +1052,7 @@ static void makeparticles(entity &e) case 35: break; default: - if(!editmode) - { + if(!editmode) { defformatstring(ds, "particles %d?", e.attr1); particle_textcopy(e.o, ds, PART_TEXT, 1, 0x6496FF, 2.0f); } @@ -1327,10 +1060,8 @@ static void makeparticles(entity &e) } } -bool printparticles(extentity &e, char *buf, int len) -{ - switch(e.attr1) - { +bool printparticles(extentity &e, char *buf, int len) { + switch(e.attr1) { case 0: case 4: case 7: case 8: case 9: case 10: case 11: case 12: case 13: nformatstring(buf, len, "%s %d %d %d 0x%.3hX %d", entities::entname(e.type), e.attr1, e.attr2, e.attr3, e.attr4, e.attr5); return true; @@ -1344,13 +1075,11 @@ bool printparticles(extentity &e, char *buf, int len) return false; } -void seedparticles() -{ +void seedparticles() { renderprogress(0, "seeding particles"); addparticleemitters(); canemit = true; - loopv(emitters) - { + loopv(emitters) { particleemitter &pe = emitters[i]; extentity &e = *pe.ent; seedemitter = &pe; @@ -1362,34 +1091,25 @@ void seedparticles() } } -void updateparticles() -{ +void updateparticles() { if(regenemitters) addparticleemitters(); - if(minimized) { canemit = false; return; } - - if(lastmillis - lastemitframe >= emitmillis) - { + if(lastmillis - lastemitframe >= emitmillis) { canemit = true; lastemitframe = lastmillis - (lastmillis%emitmillis); } else canemit = false; - - if(!editmode || showparticles) - { + if(!editmode || showparticles) { int emitted = 0, replayed = 0; addedparticles = 0; - loopv(emitters) - { + loopv(emitters) { particleemitter &pe = emitters[i]; extentity &e = *pe.ent; if(e.o.dist(camera1->o) > maxparticledistance) { pe.lastemit = lastmillis; continue; } makeparticles(e); emitted++; - if(replayparticles && pe.maxfade > 5 && pe.lastcull > pe.lastemit) - { - for(emitoffset = max(pe.lastemit + emitmillis - lastmillis, -pe.maxfade); emitoffset < 0; emitoffset += emitmillis) - { + if(replayparticles && pe.maxfade > 5 && pe.lastcull > pe.lastemit) { + for(emitoffset = max(pe.lastemit + emitmillis - lastmillis, -pe.maxfade); emitoffset < 0; emitoffset += emitmillis) { makeparticles(e); replayed++; } @@ -1398,17 +1118,14 @@ void updateparticles() pe.lastemit = lastmillis; } } - if(editmode) // show sparkly thingies for map entities in edit mode - { + if(editmode) { // show sparkly thingies for map entities in edit mode { const vector &ents = entities::getents(); // note: order matters in this case as particles of the same type are drawn in the reverse order that they are added - loopv(entgroup) - { + loopv(entgroup) { entity &e = *ents[entgroup[i]]; particle_textcopy(e.o, entname(e), PART_TEXT, 1, 0xFF4B19, 2.0f); } - loopv(ents) - { + loopv(ents) { entity &e = *ents[i]; if(e.type==ET_EMPTY) continue; particle_textcopy(e.o, entname(e), PART_TEXT, 1, 0x1EC850, 2.0f); diff --git a/src/engine/rendertarget.h b/src/engine/rendertarget.h index a22298b..e89393a 100644 --- a/src/engine/rendertarget.h +++ b/src/engine/rendertarget.h @@ -1,7 +1,6 @@ extern int rtsharefb, rtscissor, blurtile; -struct rendertarget -{ +struct rendertarget { int texw, texh, vieww, viewh; GLenum colorfmt, depthfmt; GLuint rendertex, renderfb, renderdb, blurtex, blurfb, blurdb; @@ -9,70 +8,49 @@ struct rendertarget float blursigma; float blurweights[MAXBLURRADIUS+1], bluroffsets[MAXBLURRADIUS+1]; float bluryweights[MAXBLURRADIUS+1], bluryoffsets[MAXBLURRADIUS+1]; - float scissorx1, scissory1, scissorx2, scissory2; #define BLURTILES 32 #define BLURTILEMASK (0xFFFFFFFFU>>(32-BLURTILES)) uint blurtiles[BLURTILES+1]; - bool initialized; - - rendertarget() : texw(0), texh(0), vieww(0), viewh(0), colorfmt(GL_FALSE), depthfmt(GL_FALSE), rendertex(0), renderfb(0), renderdb(0), blurtex(0), blurfb(0), blurdb(0), blursize(0), blurysize(0), blursigma(0), initialized(false) - { + rendertarget() : texw(0), texh(0), vieww(0), viewh(0), colorfmt(GL_FALSE), depthfmt(GL_FALSE), rendertex(0), renderfb(0), renderdb(0), blurtex(0), blurfb(0), blurdb(0), blursize(0), blurysize(0), blursigma(0), initialized(false) { } - virtual ~rendertarget() {} - - virtual GLenum attachment() const - { + virtual GLenum attachment() const { return GL_COLOR_ATTACHMENT0; } - - virtual const GLenum *colorformats() const - { + virtual const GLenum *colorformats() const { static const GLenum colorfmts[] = { GL_RGB, GL_RGB8, GL_FALSE }; return colorfmts; } - - virtual const GLenum *depthformats() const - { + virtual const GLenum *depthformats() const { static const GLenum depthfmts[] = { GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT32, GL_FALSE }; return depthfmts; } - virtual bool depthtest() const { return true; } - - void cleanup(bool fullclean = false) - { + void cleanup(bool fullclean = false) { if(renderfb) { glDeleteFramebuffers_(1, &renderfb); renderfb = 0; } if(renderdb) { glDeleteRenderbuffers_(1, &renderdb); renderdb = 0; } if(rendertex) { glDeleteTextures(1, &rendertex); rendertex = 0; } texw = texh = 0; cleanupblur(); - if(fullclean) colorfmt = depthfmt = GL_FALSE; } - - void cleanupblur() - { + void cleanupblur() { if(blurfb) { glDeleteFramebuffers_(1, &blurfb); blurfb = 0; } if(blurtex) { glDeleteTextures(1, &blurtex); blurtex = 0; } if(blurdb) { glDeleteRenderbuffers_(1, &blurdb); blurdb = 0; } blursize = blurysize = 0; blursigma = 0.0f; } - - void setupblur() - { + void setupblur() { if(!blurtex) glGenTextures(1, &blurtex); createtexture(blurtex, texw, texh, NULL, 3, 1, colorfmt); - if(!swaptexs() || rtsharefb) return; if(!blurfb) glGenFramebuffers_(1, &blurfb); glBindFramebuffer_(GL_FRAMEBUFFER, blurfb); glFramebufferTexture2D_(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blurtex, 0); - if(depthtest()) - { + if(depthtest()) { if(!blurdb) glGenRenderbuffers_(1, &blurdb); glGenRenderbuffers_(1, &blurdb); glBindRenderbuffer_(GL_RENDERBUFFER, blurdb); @@ -81,39 +59,30 @@ struct rendertarget } glBindFramebuffer_(GL_FRAMEBUFFER, 0); } - - void setup(int w, int h) - { + void setup(int w, int h) { if(!renderfb) glGenFramebuffers_(1, &renderfb); glBindFramebuffer_(GL_FRAMEBUFFER, renderfb); if(!rendertex) glGenTextures(1, &rendertex); - GLenum attach = attachment(); - if(attach == GL_DEPTH_ATTACHMENT) - { + if(attach == GL_DEPTH_ATTACHMENT) { glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); } - const GLenum *colorfmts = colorformats(); int find = 0; - do - { + do { createtexture(rendertex, w, h, NULL, 3, filter() ? 1 : 0, colorfmt ? colorfmt : colorfmts[find]); glFramebufferTexture2D_(GL_FRAMEBUFFER, attach, GL_TEXTURE_2D, rendertex, 0); if(glCheckFramebufferStatus_(GL_FRAMEBUFFER)==GL_FRAMEBUFFER_COMPLETE) break; } while(!colorfmt && colorfmts[++find]); if(!colorfmt) colorfmt = colorfmts[find]; - - if(attach != GL_DEPTH_ATTACHMENT && depthtest()) - { + if(attach != GL_DEPTH_ATTACHMENT && depthtest()) { if(!renderdb) { glGenRenderbuffers_(1, &renderdb); depthfmt = GL_FALSE; } if(!depthfmt) glBindRenderbuffer_(GL_RENDERBUFFER, renderdb); const GLenum *depthfmts = depthformats(); find = 0; - do - { + do { if(!depthfmt) glRenderbufferStorage_(GL_RENDERBUFFER, depthfmts[find], w, h); glFramebufferRenderbuffer_(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderdb); if(glCheckFramebufferStatus_(GL_FRAMEBUFFER)==GL_FRAMEBUFFER_COMPLETE) break; @@ -121,72 +90,53 @@ struct rendertarget while(!depthfmt && depthfmts[++find]); if(!depthfmt) depthfmt = depthfmts[find]; } - glBindFramebuffer_(GL_FRAMEBUFFER, 0); - texw = w; texh = h; initialized = false; } - - bool addblurtiles(float x1, float y1, float x2, float y2, float blurmargin = 0) - { + bool addblurtiles(float x1, float y1, float x2, float y2, float blurmargin = 0) { if(x1 >= 1 || y1 >= 1 || x2 <= -1 || y2 <= -1) return false; - scissorx1 = min(scissorx1, max(x1, -1.0f)); scissory1 = min(scissory1, max(y1, -1.0f)); scissorx2 = max(scissorx2, min(x2, 1.0f)); scissory2 = max(scissory2, min(y2, 1.0f)); - float blurerror = 2.0f*float(2*blursize + blurmargin); int tx1 = max(0, min(BLURTILES - 1, int((x1-blurerror/vieww + 1)/2 * BLURTILES))), ty1 = max(0, min(BLURTILES - 1, int((y1-blurerror/viewh + 1)/2 * BLURTILES))), tx2 = max(0, min(BLURTILES - 1, int((x2+blurerror/vieww + 1)/2 * BLURTILES))), ty2 = max(0, min(BLURTILES - 1, int((y2+blurerror/viewh + 1)/2 * BLURTILES))); - uint mask = (BLURTILEMASK>>(BLURTILES - (tx2+1))) & (BLURTILEMASK< scissorx2 || y1-blurerror/viewh > scissory2) return false; - if(!blurtile) return true; - int tx1 = max(0, min(BLURTILES - 1, int((x1 + 1)/2 * BLURTILES))), ty1 = max(0, min(BLURTILES - 1, int((y1 + 1)/2 * BLURTILES))), tx2 = max(0, min(BLURTILES - 1, int((x2 + 1)/2 * BLURTILES))), ty2 = max(0, min(BLURTILES - 1, int((y2 + 1)/2 * BLURTILES))); - uint mask = (BLURTILEMASK>>(BLURTILES - (tx2+1))) & (BLURTILEMASK<>= 8; x += 8; } while(!(mask&1)) { mask >>= 1; x++; } int xstart = x; @@ -207,71 +157,49 @@ struct rendertarget } gle::end(); } - else - { + else { screenquad(wscale, hscale); } } - - void blur(int wantsblursize, float wantsblursigma, int wantsblurysize, int x, int y, int w, int h, bool scissor) - { + void blur(int wantsblursize, float wantsblursigma, int wantsblurysize, int x, int y, int w, int h, bool scissor) { if(!blurtex) setupblur(); - if(blursize!=wantsblursize || blurysize != wantsblurysize || (wantsblursize && blursigma!=wantsblursigma)) - { + if(blursize!=wantsblursize || blurysize != wantsblurysize || (wantsblursize && blursigma!=wantsblursigma)) { setupblurkernel(wantsblursize, wantsblursigma, blurweights, bluroffsets); if(wantsblurysize != wantsblursize) setupblurkernel(wantsblurysize, wantsblursigma, bluryweights, bluryoffsets); blursize = wantsblursize; blursigma = wantsblursigma; blurysize = wantsblurysize; } - glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); - - if(scissor) - { + if(scissor) { glScissor(x, y, w, h); glEnable(GL_SCISSOR_TEST); } - - loopi(2) - { + loopi(2) { if(i && blurysize != blursize) setblurshader(i, texh, blurysize, bluryweights, bluryoffsets); else setblurshader(i, i ? texh : texw, blursize, blurweights, bluroffsets); - if(!swaptexs() || rtsharefb) glFramebufferTexture2D_(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, i ? rendertex : blurtex, 0); else glBindFramebuffer_(GL_FRAMEBUFFER, i ? renderfb : blurfb); glBindTexture(GL_TEXTURE_2D, i ? blurtex : rendertex); - rendertiles(); } - if(scissor) glDisable(GL_SCISSOR_TEST); - glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); } - virtual bool swaptexs() const { return false; } - virtual bool dorender() { return true; } - virtual bool shouldrender() { return true; } - - virtual void doblur(int blursize, float blursigma, int blurysize) - { + virtual void doblur(int blursize, float blursigma, int blurysize) { int sx, sy, sw, sh; bool scissoring = rtscissor && scissorblur(sx, sy, sw, sh) && sw > 0 && sh > 0; if(!scissoring) { sx = sy = 0; sw = vieww; sh = viewh; } blur(blursize, blursigma, blurysize, sx, sy, sw, sh, scissoring); } - - virtual bool scissorrender(int &x, int &y, int &w, int &h) - { - if(scissorx1 >= scissorx2 || scissory1 >= scissory2) - { - if(vieww < texw || viewh < texh) - { + virtual bool scissorrender(int &x, int &y, int &w, int &h) { + if(scissorx1 >= scissorx2 || scissory1 >= scissory2) { + if(vieww < texw || viewh < texh) { x = y = 0; w = vieww; h = viewh; @@ -285,13 +213,9 @@ struct rendertarget h = min(int(ceil((scissory2+1)/2*viewh)) + 2*blursize, viewh) - y; return true; } - - virtual bool scissorblur(int &x, int &y, int &w, int &h) - { - if(scissorx1 >= scissorx2 || scissory1 >= scissory2) - { - if(vieww < texw || viewh < texh) - { + virtual bool scissorblur(int &x, int &y, int &w, int &h) { + if(scissorx1 >= scissorx2 || scissory1 >= scissory2) { + if(vieww < texw || viewh < texh) { x = y = 0; w = vieww; h = viewh; @@ -305,45 +229,32 @@ struct rendertarget h = min(int(ceil((scissory2+1)/2*viewh)), viewh) - y; return true; } - virtual void doclear() {} - virtual bool screenrect() const { return false; } virtual bool filter() const { return true; } - - void render(int w, int h, int blursize = 0, float blursigma = 0, int blurysize = 0) - { + void render(int w, int h, int blursize = 0, float blursigma = 0, int blurysize = 0) { w = min(w, hwtexsize); h = min(h, hwtexsize); - if(screenrect()) - { + if(screenrect()) { if(w > screenw) w = screenw; if(h > screenh) h = screenh; } vieww = w; viewh = h; if(w!=texw || h!=texh || (swaptexs() && !rtsharefb ? !blurfb : blurfb)) cleanup(); - - if(!filter()) - { + if(!filter()) { if(blurtex) cleanupblur(); blursize = blurysize = 0; } - if(!rendertex) setup(w, h); - scissorx2 = scissory2 = -1; scissorx1 = scissory1 = 1; memset(blurtiles, 0, sizeof(blurtiles)); - if(!shouldrender()) return; - if(blursize && !blurtex) setupblur(); - if(swaptexs() && blursize) - { + if(swaptexs() && blursize) { swap(rendertex, blurtex); - if(!rtsharefb) - { + if(!rtsharefb) { swap(renderfb, blurfb); swap(renderdb, blurdb); } @@ -352,38 +263,26 @@ struct rendertarget if(swaptexs() && blursize && rtsharefb) glFramebufferTexture2D_(GL_FRAMEBUFFER, attachment(), GL_TEXTURE_2D, rendertex, 0); glViewport(0, 0, vieww, viewh); - doclear(); - int sx, sy, sw, sh; bool scissoring = rtscissor && scissorrender(sx, sy, sw, sh) && sw > 0 && sh > 0; - if(scissoring) - { + if(scissoring) { glScissor(sx, sy, sw, sh); glEnable(GL_SCISSOR_TEST); } - else - { + else { sx = sy = 0; sw = vieww; sh = viewh; } - if(!depthtest()) glDisable(GL_DEPTH_TEST); - bool succeeded = dorender(); - if(!depthtest()) glEnable(GL_DEPTH_TEST); - if(scissoring) glDisable(GL_SCISSOR_TEST); - - if(succeeded) - { + if(succeeded) { initialized = true; - if(blursize) doblur(blursize, blursigma, blurysize ? blurysize : blursize); } - glBindFramebuffer_(GL_FRAMEBUFFER, 0); glViewport(0, 0, screenw, screenh); } diff --git a/src/engine/rendertext.cpp b/src/engine/rendertext.cpp index 925e1a8..3fd4dc8 100644 --- a/src/engine/rendertext.cpp +++ b/src/engine/rendertext.cpp @@ -7,8 +7,7 @@ static int fontdeftex = 0; font *curfont = NULL; int curfonttex = 0; -void newfont(char *name, char *tex, int *defaultw, int *defaulth) -{ +void newfont(char *name, char *tex, int *defaultw, int *defaulth) { font *f = &fonts[name]; if(!f->name) f->name = newstring(name); f->texs.shrink(0); @@ -18,39 +17,30 @@ void newfont(char *name, char *tex, int *defaultw, int *defaulth) f->defaultw = *defaultw; f->defaulth = *defaulth; f->scale = f->defaulth; - fontdef = f; fontdeftex = 0; } -void fontoffset(char *c) -{ +void fontoffset(char *c) { if(!fontdef) return; - fontdef->charoffset = c[0]; } -void fontscale(int *scale) -{ +void fontscale(int *scale) { if(!fontdef) return; - fontdef->scale = *scale > 0 ? *scale : fontdef->defaulth; } -void fonttex(char *s) -{ +void fonttex(char *s) { if(!fontdef) return; - Texture *t = textureload(s); loopv(fontdef->texs) if(fontdef->texs[i] == t) { fontdeftex = i; return; } fontdeftex = fontdef->texs.length(); fontdef->texs.add(t); } -void fontchar(int *x, int *y, int *w, int *h, int *offsetx, int *offsety, int *advance) -{ +void fontchar(int *x, int *y, int *w, int *h, int *offsetx, int *offsety, int *advance) { if(!fontdef) return; - font::charinfo &c = fontdef->chars.add(); c.x = *x; c.y = *y; @@ -62,11 +52,9 @@ void fontchar(int *x, int *y, int *w, int *h, int *offsetx, int *offsety, int *a c.tex = fontdeftex; } -void fontskip(int *n) -{ +void fontskip(int *n) { if(!fontdef) return; - loopi(max(*n, 1)) - { + loopi(max(*n, 1)) { font::charinfo &c = fontdef->chars.add(); c.x = c.y = c.w = c.h = c.offsetx = c.offsety = c.advance = c.tex = 0; } @@ -79,8 +67,7 @@ COMMAND(fonttex, "s"); COMMAND(fontchar, "iiiiiii"); COMMAND(fontskip, "i"); -void fontalias(const char *dst, const char *src) -{ +void fontalias(const char *dst, const char *src) { font *s = fonts.access(src); if(!s) return; font *d = &fonts[dst]; @@ -91,15 +78,13 @@ void fontalias(const char *dst, const char *src) d->defaultw = s->defaultw; d->defaulth = s->defaulth; d->scale = s->scale; - fontdef = d; fontdeftex = d->texs.length()-1; } COMMAND(fontalias, "ss"); -bool setfont(const char *name) -{ +bool setfont(const char *name) { font *f = fonts.access(name); if(!f) return false; curfont = f; @@ -108,37 +93,30 @@ bool setfont(const char *name) static vector fontstack; -void pushfont() -{ +void pushfont() { fontstack.add(curfont); } -bool popfont() -{ +bool popfont() { if(fontstack.empty()) return false; curfont = fontstack.pop(); return true; } -void gettextres(int &w, int &h) -{ - if(w < MINRESW || h < MINRESH) - { - if(MINRESW > w*MINRESH/h) - { +void gettextres(int &w, int &h) { + if(w < MINRESW || h < MINRESH) { + if(MINRESW > w*MINRESH/h) { h = h*MINRESW/w; w = MINRESW; } - else - { + else { w = w*MINRESH/h; h = MINRESH; } } } -float text_widthf(const char *str) -{ +float text_widthf(const char *str) { float width, height; text_boundsf(str, width, height); return width; @@ -147,8 +125,7 @@ float text_widthf(const char *str) #define FONTTAB (4*FONTW) #define TEXTTAB(x) ((int((x)/FONTTAB)+1.0f)*FONTTAB) -void tabify(const char *str, int *numtabs) -{ +void tabify(const char *str, int *numtabs) { int tw = max(*numtabs, 0)*FONTTAB-1, tabs = 0; for(float w = text_widthf(str); w <= tw; w = TEXTTAB(w)) ++tabs; int len = strlen(str); @@ -161,24 +138,20 @@ void tabify(const char *str, int *numtabs) COMMAND(tabify, "si"); -void draw_textf(const char *fstr, int left, int top, ...) -{ +void draw_textf(const char *fstr, int left, int top, ...) { defvformatstring(str, top, fstr); draw_text(str, left, top); } const matrix4x3 *textmatrix = NULL; -static float draw_char(Texture *&tex, int c, float x, float y, float scale) -{ +static float draw_char(Texture *&tex, int c, float x, float y, float scale) { font::charinfo &info = curfont->chars[c-curfont->charoffset]; - if(tex != curfont->texs[info.tex]) - { + if(tex != curfont->texs[info.tex]) { xtraverts += gle::end(); tex = curfont->texs[info.tex]; glBindTexture(GL_TEXTURE_2D, tex->id); } - float x1 = x + scale*info.offsetx, y1 = y + scale*info.offsety, x2 = x + scale*(info.offsetx + info.w), @@ -187,40 +160,31 @@ static float draw_char(Texture *&tex, int c, float x, float y, float scale) ty1 = info.y / float(tex->ys), tx2 = (info.x + info.w) / float(tex->xs), ty2 = (info.y + info.h) / float(tex->ys); - - if(textmatrix) - { + if(textmatrix) { gle::attrib(textmatrix->transform(vec2(x1, y1))); gle::attribf(tx1, ty1); gle::attrib(textmatrix->transform(vec2(x2, y1))); gle::attribf(tx2, ty1); gle::attrib(textmatrix->transform(vec2(x2, y2))); gle::attribf(tx2, ty2); gle::attrib(textmatrix->transform(vec2(x1, y2))); gle::attribf(tx1, ty2); } - else - { + else { gle::attribf(x1, y1); gle::attribf(tx1, ty1); gle::attribf(x2, y1); gle::attribf(tx2, ty1); gle::attribf(x2, y2); gle::attribf(tx2, ty2); gle::attribf(x1, y2); gle::attribf(tx1, ty2); } - return scale*info.advance; } //stack[sp] is current color index -static void text_color(char c, char *stack, int size, int &sp, bvec color, int a) -{ - if(c=='s') // save color - { +static void text_color(char c, char *stack, int size, int &sp, bvec color, int a) { + if(c=='s') { // save color { c = stack[sp]; if(sp 0) --sp; c = stack[sp]; } // restore color else stack[sp] = c; - switch(c) - { + switch(c) { case '0': color = bvec( 64, 255, 128); break; // green: player talk case '1': color = bvec( 96, 160, 255); break; // blue: "echo" command case '2': color = bvec(255, 192, 64); break; // yellow: gameplay messages @@ -239,24 +203,21 @@ static void text_color(char c, char *stack, int size, int &sp, bvec color, int a #define TEXTSKELETON \ float y = 0, x = 0, scale = curfont->scale/float(curfont->defaulth);\ int i;\ - for(i = 0; str[i]; i++)\ - {\ + for(i = 0; str[i]; i++) { \ TEXTINDEX(i)\ int c = uchar(str[i]);\ - if(c=='\t') { x = TEXTTAB(x); TEXTWHITE(i) }\ - else if(c==' ') { x += scale*curfont->defaultw; TEXTWHITE(i) }\ + if(c=='\t') { x = TEXTTAB(x); TEXTWHITE(i) }\ + else if(c==' ') { x += scale*curfont->defaultw; TEXTWHITE(i) }\ else if(c=='\n') { TEXTLINE(i) x = 0; y += FONTH; }\ else if(c=='\f') { if(str[i+1]) { i++; TEXTCOLOR(i) }}\ - else if(curfont->chars.inrange(c-curfont->charoffset))\ - {\ + else if(curfont->chars.inrange(c-curfont->charoffset)) {\ float cw = scale*curfont->chars[c-curfont->charoffset].advance;\ if(cw <= 0) continue;\ - if(maxwidth != -1)\ - {\ + if(maxwidth != -1) {\ int j = i;\ float w = cw;\ - for(; str[i+1]; i++)\ - {\ + for(; str[i+1]; i++) {\ + \ int c = uchar(str[i+1]);\ if(c=='\f') { if(str[i+2]) i++; continue; }\ if(i-j > 16) break;\ @@ -268,15 +229,15 @@ static void text_color(char c, char *stack, int size, int &sp, bvec color, int a if(x + w > maxwidth && j!=0) { TEXTLINE(j-1) x = 0; y += FONTH; }\ TEXTWORD\ }\ - else\ - { TEXTCHAR(i) }\ + else{ \ + TEXTCHAR(i) }\ }\ } //all the chars are guaranteed to be either drawable or color commands #define TEXTWORDSKELETON \ - for(; j <= i; j++)\ - {\ + for(; j <= i; j++){ \ + \ TEXTINDEX(j)\ int c = uchar(str[j]);\ if(c=='\f') { if(str[j+1]) { j++; TEXTCOLOR(j) }}\ @@ -285,8 +246,7 @@ static void text_color(char c, char *stack, int size, int &sp, bvec color, int a #define TEXTEND(cursor) if(cursor >= i) { do { TEXTINDEX(cursor); } while(0); } -int text_visible(const char *str, float hitx, float hity, int maxwidth) -{ +int text_visible(const char *str, float hitx, float hity, int maxwidth) { #define TEXTINDEX(idx) #define TEXTWHITE(idx) if(y+FONTH > hity && x >= hitx) return idx; #define TEXTLINE(idx) if(y+FONTH > hity) return idx; @@ -304,8 +264,7 @@ int text_visible(const char *str, float hitx, float hity, int maxwidth) } //inverse of text_visible -void text_posf(const char *str, int cursor, float &cx, float &cy, int maxwidth) -{ +void text_posf(const char *str, int cursor, float &cx, float &cy, int maxwidth) { #define TEXTINDEX(idx) if(idx == cursor) { cx = x; cy = y; break; } #define TEXTWHITE(idx) #define TEXTLINE(idx) @@ -323,8 +282,7 @@ void text_posf(const char *str, int cursor, float &cx, float &cy, int maxwidth) #undef TEXTWORD } -void text_boundsf(const char *str, float &width, float &height, int maxwidth) -{ +void text_boundsf(const char *str, float &width, float &height, int maxwidth) { #define TEXTINDEX(idx) #define TEXTWHITE(idx) #define TEXTLINE(idx) if(x > width) width = x; @@ -343,8 +301,7 @@ void text_boundsf(const char *str, float &width, float &height, int maxwidth) #undef TEXTWORD } -void draw_text(const char *str, int left, int top, int r, int g, int b, int a, int cursor, int maxwidth) -{ +void draw_text(const char *str, int left, int top, int r, int g, int b, int a, int cursor, int maxwidth) { #define TEXTINDEX(idx) if(idx == cursor) { cx = x; cy = y; } #define TEXTWHITE(idx) #define TEXTLINE(idx) @@ -368,8 +325,7 @@ void draw_text(const char *str, int left, int top, int r, int g, int b, int a, i TEXTSKELETON TEXTEND(cursor) xtraverts += gle::end(); - if(cursor >= 0 && (totalmillis/250)&1) - { + if(cursor >= 0 && (totalmillis/250)&1) { gle::color(color, a); if(maxwidth != -1 && cx >= maxwidth) { cx = 0; cy += FONTH; } draw_char(tex, '_', left+cx, top+cy, scale); @@ -383,8 +339,7 @@ void draw_text(const char *str, int left, int top, int r, int g, int b, int a, i #undef TEXTWORD } -void reloadfonts() -{ +void reloadfonts() { enumerate(fonts, font, f, loopv(f.texs) if(!reloadtexture(*f.texs[i])) fatal("failed to reload font texture"); ); diff --git a/src/engine/renderva.cpp b/src/engine/renderva.cpp index 1e33702..cc0b65d 100644 --- a/src/engine/renderva.cpp +++ b/src/engine/renderva.cpp @@ -2,14 +2,12 @@ #include "engine.h" -static inline void drawtris(GLsizei numindices, const GLvoid *indices, ushort minvert, ushort maxvert) -{ +static inline void drawtris(GLsizei numindices, const GLvoid *indices, ushort minvert, ushort maxvert) { glDrawRangeElements_(GL_TRIANGLES, minvert, maxvert, numindices, GL_UNSIGNED_SHORT, indices); glde++; } -static inline void drawvatris(vtxarray *va, GLsizei numindices, const GLvoid *indices) -{ +static inline void drawvatris(vtxarray *va, GLsizei numindices, const GLvoid *indices) { drawtris(numindices, indices, va->minvert, va->maxvert); } @@ -20,48 +18,36 @@ float vfcDnear[5], vfcDfar[5]; vtxarray *visibleva; -int isvisiblesphere(float rad, const vec &cv) -{ +int isvisiblesphere(float rad, const vec &cv) { int v = VFC_FULL_VISIBLE; float dist; - - loopi(5) - { + loopi(5) { dist = vfcP[i].dist(cv); if(dist < -rad) return VFC_NOT_VISIBLE; if(dist < rad) v = VFC_PART_VISIBLE; } - if(dist > -rad) v = VFC_PART_VISIBLE; - return v; } -static inline int ishiddencube(const ivec &o, int size) -{ +static inline int ishiddencube(const ivec &o, int size) { loopi(5) if(o.dist(vfcP[i]) < -vfcDfar[i]*size) return true; return false; } -int isvisiblecube(const ivec &o, int size) -{ +int isvisiblecube(const ivec &o, int size) { int v = VFC_FULL_VISIBLE; float dist; - - loopi(5) - { + loopi(5) { dist = o.dist(vfcP[i]); if(dist < -vfcDfar[i]*size) return VFC_NOT_VISIBLE; if(dist < -vfcDnear[i]*size) v = VFC_PART_VISIBLE; } - if(dist > -vfcDfar[4]*size) v = VFC_PART_VISIBLE; - return v; } -float vadist(vtxarray *va, const vec &p) -{ +float vadist(vtxarray *va, const vec &p) { return p.dist_to_bb(va->bbmin, va->bbmax); } @@ -69,30 +55,23 @@ float vadist(vtxarray *va, const vec &p) static vtxarray *vasort[VASORTSIZE]; -void addvisibleva(vtxarray *va) -{ +void addvisibleva(vtxarray *va) { float dist = vadist(va, camera1->o); va->distance = int(dist); /*cv.dist(camera1->o) - va->size*SQRT3/2*/ - int hash = clamp(int(dist*VASORTSIZE/worldsize), 0, VASORTSIZE-1); vtxarray **prev = &vasort[hash], *cur = vasort[hash]; - - while(cur && va->distance >= cur->distance) - { + while(cur && va->distance >= cur->distance) { prev = &cur->next; cur = cur->next; } - va->next = *prev; *prev = va; } -void sortvisiblevas() -{ +void sortvisiblevas() { visibleva = NULL; vtxarray **last = &visibleva; - loopi(VASORTSIZE) if(vasort[i]) - { + loopi(VASORTSIZE) if(vasort[i]) { vtxarray *va = vasort[i]; *last = va; while(va->next) va = va->next; @@ -100,19 +79,15 @@ void sortvisiblevas() } } -void findvisiblevas(vector &vas, bool resetocclude = false) -{ - loopv(vas) - { +void findvisiblevas(vector &vas, bool resetocclude = false) { + loopv(vas) { vtxarray &v = *vas[i]; int prevvfc = resetocclude ? (int) VFC_NOT_VISIBLE : (int) v.curvfc; v.curvfc = isvisiblecube(v.o, v.size); - if(v.curvfc!=VFC_NOT_VISIBLE) - { + if(v.curvfc!=VFC_NOT_VISIBLE) { addvisibleva(&v); if(v.children.length()) findvisiblevas(v.children, prevvfc>=VFC_NOT_VISIBLE); - if(prevvfc>=VFC_NOT_VISIBLE) - { + if(prevvfc>=VFC_NOT_VISIBLE) { v.occluded = !v.texs ? OCCLUDE_GEOM : OCCLUDE_NOTHING; v.query = NULL; } @@ -120,10 +95,8 @@ void findvisiblevas(vector &vas, bool resetocclude = false) } } -void calcvfcD() -{ - loopi(5) - { +void calcvfcD() { + loopi(5) { plane &p = vfcP[i]; vfcDnear[i] = vfcDfar[i] = 0; loopk(3) if(p[k] > 0) vfcDfar[i] += p[k]; @@ -131,8 +104,7 @@ void calcvfcD() } } -void setvfcP(float z, const vec &bbmin, const vec &bbmax) -{ +void setvfcP(float z, const vec &bbmin, const vec &bbmax) { vec4 px = camprojmatrix.rowx(), py = camprojmatrix.rowy(), pz = camprojmatrix.rowz(), pw = camprojmatrix.roww(); vfcP[0] = plane(vec4(pw).mul(-bbmin.x).add(px)).normalize(); // left plane vfcP[1] = plane(vec4(pw).mul(bbmax.x).sub(px)).normalize(); // right plane @@ -140,41 +112,33 @@ void setvfcP(float z, const vec &bbmin, const vec &bbmax) vfcP[3] = plane(vec4(pw).mul(bbmax.y).sub(py)).normalize(); // top plane vfcP[4] = plane(vec4(pw).add(pz)).normalize(); // near/far planes if(z >= 0) loopi(5) vfcP[i].reflectz(z); - calcvfcD(); } plane oldvfcP[5]; -void savevfcP() -{ +void savevfcP() { memcpy(oldvfcP, vfcP, sizeof(vfcP)); } -void restorevfcP() -{ +void restorevfcP() { memcpy(vfcP, oldvfcP, sizeof(vfcP)); calcvfcD(); } -void visiblecubes(bool cull) -{ +void visiblecubes(bool cull) { memclear(vasort); - - if(cull) - { + if(cull) { setvfcP(); findvisiblevas(varoot); sortvisiblevas(); } - else - { + else { memclear(vfcP); memclear(vfcDnear); memclear(vfcDfar); visibleva = NULL; - loopv(valist) - { + loopv(valist) { vtxarray *va = valist[i]; va->distance = 0; va->curvfc = VFC_FULL_VISIBLE; @@ -186,8 +150,7 @@ void visiblecubes(bool cull) } } -static inline bool insideva(const vtxarray *va, const vec &v, int margin = 2) -{ +static inline bool insideva(const vtxarray *va, const vec &v, int margin = 2) { int size = va->size + margin; return v.x>=va->o.x-margin && v.y>=va->o.y-margin && v.z>=va->o.z-margin && v.x<=va->o.x+size && v.y<=va->o.y+size && v.z<=va->o.z+size; @@ -198,19 +161,13 @@ static inline bool insideva(const vtxarray *va, const vec &v, int margin = 2) #define MAXQUERY 2048 #define MAXQUERYFRAMES 2 -struct queryframe -{ +struct queryframe { int cur, max; occludequery queries[MAXQUERY]; - queryframe() : cur(0), max(0) {} - void flip() { loopi(cur) queries[i].owner = NULL; cur = 0; } - - occludequery *newquery(void *owner) - { - if(cur >= max) - { + occludequery *newquery(void *owner) { + if(cur >= max) { if(max >= MAXQUERY) return NULL; glGenQueries_(1, &queries[max++].id); } @@ -219,13 +176,9 @@ struct queryframe query->fragments = -1; return query; } - void reset() { loopi(max) queries[i].owner = NULL; } - - void cleanup() - { - loopi(max) - { + void cleanup() { + loopi(max) { glDeleteQueries_(1, &queries[i].id); queries[i].owner = NULL; } @@ -236,53 +189,43 @@ struct queryframe static queryframe queryframes[MAXQUERYFRAMES]; static uint flipquery = 0; -int getnumqueries() -{ +int getnumqueries() { return queryframes[flipquery].cur; } -void flipqueries() -{ +void flipqueries() { flipquery = (flipquery + 1) % MAXQUERYFRAMES; queryframes[flipquery].flip(); } -occludequery *newquery(void *owner) -{ +occludequery *newquery(void *owner) { return queryframes[flipquery].newquery(owner); } -void resetqueries() -{ +void resetqueries() { loopi(MAXQUERYFRAMES) queryframes[i].reset(); } -void clearqueries() -{ +void clearqueries() { loopi(MAXQUERYFRAMES) queryframes[i].cleanup(); } VAR(oqfrags, 0, 8, 64); VAR(oqwait, 0, 1, 1); -void startquery(occludequery *query) -{ +void startquery(occludequery *query) { glBeginQuery_(GL_SAMPLES_PASSED, query->id); } -void endquery(occludequery *query) -{ +void endquery(occludequery *query) { glEndQuery_(GL_SAMPLES_PASSED); } -bool checkquery(occludequery *query, bool nowait) -{ +bool checkquery(occludequery *query, bool nowait) { GLuint fragments; if(query->fragments >= 0) fragments = query->fragments; - else - { - if(nowait || !oqwait) - { + else { + if(nowait || !oqwait) { GLint avail; glGetQueryObjectiv_(query->id, GL_QUERY_RESULT_AVAILABLE, &avail); if(!avail) return false; @@ -295,10 +238,8 @@ bool checkquery(occludequery *query, bool nowait) static GLuint bbvbo = 0, bbebo = 0; -static void setupbb() -{ - if(!bbvbo) - { +static void setupbb() { + if(!bbvbo) { glGenBuffers_(1, &bbvbo); gle::bindvbo(bbvbo); vec verts[8]; @@ -306,8 +247,7 @@ static void setupbb() glBufferData_(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); gle::clearvbo(); } - if(!bbebo) - { + if(!bbebo) { glGenBuffers_(1, &bbebo); gle::bindebo(bbebo); GLushort tris[3*2*6]; @@ -329,41 +269,35 @@ static void setupbb() } } -static void cleanupbb() -{ +static void cleanupbb() { if(bbvbo) { glDeleteBuffers_(1, &bbvbo); bbvbo = 0; } if(bbebo) { glDeleteBuffers_(1, &bbebo); bbebo = 0; } } -void startbb(bool mask) -{ +void startbb(bool mask) { setupbb(); gle::bindvbo(bbvbo); gle::bindebo(bbebo); gle::vertexpointer(sizeof(vec), (const vec *)0); gle::enablevertex(); SETSHADER(bbquery); - if(mask) - { + if(mask) { glDepthMask(GL_FALSE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); } } -void endbb(bool mask) -{ +void endbb(bool mask) { gle::disablevertex(); gle::clearvbo(); gle::clearebo(); - if(mask) - { + if(mask) { glDepthMask(GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } } -void drawbb(const ivec &bo, const ivec &br) -{ +void drawbb(const ivec &bo, const ivec &br) { LOCALPARAMF(bborigin, bo.x, bo.y, bo.z); LOCALPARAMF(bbsize, br.x, br.y, br.z); glDrawRangeElements_(GL_TRIANGLES, 0, 8-1, 3*2*6, GL_UNSIGNED_SHORT, (ushort *)0); @@ -374,53 +308,40 @@ extern int octaentsize; static octaentities *visiblemms, **lastvisiblemms; -static inline bool insideoe(const octaentities *oe, const vec &v, int margin = 1) -{ +static inline bool insideoe(const octaentities *oe, const vec &v, int margin = 1) { return v.x>=oe->bbmin.x-margin && v.y>=oe->bbmin.y-margin && v.z>=oe->bbmin.z-margin && v.x<=oe->bbmax.x+margin && v.y<=oe->bbmax.y+margin && v.z<=oe->bbmax.z+margin; } -void findvisiblemms(const vector &ents, bool doquery) -{ +void findvisiblemms(const vector &ents, bool doquery) { visiblemms = NULL; lastvisiblemms = &visiblemms; - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(va->mapmodels.empty() || va->occluded >= OCCLUDE_BB) continue; - loopv(va->mapmodels) - { + loopv(va->mapmodels) { octaentities *oe = va->mapmodels[i]; - bool occluded = doquery && oe->query && oe->query->owner == oe && checkquery(oe->query); - if(occluded) - { + if(occluded) { oe->distance = -1; - oe->next = NULL; *lastvisiblemms = oe; lastvisiblemms = &oe->next; } - else - { + else { int visible = 0; - loopv(oe->mapmodels) - { + loopv(oe->mapmodels) { extentity &e = *ents[oe->mapmodels[i]]; if(e.flags&EF_NOVIS) continue; e.flags |= EF_RENDER; ++visible; } if(!visible) continue; - oe->distance = int(camera1->o.dist_to_bb(oe->o, oe->size)); - octaentities **prev = &visiblemms, *cur = visiblemms; - while(cur && cur->distance >= 0 && oe->distance > cur->distance) - { + while(cur && cur->distance >= 0 && oe->distance > cur->distance) { prev = &cur->next; cur = cur->next; } - if(*prev == NULL) lastvisiblemms = &oe->next; oe->next = *prev; *prev = oe; @@ -431,30 +352,24 @@ void findvisiblemms(const vector &ents, bool doquery) VAR(oqmm, 0, 4, 8); -void rendermapmodel(extentity &e) -{ +void rendermapmodel(extentity &e) { int anim = ANIM_MAPMODEL|ANIM_LOOP, basetime = 0; mapmodelinfo *mmi = getmminfo(e.attr2); if(mmi) rendermodel(&e.light, mmi->name, anim, e.o, e.attr1, 0, MDL_CULL_VFC | MDL_CULL_DIST | MDL_DYNLIGHT, NULL, NULL, basetime); } -void rendermapmodels() -{ +void rendermapmodels() { static int skipoq = 0; bool doquery = !drawtex && oqfrags && oqmm; const vector &ents = entities::getents(); findvisiblemms(ents, doquery); - startmodelbatches(); - for(octaentities *oe = visiblemms; oe; oe = oe->next) if(oe->distance>=0) - { + for(octaentities *oe = visiblemms; oe; oe = oe->next) if(oe->distance>=0) { bool rendered = false; - loopv(oe->mapmodels) - { + loopv(oe->mapmodels) { extentity &e = *ents[oe->mapmodels[i]]; if(!(e.flags&EF_RENDER)) continue; - if(!rendered) - { + if(!rendered) { rendered = true; oe->query = doquery && oe->distance>0 && !(++skipoq%oqmm) ? newquery(oe) : NULL; if(oe->query) startmodelquery(oe->query); @@ -465,14 +380,11 @@ void rendermapmodels() if(rendered && oe->query) endmodelquery(); } endmodelbatches(); - bool queried = true; - for(octaentities *oe = visiblemms; oe; oe = oe->next) if(oe->distance<0) - { + for(octaentities *oe = visiblemms; oe; oe = oe->next) if(oe->distance<0) { oe->query = doquery && !insideoe(oe, camera1->o) ? newquery(oe) : NULL; if(!oe->query) continue; - if(queried) - { + if(queried) { startbb(); queried = false; } @@ -480,25 +392,20 @@ void rendermapmodels() drawbb(oe->bbmin, ivec(oe->bbmax).sub(oe->bbmin)); endquery(oe->query); } - if(!queried) - { + if(!queried) { endbb(); } } -static inline bool bbinsideva(const ivec &bo, const ivec &br, vtxarray *va) -{ +static inline bool bbinsideva(const ivec &bo, const ivec &br, vtxarray *va) { return bo.x >= va->bbmin.x && bo.y >= va->bbmin.y && bo.z >= va->bbmin.z && br.x <= va->bbmax.x && br.y <= va->bbmax.y && br.z <= va->bbmax.z; } -static inline bool bboccluded(const ivec &bo, const ivec &br, cube *c, const ivec &o, int size) -{ - loopoctabox(o, size, bo, br) - { +static inline bool bboccluded(const ivec &bo, const ivec &br, cube *c, const ivec &o, int size) { + loopoctabox(o, size, bo, br) { ivec co(i, o, size); - if(c[i].ext && c[i].ext->va) - { + if(c[i].ext && c[i].ext->va) { vtxarray *va = c[i].ext->va; if(va->occluded >= OCCLUDE_BB && bbinsideva(bo, br, va)) continue; } @@ -508,24 +415,20 @@ static inline bool bboccluded(const ivec &bo, const ivec &br, cube *c, const ive return true; } -bool bboccluded(const ivec &bo, const ivec &br) -{ +bool bboccluded(const ivec &bo, const ivec &br) { int diff = (bo.x^br.x) | (bo.y^br.y) | (bo.z^br.z); if(diff&~((1<ext && c->ext->va) - { + if(c->ext && c->ext->va) { vtxarray *va = c->ext->va; if(va->occluded >= OCCLUDE_BB && bbinsideva(bo, br, va)) return true; } scale--; - while(c->children && !(diff&(1<children && !(diff&(1<children[octastep(bo.x, bo.y, bo.z, scale)]; - if(c->ext && c->ext->va) - { + if(c->ext && c->ext->va) { vtxarray *va = c->ext->va; if(va->occluded >= OCCLUDE_BB && bbinsideva(bo, br, va)) return true; } @@ -539,103 +442,71 @@ VAR(outline, 0, 0, 1); HVARP(outlinecolour, 0, 0, 0xFFFFFF); VAR(dtoutline, 0, 1, 1); -void renderoutline() -{ +void renderoutline() { notextureshader->set(); - gle::enablevertex(); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); gle::color(vec::hexcolor(outlinecolour)); - enablepolygonoffset(GL_POLYGON_OFFSET_LINE); - if(!dtoutline) glDisable(GL_DEPTH_TEST); - vtxarray *prev = NULL; - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(va->occluded >= OCCLUDE_BB) continue; if(!va->alphaback && !va->alphafront && (!va->texs || va->occluded >= OCCLUDE_GEOM)) continue; - - if(!prev || va->vbuf != prev->vbuf) - { + if(!prev || va->vbuf != prev->vbuf) { gle::bindvbo(va->vbuf); gle::bindebo(va->ebuf); const vertex *ptr = 0; gle::vertexpointer(sizeof(vertex), ptr->pos.v); } - - if(va->texs && va->occluded < OCCLUDE_GEOM) - { + if(va->texs && va->occluded < OCCLUDE_GEOM) { drawvatris(va, 3*va->tris, va->edata); xtravertsva += va->verts; } - if(va->alphatris) - { + if(va->alphatris) { drawvatris(va, 3*va->alphatris, &va->edata[3*(va->tris + va->blendtris)]); xtravertsva += 3*va->alphatris; } - prev = va; } - if(!dtoutline) glEnable(GL_DEPTH_TEST); - disablepolygonoffset(GL_POLYGON_OFFSET_LINE); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - gle::clearvbo(); gle::clearebo(); gle::disablevertex(); } -void rendershadowmapreceivers() -{ +void rendershadowmapreceivers() { SETSHADER(shadowmapreceiver); - gle::enablevertex(); - glCullFace(GL_FRONT); glDepthMask(GL_FALSE); glDepthFunc(GL_GREATER); - extern int ati_minmax_bug; if(!ati_minmax_bug) glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); - glEnable(GL_BLEND); glBlendEquation_(GL_MAX); glBlendFunc(GL_ONE, GL_ONE); - vtxarray *prev = NULL; - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(!va->texs || !isshadowmapreceiver(va)) continue; - - if(!prev || va->vbuf != prev->vbuf) - { + if(!prev || va->vbuf != prev->vbuf) { gle::bindvbo(va->vbuf); gle::bindebo(va->ebuf); const vertex *ptr = 0; gle::vertexpointer(sizeof(vertex), ptr->pos.v); } - drawvatris(va, 3*va->tris, va->edata); xtravertsva += va->verts; - prev = va; } - glDisable(GL_BLEND); glBlendEquation_(GL_FUNC_ADD); - glCullFace(GL_BACK); glDepthMask(GL_TRUE); glDepthFunc(GL_LESS); - if(!ati_minmax_bug) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - gle::clearvbo(); gle::clearebo(); gle::disablevertex(); @@ -645,8 +516,7 @@ VAR(oqdist, 0, 256, 1024); VAR(zpass, 0, 1, 1); VAR(envpass, 0, 1, 1); -struct renderstate -{ +struct renderstate { bool colormask, depthmask, blending; int alphaing; GLuint vbuf; @@ -660,68 +530,54 @@ struct renderstate int texgendim; int visibledynlights; uint dynlightmask; - - renderstate() : colormask(true), depthmask(true), blending(false), alphaing(0), vbuf(0), vattribs(false), vquery(false), colorscale(1, 1, 1), alphascale(0), slot(NULL), texgenslot(NULL), vslot(NULL), texgenvslot(NULL), texgenscroll(0, 0), texgendim(-1), visibledynlights(0), dynlightmask(0) - { + renderstate() : colormask(true), depthmask(true), blending(false), alphaing(0), vbuf(0), vattribs(false), vquery(false), colorscale(1, 1, 1), alphascale(0), slot(NULL), texgenslot(NULL), vslot(NULL), texgenvslot(NULL), texgenscroll(0, 0), texgendim(-1), visibledynlights(0), dynlightmask(0) { loopk(8) textures[k] = 0; } }; -static inline void disablevbuf(renderstate &cur) -{ +static inline void disablevbuf(renderstate &cur) { gle::clearvbo(); gle::clearebo(); cur.vbuf = 0; } -static inline void enablevquery(renderstate &cur) -{ +static inline void enablevquery(renderstate &cur) { if(cur.colormask) { cur.colormask = false; glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); } if(cur.depthmask) { cur.depthmask = false; glDepthMask(GL_FALSE); } startbb(false); cur.vquery = true; } -static inline void disablevquery(renderstate &cur) -{ +static inline void disablevquery(renderstate &cur) { endbb(false); cur.vquery = false; } -static void renderquery(renderstate &cur, occludequery *query, vtxarray *va, bool full = true) -{ +static void renderquery(renderstate &cur, occludequery *query, vtxarray *va, bool full = true) { if(!cur.vquery) enablevquery(cur); - startquery(query); - if(full) drawbb(ivec(va->bbmin).sub(1), ivec(va->bbmax).sub(va->bbmin).add(2)); else drawbb(va->geommin, ivec(va->geommax).sub(va->geommin)); - endquery(query); } -enum -{ +enum { RENDERPASS_LIGHTMAP = 0, RENDERPASS_Z, RENDERPASS_LIGHTMAP_BLEND }; -struct geombatch -{ +struct geombatch { const elementset &es; VSlot &vslot; ushort *edata; vtxarray *va; int next, batch; - geombatch(const elementset &es, ushort *edata, vtxarray *va) : es(es), vslot(lookupvslot(es.texture)), edata(edata), va(va), - next(-1), batch(-1) - {} - - int compare(const geombatch &b) const - { + next(-1), batch(-1) { + } + int compare(const geombatch &b) const { if(va->vbuf < b.va->vbuf) return -1; if(va->vbuf > b.va->vbuf) return 1; if(va->dynlightmask < b.va->dynlightmask) return -1; @@ -743,73 +599,59 @@ struct geombatch static vector geombatches; static int firstbatch = -1, numbatches = 0; -static void mergetexs(renderstate &cur, vtxarray *va, elementset *texs = NULL, int numtexs = 0, ushort *edata = NULL) -{ - if(!texs) - { +static void mergetexs(renderstate &cur, vtxarray *va, elementset *texs = NULL, int numtexs = 0, ushort *edata = NULL) { + if(!texs) { texs = va->eslist; numtexs = va->texs; edata = va->edata; - if(cur.alphaing) - { + if(cur.alphaing) { texs += va->texs + va->blends; edata += 3*(va->tris + va->blendtris); numtexs = va->alphaback; if(cur.alphaing > 1) numtexs += va->alphafront; } } - - if(firstbatch < 0) - { + if(firstbatch < 0) { firstbatch = geombatches.length(); numbatches = numtexs; - loopi(numtexs-1) - { + loopi(numtexs-1) { geombatches.add(geombatch(texs[i], edata, va)).next = i+1; edata += texs[i].length[1]; } geombatches.add(geombatch(texs[numtexs-1], edata, va)); return; } - int prevbatch = -1, curbatch = firstbatch, curtex = 0; - do - { + do { geombatch &b = geombatches.add(geombatch(texs[curtex], edata, va)); edata += texs[curtex].length[1]; int dir = -1; - while(curbatch >= 0) - { + while(curbatch >= 0) { dir = b.compare(geombatches[curbatch]); if(dir <= 0) break; prevbatch = curbatch; curbatch = geombatches[curbatch].next; } - if(!dir) - { + if(!dir) { int last = curbatch, next; - for(;;) - { + for(;;) { next = geombatches[last].batch; if(next < 0) break; last = next; } - if(last==curbatch) - { + if(last==curbatch) { b.batch = curbatch; b.next = geombatches[curbatch].next; if(prevbatch < 0) firstbatch = geombatches.length()-1; else geombatches[prevbatch].next = geombatches.length()-1; curbatch = geombatches.length()-1; } - else - { + else { b.batch = next; geombatches[last].batch = geombatches.length()-1; } } - else - { + else { numbatches++; b.next = curbatch; if(prevbatch < 0) firstbatch = geombatches.length()-1; @@ -820,11 +662,9 @@ static void mergetexs(renderstate &cur, vtxarray *va, elementset *texs = NULL, i while(++curtex < numtexs); } -static inline void enablevattribs(renderstate &cur, bool all = true) -{ +static inline void enablevattribs(renderstate &cur, bool all = true) { gle::enablevertex(); - if(all) - { + if(all) { gle::enabletexcoord0(); gle::enabletexcoord1(); gle::enablenormal(); @@ -833,11 +673,9 @@ static inline void enablevattribs(renderstate &cur, bool all = true) cur.vattribs = true; } -static inline void disablevattribs(renderstate &cur, bool all = true) -{ +static inline void disablevattribs(renderstate &cur, bool all = true) { gle::disablevertex(); - if(all) - { + if(all) { gle::disabletexcoord0(); gle::disabletexcoord1(); gle::disablenormal(); @@ -846,17 +684,13 @@ static inline void disablevattribs(renderstate &cur, bool all = true) cur.vattribs = false; } -static void changevbuf(renderstate &cur, int pass, vtxarray *va) -{ +static void changevbuf(renderstate &cur, int pass, vtxarray *va) { gle::bindvbo(va->vbuf); gle::bindebo(va->ebuf); cur.vbuf = va->vbuf; - vertex *vdata = (vertex *)0; gle::vertexpointer(sizeof(vertex), vdata->pos.v); - - if(pass==RENDERPASS_LIGHTMAP) - { + if(pass==RENDERPASS_LIGHTMAP) { gle::normalpointer(sizeof(vertex), vdata->norm.v, GL_BYTE); gle::texcoord0pointer(sizeof(vertex), vdata->tc.v); gle::texcoord1pointer(sizeof(vertex), vdata->lm.v, GL_SHORT); @@ -864,86 +698,68 @@ static void changevbuf(renderstate &cur, int pass, vtxarray *va) } } -static void changebatchtmus(renderstate &cur, int pass, geombatch &b) -{ +static void changebatchtmus(renderstate &cur, int pass, geombatch &b) { bool changed = false; extern bool brightengeom; extern int fullbright; int lmid = brightengeom && (b.es.lmid < LMID_RESERVED || (fullbright && editmode)) ? (int) LMID_BRIGHT : (int) b.es.lmid; - if(cur.textures[1]!=lightmaptexs[lmid].id) - { + if(cur.textures[1]!=lightmaptexs[lmid].id) { glActiveTexture_(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, cur.textures[1] = lightmaptexs[lmid].id); changed = true; } int tmu = 2; - if(b.vslot.slot->shader->type&SHADER_NORMALSLMS) - { - if(cur.textures[tmu]!=lightmaptexs[lmid+1].id) - { + if(b.vslot.slot->shader->type&SHADER_NORMALSLMS) { + if(cur.textures[tmu]!=lightmaptexs[lmid+1].id) { glActiveTexture_(GL_TEXTURE0+tmu); glBindTexture(GL_TEXTURE_2D, cur.textures[tmu] = lightmaptexs[lmid+1].id); changed = true; } tmu++; } - if(changed) glActiveTexture_(GL_TEXTURE0); - - if(cur.dynlightmask != b.va->dynlightmask) - { + if(cur.dynlightmask != b.va->dynlightmask) { cur.visibledynlights = setdynlights(b.va); cur.dynlightmask = b.va->dynlightmask; } } -static void changeslottmus(renderstate &cur, int pass, Slot &slot, VSlot &vslot) -{ - if(pass==RENDERPASS_LIGHTMAP) - { +static void changeslottmus(renderstate &cur, int pass, Slot &slot, VSlot &vslot) { + if(pass==RENDERPASS_LIGHTMAP) { GLuint diffusetex = slot.sts.empty() ? notexture->id : slot.sts[0].t->id; if(cur.textures[0]!=diffusetex) glBindTexture(GL_TEXTURE_2D, cur.textures[0] = diffusetex); } - - if(cur.alphaing) - { + if(cur.alphaing) { float alpha = cur.alphaing > 1 ? vslot.alphafront : vslot.alphaback; - if(cur.colorscale != vslot.colorscale || cur.alphascale != alpha) - { + if(cur.colorscale != vslot.colorscale || cur.alphascale != alpha) { cur.colorscale = vslot.colorscale; cur.alphascale = alpha; GLOBALPARAMF(colorparams, 2*alpha*vslot.colorscale.x, 2*alpha*vslot.colorscale.y, 2*alpha*vslot.colorscale.z, alpha); } } - else if(cur.colorscale != vslot.colorscale) - { + else if(cur.colorscale != vslot.colorscale) { cur.colorscale = vslot.colorscale; GLOBALPARAMF(colorparams, 2*vslot.colorscale.x, 2*vslot.colorscale.y, 2*vslot.colorscale.z, 1); } int tmu = 2; if(slot.shader->type&SHADER_NORMALSLMS) tmu++; - loopvj(slot.sts) - { + loopvj(slot.sts) { Slot::Tex &t = slot.sts[j]; if(t.type==TEX_DIFFUSE || t.combined>=0) continue; - if(cur.textures[tmu]!=t.t->id) - { + if(cur.textures[tmu]!=t.t->id) { glActiveTexture_(GL_TEXTURE0+tmu); glBindTexture(GL_TEXTURE_2D, cur.textures[tmu] = t.t->id); } if(++tmu >= 8) break; } glActiveTexture_(GL_TEXTURE0); - cur.slot = &slot; cur.vslot = &vslot; } -static void changeshader(renderstate &cur, Shader *s, Slot &slot, VSlot &vslot, bool shadowed) -{ - if(!cur.blending && !cur.alphaing) - { +static void changeshader(renderstate &cur, Shader *s, Slot &slot, VSlot &vslot, bool shadowed) { + if(!cur.blending && !cur.alphaing) { if(shadowed) s->setvariant(cur.visibledynlights, 3, slot, vslot); else s->setvariant(cur.visibledynlights, 2, slot, vslot); } @@ -952,17 +768,14 @@ static void changeshader(renderstate &cur, Shader *s, Slot &slot, VSlot &vslot, else s->setvariant(cur.visibledynlights-1, 0, slot, vslot); } -static void changetexgen(renderstate &cur, int dim, Slot &slot, VSlot &vslot) -{ - if(cur.texgenslot != &slot || cur.texgenvslot != &vslot) - { +static void changetexgen(renderstate &cur, int dim, Slot &slot, VSlot &vslot) { + if(cur.texgenslot != &slot || cur.texgenvslot != &vslot) { Texture *curtex = !cur.texgenslot || cur.texgenslot->sts.empty() ? notexture : cur.texgenslot->sts[0].t, *tex = slot.sts.empty() ? notexture : slot.sts[0].t; if(!cur.texgenvslot || slot.sts.empty() || (curtex->xs != tex->xs || curtex->ys != tex->ys || cur.texgenvslot->rotation != vslot.rotation || cur.texgenvslot->scale != vslot.scale || - cur.texgenvslot->offset != vslot.offset || cur.texgenvslot->scroll != vslot.scroll)) - { + cur.texgenvslot->offset != vslot.offset || cur.texgenvslot->scroll != vslot.scroll)) { const texrotation &r = texrotations[vslot.rotation]; float xs = r.flipx ? -tex->xs : tex->xs, ys = r.flipy ? -tex->ys : tex->ys; @@ -970,8 +783,7 @@ static void changetexgen(renderstate &cur, int dim, Slot &slot, VSlot &vslot) if(r.swapxy) swap(scroll.x, scroll.y); scroll.x *= lastmillis*tex->xs/xs; scroll.y *= lastmillis*tex->ys/ys; - if(cur.texgenscroll != scroll) - { + if(cur.texgenscroll != scroll) { cur.texgenscroll = scroll; cur.texgendim = -1; } @@ -979,23 +791,18 @@ static void changetexgen(renderstate &cur, int dim, Slot &slot, VSlot &vslot) cur.texgenslot = &slot; cur.texgenvslot = &vslot; } - if(cur.texgendim == dim) return; GLOBALPARAM(texgenscroll, cur.texgenscroll); cur.texgendim = dim; } -static void renderbatch(renderstate &cur, int pass, geombatch &b) -{ +static void renderbatch(renderstate &cur, int pass, geombatch &b) { geombatch *shadowed = NULL; int rendered = -1; - for(geombatch *curbatch = &b;; curbatch = &geombatches[curbatch->batch]) - { + for(geombatch *curbatch = &b;; curbatch = &geombatches[curbatch->batch]) { ushort len = curbatch->es.length[curbatch->va->shadowed ? 0 : 1]; - if(len) - { - if(rendered < 0) - { + if(len) { + if(rendered < 0) { changeshader(cur, b.vslot.slot->shader, *b.vslot.slot, b.vslot, false); rendered = 0; gbatches++; @@ -1008,12 +815,9 @@ static void renderbatch(renderstate &cur, int pass, geombatch &b) if(curbatch->es.length[1] > len && !shadowed) shadowed = curbatch; if(curbatch->batch < 0) break; } - if(shadowed) for(geombatch *curbatch = shadowed;; curbatch = &geombatches[curbatch->batch]) - { - if(curbatch->va->shadowed && curbatch->es.length[1] > curbatch->es.length[0]) - { - if(rendered < 1) - { + if(shadowed) for(geombatch *curbatch = shadowed;; curbatch = &geombatches[curbatch->batch]) { + if(curbatch->va->shadowed && curbatch->es.length[1] > curbatch->es.length[0]) { + if(rendered < 1) { changeshader(cur, b.vslot.slot->shader, *b.vslot.slot, b.vslot, true); rendered = 1; gbatches++; @@ -1026,56 +830,44 @@ static void renderbatch(renderstate &cur, int pass, geombatch &b) } } -static void resetbatches() -{ +static void resetbatches() { geombatches.setsize(0); firstbatch = -1; numbatches = 0; } -static void renderbatches(renderstate &cur, int pass) -{ +static void renderbatches(renderstate &cur, int pass) { cur.slot = NULL; cur.vslot = NULL; int curbatch = firstbatch; - if(curbatch >= 0) - { - if(cur.alphaing) - { + if(curbatch >= 0) { + if(cur.alphaing) { if(cur.depthmask) { cur.depthmask = false; glDepthMask(GL_FALSE); } } else if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); } if(!cur.colormask) { cur.colormask = true; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, cur.alphaing ? GL_FALSE : GL_TRUE); } - if(!cur.vattribs) - { + if(!cur.vattribs) { if(cur.vquery) disablevquery(cur); enablevattribs(cur); } } - while(curbatch >= 0) - { + while(curbatch >= 0) { geombatch &b = geombatches[curbatch]; curbatch = b.next; - if(cur.vbuf != b.va->vbuf) changevbuf(cur, pass, b.va); - if(cur.vslot != &b.vslot) - { + if(cur.vslot != &b.vslot) { changeslottmus(cur, pass, *b.vslot.slot, b.vslot); if(cur.texgendim != b.es.dim || (cur.texgendim <= 2 && cur.texgenvslot != &b.vslot)) changetexgen(cur, b.es.dim, *b.vslot.slot, b.vslot); } else if(cur.texgendim != b.es.dim) changetexgen(cur, b.es.dim, *b.vslot.slot, b.vslot); if(pass == RENDERPASS_LIGHTMAP) changebatchtmus(cur, pass, b); - renderbatch(cur, pass, b); } - resetbatches(); } -void renderzpass(renderstate &cur, vtxarray *va) -{ - if(!cur.vattribs) - { +void renderzpass(renderstate &cur, vtxarray *va) { + if(!cur.vattribs) { if(cur.vquery) disablevquery(cur); enablevattribs(cur, false); } @@ -1084,8 +876,7 @@ void renderzpass(renderstate &cur, vtxarray *va) if(cur.colormask) { cur.colormask = false; glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); } int firsttex = 0, numtris = va->tris; ushort *edata = va->edata; - if(cur.alphaing) - { + if(cur.alphaing) { firsttex += va->texs + va->blends; edata += 3*(va->tris + va->blendtris); numtris = va->alphatris; @@ -1098,8 +889,8 @@ void renderzpass(renderstate &cur, vtxarray *va) #define startvaquery(va, flush) \ do { \ - if(va->query) \ - { \ + if(va->query) { \ + \ flush; \ startquery(va->query); \ } \ @@ -1108,8 +899,8 @@ void renderzpass(renderstate &cur, vtxarray *va) #define endvaquery(va, flush) \ do { \ - if(va->query) \ - { \ + if(va->query) { \ + \ flush; \ endquery(va->query); \ } \ @@ -1117,16 +908,13 @@ void renderzpass(renderstate &cur, vtxarray *va) VAR(batchgeom, 0, 1, 1); -void renderva(renderstate &cur, vtxarray *va, int pass = RENDERPASS_LIGHTMAP, bool doquery = false) -{ - switch(pass) - { +void renderva(renderstate &cur, vtxarray *va, int pass = RENDERPASS_LIGHTMAP, bool doquery = false) { + switch(pass) { case RENDERPASS_LIGHTMAP: if(!cur.alphaing) vverts += va->verts; va->shadowed = false; va->dynlightmask = 0; - if(!drawtex && !cur.alphaing) - { + if(!drawtex && !cur.alphaing) { va->shadowed = isshadowmapreceiver(va); calcdynlightmask(va); } @@ -1135,16 +923,13 @@ void renderva(renderstate &cur, vtxarray *va, int pass = RENDERPASS_LIGHTMAP, bo if(doquery) endvaquery(va, { if(geombatches.length()) renderbatches(cur, pass); }); else if(!batchgeom && geombatches.length()) renderbatches(cur, pass); break; - - case RENDERPASS_LIGHTMAP_BLEND: - { + case RENDERPASS_LIGHTMAP_BLEND: { if(doquery) startvaquery(va, { if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); }); mergetexs(cur, va, &va->eslist[va->texs], va->blends, va->edata + 3*va->tris); if(doquery) endvaquery(va, { if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); }); else if(!batchgeom && geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); break; } - case RENDERPASS_Z: if(doquery) startvaquery(va, ); renderzpass(cur, va); @@ -1153,62 +938,49 @@ void renderva(renderstate &cur, vtxarray *va, int pass = RENDERPASS_LIGHTMAP, bo } } -void cleanupva() -{ +void cleanupva() { clearvas(worldroot); clearqueries(); cleanupbb(); } -void setupgeom(renderstate &cur) -{ +void setupgeom(renderstate &cur) { GLOBALPARAMF(colorparams, 2, 2, 2, 1); GLOBALPARAM(camera, camera1->o); GLOBALPARAMF(ambient, ambientcolor.x/255.0f, ambientcolor.y/255.0f, ambientcolor.z/255.0f); GLOBALPARAMF(millis, lastmillis/1000.0f); - glActiveTexture_(GL_TEXTURE0); } -void cleanupgeom(renderstate &cur) -{ +void cleanupgeom(renderstate &cur) { if(cur.vattribs) disablevattribs(cur); if(cur.vbuf) disablevbuf(cur); } VAR(oqgeom, 0, 1, 1); -void rendergeom(void) -{ +void rendergeom(void) { bool mainpass = !drawtex, doOQ = oqfrags && oqgeom && mainpass, doZP = doOQ && zpass, doSM = shadowmap && !drawtex; renderstate cur; - if(mainpass) - { + if(mainpass) { flipqueries(); vtris = vverts = 0; } - if(!doZP) - { + if(!doZP) { if(shadowmap && mainpass) rendershadowmap(); setupgeom(cur); if(doSM) pushshadowmap(); } - finddynlights(); - resetbatches(); - int blends = 0; - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(!va->texs) continue; - if(doOQ && (zpass || va->distance > oqdist) && !insideva(va, camera1->o)) - { - if(va->parent && va->parent->occluded >= OCCLUDE_BB) - { + if(doOQ && (zpass || va->distance > oqdist) && !insideva(va, camera1->o)) { + if(va->parent && va->parent->occluded >= OCCLUDE_BB) { va->query = NULL; va->occluded = OCCLUDE_PARENT; continue; @@ -1217,10 +989,8 @@ void rendergeom(void) va->query = newquery(va); if((!va->query && zpass) || !va->occluded) va->occluded = OCCLUDE_NOTHING; - if(va->occluded >= OCCLUDE_GEOM) - { - if(va->query) - { + if(va->occluded >= OCCLUDE_GEOM) { + if(va->query) { if(!zpass && geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); if(cur.vattribs) disablevattribs(cur, !doZP); if(cur.vbuf) disablevbuf(cur); @@ -1229,117 +999,85 @@ void rendergeom(void) continue; } } - else - { + else { va->query = NULL; va->occluded = OCCLUDE_NOTHING; } - if(!doZP) blends += va->blends; renderva(cur, va, doZP ? RENDERPASS_Z : RENDERPASS_LIGHTMAP, doOQ); } - if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); - if(cur.vquery) disablevquery(cur); if(cur.vattribs) disablevattribs(cur, !doZP); if(cur.vbuf) disablevbuf(cur); - if(!cur.colormask) { cur.colormask = true; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); } - bool multipassing = false; - - if(doZP) - { + if(doZP) { glFlush(); - if(shadowmap && mainpass) rendershadowmap(); setupgeom(cur); if(doSM) pushshadowmap(); - if(!multipassing) { multipassing = true; glDepthFunc(GL_LEQUAL); } cur.texgendim = -1; - - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(!va->texs || va->occluded >= OCCLUDE_GEOM) continue; blends += va->blends; renderva(cur, va, RENDERPASS_LIGHTMAP); } if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(!va->texs || va->occluded < OCCLUDE_GEOM) continue; else if((va->parent && va->parent->occluded >= OCCLUDE_BB) || - (va->query && checkquery(va->query))) - { + (va->query && checkquery(va->query))) { va->occluded = OCCLUDE_BB; continue; } - blends += va->blends; renderva(cur, va, RENDERPASS_LIGHTMAP); } if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); } - - if(blends) - { + if(blends) { if(cur.vbuf) disablevbuf(cur); - if(!multipassing) { multipassing = true; glDepthFunc(GL_LEQUAL); } glDepthMask(GL_FALSE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); - cur.texgendim = -1; cur.blending = true; - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(!va->blends) continue; if(va->occluded >= OCCLUDE_GEOM) continue; renderva(cur, va, RENDERPASS_LIGHTMAP_BLEND); } if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); cur.blending = false; - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDisable(GL_BLEND); glDepthMask(GL_TRUE); } - - if(doSM) popshadowmap(); - if(cur.vattribs) disablevattribs(cur); - if(multipassing) glDepthFunc(GL_LESS); - cleanupgeom(cur); } -void renderalphageom(void) -{ +void renderalphageom(void) { static vector alphavas; alphavas.setsize(0); bool hasback = false; - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(!va->alphatris) continue; if(va->occluded >= OCCLUDE_BB) continue; alphavas.add(va); if(va->alphabacktris) hasback = true; } if(alphavas.empty()) return; - resetbatches(); - renderstate cur; cur.alphaing = 1; - - loop(front, 2) if(front || hasback) - { + loop(front, 2) if(front || hasback) { cur.alphaing = front+1; if(!front) glCullFace(GL_FRONT); cur.vbuf = 0; @@ -1348,12 +1086,9 @@ void renderalphageom(void) if(cur.depthmask) { cur.depthmask = false; glDepthMask(GL_FALSE); } cur.colormask = true; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); - if(cur.vattribs) disablevattribs(cur, false); if(cur.vbuf) disablevbuf(cur); - setupgeom(cur); - glDepthFunc(GL_LEQUAL); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); @@ -1363,14 +1098,11 @@ void renderalphageom(void) cur.alphascale = -1; loopv(alphavas) if(front || alphavas[i]->alphabacktris) renderva(cur, alphavas[i], RENDERPASS_LIGHTMAP); if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); - cleanupgeom(cur); - if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); } glDisable(GL_BLEND); glDepthFunc(GL_LESS); if(!front) glCullFace(GL_BACK); } - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } diff --git a/src/engine/server.cpp b/src/engine/server.cpp index 7e338b3..29761e1 100644 --- a/src/engine/server.cpp +++ b/src/engine/server.cpp @@ -7,25 +7,20 @@ static FILE *logfile = NULL; -void closelogfile() -{ - if(logfile) - { +void closelogfile() { + if(logfile) { fclose(logfile); logfile = NULL; } } -FILE *getlogfile() -{ +FILE *getlogfile() { return logfile ? logfile : stdout; } -void setlogfile(const char *fname) -{ +void setlogfile(const char *fname) { closelogfile(); - if(fname && fname[0]) - { + if(fname && fname[0]) { fname = findfile(fname, "w"); if(fname) logfile = fopen(fname, "w"); } @@ -33,8 +28,7 @@ void setlogfile(const char *fname) if(f) setvbuf(f, NULL, _IOLBF, BUFSIZ); } -void logoutf(const char *fmt, ...) -{ +void logoutf(const char *fmt, ...) { va_list args; va_start(args, fmt); logoutfv(fmt, args); @@ -42,28 +36,24 @@ void logoutf(const char *fmt, ...) } -static void writelog(FILE *file, const char *buf) -{ +static void writelog(FILE *file, const char *buf) { static uchar ubuf[512]; size_t len = strlen(buf), carry = 0; - while(carry < len) - { + while(carry < len) { size_t numu = encodeutf8(ubuf, sizeof(ubuf)-1, &((const uchar *)buf)[carry], len - carry, &carry); if(carry >= len) ubuf[numu++] = '\n'; fwrite(ubuf, 1, numu, file); } } -static void writelogv(FILE *file, const char *fmt, va_list args) -{ +static void writelogv(FILE *file, const char *fmt, va_list args) { static char buf[LOGSTRLEN]; vformatstring(buf, fmt, args, sizeof(buf)); writelog(file, buf); } #ifdef STANDALONE -void fatal(const char *fmt, ...) -{ +void fatal(const char *fmt, ...) { void cleanupserver(); cleanupserver(); defvformatstring(msg,fmt,fmt); @@ -73,8 +63,7 @@ void fatal(const char *fmt, ...) exit(EXIT_FAILURE); } -void conoutfv(int type, const char *fmt, va_list args) -{ +void conoutfv(int type, const char *fmt, va_list args) { logoutfv(fmt, args); } #endif @@ -83,8 +72,7 @@ void conoutfv(int type, const char *fmt, va_list args) enum { ST_EMPTY, ST_LOCAL, ST_TCPIP }; -struct client // server side version of "dynent" type -{ +struct client { // server side version of "dynent" type { int type; int num; ENetPeer *peer; @@ -103,53 +91,44 @@ int localclients = 0, nonlocalclients = 0; bool hasnonlocalclients() { return nonlocalclients!=0; } bool haslocalclients() { return localclients!=0; } -client &addclient(int type) -{ +client &addclient(int type) { client *c = NULL; - loopv(clients) if(clients[i]->type==ST_EMPTY) - { + loopv(clients) if(clients[i]->type==ST_EMPTY) { c = clients[i]; break; } - if(!c) - { + if(!c) { c = new client; c->num = clients.length(); clients.add(c); } c->info = server::newclientinfo(); c->type = type; - switch(type) - { + switch(type) { case ST_TCPIP: nonlocalclients++; break; case ST_LOCAL: localclients++; break; } return *c; } -void delclient(client *c) -{ +void delclient(client *c) { if(!c) return; - switch(c->type) - { + switch(c->type) { case ST_TCPIP: nonlocalclients--; if(c->peer) c->peer->data = NULL; break; case ST_LOCAL: localclients--; break; case ST_EMPTY: return; } c->type = ST_EMPTY; c->peer = NULL; - if(c->info) - { + if(c->info) { server::deleteclientinfo(c->info); c->info = NULL; } } -void cleanupserver() -{ +void cleanupserver() { if(serverhost) enet_host_destroy(serverhost); serverhost = NULL; - if(pongsock != ENET_SOCKET_NULL) enet_socket_destroy(pongsock); if(lansock != ENET_SOCKET_NULL) enet_socket_destroy(lansock); pongsock = lansock = ENET_SOCKET_NULL; @@ -167,18 +146,14 @@ ENetPeer *getclientpeer(int i) { return clients.inrange(i) && clients[i]->type== int getnumclients() { return clients.length(); } uint getclientip(int n) { return clients.inrange(n) && clients[n]->type==ST_TCPIP ? clients[n]->peer->address.host : 0; } -void sendpacket(int n, int chan, ENetPacket *packet, int exclude) -{ - if(n<0) - { +void sendpacket(int n, int chan, ENetPacket *packet, int exclude) { + if(n<0) { server::recordpacket(chan, packet->data, packet->dataLength); loopv(clients) if(i!=exclude && server::allowbroadcast(i)) sendpacket(i, chan, packet); return; } - switch(clients[n]->type) - { - case ST_TCPIP: - { + switch(clients[n]->type) { + case ST_TCPIP: { enet_peer_send(clients[n]->peer, chan, packet); break; } @@ -191,43 +166,35 @@ void sendpacket(int n, int chan, ENetPacket *packet, int exclude) } } -ENetPacket *sendf(int cn, int chan, const char *format, ...) -{ +ENetPacket *sendf(int cn, int chan, const char *format, ...) { int exclude = -1; bool reliable = false; if(*format=='r') { reliable = true; ++format; } packetbuf p(MAXTRANS, reliable ? ENET_PACKET_FLAG_RELIABLE : 0); va_list args; va_start(args, format); - while(*format) switch(*format++) - { + while(*format) switch(*format++) { case 'x': exclude = va_arg(args, int); break; - - case 'v': - { + case 'v': { int n = va_arg(args, int); int *v = va_arg(args, int *); loopi(n) putint(p, v[i]); break; } - - case 'i': - { + case 'i': { int n = isdigit(*format) ? *format++-'0' : 1; loopi(n) putint(p, va_arg(args, int)); break; } - case 'f': - { + case 'f': { int n = isdigit(*format) ? *format++-'0' : 1; loopi(n) putfloat(p, (float)va_arg(args, double)); break; } case 's': sendstring(va_arg(args, const char *), p); break; - case 'm': - { + case 'm': { int n = va_arg(args, int); p.put(va_arg(args, uchar *), n); break; @@ -239,26 +206,20 @@ ENetPacket *sendf(int cn, int chan, const char *format, ...) return packet->referenceCount > 0 ? packet : NULL; } -ENetPacket *sendfile(int cn, int chan, stream *file, const char *format, ...) -{ - if(cn < 0) - { +ENetPacket *sendfile(int cn, int chan, stream *file, const char *format, ...) { + if(cn < 0) { #ifdef STANDALONE return NULL; #endif } else if(!clients.inrange(cn)) return NULL; - int len = (int)min(file->size(), stream::offset(INT_MAX)); if(len <= 0 || len > 16<<20) return NULL; - packetbuf p(MAXTRANS+len, ENET_PACKET_FLAG_RELIABLE); va_list args; va_start(args, format); - while(*format) switch(*format++) - { - case 'i': - { + while(*format) switch(*format++) { + case 'i': { int n = isdigit(*format) ? *format++-'0' : 1; loopi(n) putint(p, va_arg(args, int)); break; @@ -267,10 +228,8 @@ ENetPacket *sendfile(int cn, int chan, stream *file, const char *format, ...) case 'l': putint(p, len); break; } va_end(args); - file->seek(0, SEEK_SET); file->read(p.subbuf(len).buf, len); - ENetPacket *packet = p.finalize(); if(cn >= 0) sendpacket(cn, chan, packet, -1); #ifndef STANDALONE @@ -279,10 +238,8 @@ ENetPacket *sendfile(int cn, int chan, stream *file, const char *format, ...) return packet->referenceCount > 0 ? packet : NULL; } -const char *disconnectreason(int reason) -{ - switch(reason) - { +const char *disconnectreason(int reason) { + switch(reason) { case DISC_EOP: return "end of packet"; case DISC_LOCAL: return "server is in local mode"; case DISC_KICK: return "kicked/banned"; @@ -297,8 +254,7 @@ const char *disconnectreason(int reason) } } -void disconnect_client(int n, int reason) -{ +void disconnect_client(int n, int reason) { if(!clients.inrange(n) || clients[n]->type!=ST_TCPIP) return; enet_peer_disconnect(clients[n]->peer, reason); server::clientdisconnect(n); @@ -311,33 +267,28 @@ void disconnect_client(int n, int reason) server::sendservmsg(s); } -void kicknonlocalclients(int reason) -{ +void kicknonlocalclients(int reason) { loopv(clients) if(clients[i]->type==ST_TCPIP) disconnect_client(i, reason); } -void process(ENetPacket *packet, int sender, int chan) // sender may be -1 -{ +void process(ENetPacket *packet, int sender, int chan) { // sender may be -1 { packetbuf p(packet); server::parsepacket(sender, chan, p); if(p.overread()) { disconnect_client(sender, DISC_EOP); return; } } -void localclienttoserver(int chan, ENetPacket *packet) -{ +void localclienttoserver(int chan, ENetPacket *packet) { client *c = NULL; loopv(clients) if(clients[i]->type==ST_LOCAL) { c = clients[i]; break; } if(c) process(packet, c->num, chan); } #ifdef STANDALONE -bool resolverwait(const char *name, ENetAddress *address) -{ +bool resolverwait(const char *name, ENetAddress *address) { return enet_address_set_host(address, name) >= 0; } -int connectwithtimeout(ENetSocket sock, const char *hostname, const ENetAddress &remoteaddress) -{ +int connectwithtimeout(ENetSocket sock, const char *hostname, const ENetAddress &remoteaddress) { return enet_socket_connect(sock, &remoteaddress); } #endif @@ -349,48 +300,38 @@ vector masterout, masterin; int masteroutpos = 0, masterinpos = 0; VARN(updatemaster, allowupdatemaster, 0, 1, 1); -void disconnectmaster() -{ - if(mastersock != ENET_SOCKET_NULL) - { +void disconnectmaster() { + if(mastersock != ENET_SOCKET_NULL) { server::masterdisconnected(); enet_socket_destroy(mastersock); mastersock = ENET_SOCKET_NULL; } - masterout.setsize(0); masterin.setsize(0); masteroutpos = masterinpos = 0; - masteraddress.host = ENET_HOST_ANY; masteraddress.port = ENET_PORT_ANY; - lastupdatemaster = masterconnecting = masterconnected = 0; } SVARF(mastername, server::defaultmaster(), disconnectmaster()); VARF(masterport, 1, server::masterport(), 0xFFFF, disconnectmaster()); -ENetSocket connectmaster(bool wait) -{ +ENetSocket connectmaster(bool wait) { if(!mastername[0]) return ENET_SOCKET_NULL; - if(masteraddress.host == ENET_HOST_ANY) - { + if(masteraddress.host == ENET_HOST_ANY) { if(isdedicatedserver()) logoutf("looking up %s...", mastername); masteraddress.port = masterport; if(!resolverwait(mastername, &masteraddress)) return ENET_SOCKET_NULL; } ENetSocket sock = enet_socket_create(ENET_SOCKET_TYPE_STREAM); - if(sock == ENET_SOCKET_NULL) - { + if(sock == ENET_SOCKET_NULL) { if(isdedicatedserver()) logoutf("could not open master server socket"); return ENET_SOCKET_NULL; } - if(wait || serveraddress.host == ENET_HOST_ANY || !enet_socket_bind(sock, &serveraddress)) - { + if(wait || serveraddress.host == ENET_HOST_ANY || !enet_socket_bind(sock, &serveraddress)) { enet_socket_set_option(sock, ENET_SOCKOPT_NONBLOCK, 1); - if(wait) - { + if(wait) { if(!connectwithtimeout(sock, mastername, masteraddress)) return sock; } else if(!enet_socket_connect(sock, &masteraddress)) return sock; @@ -400,78 +341,60 @@ ENetSocket connectmaster(bool wait) return ENET_SOCKET_NULL; } -bool requestmaster(const char *req) -{ - if(mastersock == ENET_SOCKET_NULL) - { +bool requestmaster(const char *req) { + if(mastersock == ENET_SOCKET_NULL) { mastersock = connectmaster(false); if(mastersock == ENET_SOCKET_NULL) return false; lastconnectmaster = masterconnecting = totalmillis ? totalmillis : 1; } - if(masterout.length() >= 4096) return false; - masterout.put(req, strlen(req)); return true; } -bool requestmasterf(const char *fmt, ...) -{ +bool requestmasterf(const char *fmt, ...) { defvformatstring(req, fmt, fmt); return requestmaster(req); } -void processmasterinput() -{ +void processmasterinput() { if(masterinpos >= masterin.length()) return; - char *input = &masterin[masterinpos], *end = (char *)memchr(input, '\n', masterin.length() - masterinpos); - while(end) - { + while(end) { *end = '\0'; - const char *args = input; while(args < end && !iscubespace(*args)) args++; int cmdlen = args - input; while(args < end && iscubespace(*args)) args++; - if(matchstring(input, cmdlen, "failreg")) conoutf(CON_ERROR, "master server registration failed: %s", args); else if(matchstring(input, cmdlen, "succreg")) conoutf("master server registration succeeded"); - else server::processmasterinput(input, cmdlen, args); - + else server::processmasterinput(input, cmdlen); end++; masterinpos = end - masterin.getbuf(); input = end; end = (char *)memchr(input, '\n', masterin.length() - masterinpos); } - - if(masterinpos >= masterin.length()) - { + if(masterinpos >= masterin.length()) { masterin.setsize(0); masterinpos = 0; } } -void flushmasteroutput() -{ - if(masterconnecting && totalmillis - masterconnecting >= 60000) - { +void flushmasteroutput() { + if(masterconnecting && totalmillis - masterconnecting >= 60000) { logoutf("could not connect to master server"); disconnectmaster(); } if(masterout.empty() || !masterconnected) return; - ENetBuffer buf; buf.data = &masterout[masteroutpos]; buf.dataLength = masterout.length() - masteroutpos; int sent = enet_socket_send(mastersock, NULL, &buf, 1); - if(sent >= 0) - { + if(sent >= 0) { masteroutpos += sent; - if(masteroutpos >= masterout.length()) - { + if(masteroutpos >= masterout.length()) { masterout.setsize(0); masteroutpos = 0; } @@ -479,17 +402,14 @@ void flushmasteroutput() else disconnectmaster(); } -void flushmasterinput() -{ +void flushmasterinput() { if(masterin.length() >= masterin.capacity()) masterin.reserve(4096); - ENetBuffer buf; buf.data = masterin.getbuf() + masterin.length(); buf.dataLength = masterin.capacity() - masterin.length(); int recv = enet_socket_receive(mastersock, NULL, &buf, 1); - if(recv > 0) - { + if(recv > 0) { masterin.advance(recv); processmasterinput(); } @@ -498,8 +418,7 @@ void flushmasterinput() static ENetAddress pongaddr; -void sendserverinforeply(ucharbuf &p) -{ +void sendserverinforeply(ucharbuf &p) { ENetBuffer buf; buf.data = p.buf; buf.dataLength = p.length(); @@ -508,33 +427,27 @@ void sendserverinforeply(ucharbuf &p) #define MAXPINGDATA 32 -void checkserversockets() // reply all server info requests -{ +void checkserversockets() { // reply all server info requests { static ENetSocketSet readset, writeset; ENET_SOCKETSET_EMPTY(readset); ENET_SOCKETSET_EMPTY(writeset); ENetSocket maxsock = pongsock; ENET_SOCKETSET_ADD(readset, pongsock); - if(mastersock != ENET_SOCKET_NULL) - { + if(mastersock != ENET_SOCKET_NULL) { maxsock = max(maxsock, mastersock); ENET_SOCKETSET_ADD(readset, mastersock); if(!masterconnected) ENET_SOCKETSET_ADD(writeset, mastersock); } - if(lansock != ENET_SOCKET_NULL) - { + if(lansock != ENET_SOCKET_NULL) { maxsock = max(maxsock, lansock); ENET_SOCKETSET_ADD(readset, lansock); } if(enet_socketset_select(maxsock, &readset, &writeset, 0) <= 0) return; - ENetBuffer buf; uchar pong[MAXTRANS]; - loopi(2) - { + loopi(2) { ENetSocket sock = i ? lansock : pongsock; if(sock == ENET_SOCKET_NULL || !ENET_SOCKETSET_CHECK(readset, sock)) continue; - buf.data = pong; buf.dataLength = sizeof(pong); int len = enet_socket_receive(sock, &pongaddr, &buf, 1); @@ -543,21 +456,15 @@ void checkserversockets() // reply all server info requests p.len += len; server::serverinforeply(req, p); } - - if(mastersock != ENET_SOCKET_NULL) - { - if(!masterconnected) - { - if(ENET_SOCKETSET_CHECK(readset, mastersock) || ENET_SOCKETSET_CHECK(writeset, mastersock)) - { + if(mastersock != ENET_SOCKET_NULL) { + if(!masterconnected) { + if(ENET_SOCKETSET_CHECK(readset, mastersock) || ENET_SOCKETSET_CHECK(writeset, mastersock)) { int error = 0; - if(enet_socket_get_option(mastersock, ENET_SOCKOPT_ERROR, &error) < 0 || error) - { + if(enet_socket_get_option(mastersock, ENET_SOCKOPT_ERROR, &error) < 0 || error) { logoutf("could not connect to master server"); disconnectmaster(); } - else - { + else { masterconnecting = 0; masterconnected = totalmillis ? totalmillis : 1; server::masterconnected(); @@ -576,8 +483,7 @@ VARF(serverport, 0, server::serverport(), 0xFFFF-1, { if(!serverport) serverport int curtime = 0, lastmillis = 0, elapsedtime = 0, totalmillis = 0; #endif -void updatemasterserver() -{ +void updatemasterserver() { if(!masterconnected && lastconnectmaster && totalmillis-lastconnectmaster <= 5*60*1000) return; if(mastername[0] && allowupdatemaster) requestmasterf("regserv %d\n", serverport); lastupdatemaster = totalmillis ? totalmillis : 1; @@ -585,30 +491,23 @@ void updatemasterserver() uint totalsecs = 0; -void updatetime() -{ +void updatetime() { static int lastsec = 0; - if(totalmillis - lastsec >= 1000) - { + if(totalmillis - lastsec >= 1000) { int cursecs = (totalmillis - lastsec) / 1000; totalsecs += cursecs; lastsec += cursecs * 1000; } } -void serverslice(bool dedicated, uint timeout) // main server update, called from main loop in sp, or from below in dedicated server -{ - if(!serverhost) - { +void serverslice(bool dedicated, uint timeout) { // main server update, called from main loop in sp, or from below in dedicated server { + if(!serverhost) { server::serverupdate(); server::sendpackets(); return; } - // below is network only - - if(dedicated) - { + if(dedicated) { int millis = (int)enet_time_get(); elapsedtime = millis - totalmillis; static int timeerr = 0; @@ -621,33 +520,24 @@ void serverslice(bool dedicated, uint timeout) // main server update, called f updatetime(); } server::serverupdate(); - flushmasteroutput(); checkserversockets(); - if(!lastupdatemaster || totalmillis-lastupdatemaster>60*60*1000) // send alive signal to masterserver every hour of uptime updatemasterserver(); - - if(totalmillis-laststatus>60*1000) // display bandwidth stats, useful for server ops - { + if(totalmillis-laststatus>60*1000) { // display bandwidth stats, useful for server ops { laststatus = totalmillis; if(nonlocalclients || serverhost->totalSentData || serverhost->totalReceivedData) logoutf("status: %d remote clients, %.1f send, %.1f rec (K/sec)", nonlocalclients, serverhost->totalSentData/60.0f/1024, serverhost->totalReceivedData/60.0f/1024); serverhost->totalSentData = serverhost->totalReceivedData = 0; } - ENetEvent event; bool serviced = false; - while(!serviced) - { - if(enet_host_check_events(serverhost, &event) <= 0) - { + while(!serviced) { + if(enet_host_check_events(serverhost, &event) <= 0) { if(enet_host_service(serverhost, &event, timeout) <= 0) break; serviced = true; } - switch(event.type) - { - case ENET_EVENT_TYPE_CONNECT: - { + switch(event.type) { + case ENET_EVENT_TYPE_CONNECT: { client &c = addclient(ST_TCPIP); c.peer = event.peer; c.peer->data = &c; @@ -658,15 +548,13 @@ void serverslice(bool dedicated, uint timeout) // main server update, called f if(reason) disconnect_client(c.num, reason); break; } - case ENET_EVENT_TYPE_RECEIVE: - { + case ENET_EVENT_TYPE_RECEIVE: { client *c = (client *)event.peer->data; if(c) process(event.packet, c->num, event.channelID); if(event.packet->referenceCount==0) enet_packet_destroy(event.packet); break; } - case ENET_EVENT_TYPE_DISCONNECT: - { + case ENET_EVENT_TYPE_DISCONNECT: { client *c = (client *)event.peer->data; if(!c) break; logoutf("disconnected client (%s)", c->hostname); @@ -681,17 +569,14 @@ void serverslice(bool dedicated, uint timeout) // main server update, called f if(server::sendpackets()) enet_host_flush(serverhost); } -void flushserver(bool force) -{ +void flushserver(bool force) { if(server::sendpackets(force) && serverhost) enet_host_flush(serverhost); } #ifndef STANDALONE -void localdisconnect(bool cleanup) -{ +void localdisconnect(bool cleanup) { bool disconnected = false; - loopv(clients) if(clients[i]->type==ST_LOCAL) - { + loopv(clients) if(clients[i]->type==ST_LOCAL) { server::localdisconnect(i); delclient(clients[i]); disconnected = true; @@ -701,8 +586,7 @@ void localdisconnect(bool cleanup) mainmenu = 1; } -void localconnect() -{ +void localconnect() { if(initing) return; client &c = addclient(ST_LOCAL); copystring(c.hostname, "local"); @@ -711,8 +595,7 @@ void localconnect() } #endif -void logoutfv(const char *fmt, va_list args) -{ +void logoutfv(const char *fmt, va_list args) { FILE *f = getlogfile(); if(f) writelogv(f, fmt, args); } @@ -721,19 +604,17 @@ static bool dedicatedserver = false; bool isdedicatedserver() { return dedicatedserver; } -void rundedicatedserver() -{ +void rundedicatedserver() { dedicatedserver = true; logoutf("dedicated server started, waiting for clients..."); for(;;) serverslice(true, 5); dedicatedserver = false; } -bool servererror(bool dedicated, const char *desc) -{ +bool servererror(bool dedicated, const char *desc) { + (void) dedicated; #ifndef STANDALONE - if(!dedicated) - { + if(!dedicated) { conoutf(CON_ERROR, "%s", desc); cleanupserver(); } @@ -743,11 +624,9 @@ bool servererror(bool dedicated, const char *desc) return false; } -bool setuplistenserver(bool dedicated) -{ +bool setuplistenserver(bool dedicated) { ENetAddress address = { ENET_HOST_ANY, enet_uint16(serverport <= 0 ? server::serverport() : serverport) }; - if(*serverip) - { + if(*serverip) { if(enet_address_set_host(&address, serverip)<0) conoutf(CON_WARN, "WARNING: server ip not resolved"); else serveraddress.host = address.host; } @@ -756,8 +635,7 @@ bool setuplistenserver(bool dedicated) serverhost->duplicatePeers = maxdupclients ? maxdupclients : MAXCLIENTS; address.port = server::serverinfoport(serverport > 0 ? serverport : -1); pongsock = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); - if(pongsock != ENET_SOCKET_NULL && enet_socket_bind(pongsock, &address) < 0) - { + if(pongsock != ENET_SOCKET_NULL && enet_socket_bind(pongsock, &address) < 0) { enet_socket_destroy(pongsock); pongsock = ENET_SOCKET_NULL; } @@ -765,8 +643,7 @@ bool setuplistenserver(bool dedicated) else enet_socket_set_option(pongsock, ENET_SOCKOPT_NONBLOCK, 1); address.port = server::laninfoport(); lansock = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); - if(lansock != ENET_SOCKET_NULL && (enet_socket_set_option(lansock, ENET_SOCKOPT_REUSEADDR, 1) < 0 || enet_socket_bind(lansock, &address) < 0)) - { + if(lansock != ENET_SOCKET_NULL && (enet_socket_set_option(lansock, ENET_SOCKOPT_REUSEADDR, 1) < 0 || enet_socket_bind(lansock, &address) < 0)) { enet_socket_destroy(lansock); lansock = ENET_SOCKET_NULL; } @@ -775,16 +652,11 @@ bool setuplistenserver(bool dedicated) return true; } -void initserver(bool listen, bool dedicated) -{ +void initserver(bool listen, bool dedicated) { execfile("server-init.cfg", false); - if(listen) setuplistenserver(dedicated); - server::serverinit(); - - if(listen) - { + if(listen) { dedicatedserver = dedicated; updatemasterserver(); if(dedicated) rundedicatedserver(); // never returns @@ -795,37 +667,27 @@ void initserver(bool listen, bool dedicated) } #ifndef STANDALONE -void startlistenserver(int *usemaster) -{ +void startlistenserver(int *usemaster) { if(serverhost) { conoutf(CON_ERROR, "listen server is already running"); return; } - allowupdatemaster = *usemaster>0 ? 1 : 0; - if(!setuplistenserver(false)) return; - updatemasterserver(); - conoutf("listen server started for %d clients%s", maxclients, allowupdatemaster ? " and listed with master server" : ""); } COMMAND(startlistenserver, "i"); -void stoplistenserver() -{ +void stoplistenserver() { if(!serverhost) { conoutf(CON_ERROR, "listen server is not running"); return; } - kicknonlocalclients(); enet_host_flush(serverhost); cleanupserver(); - conoutf("listen server stopped"); } COMMAND(stoplistenserver, ""); #endif -bool serveroption(char *opt) -{ - switch(opt[1]) - { +bool serveroption(char *opt) { + switch(opt[1]) { case 'u': setvar("serveruprate", atoi(opt+2)); return true; case 'c': setvar("maxclients", atoi(opt+2)); return true; case 'i': setsvar("serverip", opt+2); return true; @@ -843,8 +705,7 @@ bool serveroption(char *opt) vector gameargs; #ifdef STANDALONE -int main(int argc, char **argv) -{ +int main(int argc, char **argv) { setlogfile(NULL); if(enet_initialize()<0) fatal("Unable to initialise network module"); atexit(enet_deinitialize); diff --git a/src/engine/serverbrowser.cpp b/src/engine/serverbrowser.cpp index 85109bf..a839c35 100644 --- a/src/engine/serverbrowser.cpp +++ b/src/engine/serverbrowser.cpp @@ -4,15 +4,13 @@ #define PROTOCOL_VERSION 260 // bump when protocol changes, dpulicate -struct resolverthread -{ +struct resolverthread { SDL_Thread *thread; const char *query; int starttime; }; -struct resolverresult -{ +struct resolverresult { const char *query; ENetAddress address; }; @@ -26,28 +24,23 @@ SDL_cond *querycond, *resultcond; #define RESOLVERTHREADS 2 #define RESOLVERLIMIT 3000 -int resolverloop(void * data) -{ +int resolverloop(void * data) { resolverthread *rt = (resolverthread *)data; SDL_LockMutex(resolvermutex); SDL_Thread *thread = rt->thread; SDL_UnlockMutex(resolvermutex); if(!thread || SDL_GetThreadID(thread) != SDL_ThreadID()) return 0; - while(thread == rt->thread) - { + while(thread == rt->thread) { SDL_LockMutex(resolvermutex); while(resolverqueries.empty()) SDL_CondWait(querycond, resolvermutex); rt->query = resolverqueries.pop(); rt->starttime = totalmillis; SDL_UnlockMutex(resolvermutex); - ENetAddress address = { ENET_HOST_ANY, ENET_PORT_ANY }; enet_address_set_host(&address, rt->query); - SDL_LockMutex(resolvermutex); - if(rt->query && thread == rt->thread) - { + if(rt->query && thread == rt->thread) { resolverresult &rr = resolverresults.add(); rr.query = rt->query; rr.address = address; @@ -60,15 +53,12 @@ int resolverloop(void * data) return 0; } -void resolverinit() -{ +void resolverinit() { resolvermutex = SDL_CreateMutex(); querycond = SDL_CreateCond(); resultcond = SDL_CreateCond(); - SDL_LockMutex(resolvermutex); - loopi(RESOLVERTHREADS) - { + loopi(RESOLVERTHREADS) { resolverthread &rt = resolverthreads.add(); rt.query = NULL; rt.starttime = 0; @@ -77,11 +67,9 @@ void resolverinit() SDL_UnlockMutex(resolvermutex); } -void resolverstop(resolverthread &rt) -{ +void resolverstop(resolverthread &rt) { SDL_LockMutex(resolvermutex); - if(rt.query) - { + if(rt.query) { #if SDL_VERSION_ATLEAST(2, 0, 2) SDL_DetachThread(rt.thread); #endif @@ -92,47 +80,38 @@ void resolverstop(resolverthread &rt) SDL_UnlockMutex(resolvermutex); } -void resolverclear() -{ +void resolverclear() { if(resolverthreads.empty()) return; - SDL_LockMutex(resolvermutex); resolverqueries.shrink(0); resolverresults.shrink(0); - loopv(resolverthreads) - { + loopv(resolverthreads) { resolverthread &rt = resolverthreads[i]; resolverstop(rt); } SDL_UnlockMutex(resolvermutex); } -void resolverquery(const char *name) -{ +void resolverquery(const char *name) { if(resolverthreads.empty()) resolverinit(); - SDL_LockMutex(resolvermutex); resolverqueries.add(name); SDL_CondSignal(querycond); SDL_UnlockMutex(resolvermutex); } -bool resolvercheck(const char **name, ENetAddress *address) -{ +bool resolvercheck(const char **name, ENetAddress *address) { bool resolved = false; SDL_LockMutex(resolvermutex); - if(!resolverresults.empty()) - { + if(!resolverresults.empty()) { resolverresult &rr = resolverresults.pop(); *name = rr.query; address->host = rr.address.host; resolved = true; } - else loopv(resolverthreads) - { + else loopv(resolverthreads) { resolverthread &rt = resolverthreads[i]; - if(rt.query && totalmillis - rt.starttime > RESOLVERLIMIT) - { + if(rt.query && totalmillis - rt.starttime > RESOLVERLIMIT) { resolverstop(rt); *name = rt.query; resolved = true; @@ -142,39 +121,31 @@ bool resolvercheck(const char **name, ENetAddress *address) return resolved; } -bool resolverwait(const char *name, ENetAddress *address) -{ +bool resolverwait(const char *name, ENetAddress *address) { if(resolverthreads.empty()) resolverinit(); - defformatstring(text, "resolving %s... (esc to abort)", name); renderprogress(0, text); - SDL_LockMutex(resolvermutex); resolverqueries.add(name); SDL_CondSignal(querycond); int starttime = SDL_GetTicks(), timeout = 0; bool resolved = false; - for(;;) - { + for(;;) { SDL_CondWaitTimeout(resultcond, resolvermutex, 250); - loopv(resolverresults) if(resolverresults[i].query == name) - { + loopv(resolverresults) if(resolverresults[i].query == name) { address->host = resolverresults[i].address.host; resolverresults.remove(i); resolved = true; break; } if(resolved) break; - timeout = SDL_GetTicks() - starttime; renderprogress(min(float(timeout)/RESOLVERLIMIT, 1.0f), text); if(interceptkey(SDLK_ESCAPE)) timeout = RESOLVERLIMIT + 1; if(timeout > RESOLVERLIMIT) break; } - if(!resolved && timeout > RESOLVERLIMIT) - { - loopv(resolverthreads) - { + if(!resolved && timeout > RESOLVERLIMIT) { + loopv(resolverthreads) { resolverthread &rt = resolverthreads[i]; if(rt.query == name) { resolverstop(rt); break; } } @@ -185,24 +156,19 @@ bool resolverwait(const char *name, ENetAddress *address) #define CONNLIMIT 20000 -int connectwithtimeout(ENetSocket sock, const char *hostname, const ENetAddress &address) -{ +int connectwithtimeout(ENetSocket sock, const char *hostname, const ENetAddress &address) { defformatstring(text, "connecting to %s... (esc to abort)", hostname); renderprogress(0, text); - ENetSocketSet readset, writeset; - if(!enet_socket_connect(sock, &address)) for(int starttime = SDL_GetTicks(), timeout = 0; timeout <= CONNLIMIT;) - { + if(!enet_socket_connect(sock, &address)) for(int starttime = SDL_GetTicks(), timeout = 0; timeout <= CONNLIMIT;) { ENET_SOCKETSET_EMPTY(readset); ENET_SOCKETSET_EMPTY(writeset); ENET_SOCKETSET_ADD(readset, sock); ENET_SOCKETSET_ADD(writeset, sock); int result = enet_socketset_select(sock, &readset, &writeset, 250); if(result < 0) break; - else if(result > 0) - { - if(ENET_SOCKETSET_CHECK(readset, sock) || ENET_SOCKETSET_CHECK(writeset, sock)) - { + else if(result > 0) { + if(ENET_SOCKETSET_CHECK(readset, sock) || ENET_SOCKETSET_CHECK(writeset, sock)) { int error = 0; if(enet_socket_get_option(sock, ENET_SOCKOPT_ERROR, &error) < 0 || error) break; return 0; @@ -212,45 +178,30 @@ int connectwithtimeout(ENetSocket sock, const char *hostname, const ENetAddress renderprogress(min(float(timeout)/CONNLIMIT, 1.0f), text); if(interceptkey(SDLK_ESCAPE)) break; } - return -1; } -struct pingattempts -{ +struct pingattempts { enum { MAXATTEMPTS = 2 }; - int offset, attempts[MAXATTEMPTS]; - pingattempts() : offset(0) { clearattempts(); } - void clearattempts() { memset(attempts, 0, sizeof(attempts)); } - void setoffset() { offset = 1 + rnd(0xFFFFFF); } - - int encodeping(int millis) - { + int encodeping(int millis) { millis += offset; return millis ? millis : 1; } - - int decodeping(int val) - { + int decodeping(int val) { return val - offset; } - - int addattempt(int millis) - { + int addattempt(int millis) { int val = encodeping(millis); loopk(MAXATTEMPTS-1) attempts[k+1] = attempts[k]; attempts[0] = val; return val; } - - bool checkattempt(int val, bool del = true) - { - if(val) loopk(MAXATTEMPTS) if(attempts[k] == val) - { + bool checkattempt(int val, bool del = true) { + if(val) loopk(MAXATTEMPTS) if(attempts[k] == val) { if(del) attempts[k] = 0; return true; } @@ -261,15 +212,11 @@ struct pingattempts enum { UNRESOLVED = 0, RESOLVING, RESOLVED }; -struct serverinfo : pingattempts -{ - enum - { +struct serverinfo : pingattempts { + enum { WAITING = INT_MAX, - MAXPINGS = 3 }; - string name, map, sdesc; int port, numplayers, resolved, ping, lastping, nextping; int pings[MAXPINGS]; @@ -277,65 +224,47 @@ struct serverinfo : pingattempts ENetAddress address; bool keep; const char *password; - serverinfo() - : port(-1), numplayers(0), resolved(UNRESOLVED), keep(false), password(NULL) - { + : port(-1), numplayers(0), resolved(UNRESOLVED), keep(false), password(NULL) { name[0] = map[0] = sdesc[0] = '\0'; clearpings(); setoffset(); } - - ~serverinfo() - { + ~serverinfo() { DELETEA(password); } - - void clearpings() - { + void clearpings() { ping = WAITING; loopk(MAXPINGS) pings[k] = WAITING; nextping = 0; lastping = -1; clearattempts(); } - - void cleanup() - { + void cleanup() { clearpings(); attr.setsize(0); numplayers = 0; } - - void reset() - { + void reset() { lastping = -1; } - - void checkdecay(int decay) - { + void checkdecay(int decay) { if(lastping >= 0 && totalmillis - lastping >= decay) cleanup(); if(lastping < 0) lastping = totalmillis; } - - void calcping() - { + void calcping() { int numpings = 0, totalpings = 0; loopk(MAXPINGS) if(pings[k] != WAITING) { totalpings += pings[k]; numpings++; } ping = numpings ? totalpings/numpings : WAITING; } - - void addping(int rtt, int millis) - { + void addping(int rtt, int millis) { if(millis >= lastping) lastping = -1; pings[nextping] = rtt; nextping = (nextping+1)%MAXPINGS; calcping(); } - - static bool compare(serverinfo *a, serverinfo *b) - { + static bool compare(serverinfo *a, serverinfo *b) { bool ac = (a->attr.length() != 0) && (a->attr[0]==PROTOCOL_VERSION); bool bc = (b->attr.length() != 0) && (b->attr[0]==PROTOCOL_VERSION); if(ac > bc) return true; @@ -358,36 +287,27 @@ vector servers; ENetSocket pingsock = ENET_SOCKET_NULL; int lastinfo = 0; -static serverinfo *newserver(const char *name, int port, uint ip = ENET_HOST_ANY) -{ +static serverinfo *newserver(const char *name, int port, uint ip = ENET_HOST_ANY) { serverinfo *si = new serverinfo; si->address.host = ip; si->address.port = server::serverinfoport(port); if(ip!=ENET_HOST_ANY) si->resolved = RESOLVED; - si->port = port; if(name) copystring(si->name, name); - else if(ip==ENET_HOST_ANY || enet_address_get_host_ip(&si->address, si->name, sizeof(si->name)) < 0) - { + else if(ip==ENET_HOST_ANY || enet_address_get_host_ip(&si->address, si->name, sizeof(si->name)) < 0) { delete si; return NULL; - } - servers.add(si); - return si; } -void addserver(const char *name, int port, const char *password, bool keep) -{ +void addserver(const char *name, int port, const char *password, bool keep) { if(port <= 0) port = server::serverport(); - loopv(servers) - { + loopv(servers) { serverinfo *s = servers[i]; if(strcmp(s->name, name) || s->port != port) continue; - if(password && (!s->password || strcmp(s->password, password))) - { + if(password && (!s->password || strcmp(s->password, password))) { DELETEA(s->password); s->password = newstring(password); } @@ -407,47 +327,37 @@ VARP(maxservpings, 0, 10, 1000); pingattempts lanpings; -template static inline void buildping(ENetBuffer &buf, uchar (&ping)[N], pingattempts &a) -{ +template static inline void buildping(ENetBuffer &buf, uchar (&ping)[N], pingattempts &a) { ucharbuf p(ping, N); putint(p, a.addattempt(totalmillis)); buf.data = ping; buf.dataLength = p.length(); } -void pingservers() -{ - if(pingsock == ENET_SOCKET_NULL) - { +void pingservers() { + if(pingsock == ENET_SOCKET_NULL) { pingsock = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); - if(pingsock == ENET_SOCKET_NULL) - { + if(pingsock == ENET_SOCKET_NULL) { lastinfo = totalmillis; return; } enet_socket_set_option(pingsock, ENET_SOCKOPT_NONBLOCK, 1); enet_socket_set_option(pingsock, ENET_SOCKOPT_BROADCAST, 1); - lanpings.setoffset(); } - ENetBuffer buf; uchar ping[MAXTRANS]; - static int lastping = 0; if(lastping >= servers.length()) lastping = 0; - loopi(maxservpings ? min(servers.length(), maxservpings) : servers.length()) - { + loopi(maxservpings ? min(servers.length(), maxservpings) : servers.length()) { serverinfo &si = *servers[lastping]; if(++lastping >= servers.length()) lastping = 0; if(si.address.host == ENET_HOST_ANY) continue; buildping(buf, ping, si); enet_socket_send(pingsock, &si.address, &buf, 1); - si.checkdecay(servpingdecay); } - if(searchlan) - { + if(searchlan) { ENetAddress address; address.host = ENET_HOST_BROADCAST; address.port = server::laninfoport(); @@ -457,31 +367,24 @@ void pingservers() lastinfo = totalmillis; } -void checkresolver() -{ +void checkresolver() { int resolving = 0; - loopv(servers) - { + loopv(servers) { serverinfo &si = *servers[i]; if(si.resolved == RESOLVED) continue; - if(si.address.host == ENET_HOST_ANY) - { + if(si.address.host == ENET_HOST_ANY) { if(si.resolved == UNRESOLVED) { si.resolved = RESOLVING; resolverquery(si.name); } resolving++; } } if(!resolving) return; - const char *name = NULL; - for(;;) - { + for(;;) { ENetAddress addr = { ENET_HOST_ANY, ENET_PORT_ANY }; if(!resolvercheck(&name, &addr)) break; - loopv(servers) - { + loopv(servers) { serverinfo &si = *servers[i]; - if(name == si.name) - { + if(name == si.name) { si.resolved = RESOLVED; si.address.host = addr.host; break; @@ -492,8 +395,7 @@ void checkresolver() static int lastreset = 0; -void checkpings() -{ +void checkpings() { if(pingsock==ENET_SOCKET_NULL) return; enet_uint32 events = ENET_SOCKET_WAIT_RECEIVE; ENetBuffer buf; @@ -502,22 +404,19 @@ void checkpings() char text[MAXTRANS]; buf.data = ping; buf.dataLength = sizeof(ping); - while(enet_socket_wait(pingsock, &events, 0) >= 0 && events) - { + while(enet_socket_wait(pingsock, &events, 0) >= 0 && events) { int len = enet_socket_receive(pingsock, &addr, &buf, 1); if(len <= 0) return; ucharbuf p(ping, len); int millis = getint(p); serverinfo *si = NULL; loopv(servers) if(addr.host == servers[i]->address.host && addr.port == servers[i]->address.port) { si = servers[i]; break; } - if(si) - { + if(si) { if(!si->checkattempt(millis)) continue; millis = si->decodeping(millis); } else if(!searchlan || !lanpings.checkattempt(millis, false)) continue; - else - { + else { si = newserver(NULL, server::serverport(addr.port), addr.host); millis = lanpings.decodeping(millis); } @@ -534,8 +433,7 @@ void checkpings() } } -void sortservers() -{ +void sortservers() { servers.sort(serverinfo::compare); } COMMAND(sortservers, ""); @@ -543,17 +441,14 @@ COMMAND(sortservers, ""); VARP(autosortservers, 0, 1, 1); VARP(autoupdateservers, 0, 1, 1); -void refreshservers() -{ +void refreshservers() { static int lastrefresh = 0; if(lastrefresh==totalmillis) return; - if(totalmillis - lastrefresh > 1000) - { + if(totalmillis - lastrefresh > 1000) { loopv(servers) servers[i]->reset(); lastreset = totalmillis; } lastrefresh = totalmillis; - checkresolver(); checkpings(); if(totalmillis - lastinfo >= servpingrate/(maxservpings ? max(1, (servers.length() + maxservpings - 1) / maxservpings) : 1)) pingservers(); @@ -562,26 +457,21 @@ void refreshservers() serverinfo *selectedserver = NULL; -const char *showservers(g3d_gui *cgui, uint *header, int pagemin, int pagemax) -{ +const char *showservers(g3d_gui *cgui, uint *header, int pagemin, int pagemax) { refreshservers(); - if(servers.empty()) - { + if(servers.empty()) { if(header) execute(header); return NULL; } serverinfo *sc = NULL; - for(int start = 0; start < servers.length();) - { + for(int start = 0; start < servers.length();) { if(start > 0) cgui->tab(); if(header) execute(header); int end = servers.length(); cgui->pushlist(); - loopi(10) - { + loopi(10) { if(!game::serverinfostartcolumn(cgui, i)) break; - for(int j = start; j < end; j++) - { + for(int j = start; j < end; j++) { if(!i && j+1 - start >= pagemin && (j+1 - start >= pagemax || cgui->shouldtab())) { end = j; break; } serverinfo &si = *servers[j]; const char *sdesc = si.sdesc; @@ -600,8 +490,7 @@ const char *showservers(g3d_gui *cgui, uint *header, int pagemin, int pagemax) return "connectselected"; } -void connectselected() -{ +void connectselected() { if(!selectedserver) return; connectserv(selectedserver->name, selectedserver->port, selectedserver->password); selectedserver = NULL; @@ -609,8 +498,7 @@ void connectselected() COMMAND(connectselected, ""); -void clearservers(bool full = false) -{ +void clearservers(bool full = false) { resolverclear(); if(full) servers.deletecontents(); else loopvrev(servers) if(!servers[i]->keep) delete servers.remove(i); @@ -619,24 +507,19 @@ void clearservers(bool full = false) #define RETRIEVELIMIT 20000 -void retrieveservers(vector &data) -{ +void retrieveservers(vector &data) { ENetSocket sock = connectmaster(true); if(sock == ENET_SOCKET_NULL) return; - extern char *mastername; defformatstring(text, "retrieving servers from %s... (esc to abort)", mastername); renderprogress(0, text); - int starttime = SDL_GetTicks(), timeout = 0; const char *req = "list\n"; int reqlen = strlen(req); ENetBuffer buf; - while(reqlen > 0) - { + while(reqlen > 0) { enet_uint32 events = ENET_SOCKET_WAIT_SEND; - if(enet_socket_wait(sock, &events, 250) >= 0 && events) - { + if(enet_socket_wait(sock, &events, 250) >= 0 && events) { buf.data = (void *)req; buf.dataLength = reqlen; int sent = enet_socket_send(sock, NULL, &buf, 1); @@ -650,12 +533,9 @@ void retrieveservers(vector &data) if(interceptkey(SDLK_ESCAPE)) timeout = RETRIEVELIMIT + 1; if(timeout > RETRIEVELIMIT) break; } - - if(reqlen <= 0) for(;;) - { + if(reqlen <= 0) for(;;) { enet_uint32 events = ENET_SOCKET_WAIT_RECEIVE; - if(enet_socket_wait(sock, &events, 250) >= 0 && events) - { + if(enet_socket_wait(sock, &events, 250) >= 0 && events) { if(data.length() >= data.capacity()) data.reserve(4096); buf.data = data.getbuf() + data.length(); buf.dataLength = data.capacity() - data.length(); @@ -668,39 +548,31 @@ void retrieveservers(vector &data) if(interceptkey(SDLK_ESCAPE)) timeout = RETRIEVELIMIT + 1; if(timeout > RETRIEVELIMIT) break; } - if(data.length()) data.add('\0'); enet_socket_destroy(sock); } bool updatedservers = false; -void updatefrommaster() -{ +void updatefrommaster() { vector data; retrieveservers(data); if(data.empty()) conoutf(CON_ERROR, "master server not replying"); - else - { + else { clearservers(); char *line = data.getbuf(); - while(char *end = (char *)memchr(line, '\n', data.length() - (line - data.getbuf()))) - { + while(char *end = (char *)memchr(line, '\n', data.length() - (line - data.getbuf()))) { *end = '\0'; - const char *args = line; while(args < end && !iscubespace(*args)) args++; int cmdlen = args - line; while(args < end && iscubespace(*args)) args++; - - if(matchstring(line, cmdlen, "addserver")) - { + if(matchstring(line, cmdlen, "addserver")) { string ip; int port; if(sscanf(args, "%100s %d", ip, &port) == 2) addserver(ip, port); } else if(matchstring(line, cmdlen, "echo")) conoutf("\f1%s", args); - line = end + 1; } } @@ -708,8 +580,7 @@ void updatefrommaster() updatedservers = true; } -void initservers() -{ +void initservers() { selectedserver = NULL; if(autoupdateservers && !updatedservers) updatefrommaster(); } @@ -720,17 +591,14 @@ ICOMMAND(clearservers, "i", (int *full), clearservers(*full!=0)); COMMAND(updatefrommaster, ""); COMMAND(initservers, ""); -void writeservercfg() -{ +void writeservercfg() { if(!game::savedservers()) return; stream *f = openutf8file(path(game::savedservers(), true), "w"); if(!f) return; int kept = 0; - loopv(servers) - { + loopv(servers) { serverinfo *s = servers[i]; - if(s->keep) - { + if(s->keep) { if(!kept) f->printf("// servers that should never be cleared from the server list\n\n"); if(s->password) f->printf("keepserver %s %d %s\n", escapeid(s->name), s->port, escapestring(s->password)); else f->printf("keepserver %s %d\n", escapeid(s->name), s->port); @@ -739,11 +607,9 @@ void writeservercfg() } if(kept) f->printf("\n"); f->printf("// servers connected to are added here automatically\n\n"); - loopv(servers) - { + loopv(servers) { serverinfo *s = servers[i]; - if(!s->keep) - { + if(!s->keep) { if(s->password) f->printf("addserver %s %d %s\n", escapeid(s->name), s->port, escapestring(s->password)); else f->printf("addserver %s %d\n", escapeid(s->name), s->port); } diff --git a/src/engine/shader.cpp b/src/engine/shader.cpp index 67b9e42..8f5e9b7 100644 --- a/src/engine/shader.cpp +++ b/src/engine/shader.cpp @@ -18,41 +18,32 @@ VAR(maxvsuniforms, 1, 0, 0); VAR(maxfsuniforms, 1, 0, 0); VAR(maxvaryings, 1, 0, 0); -void loadshaders() -{ +void loadshaders() { standardshaders = true; execfile("data/glsl.cfg"); standardshaders = false; - nullshader = lookupshaderbyname("null"); hudshader = lookupshaderbyname("hud"); hudnotextureshader = lookupshaderbyname("hudnotexture"); stdworldshader = lookupshaderbyname("stdworld"); if(!nullshader || !hudshader || !hudnotextureshader || !stdworldshader) fatal("cannot find shader definitions"); - dummyslot.shader = stdworldshader; - textureshader = lookupshaderbyname("texture"); notextureshader = lookupshaderbyname("notexture"); nocolorshader = lookupshaderbyname("nocolor"); - nullshader->set(); - loadedshaders = true; } -Shader *lookupshaderbyname(const char *name) -{ +Shader *lookupshaderbyname(const char *name) { Shader *s = shaders.access(name); return s && s->loaded() ? s : NULL; } -Shader *generateshader(const char *name, const char *fmt, ...) -{ +Shader *generateshader(const char *name, const char *fmt, ...) { if(!loadedshaders) return NULL; Shader *s = name ? lookupshaderbyname(name) : NULL; - if(!s) - { + if(!s) { defvformatstring(cmd, fmt, fmt); bool wasstandard = standardshaders; standardshaders = true; @@ -64,29 +55,24 @@ Shader *generateshader(const char *name, const char *fmt, ...) return s; } -static void showglslinfo(GLenum type, GLuint obj, const char *name, const char **parts = NULL, int numparts = 0) -{ +static void showglslinfo(GLenum type, GLuint obj, const char *name, const char **parts = NULL, int numparts = 0) { GLint length = 0; if(type) glGetShaderiv_(obj, GL_INFO_LOG_LENGTH, &length); else glGetProgramiv_(obj, GL_INFO_LOG_LENGTH, &length); - if(length > 1) - { + if(length > 1) { conoutf(CON_ERROR, "GLSL ERROR (%s:%s)", type == GL_VERTEX_SHADER ? "VS" : (type == GL_FRAGMENT_SHADER ? "FS" : "PROG"), name); FILE *l = getlogfile(); - if(l) - { + if(l) { GLchar *log = new GLchar[length]; if(type) glGetShaderInfoLog_(obj, length, &length, log); else glGetProgramInfoLog_(obj, length, &length, log); fprintf(l, "%s\n", log); bool partlines = log[0] != '0'; int line = 0; - loopi(numparts) - { + loopi(numparts) { const char *part = parts[i]; int startline = line; - while(*part) - { + while(*part) { const char *next = strchr(part, '\n'); if(++line > 1000) goto done; if(partlines) fprintf(l, "%d(%d): ", i, line - startline); else fprintf(l, "%d: ", line); @@ -101,30 +87,26 @@ static void showglslinfo(GLenum type, GLuint obj, const char *name, const char * } } -static void compileglslshader(GLenum type, GLuint &obj, const char *def, const char *name, bool msg = true) -{ +static void compileglslshader(GLenum type, GLuint &obj, const char *def, const char *name, bool msg = true) { const char *source = def + strspn(def, " \t\r\n"); const char *parts[16]; int numparts = 0; - static const struct { int version; const char * const header; } glslversions[] = - { - { 330, "#version 330\n" }, - { 150, "#version 150\n" }, - { 130, "#version 130\n" }, - { 120, "#version 120\n" } + static const struct { int version; const char * const header; } glslversions[] = { + { + 330, "#version 330\n" }, { + 150, "#version 150\n" }, { + 130, "#version 130\n" }, { + 120, "#version 120\n" } }; - loopi(sizeof(glslversions)/sizeof(glslversions[0])) if(glslversion >= glslversions[i].version) - { + loopi(sizeof(glslversions)/sizeof(glslversions[0])) if(glslversion >= glslversions[i].version) { parts[numparts++] = glslversions[i].header; break; } - if(glslversion >= 130) - { + if(glslversion >= 130) { if(type == GL_VERTEX_SHADER) parts[numparts++] = "#define attribute in\n" "#define varying out\n"; - else if(type == GL_FRAGMENT_SHADER) - { + else if(type == GL_FRAGMENT_SHADER) { parts[numparts++] = "#define varying in\n"; if(glslversion < 150) parts[numparts++] = "precision highp float;\n"; if(glversion >= 300) parts[numparts++] = @@ -137,35 +119,30 @@ static void compileglslshader(GLenum type, GLuint &obj, const char *def, const c "#define textureCube(sampler, coords) texture(sampler, coords)\n"; } parts[numparts++] = source; - obj = glCreateShader_(type); glShaderSource_(obj, numparts, (const GLchar **)parts, NULL); glCompileShader_(obj); GLint success; glGetShaderiv_(obj, GL_COMPILE_STATUS, &success); - if(!success) - { + if(!success) { if(msg) showglslinfo(type, obj, name, parts, numparts); glDeleteShader_(obj); obj = 0; } } -static void bindglsluniform(Shader &s, UniformLoc &u) -{ +static void bindglsluniform(Shader &s, UniformLoc &u) { u.loc = glGetUniformLocation_(s.program, u.name); if(!u.blockname || !hasUBO) return; GLuint bidx = glGetUniformBlockIndex_(s.program, u.blockname); GLuint uidx = GL_INVALID_INDEX; glGetUniformIndices_(s.program, 1, &u.name, &uidx); - if(bidx != GL_INVALID_INDEX && uidx != GL_INVALID_INDEX) - { + if(bidx != GL_INVALID_INDEX && uidx != GL_INVALID_INDEX) { GLint sizeval = 0, offsetval = 0, strideval = 0; glGetActiveUniformBlockiv_(s.program, bidx, GL_UNIFORM_BLOCK_DATA_SIZE, &sizeval); if(sizeval <= 0) return; glGetActiveUniformsiv_(s.program, 1, &uidx, GL_UNIFORM_OFFSET, &offsetval); - if(u.stride > 0) - { + if(u.stride > 0) { glGetActiveUniformsiv_(s.program, 1, &uidx, GL_UNIFORM_ARRAY_STRIDE, &strideval); if(strideval > u.stride) return; } @@ -175,69 +152,57 @@ static void bindglsluniform(Shader &s, UniformLoc &u) } } -static void linkglslprogram(Shader &s, bool msg = true) -{ +static void linkglslprogram(Shader &s, bool msg = true) { s.program = s.vsobj && s.psobj ? glCreateProgram_() : 0; GLint success = 0; - if(s.program) - { + if(s.program) { glAttachShader_(s.program, s.vsobj); glAttachShader_(s.program, s.psobj); uint attribs = 0; - loopv(s.attriblocs) - { + loopv(s.attriblocs) { AttribLoc &a = s.attriblocs[i]; glBindAttribLocation_(s.program, a.loc, a.name); attribs |= 1<= 300) - { + if(glversion >= 300) { glBindFragDataLocation_(s.program, 0, "cube2_FragColor"); } glLinkProgram_(s.program); glGetProgramiv_(s.program, GL_LINK_STATUS, &success); } - if(success) - { + if(success) { glUseProgram_(s.program); - loopi(8) - { + loopi(8) { static const char * const texnames[8] = { "tex0", "tex1", "tex2", "tex3", "tex4", "tex5", "tex6", "tex7" }; GLint loc = glGetUniformLocation_(s.program, texnames[i]); if(loc != -1) glUniform1i_(loc, i); } - loopv(s.defaultparams) - { + loopv(s.defaultparams) { SlotShaderParamState ¶m = s.defaultparams[i]; param.loc = glGetUniformLocation_(s.program, param.name); } loopv(s.uniformlocs) bindglsluniform(s, s.uniformlocs[i]); glUseProgram_(0); } - else if(s.program) - { + else if(s.program) { if(msg) showglslinfo(GL_FALSE, s.program, s.name); glDeleteProgram_(s.program); s.program = 0; } } -int getlocalparam(const char *name) -{ +int getlocalparam(const char *name) { return localparams.access(name, int(localparams.numelems)); } -static int addlocalparam(Shader &s, const char *name, int loc, int size, GLenum format) -{ +static int addlocalparam(Shader &s, const char *name, int loc, int size, GLenum format) { int idx = getlocalparam(name); - if(idx >= s.localparamremap.length()) - { + if(idx >= s.localparamremap.length()) { int n = idx + 1 - s.localparamremap.length(); memset(s.localparamremap.pad(n), 0xFF, n); } s.localparamremap[idx] = s.localparams.length(); - LocalShaderParamState &l = s.localparams.add(); l.name = name; l.loc = loc; @@ -246,11 +211,9 @@ static int addlocalparam(Shader &s, const char *name, int loc, int size, GLenum return idx; } -GlobalShaderParamState *getglobalparam(const char *name) -{ +GlobalShaderParamState *getglobalparam(const char *name) { GlobalShaderParamState *param = globalparams.access(name); - if(!param) - { + if(!param) { param = &globalparams[name]; param->name = name; memset(param->buf, -1, sizeof(param->buf)); @@ -259,8 +222,7 @@ GlobalShaderParamState *getglobalparam(const char *name) return param; } -static GlobalShaderParamUse *addglobalparam(Shader &s, GlobalShaderParamState *param, int loc, int size, GLenum format) -{ +static GlobalShaderParamUse *addglobalparam(Shader &s, GlobalShaderParamState *param, int loc, int size, GLenum format) { GlobalShaderParamUse &g = s.globalparams.add(); g.param = param; g.version = -2; @@ -270,10 +232,8 @@ static GlobalShaderParamUse *addglobalparam(Shader &s, GlobalShaderParamState *p return &g; } -static void setglsluniformformat(Shader &s, const char *name, GLenum format, int size) -{ - switch(format) - { +static void setglsluniformformat(Shader &s, const char *name, GLenum format, int size) { + switch(format) { case GL_FLOAT: case GL_FLOAT_VEC2: case GL_FLOAT_VEC3: @@ -294,31 +254,26 @@ static void setglsluniformformat(Shader &s, const char *name, GLenum format, int return; } if(!strncmp(name, "gl_", 3)) return; - int loc = glGetUniformLocation_(s.program, name); if(loc < 0) return; - loopvj(s.defaultparams) if(s.defaultparams[j].loc == loc) - { + loopvj(s.defaultparams) if(s.defaultparams[j].loc == loc) { s.defaultparams[j].format = format; return; } loopvj(s.uniformlocs) if(s.uniformlocs[j].loc == loc) return; loopvj(s.globalparams) if(s.globalparams[j].loc == loc) return; loopvj(s.localparams) if(s.localparams[j].loc == loc) return; - name = getshaderparamname(name); GlobalShaderParamState *param = globalparams.access(name); if(param) addglobalparam(s, param, loc, size, format); else addlocalparam(s, name, loc, size, format); } -static void allocglslactiveuniforms(Shader &s) -{ +static void allocglslactiveuniforms(Shader &s) { GLint numactive = 0; glGetProgramiv_(s.program, GL_ACTIVE_UNIFORMS, &numactive); string name; - loopi(numactive) - { + loopi(numactive) { GLsizei namelen = 0; GLint size = 0; GLenum format = GL_FLOAT_VEC4; @@ -332,19 +287,16 @@ static void allocglslactiveuniforms(Shader &s) } } -void Shader::allocparams(Slot *slot) -{ - if(slot) - { -#define UNIFORMTEX(name, tmu) \ - { \ +void Shader::allocparams(Slot *slot) { + if(slot) { +#define UNIFORMTEX(name, tmu) { \ + \ loc = glGetUniformLocation_(program, name); \ int val = tmu; \ if(loc != -1) glUniform1i_(loc, val); \ } int loc, tmu = 2; - if(type & SHADER_NORMALSLMS) - { + if(type & SHADER_NORMALSLMS) { UNIFORMTEX("lmcolor", 1); UNIFORMTEX("lmdir", 2); tmu++; @@ -352,19 +304,16 @@ void Shader::allocparams(Slot *slot) else UNIFORMTEX("lightmap", 1); UNIFORMTEX("shadowmap", 7); int stex = 0; - loopv(slot->sts) - { + loopv(slot->sts) { Slot::Tex &t = slot->sts[i]; - switch(t.type) - { + switch(t.type) { case TEX_DIFFUSE: UNIFORMTEX("diffusemap", 0); break; case TEX_NORMAL: UNIFORMTEX("normalmap", tmu++); break; case TEX_DECAL: UNIFORMTEX("decal", tmu++); break; case TEX_SPEC: if(t.combined<0) UNIFORMTEX("specmap", tmu++); break; case TEX_DEPTH: if(t.combined<0) UNIFORMTEX("depthmap", tmu++); break; case TEX_ALPHA: if(t.combined<0) UNIFORMTEX("alphamap", tmu++); break; - case TEX_UNKNOWN: - { + case TEX_UNKNOWN: { defformatstring(sname, "stex%d", stex++); UNIFORMTEX(sname, tmu++); break; @@ -377,32 +326,25 @@ void Shader::allocparams(Slot *slot) int GlobalShaderParamState::nextversion = 0; -void GlobalShaderParamState::resetversions() -{ - enumerate(shaders, Shader, s, - { - loopv(s.globalparams) - { +void GlobalShaderParamState::resetversions() { + enumerate(shaders, Shader, s, { + loopv(s.globalparams) { GlobalShaderParamUse &u = s.globalparams[i]; if(u.version != u.param->version) u.version = -2; } }); nextversion = 0; enumerate(globalparams, GlobalShaderParamState, g, { g.version = ++nextversion; }); - enumerate(shaders, Shader, s, - { - loopv(s.globalparams) - { + enumerate(shaders, Shader, s, { + loopv(s.globalparams) { GlobalShaderParamUse &u = s.globalparams[i]; if(u.version >= 0) u.version = u.param->version; } }); } -static inline void setslotparam(SlotShaderParamState &l, const float *val) -{ - switch(l.format) - { +static inline void setslotparam(SlotShaderParamState &l, const float *val) { + switch(l.format) { case GL_BOOL: case GL_FLOAT: glUniform1fv_(l.loc, 1, val); break; case GL_BOOL_VEC2: @@ -426,52 +368,46 @@ static inline void setslotparam(SlotShaderParamState &l, const float *val) } while(0) #define SETSLOTPARAMS(slotparams) \ - loopv(slotparams) \ - { \ + loopv(slotparams) { \ + \ SlotShaderParam &p = slotparams[i]; \ if(!defaultparams.inrange(p.loc)) continue; \ SlotShaderParamState &l = defaultparams[p.loc]; \ SETSLOTPARAM(l, unimask, p.loc, p.val); \ } #define SETDEFAULTPARAMS \ - loopv(defaultparams) \ - { \ + loopv(defaultparams) { \ + \ SlotShaderParamState &l = defaultparams[i]; \ SETSLOTPARAM(l, unimask, i, l.val); \ } -void Shader::setslotparams(Slot &slot) -{ +void Shader::setslotparams(Slot &slot) { uint unimask = 0; SETSLOTPARAMS(slot.params) SETDEFAULTPARAMS } -void Shader::setslotparams(Slot &slot, VSlot &vslot) -{ +void Shader::setslotparams(Slot &slot, VSlot &vslot) { uint unimask = 0; - if(vslot.slot == &slot) - { + if(vslot.slot == &slot) { SETSLOTPARAMS(vslot.params) SETSLOTPARAMS(slot.params) SETDEFAULTPARAMS } - else - { + else { SETSLOTPARAMS(slot.params) SETDEFAULTPARAMS } } -void Shader::bindprograms() -{ +void Shader::bindprograms() { if(this == lastshader || type&(SHADER_DEFERRED|SHADER_INVALID)) return; glUseProgram_(program); lastshader = this; } -bool Shader::compile() -{ +bool Shader::compile() { if(!vsstr) vsobj = !reusevs || reusevs->invalid() ? 0 : reusevs->vsobj; else compileglslshader(GL_VERTEX_SHADER, vsobj, vsstr, name, !variantshader); if(!psstr) psobj = !reuseps || reuseps->invalid() ? 0 : reuseps->psobj; @@ -480,8 +416,7 @@ bool Shader::compile() return program!=0; } -void Shader::cleanup(bool invalid) -{ +void Shader::cleanup(bool invalid) { detailshader = NULL; used = false; if(vsobj) { if(!reusevs) glDeleteShader_(vsobj); vsobj = 0; } @@ -490,8 +425,7 @@ void Shader::cleanup(bool invalid) localparams.setsize(0); localparamremap.setsize(0); globalparams.setsize(0); - if(standard || invalid) - { + if(standard || invalid) { type = SHADER_INVALID; DELETEA(vsstr); DELETEA(psstr); @@ -511,28 +445,24 @@ void Shader::cleanup(bool invalid) bool Shader::isnull(const Shader *s) { return !s; } -static void genattriblocs(Shader &s, const char *vs, const char *ps, Shader *reusevs, Shader *reuseps) -{ +static void genattriblocs(Shader &s, const char *vs, const char *ps, Shader *reusevs, Shader *reuseps) { static int len = strlen("//:attrib"); string name; int loc; if(reusevs) s.attriblocs = reusevs->attriblocs; - else while((vs = strstr(vs, "//:attrib"))) - { + else while((vs = strstr(vs, "//:attrib"))) { if(sscanf(vs, "//:attrib %100s %d", name, &loc) == 2) s.attriblocs.add(AttribLoc(getshaderparamname(name), loc)); vs += len; } } -static void genuniformlocs(Shader &s, const char *vs, const char *ps, Shader *reusevs, Shader *reuseps) -{ +static void genuniformlocs(Shader &s, const char *vs, const char *ps, Shader *reusevs, Shader *reuseps) { static int len = strlen("//:uniform"); string name, blockname; int binding, stride; if(reusevs) s.uniformlocs = reusevs->uniformlocs; - else while((vs = strstr(vs, "//:uniform"))) - { + else while((vs = strstr(vs, "//:uniform"))) { int numargs = sscanf(vs, "//:uniform %100s %100s %d %d", name, blockname, &binding, &stride); if(numargs >= 3) s.uniformlocs.add(UniformLoc(getshaderparamname(name), getshaderparamname(blockname), binding, numargs >= 4 ? stride : 0)); else if(numargs >= 1) s.uniformlocs.add(UniformLoc(getshaderparamname(name))); @@ -540,14 +470,11 @@ static void genuniformlocs(Shader &s, const char *vs, const char *ps, Shader *re } } -Shader *newshader(int type, const char *name, const char *vs, const char *ps, Shader *variant = NULL, int row = 0) -{ - if(Shader::lastshader) - { +Shader *newshader(int type, const char *name, const char *vs, const char *ps, Shader *variant = NULL, int row = 0) { + if(Shader::lastshader) { glUseProgram_(0); Shader::lastshader = NULL; } - Shader *exists = shaders.access(name); char *rname = exists ? exists->name : newstring(name); Shader &s = shaders[rname]; @@ -560,17 +487,14 @@ Shader *newshader(int type, const char *name, const char *vs, const char *ps, Sh s.standard = standardshaders; if(forceshaders) s.forced = true; s.reusevs = s.reuseps = NULL; - if(variant) - { + if(variant) { int row = 0, col = 0; - if(!vs[0] || sscanf(vs, "%d , %d", &row, &col) >= 1) - { + if(!vs[0] || sscanf(vs, "%d , %d", &row, &col) >= 1) { DELETEA(s.vsstr); s.reusevs = !vs[0] ? variant : variant->getvariant(col, row); } row = col = 0; - if(!ps[0] || sscanf(ps, "%d , %d", &row, &col) >= 1) - { + if(!ps[0] || sscanf(ps, "%d , %d", &row, &col) >= 1) { DELETEA(s.psstr); s.reuseps = !ps[0] ? variant : variant->getvariant(col, row); } @@ -581,8 +505,7 @@ Shader *newshader(int type, const char *name, const char *vs, const char *ps, Sh s.uniformlocs.setsize(0); genattriblocs(s, vs, ps, s.reusevs, s.reuseps); genuniformlocs(s, vs, ps, s.reusevs, s.reuseps); - if(!s.compile()) - { + if(!s.compile()) { s.cleanup(true); if(variant) shaders.remove(rname); return NULL; @@ -592,19 +515,16 @@ Shader *newshader(int type, const char *name, const char *vs, const char *ps, Sh return &s; } -void setupshaders() -{ +void setupshaders() { GLint val; glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &val); maxvsuniforms = val/4; glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &val); maxfsuniforms = val/4; - if(glversion < 300) - { + if(glversion < 300) { glGetIntegerv(GL_MAX_VARYING_COMPONENTS, &val); maxvaryings = val; } - standardshaders = true; nullshader = newshader(0, "null", "attribute vec4 vvertex;\n" @@ -644,38 +564,31 @@ void setupshaders() " gl_FragColor = color;\n" "}\n"); standardshaders = false; - if(!nullshader || !hudshader || !hudnotextureshader) fatal("failed to setup shaders"); - dummyslot.shader = nullshader; } -static const char *findglslmain(const char *s) -{ +static const char *findglslmain(const char *s) { const char *main = strstr(s, "main"); if(!main) return NULL; for(; main >= s; main--) switch(*main) { case '\r': case '\n': case ';': return main + 1; } return s; } -static void gengenericvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 0) -{ +static void gengenericvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 0) { int rowoffset = 0; bool vschanged = false, pschanged = false; vector vsv, psv; vsv.put(vs, strlen(vs)+1); psv.put(ps, strlen(ps)+1); - static const int len = strlen("//:variant"), olen = strlen("override"); - for(char *vspragma = vsv.getbuf();; vschanged = true) - { + for(char *vspragma = vsv.getbuf();; vschanged = true) { vspragma = strstr(vspragma, "//:variant"); if(!vspragma) break; if(sscanf(vspragma + len, "row %d", &rowoffset) == 1) continue; memset(vspragma, ' ', len); vspragma += len; - if(!strncmp(vspragma, "override", olen)) - { + if(!strncmp(vspragma, "override", olen)) { memset(vspragma, ' ', olen); vspragma += olen; char *end = vspragma + strcspn(vspragma, "\n\r"); @@ -684,15 +597,13 @@ static void gengenericvariant(Shader &s, const char *sname, const char *vs, cons memset(end, ' ', endlen); } } - for(char *pspragma = psv.getbuf();; pschanged = true) - { + for(char *pspragma = psv.getbuf();; pschanged = true) { pspragma = strstr(pspragma, "//:variant"); if(!pspragma) break; if(sscanf(pspragma + len, "row %d", &rowoffset) == 1) continue; memset(pspragma, ' ', len); pspragma += len; - if(!strncmp(pspragma, "override", olen)) - { + if(!strncmp(pspragma, "override", olen)) { memset(pspragma, ' ', olen); pspragma += olen; char *end = pspragma + strcspn(pspragma, "\n\r"); @@ -713,52 +624,38 @@ static void gengenericvariant(Shader &s, const char *sname, const char *vs, cons bool minimizedynlighttcusage() { return glversion < 300 && maxvaryings < 48; } -static void gendynlightvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 0) -{ +static void gendynlightvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 0) { int numlights = minimizedynlighttcusage() ? 1 : MAXDYNLIGHTS; - const char *vspragma = strstr(vs, "//:dynlight"), *pspragma = strstr(ps, "//:dynlight"); if(!vspragma || !pspragma) return; - string pslight; vspragma += strcspn(vspragma, "\n"); if(*vspragma) vspragma++; - if(sscanf(pspragma, "//:dynlight %100s", pslight)!=1) return; - pspragma += strcspn(pspragma, "\n"); if(*pspragma) pspragma++; - const char *vsmain = findglslmain(vs), *psmain = findglslmain(ps); if(vsmain > vspragma) vsmain = vs; if(psmain > pspragma) psmain = ps; - vector vsdl, psdl; - loopi(MAXDYNLIGHTS) - { + loopi(MAXDYNLIGHTS) { vsdl.setsize(0); psdl.setsize(0); if(vsmain >= vs) vsdl.put(vs, vsmain - vs); if(psmain >= ps) psdl.put(ps, psmain - ps); - defformatstring(pos, "uniform vec4 dynlightpos[%d];\n", i+1); vsdl.put(pos, strlen(pos)); psdl.put(pos, strlen(pos)); defformatstring(color, "uniform vec3 dynlightcolor[%d];\n", i+1); psdl.put(color, strlen(color)); - - loopk(min(i+1, numlights)) - { + loopk(min(i+1, numlights)) { defformatstring(dir, "%sdynlight%ddir%s", !k ? "varying vec3 " : " ", k, k==i || k+1==numlights ? ";\n" : ","); vsdl.put(dir, strlen(dir)); psdl.put(dir, strlen(dir)); } - vsdl.put(vsmain, vspragma-vsmain); psdl.put(psmain, pspragma-psmain); - - loopk(i+1) - { + loopk(i+1) { defformatstring(tc, k%s", i+1, sname); Shader *variant = newshader(s.type, name, vsdl.getbuf(), psdl.getbuf(), &s, row); if(!variant) return; } } -static void genshadowmapvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 1) -{ +static void genshadowmapvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 1) { const char *vspragma = strstr(vs, "//:shadowmap"), *pspragma = strstr(ps, "//:shadowmap"); if(!vspragma || !pspragma) return; - string pslight; vspragma += strcspn(vspragma, "\n"); if(*vspragma) vspragma++; - if(sscanf(pspragma, "//:shadowmap %100s", pslight)!=1) return; - pspragma += strcspn(pspragma, "\n"); if(*pspragma) pspragma++; - const char *vsmain = findglslmain(vs), *psmain = findglslmain(ps); if(vsmain > vspragma) vsmain = vs; if(psmain > pspragma) psmain = ps; - vector vssm, pssm; if(vsmain >= vs) vssm.put(vs, vsmain - vs); if(psmain >= ps) pssm.put(ps, psmain - ps); - const char *vsdecl = "uniform mat4 shadowmapproject;\n" "varying vec3 shadowmaptc;\n"; vssm.put(vsdecl, strlen(vsdecl)); - const char *psdecl = "uniform sampler2D shadowmap;\n" "uniform vec4 shadowmapambient;\n" "varying vec3 shadowmaptc;\n"; pssm.put(psdecl, strlen(psdecl)); - vssm.put(vsmain, vspragma-vsmain); pssm.put(psmain, pspragma-psmain); - extern int smoothshadowmappeel; const char *tcgen = "shadowmaptc = vec3(shadowmapproject * vvertex);\n"; @@ -827,7 +711,6 @@ static void genshadowmapvariant(Shader &s, const char *sname, const char *vs, co "vec4 smvals = texture2D(shadowmap, shadowmaptc.xy);\n" "vec2 smdiff = clamp(smvals.xz - shadowmaptc.zz*smvals.y, 0.0, 1.0);\n" "float shadowed = clamp((smdiff.x > 0.0 ? smvals.w : 0.0) - 8.0*smdiff.y, 0.0, 1.0);\n" : - "vec4 smvals = texture2D(shadowmap, shadowmaptc.xy);\n" "float smtest = shadowmaptc.z*smvals.y;\n" "float shadowed = smtest < smvals.x && smtest > smvals.z ? smvals.w : 0.0;\n"; @@ -836,32 +719,26 @@ static void genshadowmapvariant(Shader &s, const char *sname, const char *vs, co "%s.rgb -= shadowed*clamp(%s.rgb - shadowmapambient.rgb, 0.0, 1.0);\n", pslight, pslight); pssm.put(smlight, strlen(smlight)); - vssm.put(vspragma, strlen(vspragma)+1); pssm.put(pspragma, strlen(pspragma)+1); - defformatstring(name, "%s", sname); Shader *variant = newshader(s.type, name, vssm.getbuf(), pssm.getbuf(), &s, row); if(!variant) return; - if(strstr(vs, "//:dynlight")) gendynlightvariant(s, name, vssm.getbuf(), pssm.getbuf(), row); } -static void genuniformdefs(vector &vsbuf, vector &psbuf, const char *vs, const char *ps, Shader *variant = NULL) -{ +static void genuniformdefs(vector &vsbuf, vector &psbuf, const char *vs, const char *ps, Shader *variant = NULL) { if(variant ? variant->defaultparams.empty() : slotparams.empty()) return; const char *vsmain = findglslmain(vs), *psmain = findglslmain(ps); if(!vsmain || !psmain) return; vsbuf.put(vs, vsmain - vs); psbuf.put(ps, psmain - ps); - if(variant) loopv(variant->defaultparams) - { + if(variant) loopv(variant->defaultparams) { defformatstring(uni, "\nuniform vec4 %s;\n", variant->defaultparams[i].name); vsbuf.put(uni, strlen(uni)); psbuf.put(uni, strlen(uni)); } - else loopv(slotparams) - { + else loopv(slotparams) { defformatstring(uni, "\nuniform vec4 %s;\n", slotparams[i].name); vsbuf.put(uni, strlen(uni)); psbuf.put(uni, strlen(uni)); @@ -872,8 +749,7 @@ static void genuniformdefs(vector &vsbuf, vector &psbuf, const char VAR(defershaders, 0, 1, 1); -void defershader(int *type, const char *name, const char *contents) -{ +void defershader(int *type, const char *name, const char *contents) { Shader *exists = shaders.access(name); if(exists && !exists->invalid()) return; if(!defershaders) { execute(contents); return; } @@ -886,10 +762,8 @@ void defershader(int *type, const char *name, const char *contents) s.standard = standardshaders; } -void Shader::force() -{ +void Shader::force() { if(!deferred() || !defer) return; - char *cmd = defer; defer = NULL; bool wasstandard = standardshaders, wasforcing = forceshaders; @@ -903,24 +777,20 @@ void Shader::force() forceshaders = wasforcing; standardshaders = wasstandard; delete[] cmd; - - if(deferred()) - { + if(deferred()) { DELETEA(defer); type = SHADER_INVALID; } } -void fixshaderdetail() -{ +void fixshaderdetail() { // must null out separately because fixdetailshader can recursively set it enumerate(shaders, Shader, s, { if(!s.forced) s.detailshader = NULL; }); enumerate(shaders, Shader, s, { if(s.forced) s.fixdetailshader(); }); linkslotshaders(); } -int Shader::uniformlocversion() -{ +int Shader::uniformlocversion() { static int version = 0; if(++version >= 0) return version; version = 0; @@ -930,28 +800,23 @@ int Shader::uniformlocversion() VARFP(shaderdetail, 0, MAXSHADERDETAIL, MAXSHADERDETAIL, fixshaderdetail()); -void Shader::fixdetailshader(bool shouldforce, bool recurse) -{ +void Shader::fixdetailshader(bool shouldforce, bool recurse) { Shader *alt = this; detailshader = NULL; - do - { + do { Shader *cur = shaderdetail < MAXSHADERDETAIL ? alt->fastshader[shaderdetail] : alt; if(cur->deferred() && shouldforce) cur->force(); - if(!cur->invalid()) - { + if(!cur->invalid()) { if(cur->deferred()) break; detailshader = cur; break; } alt = alt->altshader; } while(alt && alt!=this); - if(recurse && detailshader) loopv(detailshader->variants) detailshader->variants[i]->fixdetailshader(shouldforce, false); } -Shader *useshaderbyname(const char *name) -{ +Shader *useshaderbyname(const char *name) { Shader *s = shaders.access(name); if(!s) return NULL; if(!s->detailshader) s->fixdetailshader(); @@ -959,17 +824,14 @@ Shader *useshaderbyname(const char *name) return s; } -void shader(int *type, char *name, char *vs, char *ps) -{ +void shader(int *type, char *name, char *vs, char *ps) { if(lookupshaderbyname(name)) return; - defformatstring(info, "shader %s", name); renderprogress(loadprogress, info); - vector vsbuf, psbuf, vsbak, psbak; #define GENSHADER(cond, body) \ - if(cond) \ - { \ + if(cond) { \ + \ if(vsbuf.length()) { vsbak.setsize(0); vsbak.put(vs, strlen(vs)+1); vs = vsbak.getbuf(); vsbuf.setsize(0); } \ if(psbuf.length()) { psbak.setsize(0); psbak.put(ps, strlen(ps)+1); ps = psbak.getbuf(); psbuf.setsize(0); } \ body; \ @@ -978,78 +840,63 @@ void shader(int *type, char *name, char *vs, char *ps) } GENSHADER(slotparams.length(), genuniformdefs(vsbuf, psbuf, vs, ps)); Shader *s = newshader(*type, name, vs, ps); - if(s) - { + if(s) { if(strstr(vs, "//:shadowmap")) genshadowmapvariant(*s, s->name, vs, ps); if(strstr(vs, "//:dynlight")) gendynlightvariant(*s, s->name, vs, ps); } slotparams.shrink(0); } -void variantshader(int *type, char *name, int *row, char *vs, char *ps) -{ - if(*row < 0) - { +void variantshader(int *type, char *name, int *row, char *vs, char *ps) { + if(*row < 0) { shader(type, name, vs, ps); return; } else if(*row >= MAXVARIANTROWS) return; - Shader *s = lookupshaderbyname(name); if(!s) return; - defformatstring(varname, "%s", s->numvariants(*row), *row, name); //defformatstring(info, "shader %s", varname); //renderprogress(loadprogress, info); vector vsbuf, psbuf, vsbak, psbak; GENSHADER(s->defaultparams.length(), genuniformdefs(vsbuf, psbuf, vs, ps, s)); Shader *v = newshader(*type, varname, vs, ps, s, *row); - if(v) - { + if(v) { if(strstr(vs, "//:dynlight")) gendynlightvariant(*s, varname, vs, ps, *row); if(strstr(ps, "//:variant") || strstr(vs, "//:variant")) gengenericvariant(*s, varname, vs, ps, *row); } } -void setshader(char *name) -{ +void setshader(char *name) { slotparams.shrink(0); Shader *s = shaders.access(name); - if(!s) - { + if(!s) { conoutf(CON_ERROR, "no such shader: %s", name); } else slotshader = s; } -void resetslotshader() -{ +void resetslotshader() { slotshader = NULL; slotparams.shrink(0); } -void setslotshader(Slot &s) -{ +void setslotshader(Slot &s) { s.shader = slotshader; - if(!s.shader) - { + if(!s.shader) { s.shader = stdworldshader; return; } loopv(slotparams) s.params.add(slotparams[i]); } -static void linkslotshaderparams(vector ¶ms, Shader *sh, bool load) -{ - if(sh) loopv(params) - { +static void linkslotshaderparams(vector ¶ms, Shader *sh, bool load) { + if(sh) loopv(params) { int loc = -1; SlotShaderParam ¶m = params[i]; - loopv(sh->defaultparams) - { + loopv(sh->defaultparams) { SlotShaderParamState &dparam = sh->defaultparams[i]; - if(dparam.name==param.name) - { + if(dparam.name==param.name) { if(memcmp(param.val, dparam.val, sizeof(param.val))) loc = i; break; } @@ -1059,35 +906,27 @@ static void linkslotshaderparams(vector ¶ms, Shader *sh, bo else if(load) loopv(params) params[i].loc = -1; } -void linkslotshader(Slot &s, bool load) -{ +void linkslotshader(Slot &s, bool load) { if(!s.shader) return; - if(load && !s.shader->detailshader) s.shader->fixdetailshader(); - linkslotshaderparams(s.params, s.shader->detailshader, load); } -void linkvslotshader(VSlot &s, bool load) -{ +void linkvslotshader(VSlot &s, bool load) { if(!s.slot->shader) return; - Shader *sh = s.slot->shader->detailshader; linkslotshaderparams(s.params, sh, load); - if(!sh) return; } -void altshader(char *origname, char *altname) -{ +void altshader(char *origname, char *altname) { Shader *orig = shaders.access(origname), *alt = shaders.access(altname); if(!orig || !alt) return; orig->altshader = alt; orig->fixdetailshader(false); } -void fastshader(char *nice, char *fast, int *detail) -{ +void fastshader(char *nice, char *fast, int *detail) { Shader *ns = shaders.access(nice), *fs = shaders.access(fast); if(!ns || !fs) return; loopi(min(*detail+1, MAXSHADERDETAIL)) ns->fastshader[i] = fs; @@ -1106,21 +945,17 @@ ICOMMAND(isshaderdefined, "s", (char *name), intret(lookupshaderbyname(name) ? 1 static hashset shaderparamnames(256); -const char *getshaderparamname(const char *name, bool insert) -{ +const char *getshaderparamname(const char *name, bool insert) { const char *exists = shaderparamnames.find(name, NULL); if(exists || !insert) return exists; return shaderparamnames.add(newstring(name)); } -void addslotparam(const char *name, float x, float y, float z, float w) -{ +void addslotparam(const char *name, float x, float y, float z, float w) { if(name) name = getshaderparamname(name); - loopv(slotparams) - { + loopv(slotparams) { SlotShaderParam ¶m = slotparams[i]; - if(param.name==name) - { + if(param.name==name) { param.val[0] = x; param.val[1] = y; param.val[2] = z; @@ -1136,8 +971,7 @@ ICOMMAND(setuniformparam, "sffff", (char *name, float *x, float *y, float *z, fl ICOMMAND(setshaderparam, "sffff", (char *name, float *x, float *y, float *z, float *w), addslotparam(name, *x, *y, *z, *w)); ICOMMAND(defuniformparam, "sffff", (char *name, float *x, float *y, float *z, float *w), addslotparam(name, *x, *y, *z, *w)); -void cleanupshaders() -{ +void cleanupshaders() { loadedshaders = false; nullshader = hudshader = hudnotextureshader = textureshader = notextureshader = nocolorshader = stdworldshader = NULL; enumerate(shaders, Shader, s, s.cleanup()); @@ -1145,21 +979,17 @@ void cleanupshaders() glUseProgram_(0); } -void reloadshaders() -{ +void reloadshaders() { identflags &= ~IDF_PERSIST; loadshaders(); identflags |= IDF_PERSIST; linkslotshaders(); - enumerate(shaders, Shader, s, - { - if(!s.standard && !(s.type&(SHADER_DEFERRED|SHADER_INVALID)) && !s.variantshader) - { + enumerate(shaders, Shader, s, { + if(!s.standard && !(s.type&(SHADER_DEFERRED|SHADER_INVALID)) && !s.variantshader) { defformatstring(info, "shader %s", s.name); renderprogress(0.0, info); if(!s.compile()) s.cleanup(true); - loopv(s.variants) - { + loopv(s.variants) { Shader *v = s.variants[i]; if((v->reusevs && v->reusevs->invalid()) || (v->reuseps && v->reuseps->invalid()) || @@ -1171,8 +1001,7 @@ void reloadshaders() }); } -void setupblurkernel(int radius, float sigma, float *weights, float *offsets) -{ +void setupblurkernel(int radius, float sigma, float *weights, float *offsets) { if(radius<1 || radius>MAXBLURRADIUS) return; sigma *= 2*radius; float total = 1.0f/sigma; @@ -1180,8 +1009,7 @@ void setupblurkernel(int radius, float sigma, float *weights, float *offsets) offsets[0] = 0; // rely on bilinear filtering to sample 2 pixels at once // transforms a*X + b*Y into (u+v)*[X*u/(u+v) + Y*(1 - u/(u+v))] - loopi(radius) - { + loopi(radius) { float weight1 = exp(-((2*i)*(2*i)) / (2*sigma*sigma)) / sigma, weight2 = exp(-((2*i+1)*(2*i+1)) / (2*sigma*sigma)) / sigma, scale = weight1 + weight2, @@ -1194,13 +1022,11 @@ void setupblurkernel(int radius, float sigma, float *weights, float *offsets) for(int i = radius+1; i <= MAXBLURRADIUS; i++) weights[i] = offsets[i] = 0; } -void setblurshader(int pass, int size, int radius, float *weights, float *offsets) -{ +void setblurshader(int pass, int size, int radius, float *weights, float *offsets) { if(radius<1 || radius>MAXBLURRADIUS) return; static Shader *blurshader[7][2] = { { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } }; Shader *&s = blurshader[radius-1][pass]; - if(!s) - { + if(!s) { defformatstring(name, "blur%c%d", 'x'+pass, radius); s = lookupshaderbyname(name); } diff --git a/src/engine/shadowmap.cpp b/src/engine/shadowmap.cpp index 24a6fe5..1eefe4b 100644 --- a/src/engine/shadowmap.cpp +++ b/src/engine/shadowmap.cpp @@ -11,8 +11,7 @@ VARP(shadowmapdist, 128, 256, 512); VARFP(fpshadowmap, 0, 0, 1, cleanshadowmap()); VARFP(shadowmapprecision, 0, 0, 1, cleanshadowmap()); bvec shadowmapambientcolor(0, 0, 0); -HVARFR(shadowmapambient, 0, 0, 0xFFFFFF, -{ +HVARFR(shadowmapambient, 0, 0, 0xFFFFFF, { if(shadowmapambient <= 255) shadowmapambient |= (shadowmapambient<<8) | (shadowmapambient<<16); shadowmapambientcolor = bvec((shadowmapambient>>16)&0xFF, (shadowmapambient>>8)&0xFF, shadowmapambient&0xFF); }); @@ -27,36 +26,29 @@ vec shadowoffset(0, 0, 0), shadowfocus(0, 0, 0), shadowdir(0, SHADOWSKEW, 1); VAR(shadowmapcasters, 1, 0, 0); float shadowmapmaxz = 0; -void setshadowdir(int angle) -{ +void setshadowdir(int angle) { shadowdir = vec(0, SHADOWSKEW, 1); shadowdir.rotate_around_z(angle*RAD); } VARFR(shadowmapangle, 0, 0, 360, setshadowdir(shadowmapangle)); -void guessshadowdir() -{ +void guessshadowdir() { if(shadowmapangle) return; - vec dir; - { + vec dir; { vec lightpos(0, 0, 0), casterpos(0, 0, 0); int numlights = 0, numcasters = 0; const vector &ents = entities::getents(); - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; - switch(e.type) - { + switch(e.type) { case ET_LIGHT: if(!e.attr1) { lightpos.add(e.o); numlights++; } break; - case ET_MAPMODEL: casterpos.add(e.o); numcasters++; break; - default: if(e.typeyaw*RAD); - vec dir; vecfromyawpitch(camera1->yaw, camera1->pitch, 1, 0, dir); dir.z = 0; dir.mul(shadowmapradius); - vec dirx, diry; vecfromyawpitch(camera1->yaw, 0, 0, 1, dirx); vecfromyawpitch(camera1->yaw, 0, 1, 0, diry); shadowoffset.x = -fmod(dirx.dot(camera1->o) - skewdir.x*camera1->o.z, 2.0f*shadowmapradius/vieww); shadowoffset.y = -fmod(diry.dot(camera1->o) - skewdir.y*camera1->o.z, 2.0f*shadowmapradius/viewh); - shadowmatrix.ortho(-shadowmapradius, shadowmapradius, -shadowmapradius, shadowmapradius, -shadowmapdist, shadowmapdist); shadowmatrix.mul(matrix3(vec(1, 0, 0), vec(0, 1, 0), vec(skewdir.x, skewdir.y, 1))); shadowmatrix.translate(skewdir.x*shadowmapheight + shadowoffset.x, skewdir.y*shadowmapheight + shadowoffset.y + dir.magnitude(), -shadowmapheight); shadowmatrix.rotate_around_z((camera1->yaw+180)*-RAD); shadowmatrix.translate(vec(camera1->o).neg()); GLOBALPARAM(shadowmatrix, shadowmatrix); - shadowfocus = camera1->o; shadowfocus.add(dir); shadowfocus.add(vec(shadowdir).mul(shadowmapheight)); shadowfocus.add(dirx.mul(shadowoffset.x)); shadowfocus.add(diry.mul(shadowoffset.y)); - gle::colorf(0, 0, 0); - GLOBALPARAMF(shadowmapbias, -shadowmapbias/float(shadowmapdist), 1 - (shadowmapbias + (smoothshadowmappeel ? 0 : shadowmappeelbias))/float(shadowmapdist)); - shadowmapcasters = 0; shadowmapmaxz = shadowfocus.z - shadowmapdist; shadowmapping = true; rendergame(); shadowmapping = false; shadowmapmaxz = min(shadowmapmaxz, shadowfocus.z); - - if(shadowmapcasters && smdepthpeel) - { + if(shadowmapcasters && smdepthpeel) { int sx, sy, sw, sh; bool scissoring = rtscissor && scissorblur(sx, sy, sw, sh) && sw > 0 && sh > 0; if(scissoring) glScissor(sx, sy, sw, sh); if(!rtscissor || scissoring) rendershadowmapreceivers(); } - return shadowmapcasters>0; } } shadowmaptex; -void cleanshadowmap() -{ +void cleanshadowmap() { shadowmaptex.cleanup(true); } -void calcshadowmapbb(const vec &o, float xyrad, float zrad, float &x1, float &y1, float &x2, float &y2) -{ +void calcshadowmapbb(const vec &o, float xyrad, float zrad, float &x1, float &y1, float &x2, float &y2) { vec skewdir(shadowdir); skewdir.rotate_around_z(-camera1->yaw*RAD); - vec ro(o); ro.sub(camera1->o); ro.rotate_around_z(-(camera1->yaw+180)*RAD); ro.x += ro.z * skewdir.x + shadowoffset.x; ro.y += ro.z * skewdir.y + shadowmapradius * cosf(camera1->pitch*RAD) + shadowoffset.y; - vec high(ro), low(ro); high.x += zrad * skewdir.x; high.y += zrad * skewdir.y; low.x -= zrad * skewdir.x; low.y -= zrad * skewdir.y; - x1 = (min(high.x, low.x) - xyrad) / shadowmapradius; y1 = (min(high.y, low.y) - xyrad) / shadowmapradius; x2 = (max(high.x, low.x) + xyrad) / shadowmapradius; y2 = (max(high.y, low.y) + xyrad) / shadowmapradius; } -bool addshadowmapcaster(const vec &o, float xyrad, float zrad) -{ +bool addshadowmapcaster(const vec &o, float xyrad, float zrad) { if(o.z + zrad <= shadowfocus.z - shadowmapdist || o.z - zrad >= shadowfocus.z) return false; - shadowmapmaxz = max(shadowmapmaxz, o.z + zrad); - float x1, y1, x2, y2; calcshadowmapbb(o, xyrad, zrad, x1, y1, x2, y2); - if(!shadowmaptex.addblurtiles(x1, y1, x2, y2, 2)) return false; - shadowmapcasters++; return true; } -bool isshadowmapreceiver(vtxarray *va) -{ +bool isshadowmapreceiver(vtxarray *va) { if(!shadowmap || !shadowmapcasters) return false; - if(va->shadowmapmax.z <= shadowfocus.z - shadowmapdist || va->shadowmapmin.z >= shadowmapmaxz) return false; - float xyrad = SQRT2*0.5f*max(va->shadowmapmax.x-va->shadowmapmin.x, va->shadowmapmax.y-va->shadowmapmin.y), zrad = 0.5f*(va->shadowmapmax.z-va->shadowmapmin.z), x1, y1, x2, y2; if(xyrad<0 || zrad<0) return false; - vec center = vec(va->shadowmapmin).add(vec(va->shadowmapmax)).mul(0.5f); calcshadowmapbb(center, xyrad, zrad, x1, y1, x2, y2); - return shadowmaptex.checkblurtiles(x1, y1, x2, y2, 2); #if 0 @@ -244,8 +200,7 @@ bool isshadowmapreceiver(vtxarray *va) #endif } -bool isshadowmapcaster(const vec &o, float rad) -{ +bool isshadowmapcaster(const vec &o, float rad) { // cheaper inexact test float dz = o.z - shadowfocus.z; float cx = shadowfocus.x + dz*shadowdir.x, cy = shadowfocus.y + dz*shadowdir.y; @@ -258,22 +213,16 @@ bool isshadowmapcaster(const vec &o, float rad) return true; } -void pushshadowmap() -{ +void pushshadowmap() { if(!shadowmap || !shadowmaptex.rendertex) return; - glActiveTexture_(GL_TEXTURE7); glBindTexture(GL_TEXTURE_2D, shadowmaptex.rendertex); - matrix4 m = shadowmatrix; m.projective(-1, 1-shadowmapbias/float(shadowmapdist)); GLOBALPARAM(shadowmapproject, m); - glActiveTexture_(GL_TEXTURE0); - float r, g, b; - if(!shadowmapambient) - { + if(!shadowmapambient) { r = max(25.0f, 2.0f*ambientcolor[0]); g = max(25.0f, 2.0f*ambientcolor[1]); b = max(25.0f, 2.0f*ambientcolor[2]); @@ -282,14 +231,7 @@ void pushshadowmap() GLOBALPARAMF(shadowmapambient, r/255.0f, g/255.0f, b/255.0f); } -void popshadowmap() -{ - if(!shadowmap || !shadowmaptex.rendertex) return; -} - -void rendershadowmap() -{ +void rendershadowmap() { if(!shadowmap) return; - shadowmaptex.render(1< weights[k]) - { - for(int l = min(sorted-1, 2); l >= k; l--) - { + loopk(sorted) if(weight > weights[k]) { + for(int l = min(sorted-1, 2); l >= k; l--) { weights[l+1] = weights[l]; bones[l+1] = bones[l]; } @@ -76,9 +59,7 @@ struct skelmodel : animmodel bones[sorted] = bone; return sorted+1; } - - void finalize(int sorted) - { + void finalize(int sorted) { loopj(4-sorted) { weights[sorted+j] = 0; bones[sorted+j] = 0; } if(sorted <= 0) return; float total = 0; @@ -86,26 +67,20 @@ struct skelmodel : animmodel total = 1.0f/total; loopj(sorted) weights[j] *= total; } - - void serialize(vvertw &v) - { - if(interpindex >= 0) - { + void serialize(vvertw &v) { + if(interpindex >= 0) { v.weights[0] = 255; loopk(3) v.weights[k+1] = 0; v.bones[0] = 2*interpindex; loopk(3) v.bones[k+1] = v.bones[0]; } - else - { + else { int total = 0; loopk(4) total += (v.weights[k] = uchar(0.5f + weights[k]*255)); - while(total > 255) - { + while(total > 255) { loopk(4) if(v.weights[k] > 0 && total > 255) { v.weights[k]--; total--; } } - while(total < 255) - { + while(total < 255) { loopk(4) if(v.weights[k] < 255 && total < 255) { v.weights[k]++; total++; } } loopk(4) v.bones[k] = 2*interpbones[k]; @@ -113,118 +88,79 @@ struct skelmodel : animmodel } }; - - struct animcacheentry - { + struct animcacheentry { animstate as[MAXANIMPARTS]; float pitch; int millis; uchar *partmask; ragdolldata *ragdoll; - - animcacheentry() : ragdoll(NULL) - { + animcacheentry() : ragdoll(NULL) { loopk(MAXANIMPARTS) as[k].cur.fr1 = as[k].prev.fr1 = -1; } - - bool operator==(const animcacheentry &c) const - { + bool operator==(const animcacheentry &c) const { loopi(MAXANIMPARTS) if(as[i]!=c.as[i]) return false; return pitch==c.pitch && partmask==c.partmask && ragdoll==c.ragdoll && (!ragdoll || min(millis, c.millis) >= ragdoll->lastmove); } }; - - struct vbocacheentry : animcacheentry - { + struct vbocacheentry : animcacheentry { GLuint vbuf; int owner; - vbocacheentry() : vbuf(0), owner(-1) {} }; - - struct skelcacheentry : animcacheentry - { + struct skelcacheentry : animcacheentry { dualquat *bdata; int version; bool dirty; - skelcacheentry() : bdata(NULL), version(-1), dirty(false) {} - - void nextversion() - { + void nextversion() { version = Shader::uniformlocversion(); dirty = true; } }; - - struct blendcacheentry : skelcacheentry - { + struct blendcacheentry : skelcacheentry { int owner; - blendcacheentry() : owner(-1) {} }; - struct skelmeshgroup; - - struct skelmesh : mesh - { + struct skelmesh : mesh { vert *verts; bumpvert *bumpverts; tri *tris; int numverts, numtris, maxweights; - int voffset, eoffset, elen; ushort minvert, maxvert; - - skelmesh() : verts(NULL), bumpverts(NULL), tris(NULL), numverts(0), numtris(0), maxweights(0) - { + skelmesh() : verts(NULL), bumpverts(NULL), tris(NULL), numverts(0), numtris(0), maxweights(0) { } - - virtual ~skelmesh() - { + virtual ~skelmesh() { DELETEA(verts); DELETEA(bumpverts); DELETEA(tris); } - - int addblendcombo(const blendcombo &c) - { + int addblendcombo(const blendcombo &c) { maxweights = max(maxweights, c.size()); return ((skelmeshgroup *)group)->addblendcombo(c); } - - void smoothnorms(float limit = 0, bool areaweight = true) - { + void smoothnorms(float limit = 0, bool areaweight = true) { mesh::smoothnorms(verts, numverts, tris, numtris, limit, areaweight); } - - void buildnorms(bool areaweight = true) - { + void buildnorms(bool areaweight = true) { mesh::buildnorms(verts, numverts, tris, numtris, areaweight); } - - void calctangents(bool areaweight = true) - { + void calctangents(bool areaweight = true) { if(bumpverts) return; bumpverts = new bumpvert[numverts]; mesh::calctangents(bumpverts, verts, verts, numverts, tris, numtris, areaweight); } - - void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) - { - loopj(numverts) - { + void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) { + loopj(numverts) { vec v = m.transform(verts[j].pos); - loopi(3) - { + loopi(3) { bbmin[i] = min(bbmin[i], v[i]); bbmax[i] = max(bbmax[i], v[i]); } } } - - void genBIH(BIH::mesh &m) - { + void genBIH(BIH::mesh &m) { m.tris = (const BIH::tri *)tris; m.numtris = numtris; m.pos = (const uchar *)&verts->pos; @@ -232,44 +168,33 @@ struct skelmodel : animmodel m.tc = (const uchar *)&verts->tc; m.tcstride = sizeof(vert); } - - static inline void assignvert(vvertn &vv, int j, vert &v, blendcombo &c) - { + static inline void assignvert(vvertn &vv, int j, vert &v, blendcombo &c) { vv.pos = v.pos; vv.norm = v.norm; vv.tc = v.tc; } - - inline void assignvert(vvertbump &vv, int j, vert &v, blendcombo &c) - { + inline void assignvert(vvertbump &vv, int j, vert &v, blendcombo &c) { vv.pos = v.pos; vv.tc = v.tc; vv.tangent = bumpverts[j].tangent; } - - static inline void assignvert(vvertnw &vv, int j, vert &v, blendcombo &c) - { + static inline void assignvert(vvertnw &vv, int j, vert &v, blendcombo &c) { vv.pos = v.pos; vv.norm = v.norm; vv.tc = v.tc; c.serialize(vv); } - - inline void assignvert(vvertbumpw &vv, int j, vert &v, blendcombo &c) - { + inline void assignvert(vvertbumpw &vv, int j, vert &v, blendcombo &c) { vv.pos = v.pos; vv.tc = v.tc; vv.tangent = bumpverts[j].tangent; c.serialize(vv); } - template - int genvbo(vector &idxs, int offset, vector &vverts) - { + int genvbo(vector &idxs, int offset, vector &vverts) { voffset = offset; eoffset = idxs.length(); - loopi(numverts) - { + loopi(numverts) { vert &v = verts[i]; assignvert(vverts.add(), i, v, ((skelmeshgroup *)group)->blendcombos[v.blend]); } @@ -279,25 +204,20 @@ struct skelmodel : animmodel maxvert = voffset + numverts-1; return numverts; } - template - int genvbo(vector &idxs, int offset, vector &vverts, int *htdata, int htlen) - { + int genvbo(vector &idxs, int offset, vector &vverts, int *htdata, int htlen) { voffset = offset; eoffset = idxs.length(); minvert = 0xFFFF; - loopi(numtris) - { + loopi(numtris) { tri &t = tris[i]; - loopj(3) - { + loopj(3) { int index = t.vert[j]; vert &v = verts[index]; T vv; assignvert(vv, index, v, ((skelmeshgroup *)group)->blendcombos[v.blend]); int htidx = hthash(v.pos)&(htlen-1); - loopk(htlen) - { + loopk(htlen) { int &vidx = htdata[(htidx+k)&(htlen-1)]; if(vidx < 0) { vidx = idxs.add(ushort(vverts.length())); vverts.add(vv); break; } else if(!memcmp(&vverts[vidx], &vv, sizeof(vv))) { minvert = min(minvert, idxs.add(ushort(vidx))); break; } @@ -309,15 +229,11 @@ struct skelmodel : animmodel maxvert = max(minvert, ushort(vverts.length()-1)); return vverts.length()-voffset; } - - int genvbo(vector &idxs, int offset) - { + int genvbo(vector &idxs, int offset) { loopi(numverts) verts[i].interpindex = ((skelmeshgroup *)group)->remapblend(verts[i].blend); - voffset = offset; eoffset = idxs.length(); - loopi(numtris) - { + loopi(numtris) { tri &t = tris[i]; loopj(3) idxs.add(voffset+t.vert[j]); } @@ -326,28 +242,21 @@ struct skelmodel : animmodel elen = idxs.length()-eoffset; return numverts; } - template - static inline void fillvert(T &vv, int j, vert &v) - { + static inline void fillvert(T &vv, int j, vert &v) { vv.tc = v.tc; } - template - void fillverts(T *vdata) - { + void fillverts(T *vdata) { vdata += voffset; loopi(numverts) fillvert(vdata[i], i, verts[i]); } - - void interpverts(const dualquat * RESTRICT bdata1, const dualquat * RESTRICT bdata2, bool tangents, void * RESTRICT vdata, skin &s) - { + void interpverts(const dualquat * RESTRICT bdata1, const dualquat * RESTRICT bdata2, bool tangents, void * RESTRICT vdata, skin &s) { const int blendoffset = ((skelmeshgroup *)group)->skel->numgpubones; bdata2 -= blendoffset; - #define IPLOOP(type, dosetup, dotransform) \ - loopi(numverts) \ - { \ + loopi(numverts) { \ + \ const vert &src = verts[i]; \ type &dst = ((type * RESTRICT)vdata)[i]; \ dosetup; \ @@ -355,36 +264,26 @@ struct skelmodel : animmodel dst.pos = b.transform(src.pos); \ dotransform; \ } - - if(tangents) - { - IPLOOP(vvertbump, bumpvert &bsrc = bumpverts[i], - { + if(tangents) { + IPLOOP(vvertbump, bumpvert &bsrc = bumpverts[i], { quat q = b.transform(bsrc.tangent); fixqtangent(q, bsrc.tangent.w); dst.tangent = q; }); } - else - { - IPLOOP(vvertn, , - { + else { + IPLOOP(vvertn, , { dst.norm = b.transformnormal(src.norm); }); } - #undef IPLOOP } - - void setshader(Shader *s) - { + void setshader(Shader *s) { skelmeshgroup *g = (skelmeshgroup *)group; if(!g->skel->usegpuskel) s->set(); else s->setvariant(min(maxweights, g->vweights)-1, 0); } - - void render(const animstate *as, skin &s, vbocacheentry &vc) - { + void render(const animstate *as, skin &s, vbocacheentry &vc) { if(!Shader::lastshader) return; glDrawRangeElements_(GL_TRIANGLES, minvert, maxvert, elen, GL_UNSIGNED_SHORT, &((skelmeshgroup *)group)->edata[eoffset]); glde++; @@ -392,73 +291,50 @@ struct skelmodel : animmodel } }; - - struct tag - { + struct tag { char *name; int bone; matrix4x3 matrix; - tag() : name(NULL) {} ~tag() { DELETEA(name); } }; - - struct skelanimspec - { + struct skelanimspec { char *name; int frame, range; - skelanimspec() : name(NULL), frame(0), range(0) {} - ~skelanimspec() - { + ~skelanimspec() { DELETEA(name); } }; - - struct boneinfo - { + struct boneinfo { const char *name; int parent, children, next, group, scheduled, interpindex, interpparent, ragdollindex, correctindex; float pitchscale, pitchoffset, pitchmin, pitchmax; dualquat base, invbase; - boneinfo() : name(NULL), parent(-1), children(-1), next(-1), group(INT_MAX), scheduled(-1), interpindex(-1), interpparent(-1), ragdollindex(-1), correctindex(-1), pitchscale(0), pitchoffset(0), pitchmin(0), pitchmax(0) {} - ~boneinfo() - { + ~boneinfo() { DELETEA(name); } }; - - struct antipode - { + struct antipode { int parent, child; - antipode(int parent, int child) : parent(parent), child(child) {} }; - - struct pitchdep - { + struct pitchdep { int bone, parent; dualquat pose; }; - - struct pitchtarget - { + struct pitchtarget { int bone, frame, corrects, deps; float pitchmin, pitchmax, deviated; dualquat pose; }; - - struct pitchcorrect - { + struct pitchcorrect { int bone, target, parent; float pitchmin, pitchmax, pitchscale, pitchangle, pitchtotal; - pitchcorrect() : parent(-1), pitchangle(0), pitchtotal(0) {} }; - - struct skeleton - { + struct skeleton { char *name; int shared; vector users; @@ -472,36 +348,25 @@ struct skelmodel : animmodel vector pitchdeps; vector pitchtargets; vector pitchcorrects; - bool usegpuskel; vector skelcache; hashtable blendoffsets; - - skeleton() : name(NULL), shared(0), bones(NULL), numbones(0), numinterpbones(0), numgpubones(0), numframes(0), framebones(NULL), ragdoll(NULL), usegpuskel(false), blendoffsets(32) - { + skeleton() : name(NULL), shared(0), bones(NULL), numbones(0), numinterpbones(0), numgpubones(0), numframes(0), framebones(NULL), ragdoll(NULL), usegpuskel(false), blendoffsets(32) { } - - ~skeleton() - { + ~skeleton() { DELETEA(name); DELETEA(bones); DELETEA(framebones); DELETEP(ragdoll); - loopv(skelcache) - { + loopv(skelcache) { DELETEA(skelcache[i].bdata); } } - - skelanimspec *findskelanim(const char *name, char sep = '\0') - { + skelanimspec *findskelanim(const char *name, char sep = '\0') { int len = sep ? strlen(name) : 0; - loopv(skelanims) - { - if(skelanims[i].name) - { - if(sep) - { + loopv(skelanims) { + if(skelanims[i].name) { + if(sep) { const char *end = strchr(skelanims[i].name, ':'); if(end && end - skelanims[i].name == len && !memcmp(name, skelanims[i].name, len)) return &skelanims[i]; } @@ -510,38 +375,28 @@ struct skelmodel : animmodel } return NULL; } - - skelanimspec &addskelanim(const char *name) - { + skelanimspec &addskelanim(const char *name) { skelanimspec &sa = skelanims.add(); sa.name = name ? newstring(name) : NULL; return sa; } - - int findbone(const char *name) - { + int findbone(const char *name) { loopi(numbones) if(bones[i].name && !strcmp(bones[i].name, name)) return i; return -1; } - - int findtag(const char *name) - { + int findtag(const char *name) { loopv(tags) if(!strcmp(tags[i].name, name)) return i; return -1; } - - bool addtag(const char *name, int bone, const matrix4x3 &matrix) - { + bool addtag(const char *name, int bone, const matrix4x3 &matrix) { int idx = findtag(name); - if(idx >= 0) - { + if(idx >= 0) { if(!testtags) return false; tag &t = tags[idx]; t.bone = bone; t.matrix = matrix; } - else - { + else { tag &t = tags.add(); t.name = newstring(name); t.bone = bone; @@ -549,67 +404,52 @@ struct skelmodel : animmodel } return true; } - - void calcantipodes() - { + void calcantipodes() { antipodes.shrink(0); vector schedule; - loopi(numbones) - { - if(bones[i].group >= numbones) - { + loopi(numbones) { + if(bones[i].group >= numbones) { bones[i].scheduled = schedule.length(); schedule.add(i); } else bones[i].scheduled = -1; } - loopv(schedule) - { + loopv(schedule) { int bone = schedule[i]; const boneinfo &info = bones[bone]; - loopj(numbones) if(abs(bones[j].group) == bone && bones[j].scheduled < 0) - { + loopj(numbones) if(abs(bones[j].group) == bone && bones[j].scheduled < 0) { antipodes.add(antipode(info.interpindex, bones[j].interpindex)); bones[j].scheduled = schedule.length(); schedule.add(j); } - if(i + 1 == schedule.length()) - { + if(i + 1 == schedule.length()) { int conflict = INT_MAX; loopj(numbones) if(bones[j].group < numbones && bones[j].scheduled < 0) conflict = min(conflict, abs(bones[j].group)); - if(conflict < numbones) - { + if(conflict < numbones) { bones[conflict].scheduled = schedule.length(); schedule.add(conflict); } } } } - - void remapbones() - { - loopi(numbones) - { + void remapbones() { + loopi(numbones) { boneinfo &info = bones[i]; info.interpindex = -1; info.ragdollindex = -1; } numgpubones = 0; - loopv(users) - { + loopv(users) { skelmeshgroup *group = users[i]; - loopvj(group->blendcombos) - { + loopvj(group->blendcombos) { blendcombo &c = group->blendcombos[j]; - loopk(4) - { + loopk(4) { if(!c.weights[k]) { c.interpbones[k] = k > 0 ? c.interpbones[k-1] : 0; continue; } boneinfo &info = bones[c.bones[k]]; if(info.interpindex < 0) info.interpindex = numgpubones++; c.interpbones[k] = info.interpindex; if(info.group < 0) continue; - loopl(4) - { + loopl(4) { if(!c.weights[l]) break; if(l == k) continue; int parent = c.bones[l]; @@ -623,41 +463,33 @@ struct skelmodel : animmodel } } numinterpbones = numgpubones; - loopv(tags) - { + loopv(tags) { boneinfo &info = bones[tags[i].bone]; if(info.interpindex < 0) info.interpindex = numinterpbones++; } - if(ragdoll) - { - loopv(ragdoll->joints) - { + if(ragdoll) { + loopv(ragdoll->joints) { boneinfo &info = bones[ragdoll->joints[i].bone]; if(info.interpindex < 0) info.interpindex = numinterpbones++; info.ragdollindex = i; } } - loopi(numbones) - { + loopi(numbones) { boneinfo &info = bones[i]; if(info.interpindex < 0) continue; for(int parent = info.parent; parent >= 0 && bones[parent].interpindex < 0; parent = bones[parent].parent) bones[parent].interpindex = numinterpbones++; } - loopi(numbones) - { + loopi(numbones) { boneinfo &info = bones[i]; if(info.interpindex < 0) continue; info.interpparent = info.parent >= 0 ? bones[info.parent].interpindex : -1; } - if(ragdoll) - { - loopi(numbones) - { + if(ragdoll) { + loopi(numbones) { boneinfo &info = bones[i]; if(info.interpindex < 0 || info.ragdollindex >= 0) continue; - for(int parent = info.parent; parent >= 0; parent = bones[parent].parent) - { + for(int parent = info.parent; parent >= 0; parent = bones[parent].parent) { if(bones[parent].ragdollindex >= 0) { ragdoll->addreljoint(i, bones[parent].ragdollindex); break; } } } @@ -665,19 +497,14 @@ struct skelmodel : animmodel calcantipodes(); } - - void addpitchdep(int bone, int frame) - { - for(; bone >= 0; bone = bones[bone].parent) - { + void addpitchdep(int bone, int frame) { + for(; bone >= 0; bone = bones[bone].parent) { int pos = pitchdeps.length(); - loopvj(pitchdeps) if(bone <= pitchdeps[j].bone) - { + loopvj(pitchdeps) if(bone <= pitchdeps[j].bone) { if(bone == pitchdeps[j].bone) goto nextbone; pos = j; break; - } - { + } { pitchdep d; d.bone = bone; d.parent = -1; @@ -687,66 +514,51 @@ struct skelmodel : animmodel nextbone:; } } - - int findpitchdep(int bone) - { + int findpitchdep(int bone) { loopv(pitchdeps) if(bone <= pitchdeps[i].bone) return bone == pitchdeps[i].bone ? i : -1; return -1; } - - int findpitchcorrect(int bone) - { + int findpitchcorrect(int bone) { loopv(pitchcorrects) if(bone <= pitchcorrects[i].bone) return bone == pitchcorrects[i].bone ? i : -1; return -1; } - - void initpitchdeps() - { + void initpitchdeps() { pitchdeps.setsize(0); if(pitchtargets.empty()) return; - loopv(pitchtargets) - { + loopv(pitchtargets) { pitchtarget &t = pitchtargets[i]; t.deps = -1; addpitchdep(t.bone, t.frame); } - loopv(pitchdeps) - { + loopv(pitchdeps) { pitchdep &d = pitchdeps[i]; int parent = bones[d.bone].parent; - if(parent >= 0) - { + if(parent >= 0) { int j = findpitchdep(parent); - if(j >= 0) - { + if(j >= 0) { d.parent = j; d.pose.mul(pitchdeps[j].pose, dualquat(d.pose)); } } } - loopv(pitchtargets) - { + loopv(pitchtargets) { pitchtarget &t = pitchtargets[i]; int j = findpitchdep(t.bone); - if(j >= 0) - { + if(j >= 0) { t.deps = j; t.pose = pitchdeps[j].pose; } t.corrects = -1; - for(int parent = t.bone; parent >= 0; parent = bones[parent].parent) - { + for(int parent = t.bone; parent >= 0; parent = bones[parent].parent) { t.corrects = findpitchcorrect(parent); if(t.corrects >= 0) break; } } - loopv(pitchcorrects) - { + loopv(pitchcorrects) { pitchcorrect &c = pitchcorrects[i]; bones[c.bone].correctindex = i; c.parent = -1; - for(int parent = c.bone;;) - { + for(int parent = c.bone;;) { parent = bones[parent].parent; if(parent < 0) break; c.parent = findpitchcorrect(parent); @@ -754,56 +566,42 @@ struct skelmodel : animmodel } } } - - void optimize() - { + void optimize() { cleanup(); if(ragdoll) ragdoll->setup(); remapbones(); initpitchdeps(); } - - void expandbonemask(uchar *expansion, int bone, int val) - { + void expandbonemask(uchar *expansion, int bone, int val) { expansion[bone] = val; bone = bones[bone].children; while(bone>=0) { expandbonemask(expansion, bone, val); bone = bones[bone].next; } } - - void applybonemask(ushort *mask, uchar *partmask, int partindex) - { + void applybonemask(ushort *mask, uchar *partmask, int partindex) { if(!mask || *mask==BONEMASK_END) return; uchar *expansion = new uchar[numbones]; memset(expansion, *mask&BONEMASK_NOT ? 1 : 0, numbones); - while(*mask!=BONEMASK_END) - { + while(*mask!=BONEMASK_END) { expandbonemask(expansion, *mask&BONEMASK_BONE, *mask&BONEMASK_NOT ? 0 : 1); mask++; } loopi(numbones) if(expansion[i]) partmask[i] = partindex; delete[] expansion; } - - void linkchildren() - { - loopi(numbones) - { + void linkchildren() { + loopi(numbones) { boneinfo &b = bones[i]; b.children = -1; if(b.parent<0) b.next = -1; - else - { + else { b.next = bones[b.parent].children; bones[b.parent].children = i; } } } - int availgpubones() const { return min(maxvsuniforms - reservevpparams - 10, maxskelanimdata) / 2; } bool gpuaccelerate() const { return numframes && gpuskel && numgpubones<=availgpubones(); } - - float calcdeviation(const vec &axis, const vec &forward, const dualquat &pose1, const dualquat &pose2) - { + float calcdeviation(const vec &axis, const vec &forward, const dualquat &pose1, const dualquat &pose2) { vec forward1 = pose1.transformnormal(forward).project(axis).normalize(), forward2 = pose2.transformnormal(forward).project(axis).normalize(), daxis = vec().cross(forward1, forward2); @@ -811,35 +609,28 @@ struct skelmodel : animmodel if(daxis.dot(axis) < 0) dy = -dy; return atan2f(dy, dx)/RAD; } - - void calcpitchcorrects(float pitch, const vec &axis, const vec &forward) - { - loopv(pitchtargets) - { + void calcpitchcorrects(float pitch, const vec &axis, const vec &forward) { + loopv(pitchtargets) { pitchtarget &t = pitchtargets[i]; t.deviated = calcdeviation(axis, forward, t.pose, pitchdeps[t.deps].pose); } - loopv(pitchcorrects) - { + loopv(pitchcorrects) { pitchcorrect &c = pitchcorrects[i]; c.pitchangle = c.pitchtotal = 0; } - loopvj(pitchtargets) - { + loopvj(pitchtargets) { pitchtarget &t = pitchtargets[j]; float tpitch = pitch - t.deviated; for(int parent = t.corrects; parent >= 0; parent = pitchcorrects[parent].parent) tpitch -= pitchcorrects[parent].pitchangle; if(t.pitchmin || t.pitchmax) tpitch = clamp(tpitch, t.pitchmin, t.pitchmax); - loopv(pitchcorrects) - { + loopv(pitchcorrects) { pitchcorrect &c = pitchcorrects[i]; if(c.target != j) continue; float total = c.parent >= 0 ? pitchcorrects[c.parent].pitchtotal : 0, avail = tpitch - total, used = tpitch*c.pitchscale; - if(c.pitchmin || c.pitchmax) - { + if(c.pitchmin || c.pitchmax) { if(used < 0) used = clamp(c.pitchmin, used, 0.0f); else used = clamp(c.pitchmax, 0.0f, used); } @@ -850,39 +641,32 @@ struct skelmodel : animmodel } } } - #define INTERPBONE(bone) \ const animstate &s = as[partmask[bone]]; \ const framedata &f = partframes[partmask[bone]]; \ dualquat d; \ (d = f.fr1[bone]).mul((1-s.cur.t)*s.interp); \ d.accumulate(f.fr2[bone], s.cur.t*s.interp); \ - if(s.interp<1) \ - { \ + if(s.interp<1) { \ + \ d.accumulate(f.pfr1[bone], (1-s.prev.t)*(1-s.interp)); \ d.accumulate(f.pfr2[bone], s.prev.t*(1-s.interp)); \ } - - void interpbones(const animstate *as, float pitch, const vec &axis, const vec &forward, int numanimparts, const uchar *partmask, skelcacheentry &sc) - { + void interpbones(const animstate *as, float pitch, const vec &axis, const vec &forward, int numanimparts, const uchar *partmask, skelcacheentry &sc) { if(!sc.bdata) sc.bdata = new dualquat[numinterpbones]; sc.nextversion(); - struct framedata - { + struct framedata { const dualquat *fr1, *fr2, *pfr1, *pfr2; } partframes[MAXANIMPARTS]; - loopi(numanimparts) - { + loopi(numanimparts) { partframes[i].fr1 = &framebones[as[i].cur.fr1*numbones]; partframes[i].fr2 = &framebones[as[i].cur.fr2*numbones]; - if(as[i].interp<1) - { + if(as[i].interp<1) { partframes[i].pfr1 = &framebones[as[i].prev.fr1*numbones]; partframes[i].pfr2 = &framebones[as[i].prev.fr2*numbones]; } } - loopv(pitchdeps) - { + loopv(pitchdeps) { pitchdep &p = pitchdeps[i]; INTERPBONE(p.bone); d.normalize(); @@ -890,8 +674,7 @@ struct skelmodel : animmodel else p.pose = d; } calcpitchcorrects(pitch, axis, forward); - loopi(numbones) if(bones[i].interpindex>=0) - { + loopi(numbones) if(bones[i].interpindex>=0) { INTERPBONE(i); const boneinfo &b = bones[i]; d.normalize(); @@ -907,49 +690,39 @@ struct skelmodel : animmodel } loopv(antipodes) sc.bdata[antipodes[i].child].fixantipodal(sc.bdata[antipodes[i].parent]); } - - void initragdoll(ragdolldata &d, skelcacheentry &sc, part *p) - { + void initragdoll(ragdolldata &d, skelcacheentry &sc, part *p) { const dualquat *bdata = sc.bdata; - loopv(ragdoll->joints) - { + loopv(ragdoll->joints) { const ragdollskel::joint &j = ragdoll->joints[i]; const boneinfo &b = bones[j.bone]; const dualquat &q = bdata[b.interpindex]; - loopk(3) if(j.vert[k] >= 0) - { + loopk(3) if(j.vert[k] >= 0) { ragdollskel::vert &v = ragdoll->verts[j.vert[k]]; ragdolldata::vert &dv = d.verts[j.vert[k]]; dv.pos.add(q.transform(v.pos).mul(v.weight)); } } - if(ragdoll->animjoints) loopv(ragdoll->joints) - { + if(ragdoll->animjoints) loopv(ragdoll->joints) { const ragdollskel::joint &j = ragdoll->joints[i]; const boneinfo &b = bones[j.bone]; const dualquat &q = bdata[b.interpindex]; d.calcanimjoint(i, matrix4x3(q)); } - loopv(ragdoll->verts) - { + loopv(ragdoll->verts) { ragdolldata::vert &dv = d.verts[i]; matrixstack[matrixpos].transform(vec(dv.pos).add(p->translate).mul(p->model->scale), dv.pos); } - loopv(ragdoll->reljoints) - { + loopv(ragdoll->reljoints) { const ragdollskel::reljoint &r = ragdoll->reljoints[i]; const ragdollskel::joint &j = ragdoll->joints[r.parent]; const boneinfo &br = bones[r.bone], &bj = bones[j.bone]; d.reljoints[i].mul(dualquat(bdata[bj.interpindex]).invert(), bdata[br.interpindex]); } } - - void genragdollbones(ragdolldata &d, skelcacheentry &sc, part *p) - { + void genragdollbones(ragdolldata &d, skelcacheentry &sc, part *p) { if(!sc.bdata) sc.bdata = new dualquat[numinterpbones]; sc.nextversion(); - loopv(ragdoll->joints) - { + loopv(ragdoll->joints) { const ragdollskel::joint &j = ragdoll->joints[i]; const boneinfo &b = bones[j.bone]; vec pos(0, 0, 0); @@ -959,8 +732,7 @@ struct skelmodel : animmodel m.mul(d.tris[j.tri], pos, d.animjoints ? d.animjoints[i] : j.orient); sc.bdata[b.interpindex] = dualquat(m); } - loopv(ragdoll->reljoints) - { + loopv(ragdoll->reljoints) { const ragdollskel::reljoint &r = ragdoll->reljoints[i]; const ragdollskel::joint &j = ragdoll->joints[r.parent]; const boneinfo &br = bones[r.bone], &bj = bones[j.bone]; @@ -968,19 +740,14 @@ struct skelmodel : animmodel } loopv(antipodes) sc.bdata[antipodes[i].child].fixantipodal(sc.bdata[antipodes[i].parent]); } - - void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) - { + void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) { matrix4x3 t; t.mul(bones[tags[i].bone].base, tags[i].matrix); t.posttranslate(p->translate, p->model->scale); n.mul(m, t); } - - void calctags(part *p, skelcacheentry *sc = NULL) - { - loopv(p->links) - { + void calctags(part *p, skelcacheentry *sc = NULL) { + loopv(p->links) { linkedpart &l = p->links[i]; tag &t = tags[l.tag]; dualquat q; @@ -992,11 +759,8 @@ struct skelmodel : animmodel l.matrix = m; } } - - void cleanup(bool full = true) - { - loopv(skelcache) - { + void cleanup(bool full = true) { + loopv(skelcache) { skelcacheentry &sc = skelcache[i]; loopj(MAXANIMPARTS) sc.as[j].cur.fr1 = -1; DELETEA(sc.bdata); @@ -1005,31 +769,22 @@ struct skelmodel : animmodel blendoffsets.clear(); if(full) loopv(users) users[i]->cleanup(); } - bool canpreload() { return !numframes || gpuaccelerate(); } - - void preload() - { + void preload() { if(!numframes) return; - if(skelcache.empty()) - { + if(skelcache.empty()) { usegpuskel = gpuaccelerate(); } } - - skelcacheentry &checkskelcache(part *p, const animstate *as, float pitch, const vec &axis, const vec &forward, ragdolldata *rdata) - { - if(skelcache.empty()) - { + skelcacheentry &checkskelcache(part *p, const animstate *as, float pitch, const vec &axis, const vec &forward, ragdolldata *rdata) { + if(skelcache.empty()) { usegpuskel = gpuaccelerate(); } - int numanimparts = ((skelpart *)as->owner)->numanimparts; uchar *partmask = ((skelpart *)as->owner)->partmask; skelcacheentry *sc = NULL; bool match = false; - loopv(skelcache) - { + loopv(skelcache) { skelcacheentry &c = skelcache[i]; loopj(numanimparts) if(c.as[j]!=as[j]) goto mismatch; if(c.pitch != pitch || c.partmask != partmask || c.ragdoll != rdata || (rdata && c.millis < rdata->lastmove)) goto mismatch; @@ -1040,8 +795,7 @@ struct skelmodel : animmodel if(c.millis < lastmillis) { sc = &c; break; } } if(!sc) sc = &skelcache.add(); - if(!match) - { + if(!match) { loopi(numanimparts) sc->as[i] = as[i]; sc->pitch = pitch; sc->partmask = partmask; @@ -1052,101 +806,73 @@ struct skelmodel : animmodel sc->millis = lastmillis; return *sc; } - - int getblendoffset(UniformLoc &u) - { + int getblendoffset(UniformLoc &u) { int &offset = blendoffsets.access(Shader::lastshader->program, -1); - if(offset < 0) - { + if(offset < 0) { defformatstring(offsetname, "%s[%d]", u.name, 2*numgpubones); offset = glGetUniformLocation_(Shader::lastshader->program, offsetname); } return offset; } - - void setglslbones(UniformLoc &u, skelcacheentry &sc, skelcacheentry &bc, int count) - { + void setglslbones(UniformLoc &u, skelcacheentry &sc, skelcacheentry &bc, int count) { if(u.version == bc.version && u.data == bc.bdata) return; glUniform4fv_(u.loc, 2*numgpubones, sc.bdata[0].real.v); - if(count > 0) - { + if(count > 0) { int offset = getblendoffset(u); if(offset >= 0) glUniform4fv_(offset, 2*count, bc.bdata[0].real.v); } u.version = bc.version; u.data = bc.bdata; } - - void setgpubones(skelcacheentry &sc, blendcacheentry *bc, int count) - { + void setgpubones(skelcacheentry &sc, blendcacheentry *bc, int count) { if(!Shader::lastshader) return; if(Shader::lastshader->uniformlocs.length() < 1) return; UniformLoc &u = Shader::lastshader->uniformlocs[0]; setglslbones(u, sc, bc ? *bc : sc, count); } - - bool shouldcleanup() const - { + bool shouldcleanup() const { return numframes && (skelcache.empty() || gpuaccelerate()!=usegpuskel); } }; - - struct skelmeshgroup : meshgroup - { + struct skelmeshgroup : meshgroup { skeleton *skel; - vector blendcombos; int numblends[4]; - static const int MAXBLENDCACHE = 16; blendcacheentry blendcache[MAXBLENDCACHE]; - static const int MAXVBOCACHE = 16; vbocacheentry vbocache[MAXVBOCACHE]; - ushort *edata; GLuint ebuf; bool vtangents; int vlen, vertsize, vblends, vweights; uchar *vdata; - - skelmeshgroup() : skel(NULL), edata(NULL), ebuf(0), vtangents(false), vlen(0), vertsize(0), vblends(0), vweights(0), vdata(NULL) - { + skelmeshgroup() : skel(NULL), edata(NULL), ebuf(0), vtangents(false), vlen(0), vertsize(0), vblends(0), vweights(0), vdata(NULL) { memset(numblends, 0, sizeof(numblends)); } - - virtual ~skelmeshgroup() - { - if(skel) - { + virtual ~skelmeshgroup() { + if(skel) { if(skel->shared) skel->users.removeobj(this); else DELETEP(skel); } if(ebuf) glDeleteBuffers_(1, &ebuf); - loopi(MAXBLENDCACHE) - { + loopi(MAXBLENDCACHE) { DELETEA(blendcache[i].bdata); } - loopi(MAXVBOCACHE) - { + loopi(MAXVBOCACHE) { if(vbocache[i].vbuf) glDeleteBuffers_(1, &vbocache[i].vbuf); } DELETEA(vdata); } - - void shareskeleton(char *name) - { - if(!name) - { + void shareskeleton(char *name) { + if(!name) { skel = new skeleton; skel->users.add(this); return; } - static hashnameset skeletons; if(skeletons.access(name)) skel = skeletons[name]; - else - { + else { skel = new skeleton; skel->name = newstring(name); skeletons.add(skel); @@ -1154,38 +880,26 @@ struct skelmodel : animmodel skel->users.add(this); skel->shared++; } - - int findtag(const char *name) - { + int findtag(const char *name) { return skel->findtag(name); } - void *animkey() { return skel; } int totalframes() const { return max(skel->numframes, 1); } - virtual skelanimspec *loadanim(const char *filename) { (void) filename; return NULL; } - - void genvbo(bool tangents, vbocacheentry &vc) - { + void genvbo(bool tangents, vbocacheentry &vc) { if(!vc.vbuf) glGenBuffers_(1, &vc.vbuf); if(ebuf) return; - vector idxs; - if(tangents) loopv(meshes) ((skelmesh *)meshes[i])->calctangents(); - vtangents = tangents; vlen = 0; vblends = 0; - if(skel->numframes && !skel->usegpuskel) - { + if(skel->numframes && !skel->usegpuskel) { vweights = 1; - loopv(blendcombos) - { + loopv(blendcombos) { blendcombo &c = blendcombos[i]; c.interpindex = c.weights[1] ? skel->numgpubones + vblends++ : -1; } - vertsize = tangents ? sizeof(vvertbump) : sizeof(vvertn); loopv(meshes) vlen += ((skelmesh *)meshes[i])->genvbo(idxs, vlen); DELETEA(vdata); @@ -1197,25 +911,20 @@ struct skelmodel : animmodel else FILLVDATA(vvertn); #undef FILLVDATA } - else - { - if(skel->numframes) - { + else { + if(skel->numframes) { vweights = 4; int availbones = skel->availgpubones() - skel->numgpubones; while(vweights > 1 && availbones >= numblends[vweights-1]) availbones -= numblends[--vweights]; - loopv(blendcombos) - { + loopv(blendcombos) { blendcombo &c = blendcombos[i]; c.interpindex = c.size() > vweights ? skel->numgpubones + vblends++ : -1; } } - else - { + else { vweights = 0; loopv(blendcombos) blendcombos[i].interpindex = -1; } - gle::bindvbo(vc.vbuf); #define GENVBO(type, args) do { \ vertsize = sizeof(type); \ @@ -1225,13 +934,11 @@ struct skelmodel : animmodel } while(0) #define GENVBOANIM(type) GENVBO(type, (idxs, vlen, vverts)) #define GENVBOSTAT(type) GENVBO(type, (idxs, vlen, vverts, htdata, htlen)) - if(skel->numframes) - { + if(skel->numframes) { if(tangents) GENVBOANIM(vvertbumpw); else GENVBOANIM(vvertnw); } - else - { + else { int numverts = 0, htlen = 128; loopv(meshes) numverts += ((skelmesh *)meshes[i])->numverts; while(htlen < numverts) htlen *= 2; @@ -1247,68 +954,51 @@ struct skelmodel : animmodel #undef GENVBOSTAT gle::clearvbo(); } - glGenBuffers_(1, &ebuf); gle::bindebo(ebuf); glBufferData_(GL_ELEMENT_ARRAY_BUFFER, idxs.length()*sizeof(ushort), idxs.getbuf(), GL_STATIC_DRAW); gle::clearebo(); } - - void bindvbo(const animstate *as, vbocacheentry &vc, skelcacheentry *sc = NULL, blendcacheentry *bc = NULL) - { + void bindvbo(const animstate *as, vbocacheentry &vc, skelcacheentry *sc = NULL, blendcacheentry *bc = NULL) { vvert *vverts = 0; bindpos(ebuf, vc.vbuf, &vverts->pos, vertsize); - if(as->cur.anim&ANIM_NOSKIN) - { + if(as->cur.anim&ANIM_NOSKIN) { if(enabletc) disabletc(); if(enablenormals) disablenormals(); if(enabletangents) disabletangents(); } - else - { - if(vtangents) - { + else { + if(vtangents) { if(enablenormals) disablenormals(); vvertbump *vvertbumps = 0; bindtangents(&vvertbumps->tangent, vertsize); } - else - { + else { if(enabletangents) disabletangents(); vvertn *vvertns = 0; bindnormals(&vvertns->norm, vertsize); } - bindtc(&vverts->tc, vertsize); } - if(!sc || !skel->usegpuskel) - { + if(!sc || !skel->usegpuskel) { if(enablebones) disablebones(); } - else - { - if(vtangents) - { + else { + if(vtangents) { vvertbumpw *vvertbumpws = 0; bindbones(vvertbumpws->weights, vvertbumpws->bones, vertsize); } - else - { + else { vvertnw *vvertnws = 0; bindbones(vvertnws->weights, vvertnws->bones, vertsize); } } } - - void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) - { + void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) { skel->concattagtransform(p, i, m, n); } - - int addblendcombo(const blendcombo &c) - { - loopv(blendcombos) if(blendcombos[i]==c) - { + int addblendcombo(const blendcombo &c) { + loopv(blendcombos) if(blendcombos[i]==c) { blendcombos[i].uses += c.uses; return i; } @@ -1316,50 +1006,38 @@ struct skelmodel : animmodel blendcombo &a = blendcombos.add(c); return a.interpindex = blendcombos.length()-1; } - - void sortblendcombos() - { + void sortblendcombos() { blendcombos.sort(blendcombo::sortcmp); int *remap = new int[blendcombos.length()]; loopv(blendcombos) remap[blendcombos[i].interpindex] = i; - loopv(meshes) - { + loopv(meshes) { skelmesh *m = (skelmesh *)meshes[i]; - loopj(m->numverts) - { + loopj(m->numverts) { vert &v = m->verts[j]; v.blend = remap[v.blend]; } } delete[] remap; } - - int remapblend(int blend) - { + int remapblend(int blend) { const blendcombo &c = blendcombos[blend]; return c.weights[1] ? c.interpindex : c.interpbones[0]; } - - static inline void blendbones(dualquat &d, const dualquat *bdata, const blendcombo &c) - { + static inline void blendbones(dualquat &d, const dualquat *bdata, const blendcombo &c) { d = bdata[c.interpbones[0]]; d.mul(c.weights[0]); d.accumulate(bdata[c.interpbones[1]], c.weights[1]); - if(c.weights[2]) - { + if(c.weights[2]) { d.accumulate(bdata[c.interpbones[2]], c.weights[2]); if(c.weights[3]) d.accumulate(bdata[c.interpbones[3]], c.weights[3]); } } - - void blendbones(const skelcacheentry &sc, blendcacheentry &bc) - { + void blendbones(const skelcacheentry &sc, blendcacheentry &bc) { bc.nextversion(); if(!bc.bdata) bc.bdata = new dualquat[vblends]; dualquat *dst = bc.bdata - skel->numgpubones; bool normalize = !skel->usegpuskel || vweights<=1; - loopv(blendcombos) - { + loopv(blendcombos) { const blendcombo &c = blendcombos[i]; if(c.interpindex<0) break; dualquat &d = dst[c.interpindex]; @@ -1367,17 +1045,13 @@ struct skelmodel : animmodel if(normalize) d.normalize(); } } - - void cleanup() - { - loopi(MAXBLENDCACHE) - { + void cleanup() { + loopi(MAXBLENDCACHE) { blendcacheentry &c = blendcache[i]; DELETEA(c.bdata); c.owner = -1; } - loopi(MAXVBOCACHE) - { + loopi(MAXVBOCACHE) { vbocacheentry &c = vbocache[i]; if(c.vbuf) { glDeleteBuffers_(1, &c.vbuf); c.vbuf = 0; } c.owner = -1; @@ -1385,38 +1059,31 @@ struct skelmodel : animmodel if(ebuf) { glDeleteBuffers_(1, &ebuf); ebuf = 0; } if(skel) skel->cleanup(false); } - #define SEARCHCACHE(cachesize, cacheentry, cache, reusecheck) \ - loopi(cachesize) \ - { \ + loopi(cachesize) { \ + \ cacheentry &c = cache[i]; \ - if(c.owner==owner) \ - { \ + if(c.owner==owner) { \ + \ if(c==sc) return c; \ else c.owner = -1; \ break; \ } \ } \ - loopi(cachesize-1) \ - { \ + loopi(cachesize-1) { \ + \ cacheentry &c = cache[i]; \ if(reusecheck c.owner < 0 || c.millis < lastmillis) \ return c; \ } \ return cache[cachesize-1]; - - vbocacheentry &checkvbocache(skelcacheentry &sc, int owner) - { + vbocacheentry &checkvbocache(skelcacheentry &sc, int owner) { SEARCHCACHE(MAXVBOCACHE, vbocacheentry, vbocache, !c.vbuf || ); } - - blendcacheentry &checkblendcache(skelcacheentry &sc, int owner) - { + blendcacheentry &checkblendcache(skelcacheentry &sc, int owner) { SEARCHCACHE(MAXBLENDCACHE, blendcacheentry, blendcache, ) } - - void preload(part *p) - { + void preload(part *p) { if(!skel->canpreload()) return; bool tangents = false; loopv(p->skins) if(p->skins[i].tangents()) tangents = true; @@ -1425,22 +1092,16 @@ struct skelmodel : animmodel skel->preload(); if(!vbocache->vbuf) genvbo(tangents, *vbocache); } - - void render(const animstate *as, float pitch, const vec &axis, const vec &forward, dynent *d, part *p) - { + void render(const animstate *as, float pitch, const vec &axis, const vec &forward, dynent *d, part *p) { bool tangents = false; loopv(p->skins) if(p->skins[i].tangents()) tangents = true; if(skel->shouldcleanup()) { skel->cleanup(); disablevbo(); } else if(tangents!=vtangents) { cleanup(); disablevbo(); } - - if(!skel->numframes) - { - if(!(as->cur.anim&ANIM_NORENDER)) - { + if(!skel->numframes) { + if(!(as->cur.anim&ANIM_NORENDER)) { if(!vbocache->vbuf) genvbo(tangents, *vbocache); bindvbo(as, *vbocache); - loopv(meshes) - { + loopv(meshes) { skelmesh *m = (skelmesh *)meshes[i]; p->skins[i].bind(m, as); m->render(as, p->skins[i], *vbocache); @@ -1449,153 +1110,110 @@ struct skelmodel : animmodel skel->calctags(p); return; } - skelcacheentry &sc = skel->checkskelcache(p, as, pitch, axis, forward, as->cur.anim&ANIM_RAGDOLL || !d || !d->ragdoll || d->ragdoll->skel != skel->ragdoll ? NULL : d->ragdoll); - if(!(as->cur.anim&ANIM_NORENDER)) - { + if(!(as->cur.anim&ANIM_NORENDER)) { int owner = &sc-&skel->skelcache[0]; vbocacheentry &vc = skel->usegpuskel ? *vbocache : checkvbocache(sc, owner); vc.millis = lastmillis; if(!vc.vbuf) genvbo(tangents, vc); blendcacheentry *bc = NULL; - if(vblends) - { + if(vblends) { bc = &checkblendcache(sc, owner); bc->millis = lastmillis; - if(bc->owner!=owner) - { + if(bc->owner!=owner) { bc->owner = owner; *(animcacheentry *)bc = sc; blendbones(sc, *bc); } } - if(!skel->usegpuskel && vc.owner!=owner) - { + if(!skel->usegpuskel && vc.owner!=owner) { vc.owner = owner; (animcacheentry &)vc = sc; - loopv(meshes) - { + loopv(meshes) { skelmesh &m = *(skelmesh *)meshes[i]; m.interpverts(sc.bdata, bc ? bc->bdata : NULL, tangents, vdata + m.voffset*vertsize, p->skins[i]); } gle::bindvbo(vc.vbuf); glBufferData_(GL_ARRAY_BUFFER, vlen*vertsize, vdata, GL_STREAM_DRAW); } - bindvbo(as, vc, &sc, bc); - loopv(meshes) - { + loopv(meshes) { skelmesh *m = (skelmesh *)meshes[i]; p->skins[i].bind(m, as); if(skel->usegpuskel) skel->setgpubones(sc, bc, vblends); m->render(as, p->skins[i], vc); } } - skel->calctags(p, &sc); - - if(as->cur.anim&ANIM_RAGDOLL && skel->ragdoll && !d->ragdoll) - { + if(as->cur.anim&ANIM_RAGDOLL && skel->ragdoll && !d->ragdoll) { d->ragdoll = new ragdolldata(skel->ragdoll, p->model->scale); skel->initragdoll(*d->ragdoll, sc, p); d->ragdoll->init(d); } } }; - - struct animpartmask - { + struct animpartmask { animpartmask *next; int numbones; uchar bones[1]; }; - - struct skelpart : part - { + struct skelpart : part { animpartmask *buildingpartmask; - uchar *partmask; - - skelpart(animmodel *model, int index = 0) : part(model, index), buildingpartmask(NULL), partmask(NULL) - { + skelpart(animmodel *model, int index = 0) : part(model, index), buildingpartmask(NULL), partmask(NULL) { } - - virtual ~skelpart() - { + virtual ~skelpart() { DELETEA(buildingpartmask); } - - uchar *sharepartmask(animpartmask *o) - { + uchar *sharepartmask(animpartmask *o) { static animpartmask *partmasks = NULL; animpartmask *p = partmasks; - for(; p; p = p->next) if(p->numbones==o->numbones && !memcmp(p->bones, o->bones, p->numbones)) - { + for(; p; p = p->next) if(p->numbones==o->numbones && !memcmp(p->bones, o->bones, p->numbones)) { delete[] (uchar *)o; return p->bones; } - o->next = p; partmasks = o; return o->bones; } - - animpartmask *newpartmask() - { + animpartmask *newpartmask() { animpartmask *p = (animpartmask *)new uchar[sizeof(animpartmask) + ((skelmeshgroup *)meshes)->skel->numbones-1]; p->numbones = ((skelmeshgroup *)meshes)->skel->numbones; memset(p->bones, 0, p->numbones); return p; } - - void initanimparts() - { + void initanimparts() { DELETEA(buildingpartmask); buildingpartmask = newpartmask(); } - - bool addanimpart(ushort *bonemask) - { + bool addanimpart(ushort *bonemask) { if(!buildingpartmask || numanimparts>=MAXANIMPARTS) return false; ((skelmeshgroup *)meshes)->skel->applybonemask(bonemask, buildingpartmask->bones, numanimparts); numanimparts++; return true; } - - void endanimparts() - { - if(buildingpartmask) - { + void endanimparts() { + if(buildingpartmask) { partmask = sharepartmask(buildingpartmask); buildingpartmask = NULL; } - ((skelmeshgroup *)meshes)->skel->optimize(); } - - void loaded() - { + void loaded() { endanimparts(); part::loaded(); } }; - - skelmodel(const char *name) : animmodel(name) - { + skelmodel(const char *name) : animmodel(name) { } - - int linktype(animmodel *m) const - { + int linktype(animmodel *m) const { return type()==m->type() && ((skelmeshgroup *)parts[0]->meshes)->skel == ((skelmeshgroup *)m->parts[0]->meshes)->skel ? LINK_REUSE : LINK_TAG; } - bool skeletal() const { return true; } - - skelpart &addpart() - { + skelpart &addpart() { flushpart(); skelpart *p = new skelpart(this, parts.length()); parts.add(p); @@ -1603,15 +1221,11 @@ struct skelmodel : animmodel } }; -struct skeladjustment -{ +struct skeladjustment { float yaw, pitch, roll; vec translate; - skeladjustment(float yaw, float pitch, float roll, const vec &translate) : yaw(yaw), pitch(pitch), roll(roll), translate(translate) {} - - void adjust(dualquat &dq) - { + void adjust(dualquat &dq) { if(yaw) dq.mulorient(quat(vec(0, 0, 1), yaw*RAD)); if(pitch) dq.mulorient(quat(vec(0, -1, 0), pitch*RAD)); if(roll) dq.mulorient(quat(vec(-1, 0, 0), roll*RAD)); @@ -1619,22 +1233,17 @@ struct skeladjustment } }; -template struct skelloader : modelloader -{ +template struct skelloader : modelloader { static vector adjustments; - skelloader(const char *name) : modelloader(name) {} - - void flushpart() - { + void flushpart() { adjustments.setsize(0); } }; template vector skelloader::adjustments; -template struct skelcommands : modelcommands -{ +template struct skelcommands : modelcommands { typedef modelcommands commands; typedef struct MDL::skeleton skeleton; typedef struct MDL::skelmeshgroup meshgroup; @@ -1645,29 +1254,23 @@ template struct skelcommands : modelcommandsaddpart(); mdl.pitchscale = mdl.pitchoffset = mdl.pitchmin = mdl.pitchmax = 0; mdl.meshes = MDL::loading->sharemeshes(path(filename), skelname[0] ? skelname : NULL, double(*smooth > 0 ? cos(clamp(*smooth, 0.0f, 180.0f)*RAD) : 2)); if(!mdl.meshes) conoutf(CON_ERROR, "could not load %s", filename); - else - { + else { mdl.initanimparts(); mdl.initskins(); } } - - static void settag(char *name, char *tagname, float *tx, float *ty, float *tz, float *rx, float *ry, float *rz) - { + static void settag(char *name, char *tagname, float *tx, float *ty, float *tz, float *rx, float *ry, float *rz) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } part &mdl = *(part *)MDL::loading->parts.last(); int i = mdl.meshes ? ((meshgroup *)mdl.meshes)->skel->findbone(name) : -1; - if(i >= 0) - { + if(i >= 0) { float cx = *rx ? cosf(*rx/2*RAD) : 1, sx = *rx ? sinf(*rx/2*RAD) : 0, cy = *ry ? cosf(*ry/2*RAD) : 1, sy = *ry ? sinf(*ry/2*RAD) : 0, cz = *rz ? cosf(*rz/2*RAD) : 1, sz = *rz ? sinf(*rz/2*RAD) : 0; @@ -1678,27 +1281,20 @@ template struct skelcommands : modelcommandsparts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } part &mdl = *(part *)MDL::loading->parts.last(); - - if(name[0]) - { + if(name[0]) { int i = mdl.meshes ? ((meshgroup *)mdl.meshes)->skel->findbone(name) : -1; - if(i>=0) - { + if(i>=0) { boneinfo &b = ((meshgroup *)mdl.meshes)->skel->bones[i]; b.pitchscale = *pitchscale; b.pitchoffset = *pitchoffset; - if(*pitchmin || *pitchmax) - { + if(*pitchmin || *pitchmax) { b.pitchmin = *pitchmin; b.pitchmax = *pitchmax; } - else - { + else { b.pitchmin = -360*fabs(b.pitchscale) + b.pitchoffset; b.pitchmax = 360*fabs(b.pitchscale) + b.pitchoffset; } @@ -1707,23 +1303,18 @@ template struct skelcommands : modelcommandsparts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } part &mdl = *(part *)MDL::loading->parts.last(); if(!mdl.meshes) return; @@ -1732,8 +1323,7 @@ template struct skelcommands : modelcommandsskel; int bone = skel ? skel->findbone(name) : -1; - if(bone < 0) - { + if(bone < 0) { conoutf(CON_ERROR, "could not find bone %s to pitch target", name); return; } @@ -1744,24 +1334,20 @@ template struct skelcommands : modelcommandsparts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } part &mdl = *(part *)MDL::loading->parts.last(); if(!mdl.meshes) return; skeleton *skel = ((meshgroup *)mdl.meshes)->skel; int bone = skel ? skel->findbone(name) : -1; - if(bone < 0) - { + if(bone < 0) { conoutf(CON_ERROR, "could not find bone %s to pitch correct", name); return; } if(skel->findpitchcorrect(bone) >= 0) return; int targetbone = skel->findbone(targetname), target = -1; if(targetbone >= 0) loopv(skel->pitchtargets) if(skel->pitchtargets[i].bone == targetbone) { target = i; break; } - if(target < 0) - { + if(target < 0) { conoutf(CON_ERROR, "could not find pitch target %s to pitch correct %s", targetname, name); return; } @@ -1775,23 +1361,18 @@ template struct skelcommands : modelcommandspitchcorrects) if(bone <= skel->pitchcorrects[i].bone) { pos = i; break; } skel->pitchcorrects.insert(pos, c); } - - static void setanim(char *anim, char *animfile, float *speed, int *priority, int *startoffset, int *endoffset) - { + static void setanim(char *anim, char *animfile, float *speed, int *priority, int *startoffset, int *endoffset) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } - vector anims; findanims(anim, anims); if(anims.empty()) conoutf(CON_ERROR, "could not find animation %s", anim); - else - { + else { part *p = (part *)MDL::loading->parts.last(); if(!p->meshes) return; defformatstring(filename, "%s/%s", MDL::dir, animfile); animspec *sa = ((meshgroup *)p->meshes)->loadanim(path(filename)); if(!sa) conoutf(CON_ERROR, "could not load %s anim file %s", MDL::formatname(), filename); - else loopv(anims) - { + else loopv(anims) { int start = sa->frame, end = sa->range; if(*startoffset > 0) start += min(*startoffset, end-1); else if(*startoffset < 0) start += max(end + *startoffset, 0); @@ -1802,18 +1383,13 @@ template struct skelcommands : modelcommandsparts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } - part *p = (part *)MDL::loading->parts.last(); - vector bonestrs; explodelist(maskstr, bonestrs); vector bonemask; - loopv(bonestrs) - { + loopv(bonestrs) { char *bonestr = bonestrs[i]; int bone = p->meshes ? ((meshgroup *)p->meshes)->skel->findbone(bonestr[0]=='!' ? bonestr+1 : bonestr) : -1; if(bone<0) { conoutf(CON_ERROR, "could not find bone %s for anim part mask [%s]", bonestr, maskstr); bonestrs.deletearrays(); return; } @@ -1822,31 +1398,24 @@ template struct skelcommands : modelcommandsaddanimpart(bonemask.getbuf())) conoutf(CON_ERROR, "too many animation parts"); } - - static void setadjust(char *name, float *yaw, float *pitch, float *roll, float *tx, float *ty, float *tz) - { + static void setadjust(char *name, float *yaw, float *pitch, float *roll, float *tx, float *ty, float *tz) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } part &mdl = *(part *)MDL::loading->parts.last(); - if(!name[0]) return; int i = mdl.meshes ? ((meshgroup *)mdl.meshes)->skel->findbone(name) : -1; if(i < 0) { conoutf(CON_ERROR, "could not find bone %s to adjust", name); return; } while(!MDL::adjustments.inrange(i)) MDL::adjustments.add(skeladjustment(0, 0, 0, vec(0, 0, 0))); MDL::adjustments[i] = skeladjustment(*yaw, *pitch, *roll, vec(*tx/4, *ty/4, *tz/4)); } - - skelcommands() - { + skelcommands() { if(MDL::multiparted()) this->modelcommand(loadpart, "load", "ssf"); this->modelcommand(settag, "tag", "ssffffff"); this->modelcommand(setpitch, "pitch", "sffff"); this->modelcommand(setpitchtarget, "pitchtarget", "ssiff"); this->modelcommand(setpitchcorrect, "pitchcorrect", "ssfff"); - if(MDL::animated()) - { + if(MDL::animated()) { this->modelcommand(setanim, "anim", "ssfiii"); this->modelcommand(setanimpart, "animpart", "s"); this->modelcommand(setadjust, "adjust", "sffffff"); diff --git a/src/engine/sound.cpp b/src/engine/sound.cpp index d10386d..62cab3e 100644 --- a/src/engine/sound.cpp +++ b/src/engine/sound.cpp @@ -5,44 +5,34 @@ bool nosound = true; -struct soundsample -{ +struct soundsample { char *name; Mix_Chunk *chunk; - soundsample() : name(NULL), chunk(NULL) {} ~soundsample() { DELETEA(name); } - void cleanup() { if(chunk) { Mix_FreeChunk(chunk); chunk = NULL; } } bool load(bool msg = false); }; -struct soundslot -{ +struct soundslot { soundsample *sample; int volume; }; -struct soundconfig -{ +struct soundconfig { int slots, numslots; int maxuses; - - bool hasslot(const soundslot *p, const vector &v) const - { + bool hasslot(const soundslot *p, const vector &v) const { return p >= v.getbuf() + slots && p < v.getbuf() + slots+numslots && slots+numslots < v.length(); } - - int chooseslot(int flags) const - { + int chooseslot(int flags) const { if(flags&SND_NO_ALT || numslots <= 1) return slots; if(flags&SND_USE_ALT) return slots + 1 + rnd(numslots - 1); return slots + rnd(numslots); } }; -struct soundchannel -{ +struct soundchannel { int id; bool inuse; vec loc; @@ -50,14 +40,10 @@ struct soundchannel extentity *ent; int radius, volume, pan, flags; bool dirty; - soundchannel(int id) : id(id) { reset(); } - bool hasloc() const { return loc.x >= -1e15f; } void clearloc() { loc = vec(-1e16f, -1e16f, -1e16f); } - - void reset() - { + void reset() { inuse = false; clearloc(); slot = NULL; @@ -72,10 +58,8 @@ struct soundchannel vector channels; int maxchannels = 0; -soundchannel &newchannel(int n, soundslot *slot, const vec *loc = NULL, extentity *ent = NULL, int flags = 0, int radius = 0) -{ - if(ent) - { +soundchannel &newchannel(int n, soundslot *slot, const vec *loc = NULL, extentity *ent = NULL, int flags = 0, int radius = 0) { + if(ent) { loc = &ent->o; ent->flags |= EF_SOUND; } @@ -91,26 +75,22 @@ soundchannel &newchannel(int n, soundslot *slot, const vec *loc = NULL, extentit return chan; } -void freechannel(int n) -{ +void freechannel(int n) { if(!channels.inrange(n) || !channels[n].inuse) return; soundchannel &chan = channels[n]; chan.inuse = false; if(chan.ent) chan.ent->flags &= ~EF_SOUND; } -void syncchannel(soundchannel &chan) -{ +void syncchannel(soundchannel &chan) { if(!chan.dirty) return; if(!Mix_FadingChannel(chan.id)) Mix_Volume(chan.id, chan.volume); Mix_SetPanning(chan.id, 255-chan.pan, chan.pan); chan.dirty = false; } -void stopchannels() -{ - loopv(channels) - { +void stopchannels() { + loopv(channels) { soundchannel &chan = channels[i]; if(!chan.inuse) continue; Mix_HaltChannel(i); @@ -121,8 +101,7 @@ void stopchannels() void setmusicvol(int musicvol); extern int musicvol; static int curvol = 0; -VARFP(soundvol, 0, 255, 255, -{ +VARFP(soundvol, 0, 255, 255, { if(!soundvol) { stopchannels(); setmusicvol(0); } else if(!curvol) setmusicvol(musicvol); curvol = soundvol; @@ -135,19 +114,16 @@ Mix_Music *music = NULL; SDL_RWops *musicrw = NULL; stream *musicstream = NULL; -void setmusicvol(int musicvol) -{ +void setmusicvol(int musicvol) { if(nosound) return; if(music) Mix_VolumeMusic((musicvol*MIX_MAX_VOLUME)/255); } -void stopmusic() -{ +void stopmusic() { if(nosound) return; DELETEA(musicfile); DELETEA(musicdonecmd); - if(music) - { + if(music) { Mix_HaltMusic(); Mix_FreeMusic(music); music = NULL; @@ -163,34 +139,28 @@ VARF(soundchans, 1, 32, 128, initwarning("sound configuration", INIT_RESET, CHAN VARF(soundfreq, 0, MIX_DEFAULT_FREQUENCY, 48000, initwarning("sound configuration", INIT_RESET, CHANGE_SOUND)); VARF(soundbufferlen, 128, 1024, 4096, initwarning("sound configuration", INIT_RESET, CHANGE_SOUND)); -bool initaudio() -{ +bool initaudio() { static string fallback = ""; static bool initfallback = true; static bool restorefallback = false; - if(initfallback) - { + if(initfallback) { initfallback = false; if(char *env = SDL_getenv("SDL_AUDIODRIVER")) copystring(fallback, env); } - if(!fallback[0] && audiodriver[0]) - { + if(!fallback[0] && audiodriver[0]) { vector drivers; explodelist(audiodriver, drivers); - loopv(drivers) - { + loopv(drivers) { restorefallback = true; SDL_setenv("SDL_AUDIODRIVER", drivers[i], 1); - if(SDL_InitSubSystem(SDL_INIT_AUDIO) >= 0) - { + if(SDL_InitSubSystem(SDL_INIT_AUDIO) >= 0) { drivers.deletearrays(); return true; } } drivers.deletearrays(); } - if(restorefallback) - { + if(restorefallback) { restorefallback = false; unsetenv("SDL_AUDIODRIVER"); } @@ -199,30 +169,23 @@ bool initaudio() return false; } -void initsound() -{ +void initsound() { SDL_version version; SDL_GetVersion(&version); - if(version.major == 2 && version.minor == 0 && version.patch == 6) - { + if(version.major == 2 && version.minor == 0 && version.patch == 6) { nosound = true; if(usesound) conoutf(CON_ERROR, "audio is broken in SDL 2.0.6"); return; } - - if(shouldinitaudio) - { + if(shouldinitaudio) { shouldinitaudio = false; if(SDL_WasInit(SDL_INIT_AUDIO)) SDL_QuitSubSystem(SDL_INIT_AUDIO); - if(!usesound || !initaudio()) - { + if(!usesound || !initaudio()) { nosound = true; return; } } - - if(Mix_OpenAudio(soundfreq, MIX_DEFAULT_FORMAT, 2, soundbufferlen)<0) - { + if(Mix_OpenAudio(soundfreq, MIX_DEFAULT_FORMAT, 2, soundbufferlen)<0) { nosound = true; conoutf(CON_ERROR, "sound init failed (SDL_mixer): %s", Mix_GetError()); return; @@ -232,8 +195,7 @@ void initsound() nosound = false; } -void musicdone() -{ +void musicdone() { if(music) { Mix_HaltMusic(); Mix_FreeMusic(music); music = NULL; } if(musicrw) { SDL_FreeRW(musicrw); musicrw = NULL; } DELETEP(musicstream); @@ -245,34 +207,28 @@ void musicdone() delete[] cmd; } -Mix_Music *loadmusic(const char *name) -{ +Mix_Music *loadmusic(const char *name) { if(!musicstream) musicstream = openzipfile(name, "rb"); - if(musicstream) - { + if(musicstream) { if(!musicrw) musicrw = musicstream->rwops(); if(!musicrw) DELETEP(musicstream); } if(musicrw) music = Mix_LoadMUSType_RW(musicrw, MUS_NONE, 0); else music = Mix_LoadMUS(findfile(name, "rb")); - if(!music) - { + if(!music) { if(musicrw) { SDL_FreeRW(musicrw); musicrw = NULL; } DELETEP(musicstream); } return music; } -void startmusic(char *name, char *cmd) -{ +void startmusic(char *name, char *cmd) { if(nosound) return; stopmusic(); - if(soundvol && musicvol && *name) - { + if(soundvol && musicvol && *name) { defformatstring(file, "packages/%s", name); path(file); - if(loadmusic(file)) - { + if(loadmusic(file)) { DELETEA(musicfile); DELETEA(musicdonecmd); musicfile = newstring(file); @@ -281,8 +237,7 @@ void startmusic(char *name, char *cmd) Mix_VolumeMusic((musicvol*MIX_MAX_VOLUME)/255); intret(1); } - else - { + else { conoutf(CON_ERROR, "could not play music: %s", file); intret(0); } @@ -291,15 +246,12 @@ void startmusic(char *name, char *cmd) COMMANDN(music, startmusic, "ss"); -static Mix_Chunk *loadwav(const char *name) -{ +static Mix_Chunk *loadwav(const char *name) { Mix_Chunk *c = NULL; stream *z = openzipfile(name, "rb"); - if(z) - { + if(z) { SDL_RWops *rw = z->rwops(); - if(rw) - { + if(rw) { c = Mix_LoadWAV_RW(rw, 0); SDL_FreeRW(rw); } @@ -309,47 +261,39 @@ static Mix_Chunk *loadwav(const char *name) return c; } -template static void scalewav(T* dst, T* src, size_t len, int scale) -{ +template static void scalewav(T* dst, T* src, size_t len, int scale) { len /= sizeof(T); const T* end = src + len; - if(scale==2) for(; src < end; src++, dst += scale) - { + if(scale==2) for(; src < end; src++, dst += scale) { T s = src[0]; dst[0] = s; dst[1] = s; } - else if(scale==4) for(; src < end; src++, dst += scale) - { + else if(scale==4) for(; src < end; src++, dst += scale) { T s = src[0]; dst[0] = s; dst[1] = s; dst[2] = s; dst[3] = s; } - else for(; src < end; src++) - { + else for(; src < end; src++) { T s = src[0]; loopi(scale) *dst++ = s; } } -static Mix_Chunk *loadwavscaled(const char *name) -{ +static Mix_Chunk *loadwavscaled(const char *name) { int mixerfreq = 0; Uint16 mixerformat = 0; int mixerchannels = 0; if(!Mix_QuerySpec(&mixerfreq, &mixerformat, &mixerchannels)) return NULL; - SDL_AudioSpec spec; Uint8 *audiobuf = NULL; Uint32 audiolen = 0; stream *z = openzipfile(name, "rb"); - if(z) - { + if(z) { SDL_RWops *rw = z->rwops(); - if(rw) - { + if(rw) { SDL_LoadWAV_RW(rw, 0, &spec, &audiobuf, &audiolen); SDL_FreeRW(rw); } @@ -359,21 +303,17 @@ static Mix_Chunk *loadwavscaled(const char *name) if(!audiobuf) return NULL; int samplesize = ((spec.format&0xFF)/8) * spec.channels; int scale = mixerfreq / spec.freq; - if(scale >= 2) - { + if(scale >= 2) { Uint8 *scalebuf = (Uint8*)SDL_malloc(audiolen * scale); - if(scalebuf) - { - switch(samplesize) - { + if(scalebuf) { + switch(samplesize) { case 1: scalewav((uchar*)scalebuf, (uchar*)audiobuf, audiolen, scale); break; case 2: scalewav((ushort*)scalebuf, (ushort*)audiobuf, audiolen, scale); break; case 4: scalewav((uint*)scalebuf, (uint*)audiobuf, audiolen, scale); break; case 8: scalewav((ullong*)scalebuf, (ullong*)audiobuf, audiolen, scale); break; default: SDL_free(scalebuf); scalebuf = NULL; break; } - if(scalebuf) - { + if(scalebuf) { SDL_free(audiobuf); audiobuf = scalebuf; audiolen *= scale; @@ -381,16 +321,13 @@ static Mix_Chunk *loadwavscaled(const char *name) } } } - if(spec.freq != mixerfreq || spec.format != mixerformat || spec.channels != mixerchannels) - { + if(spec.freq != mixerfreq || spec.format != mixerformat || spec.channels != mixerchannels) { SDL_AudioCVT cvt; - if(SDL_BuildAudioCVT(&cvt, spec.format, spec.channels, spec.freq, mixerformat, mixerchannels, mixerfreq) < 0) - { + if(SDL_BuildAudioCVT(&cvt, spec.format, spec.channels, spec.freq, mixerformat, mixerchannels, mixerfreq) < 0) { SDL_free(audiobuf); return NULL; } - if(cvt.filters[0]) - { + if(cvt.filters[0]) { cvt.len = audiolen & ~(samplesize-1); cvt.buf = (Uint8*)SDL_malloc(cvt.len * cvt.len_mult); if(!cvt.buf) { SDL_free(audiobuf); return NULL; } @@ -409,23 +346,18 @@ static Mix_Chunk *loadwavscaled(const char *name) VARFP(fixwav, 0, 1, 1, initwarning("sound configuration", INIT_LOAD, CHANGE_SOUND)); -bool soundsample::load(bool msg) -{ +bool soundsample::load(bool msg) { if(chunk) return true; if(!name[0]) return false; - static const char * const exts[] = { "", ".wav", ".ogg" }; string filename; - loopi(sizeof(exts)/sizeof(exts[0])) - { + loopi(sizeof(exts)/sizeof(exts[0])) { formatstring(filename, "packages/sounds/%s%s", name, exts[i]); if(msg && !i) renderprogress(0, filename); path(filename); - if(fixwav) - { + if(fixwav) { size_t len = strlen(filename); - if(len >= 4 && !strcasecmp(filename + len - 4, ".wav")) - { + if(len >= 4 && !strcasecmp(filename + len - 4, ".wav")) { chunk = loadwavscaled(filename); if(chunk) return true; } @@ -433,42 +365,32 @@ bool soundsample::load(bool msg) chunk = loadwav(filename); if(chunk) return true; } - conoutf(CON_ERROR, "failed to load sample: packages/sounds/%s", name); return false; } static hashnameset samples; -static void cleanupsamples() -{ +static void cleanupsamples() { enumerate(samples, soundsample, s, s.cleanup()); } -static struct soundtype -{ +static struct soundtype { vector slots; vector configs; - - int findsound(const char *name, int vol) - { - loopv(configs) - { + int findsound(const char *name, int vol) { + loopv(configs) { soundconfig &s = configs[i]; - loopj(s.numslots) - { + loopj(s.numslots) { soundslot &c = slots[s.slots+j]; if(!strcmp(c.sample->name, name) && (!vol || c.volume==vol)) return i; } } return -1; } - - int addslot(const char *name, int vol) - { + int addslot(const char *name, int vol) { soundsample *s = samples.access(name); - if(!s) - { + if(!s) { char *n = newstring(name); s = &samples[n]; s->name = n; @@ -478,8 +400,7 @@ static struct soundtype int oldlen = slots.length(); soundslot &slot = slots.add(); // soundslots.add() may relocate slot pointers - if(slots.getbuf() != oldslots) loopv(channels) - { + if(slots.getbuf() != oldslots) loopv(channels) { soundchannel &chan = channels[i]; if(chan.inuse && chan.slot >= oldslots && chan.slot < &oldslots[oldlen]) chan.slot = &slots[chan.slot - oldslots]; @@ -488,52 +409,38 @@ static struct soundtype slot.volume = vol ? vol : 100; return oldlen; } - - int addsound(const char *name, int vol, int maxuses = 0) - { + int addsound(const char *name, int vol, int maxuses = 0) { soundconfig &s = configs.add(); s.slots = addslot(name, vol); s.numslots = 1; s.maxuses = maxuses; return configs.length()-1; } - - void addalt(const char *name, int vol) - { + void addalt(const char *name, int vol) { if(configs.empty()) return; addslot(name, vol); configs.last().numslots++; } - - void clear() - { + void clear() { slots.setsize(0); configs.setsize(0); } - - void reset() - { - loopv(channels) - { + void reset() { + loopv(channels) { soundchannel &chan = channels[i]; - if(chan.inuse && slots.inbuf(chan.slot)) - { + if(chan.inuse && slots.inbuf(chan.slot)) { Mix_HaltChannel(i); freechannel(i); } } clear(); } - - void preloadsound(int n) - { + void preloadsound(int n) { if(nosound || !configs.inrange(n)) return; soundconfig &config = configs[n]; loopk(config.numslots) slots[config.slots+k].sample->load(true); } - - bool playing(const soundchannel &chan, const soundconfig &config) const - { + bool playing(const soundchannel &chan, const soundconfig &config) const { return chan.inuse && config.hasslot(chan.slot, slots); } } gamesounds, mapsounds; @@ -553,29 +460,24 @@ COMMAND(altmapsound, "si"); ICOMMAND(numsounds, "", (), intret(gamesounds.configs.length())); ICOMMAND(nummapsounds, "", (), intret(mapsounds.configs.length())); -void soundreset() -{ +void soundreset() { gamesounds.reset(); } COMMAND(soundreset, ""); -void mapsoundreset() -{ +void mapsoundreset() { mapsounds.reset(); } COMMAND(mapsoundreset, ""); -void resetchannels() -{ +void resetchannels() { loopv(channels) if(channels[i].inuse) freechannel(i); channels.shrink(0); } -void clear_sound() -{ +void clear_sound() { if(nosound) return; stopmusic(); - cleanupsamples(); gamesounds.clear(); mapsounds.clear(); @@ -584,43 +486,34 @@ void clear_sound() resetchannels(); } -void stopmapsounds() -{ - loopv(channels) if(channels[i].inuse && channels[i].ent) - { +void stopmapsounds() { + loopv(channels) if(channels[i].inuse && channels[i].ent) { Mix_HaltChannel(i); freechannel(i); } } -void clearmapsounds() -{ +void clearmapsounds() { stopmapsounds(); mapsounds.clear(); } -void stopmapsound(extentity *e) -{ - loopv(channels) - { +void stopmapsound(extentity *e) { + loopv(channels) { soundchannel &chan = channels[i]; - if(chan.inuse && chan.ent == e) - { + if(chan.inuse && chan.ent == e) { Mix_HaltChannel(i); freechannel(i); } } } -void checkmapsounds() -{ +void checkmapsounds() { const vector &ents = entities::getents(); - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; if(e.type!=ET_SOUND) continue; - if(camera1->o.dist(e.o) < e.attr2) - { + if(camera1->o.dist(e.o) < e.attr2) { if(!(e.flags&EF_SOUND)) playsound(e.attr1, NULL, &e, SND_MAP, -1); } else if(e.flags&EF_SOUND) stopmapsound(&e); @@ -629,28 +522,23 @@ void checkmapsounds() VAR(stereo, 0, 1, 1); -bool updatechannel(soundchannel &chan) -{ +bool updatechannel(soundchannel &chan) { if(!chan.slot) return false; int vol = soundvol, pan = 255/2; - if(chan.hasloc()) - { + if(chan.hasloc()) { vec v; float dist = chan.loc.dist(camera1->o, v); int rad = 0; - if(chan.ent) - { + if(chan.ent) { rad = chan.ent->attr2; - if(chan.ent->attr3) - { + if(chan.ent->attr3) { rad -= chan.ent->attr3; dist -= chan.ent->attr3; } } else if(chan.radius > 0) rad = chan.radius; if(rad > 0) vol -= int(clamp(dist/rad, 0.0f, 1.0f)*soundvol); // simple mono distance attenuation - if(stereo && (v.x != 0 || v.y != 0) && dist>0) - { + if(stereo && (v.x != 0 || v.y != 0) && dist>0) { v.rotate_around_z(-camera1->yaw*RAD); pan = int(255.9f*(0.5f - 0.5f*v.x/v.magnitude2())); // range is from 0 (left) to 255 (right) } @@ -664,19 +552,15 @@ bool updatechannel(soundchannel &chan) return true; } -void reclaimchannels() -{ - loopv(channels) - { +void reclaimchannels() { + loopv(channels) { soundchannel &chan = channels[i]; if(chan.inuse && !Mix_Playing(i)) freechannel(i); } } -void syncchannels() -{ - loopv(channels) - { +void syncchannels() { + loopv(channels) { soundchannel &chan = channels[i]; if(chan.inuse && chan.hasloc() && updatechannel(chan)) syncchannel(chan); } @@ -684,19 +568,16 @@ void syncchannels() VARP(minimizedsounds, 0, 0, 1); -void updatesounds() -{ +void updatesounds() { if(nosound) return; if(minimized && !minimizedsounds) stopsounds(); - else - { + else { reclaimchannels(); if(mainmenu) stopmapsounds(); else checkmapsounds(); syncchannels(); } - if(music) - { + if(music) { if(!Mix_PlayingMusic()) musicdone(); else if(Mix_PausedMusic()) Mix_ResumeMusic(); } @@ -704,91 +585,70 @@ void updatesounds() VARP(maxsoundsatonce, 0, 7, 100); -void preloadsound(int n) -{ +void preloadsound(int n) { gamesounds.preloadsound(n); } -void preloadmapsound(int n) -{ +void preloadmapsound(int n) { mapsounds.preloadsound(n); } -void preloadmapsounds() -{ +void preloadmapsounds() { const vector &ents = entities::getents(); - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; if(e.type==ET_SOUND) mapsounds.preloadsound(e.attr1); } } -int playsound(int n, const vec *loc, extentity *ent, int flags, int loops, int fade, int chanid, int radius, int expire) -{ +int playsound(int n, const vec *loc, extentity *ent, int flags, int loops, int fade, int chanid, int radius, int expire) { if(nosound || !soundvol || (minimized && !minimizedsounds)) return -1; - soundtype &sounds = ent || flags&SND_MAP ? mapsounds : gamesounds; if(!sounds.configs.inrange(n)) { conoutf(CON_WARN, "unregistered sound: %d", n); return -1; } soundconfig &config = sounds.configs[n]; - - if(loc) - { + if(loc) { // cull sounds that are unlikely to be heard int maxrad = game::maxsoundradius(n); if(radius <= 0 || maxrad < radius) radius = maxrad; - if(camera1->o.dist(*loc) > 1.5f*radius) - { - if(channels.inrange(chanid) && sounds.playing(channels[chanid], config)) - { + if(camera1->o.dist(*loc) > 1.5f*radius) { + if(channels.inrange(chanid) && sounds.playing(channels[chanid], config)) { Mix_HaltChannel(chanid); freechannel(chanid); } return -1; } } - - if(chanid < 0) - { - if(config.maxuses) - { + if(chanid < 0) { + if(config.maxuses) { int uses = 0; loopv(channels) if(sounds.playing(channels[i], config) && ++uses >= config.maxuses) return -1; } - // avoid bursts of sounds with heavy packetloss and in sp static int soundsatonce = 0, lastsoundmillis = 0; if(totalmillis == lastsoundmillis) soundsatonce++; else soundsatonce = 1; lastsoundmillis = totalmillis; if(maxsoundsatonce && soundsatonce > maxsoundsatonce) return -1; } - - if(channels.inrange(chanid)) - { + if(channels.inrange(chanid)) { soundchannel &chan = channels[chanid]; - if(sounds.playing(chan, config)) - { + if(sounds.playing(chan, config)) { if(loc) chan.loc = *loc; else if(chan.hasloc()) chan.clearloc(); return chanid; } } if(fade < 0) return -1; - soundslot &slot = sounds.slots[config.chooseslot(flags)]; if(!slot.sample->chunk && !slot.sample->load()) return -1; - chanid = -1; loopv(channels) if(!channels[i].inuse) { chanid = i; break; } if(chanid < 0 && channels.length() < maxchannels) chanid = channels.length(); if(chanid < 0) loopv(channels) if(!channels[i].volume) { chanid = i; break; } if(chanid < 0) return -1; - soundchannel &chan = newchannel(chanid, &slot, loc, ent, flags, radius); updatechannel(chan); int playing = -1; - if(fade) - { + if(fade) { Mix_Volume(chanid, chan.volume); playing = expire >= 0 ? Mix_FadeInChannelTimed(chanid, slot.sample->chunk, loops, fade, expire) : Mix_FadeInChannel(chanid, slot.sample->chunk, loops, fade); } @@ -798,28 +658,23 @@ int playsound(int n, const vec *loc, extentity *ent, int flags, int loops, int f return playing; } -void stopsounds() -{ - loopv(channels) if(channels[i].inuse) - { +void stopsounds() { + loopv(channels) if(channels[i].inuse) { Mix_HaltChannel(i); freechannel(i); } } -bool stopsound(int n, int chanid, int fade) -{ +bool stopsound(int n, int chanid, int fade) { if(!gamesounds.configs.inrange(n) || !channels.inrange(chanid) || !channels[chanid].inuse || !gamesounds.playing(channels[chanid], gamesounds.configs[n])) return false; - if(!fade || !Mix_FadeOutChannel(chanid, fade)) - { + if(!fade || !Mix_FadeOutChannel(chanid, fade)) { Mix_HaltChannel(chanid); freechannel(chanid); } return true; } -int playsoundname(const char *s, const vec *loc, int vol, int flags, int loops, int fade, int chanid, int radius, int expire) -{ +int playsoundname(const char *s, const vec *loc, int vol, int flags, int loops, int fade, int chanid, int radius, int expire) { if(!vol) vol = 100; int id = gamesounds.findsound(s, vol); if(id < 0) id = gamesounds.addsound(s, vol); @@ -828,14 +683,11 @@ int playsoundname(const char *s, const vec *loc, int vol, int flags, int loops, ICOMMAND(sound, "i", (int *n), playsound(*n)); -void resetsound() -{ +void resetsound() { clearchanges(CHANGE_SOUND); - if(!nosound) - { + if(!nosound) { cleanupsamples(); - if(music) - { + if(music) { Mix_HaltMusic(); Mix_FreeMusic(music); } @@ -844,21 +696,18 @@ void resetsound() } initsound(); resetchannels(); - if(nosound) - { + if(nosound) { DELETEA(musicfile); DELETEA(musicdonecmd); music = NULL; cleanupsamples(); return; } - if(music && loadmusic(musicfile)) - { + if(music && loadmusic(musicfile)) { Mix_PlayMusic(music, musicdonecmd ? 0 : -1); Mix_VolumeMusic((musicvol*MIX_MAX_VOLUME)/255); } - else - { + else { DELETEA(musicfile); DELETEA(musicdonecmd); } diff --git a/src/engine/textedit.h b/src/engine/textedit.h index 0dcda1d..742fd33 100644 --- a/src/engine/textedit.h +++ b/src/engine/textedit.h @@ -1,31 +1,21 @@ -struct editline -{ +struct editline { enum { CHUNKSIZE = 256 }; - char *text; int len, maxlen; - editline() : text(NULL), len(0), maxlen(0) {} - editline(const char *init) : text(NULL), len(0), maxlen(0) - { + editline(const char *init) : text(NULL), len(0), maxlen(0) { set(init); } - bool empty() { return len <= 0; } - - void clear() - { + void clear() { DELETEA(text); len = maxlen = 0; } - - bool grow(int total, const char *fmt = "", ...) - { + bool grow(int total, const char *fmt = "", ...) { if(total + 1 <= maxlen) return false; maxlen = (total + CHUNKSIZE) - total%CHUNKSIZE; char *newtext = new char[maxlen]; - if(fmt) - { + if(fmt) { va_list args; va_start(args, fmt); vformatstring(newtext, fmt, args, maxlen); @@ -36,69 +26,52 @@ struct editline text = newtext; return true; } - - void set(const char *str, int slen = -1) - { - if(slen < 0) - { + void set(const char *str, int slen = -1) { + if(slen < 0) { slen = strlen(str); if(!grow(slen, "%s", str)) memcpy(text, str, slen + 1); } - else - { + else { grow(slen); memcpy(text, str, slen); text[slen] = '\0'; } len = slen; } - - void prepend(const char *str) - { + void prepend(const char *str) { int slen = strlen(str); - if(!grow(slen + len, "%s%s", str, text ? text : "")) - { + if(!grow(slen + len, "%s%s", str, text ? text : "")) { memmove(&text[slen], text, len + 1); memcpy(text, str, slen + 1); } len += slen; } - - void append(const char *str) - { + void append(const char *str) { int slen = strlen(str); if(!grow(len + slen, "%s%s", text ? text : "", str)) memcpy(&text[len], str, slen + 1); len += slen; } - - bool read(stream *f, int chop = -1) - { + bool read(stream *f, int chop = -1) { if(chop < 0) chop = INT_MAX; else chop++; set(""); - while(len + 1 < chop && f->getline(&text[len], min(maxlen, chop) - len)) - { + while(len + 1 < chop && f->getline(&text[len], min(maxlen, chop) - len)) { len += strlen(&text[len]); - if(len > 0 && text[len-1] == '\n') - { + if(len > 0 && text[len-1] == '\n') { text[--len] = '\0'; return true; } if(len + 1 >= maxlen && len + 1 < chop) grow(len + CHUNKSIZE, "%s", text); } - if(len + 1 >= chop) - { + if(len + 1 >= chop) { char buf[CHUNKSIZE]; - while(f->getline(buf, sizeof(buf))) - { + while(f->getline(buf, sizeof(buf))) { int blen = strlen(buf); if(blen > 0 && buf[blen-1] == '\n') return true; } } return len > 0; } - - void del(int start, int count) - { + void del(int start, int count) { if(!text) return; if(start < 0) { count += start; start = 0; } if(count <= 0 || start >= len) return; @@ -106,16 +79,12 @@ struct editline memmove(&text[start], &text[start+count], len + 1 - (start + count)); len -= count; } - - void chop(int newlen) - { + void chop(int newlen) { if(!text) return; len = clamp(newlen, 0, len); text[len] = '\0'; } - - void insert(char *str, int start, int count = 0) - { + void insert(char *str, int start, int count = 0) { if(count <= 0) count = strlen(str); start = clamp(start, 0, len); grow(len + count, "%s", text ? text : ""); @@ -123,12 +92,9 @@ struct editline memcpy(&text[start], str, count); len += count; } - - void combinelines(vector &src) - { + void combinelines(vector &src) { if(src.empty()) set(""); - else loopv(src) - { + else loopv(src) { if(i) append("\n"); if(!i) set(src[i].text, src[i].len); else insert(src[i].text, len, src[i].len); @@ -136,102 +102,77 @@ struct editline } }; -struct editor -{ +struct editor { int mode; //editor mode - 1= keep while focused, 2= keep while used in gui, 3= keep forever (i.e. until mode changes) bool active, rendered; const char *name; const char *filename; - int cx, cy; // cursor position - ensured to be valid after a region() or currentline() int mx, my; // selection mark, mx=-1 if following cursor - avoid direct access, instead use region() int maxx, maxy; // maxy=-1 if unlimited lines, 1 if single line editor - int scrolly; // vertical scroll offset - bool linewrap; int pixelwidth; // required for up/down/hit/draw/bounds int pixelheight; // -1 for variable sized, i.e. from bounds() - vector lines; // MUST always contain at least one line! - editor(const char *name, int mode, const char *initval) : mode(mode), active(true), rendered(false), name(newstring(name)), filename(NULL), - cx(0), cy(0), mx(-1), maxx(-1), maxy(-1), scrolly(0), linewrap(false), pixelwidth(-1), pixelheight(-1) - { + cx(0), cy(0), mx(-1), maxx(-1), maxy(-1), scrolly(0), linewrap(false), pixelwidth(-1), pixelheight(-1) { //printf("editor %08x '%s'\n", this, name); lines.add().set(initval ? initval : ""); } - - ~editor() - { + ~editor() { //printf("~editor %08x '%s'\n", this, name); DELETEA(name); DELETEA(filename); clear(NULL); } - - void clear(const char *init = "") - { + void clear(const char *init = "") { cx = cy = 0; mark(false); loopv(lines) lines[i].clear(); lines.shrink(0); if(init) lines.add().set(init); } - - void setfile(const char *fname) - { + void setfile(const char *fname) { DELETEA(filename); if(fname) filename = newstring(fname); } - - void load() - { + void load() { if(!filename) return; clear(NULL); stream *file = openutf8file(filename, "r"); - if(file) - { + if(file) { while(lines.add().read(file, maxx) && (maxy < 0 || lines.length() <= maxy)); lines.pop().clear(); delete file; } if(lines.empty()) lines.add().set(""); } - - void save() - { + void save() { if(!filename) return; stream *file = openutf8file(filename, "w"); if(!file) return; loopv(lines) file->putline(lines[i].text); delete file; } - - void mark(bool enable) - { + void mark(bool enable) { mx = (enable) ? cx : -1; my = cy; } - - void selectall() - { + void selectall() { mx = my = INT_MAX; cx = cy = 0; } - // constrain results to within buffer - s=start, e=end, return true if a selection range // also ensures that cy is always within lines[] and cx is valid - bool region(int &sx, int &sy, int &ex, int &ey) - { + bool region(int &sx, int &sy, int &ex, int &ey) { int n = lines.length(); ASSERT(n != 0); if(cy < 0) cy = 0; else if(cy >= n) cy = n-1; int len = lines[cy].len; if(cx < 0) cx = 0; else if(cx > len) cx = len; - if(mx >= 0) - { + if(mx >= 0) { if(my < 0) my = 0; else if(my >= n) my = n-1; len = lines[my].len; if(mx > len) mx = len; @@ -244,34 +185,26 @@ struct editor else if(sy==ey && sx > ex) swap(sx, ex); return (sx != ex) || (sy != ey); } - bool region() { int sx, sy, ex, ey; return region(sx, sy, ex, ey); } - // also ensures that cy is always within lines[] and cx is valid - editline ¤tline() - { + editline ¤tline() { int n = lines.length(); ASSERT(n != 0); if(cy < 0) cy = 0; else if(cy >= n) cy = n-1; if(cx < 0) cx = 0; else if(cx > lines[cy].len) cx = lines[cy].len; return lines[cy]; } - - void copyselectionto(editor *b) - { + void copyselectionto(editor *b) { if(b==this) return; - b->clear(NULL); int sx, sy, ex, ey; region(sx, sy, ex, ey); - loopi(1+ey-sy) - { + loopi(1+ey-sy) { if(b->maxy != -1 && b->lines.length() >= b->maxy) break; int y = sy+i; char *line = lines[y].text; int len = lines[y].len; - if(y == sy && y == ey) - { + if(y == sy && y == ey) { line += sx; len = ex - sx; } @@ -281,15 +214,12 @@ struct editor } if(b->lines.empty()) b->lines.add().set(""); } - - char *tostring() - { + char *tostring() { int len = 0; loopv(lines) len += lines[i].len + 1; char *str = newstring(len); int offset = 0; - loopv(lines) - { + loopv(lines) { editline &l = lines[i]; memcpy(&str[offset], l.text, l.len); offset += l.len; @@ -298,19 +228,15 @@ struct editor str[offset] = '\0'; return str; } - - char *selectiontostring() - { + char *selectiontostring() { vector buf; int sx, sy, ex, ey; region(sx, sy, ex, ey); - loopi(1+ey-sy) - { + loopi(1+ey-sy) { int y = sy+i; char *line = lines[y].text; int len = lines[y].len; - if(y == sy && y == ey) - { + if(y == sy && y == ey) { line += sx; len = ex - sx; } @@ -322,28 +248,21 @@ struct editor buf.add('\0'); return newstring(buf.getbuf(), buf.length()-1); } - - void removelines(int start, int count) - { + void removelines(int start, int count) { loopi(count) lines[start+i].clear(); lines.remove(start, count); } - - bool del() // removes the current selection (if any) - { + bool del() { // removes the current selection (if any) { int sx, sy, ex, ey; - if(!region(sx, sy, ex, ey)) - { + if(!region(sx, sy, ex, ey)) { mark(false); return false; } - if(sy == ey) - { + if(sy == ey) { if(sx == 0 && ex == lines[ey].len) removelines(sy, 1); else lines[sy].del(sx, ex - sx); } - else - { + else { if(ey > sy+1) { removelines(sy+1, ey-(sy+1)); ey = sy+1; } if(ex == lines[ey].len) removelines(ey, 1); else lines[ey].del(0, ex); if(sx == 0) removelines(sy, 1); else lines[sy].del(sx, lines[sy].len - sx); @@ -353,22 +272,17 @@ struct editor cx = sx; cy = sy; editline ¤t = currentline(); - if(cx >= current.len && cy < lines.length() - 1) - { + if(cx >= current.len && cy < lines.length() - 1) { current.append(lines[cy+1].text); removelines(cy + 1, 1); } return true; } - - void insert(char ch) - { + void insert(char ch) { del(); editline ¤t = currentline(); - if(ch == '\n') - { - if(maxy == -1 || cy < maxy-1) - { + if(ch == '\n') { + if(maxy == -1 || cy < maxy-1) { editline newline(¤t.text[cx]); current.chop(cx); cy = min(lines.length(), cy+1); @@ -377,49 +291,36 @@ struct editor else current.chop(cx); cx = 0; } - else - { + else { int len = current.len; if(maxx >= 0 && len > maxx-1) len = maxx-1; if(cx <= len) current.insert(&ch, cx++, 1); } } - - void insert(const char *s) - { + void insert(const char *s) { while(*s) insert(*s++); } - - void insertallfrom(editor *b) - { + void insertallfrom(editor *b) { if(b==this) return; - del(); - - if(b->lines.length() == 1 || maxy == 1) - { + if(b->lines.length() == 1 || maxy == 1) { editline ¤t = currentline(); char *str = b->lines[0].text; int slen = b->lines[0].len; if(maxx >= 0 && b->lines[0].len + cx > maxx) slen = maxx-cx; - if(slen > 0) - { + if(slen > 0) { int len = current.len; if(maxx >= 0 && slen + cx + len > maxx) len = max(0, maxx-(cx+slen)); current.insert(str, cx, slen); cx += slen; } } - else - { - loopv(b->lines) - { - if(!i) - { + else { + loopv(b->lines) { + if(!i) { lines[cy++].append(b->lines[i].text); } - else if(i >= b->lines.length()) - { + else if(i >= b->lines.length()) { cx = b->lines[i].len; lines[cy].prepend(b->lines[i].text); } @@ -427,14 +328,10 @@ struct editor } } } - - void key(int code) - { - switch(code) - { + void key(int code) { + switch(code) { case SDLK_UP: - if(linewrap) - { + if(linewrap) { int x, y; char *str = currentline().text; text_pos(str, cx+1, x, y, pixelwidth); @@ -443,8 +340,7 @@ struct editor cy--; break; case SDLK_DOWN: - if(linewrap) - { + if(linewrap) { int x, y, width, height; char *str = currentline().text; text_pos(str, cx, x, y, pixelwidth); @@ -479,24 +375,22 @@ struct editor cx++; break; case SDLK_DELETE: - if(!del()) - { + if(!del()) { editline ¤t = currentline(); if(cx < current.len) current.del(cx, 1); - else if(cy < lines.length()-1) - { //combine with next line + else if(cy < lines.length()-1) { + //combine with next line current.append(lines[cy+1].text); removelines(cy+1, 1); } } break; case SDLK_BACKSPACE: - if(!del()) - { + if(!del()) { editline ¤t = currentline(); if(cx > 0) current.del(--cx, 1); - else if(cy > 0) - { //combine with previous line + else if(cy > 0) { + //combine with previous line cx = lines[cy-1].len; lines[cy-1].append(current.text); removelines(cy--, 1); @@ -514,24 +408,17 @@ struct editor break; } } - - void input(const char *str, int len) - { + void input(const char *str, int len) { loopi(len) insert(str[i]); } - - void hit(int hitx, int hity, bool dragged) - { + void hit(int hitx, int hity, bool dragged) { int maxwidth = linewrap?pixelwidth:-1; int h = 0; - for(int i = scrolly; i < lines.length(); i++) - { + for(int i = scrolly; i < lines.length(); i++) { int width, height; text_bounds(lines[i].text, width, height, maxwidth); if(h + height > pixelheight) break; - - if(hity >= h && hity <= h+height) - { + if(hity >= h && hity <= h+height) { int x = text_visible(lines[i].text, hitx, hity-h, maxwidth); if(dragged) { mx = x; my = i; } else { cx = x; cy = i; }; break; @@ -539,13 +426,10 @@ struct editor h+=height; } } - - int limitscrolly() - { + int limitscrolly() { int maxwidth = linewrap?pixelwidth:-1; int slines = lines.length(); - for(int ph = pixelheight; slines > 0 && ph > 0;) - { + for(int ph = pixelheight; slines > 0 && ph > 0;) { int width, height; text_bounds(lines[slines-1].text, width, height, maxwidth); if(height > ph) break; @@ -554,39 +438,30 @@ struct editor } return slines; } - - void draw(int x, int y, int color, bool hit) - { + void draw(int x, int y, int color, bool hit) { int maxwidth = linewrap?pixelwidth:-1; - int sx, sy, ex, ey; bool selection = region(sx, sy, ex, ey); - // fix scrolly so that is always on screen if(cy < scrolly) scrolly = cy; - else - { + else { if(scrolly < 0) scrolly = 0; int h = 0; - for(int i = cy; i >= scrolly; i--) - { + for(int i = cy; i >= scrolly; i--) { int width, height; text_bounds(lines[i].text, width, height, maxwidth); if(h + height > pixelheight) { scrolly = i+1; break; } h += height; } } - - if(selection) - { + if(selection) { // convert from cursor coords into pixel coords int psx, psy, pex, pey; text_pos(lines[sy].text, sx, psx, psy, maxwidth); text_pos(lines[ey].text, ex, pex, pey, maxwidth); int maxy = lines.length(); int h = 0; - for(int i = scrolly; i < maxy; i++) - { + for(int i = scrolly; i < maxy; i++) { int width, height; text_bounds(lines[i].text, width, height, maxwidth); if(h + height > pixelheight) { maxy = i; break; } @@ -595,31 +470,26 @@ struct editor h += height; } maxy--; - - if(ey >= scrolly && sy <= maxy) - { + if(ey >= scrolly && sy <= maxy) { // crop top/bottom within window if(sy < scrolly) { sy = scrolly; psy = 0; psx = 0; } if(ey > maxy) { ey = maxy; pey = pixelheight - FONTH; pex = pixelwidth; } - hudnotextureshader->set(); gle::colorub(0xA0, 0x80, 0x80); gle::defvertex(2); gle::begin(GL_QUADS); - if(psy == pey) - { + if(psy == pey) { gle::attribf(x+psx, y+psy); gle::attribf(x+pex, y+psy); gle::attribf(x+pex, y+pey+FONTH); gle::attribf(x+psx, y+pey+FONTH); } - else - { gle::attribf(x+psx, y+psy); + else { + gle::attribf(x+psx, y+psy); gle::attribf(x+psx, y+psy+FONTH); gle::attribf(x+pixelwidth, y+psy+FONTH); gle::attribf(x+pixelwidth, y+psy); - if(pey-psy > FONTH) - { + if(pey-psy > FONTH) { gle::attribf(x, y+psy+FONTH); gle::attribf(x+pixelwidth, y+psy+FONTH); gle::attribf(x+pixelwidth, y+pey); @@ -634,17 +504,13 @@ struct editor hudshader->set(); } } - int h = 0; - for(int i = scrolly; i < lines.length(); i++) - { + for(int i = scrolly; i < lines.length(); i++) { int width, height; text_bounds(lines[i].text, width, height, maxwidth); if(h + height > pixelheight) break; - draw_text(lines[i].text, x, y+h, color>>16, (color>>8)&0xFF, color&0xFF, 0xFF, hit&&(cy==i)?cx:-1, maxwidth); - if(linewrap && height > FONTH) // line wrap indicator - { + if(linewrap && height > FONTH) { // line wrap indicator { hudnotextureshader->set(); gle::colorub(0x80, 0xA0, 0x80); gle::defvertex(2); @@ -666,24 +532,19 @@ static vector editors; static editor *currentfocus() { return editors.length() ? editors.last() : NULL; } -static void readyeditors() -{ +static void readyeditors() { loopv(editors) editors[i]->active = (editors[i]->mode==EDITORFOREVER); } -static void flusheditors() -{ - loopvrev(editors) if(!editors[i]->active) - { +static void flusheditors() { + loopvrev(editors) if(!editors[i]->active) { editor *e = editors.remove(i); DELETEP(e); } } -static editor *useeditor(const char *name, int mode, bool focus, const char *initval = NULL) -{ - loopv(editors) if(strcmp(editors[i]->name, name) == 0) - { +static editor *useeditor(const char *name, int mode, bool focus, const char *initval = NULL) { + loopv(editors) if(strcmp(editors[i]->name, name) == 0) { editor *e = editors[i]; if(focus) { editors.add(e); editors.remove(i); } // re-position as last e->active = true; @@ -703,8 +564,7 @@ static editor *useeditor(const char *name, int mode, bool focus, const char *ini ICOMMAND(textlist, "", (), // @DEBUG return list of all the editors vector s; - loopv(editors) - { + loopv(editors) { if(i > 0) s.put(", ", 2); s.put(editors[i]->name, strlen(editors[i]->name)); } @@ -731,19 +591,16 @@ TEXTCOMMAND(textsave, "s", (char *file), // saves the topmost (filename is opti top->save(); ); TEXTCOMMAND(textload, "s", (char *file), // loads into the topmost editor, returns filename if no args - if(*file) - { + if(*file) { top->setfile(path(file, true)); top->load(); } else if(top->filename) result(top->filename); ); -TEXTCOMMAND(textinit, "sss", (char *name, char *file, char *initval), // loads into named editor if no file assigned and editor has been rendered -{ +TEXTCOMMAND(textinit, "sss", (char *name, char *file, char *initval), { // loads into named editor if no file assigned and editor has been rendered { editor *e = NULL; loopv(editors) if(!strcmp(editors[i]->name, name)) { e = editors[i]; break; } - if(e && e->rendered && !e->filename && *file && (e->lines.empty() || (e->lines.length() == 1 && !strcmp(e->lines[0].text, initval)))) - { + if(e && e->rendered && !e->filename && *file && (e->lines.empty() || (e->lines.length() == 1 && !strcmp(e->lines[0].text, initval)))) { e->setfile(path(file, true)); e->load(); } diff --git a/src/engine/texture.cpp b/src/engine/texture.cpp index 7f391a9..0f7a5df 100644 --- a/src/engine/texture.cpp +++ b/src/engine/texture.cpp @@ -8,33 +8,26 @@ (SDL_VERSIONNUM(SDL_IMAGE_MAJOR_VERSION, SDL_IMAGE_MINOR_VERSION, SDL_IMAGE_PATCHLEVEL) >= SDL_VERSIONNUM(X, Y, Z)) #endif -template static void halvetexture(uchar * RESTRICT src, uint sw, uint sh, uint stride, uchar * RESTRICT dst) -{ - for(uchar *yend = &src[sh*stride]; src < yend;) - { - for(uchar *xend = &src[sw*BPP], *xsrc = src; xsrc < xend; xsrc += 2*BPP, dst += BPP) - { +template static void halvetexture(uchar * RESTRICT src, uint sw, uint sh, uint stride, uchar * RESTRICT dst) { + for(uchar *yend = &src[sh*stride]; src < yend;) { + for(uchar *xend = &src[sw*BPP], *xsrc = src; xsrc < xend; xsrc += 2*BPP, dst += BPP) { loopi(BPP) dst[i] = (uint(xsrc[i]) + uint(xsrc[i+BPP]) + uint(xsrc[stride+i]) + uint(xsrc[stride+i+BPP]))>>2; } src += 2*stride; } } -template static void shifttexture(uchar * RESTRICT src, uint sw, uint sh, uint stride, uchar * RESTRICT dst, uint dw, uint dh) -{ +template static void shifttexture(uchar * RESTRICT src, uint sw, uint sh, uint stride, uchar * RESTRICT dst, uint dw, uint dh) { uint wfrac = sw/dw, hfrac = sh/dh, wshift = 0, hshift = 0; while(dw< static void shifttexture(uchar * RESTRICT src, uint sw, uint s } } -template static void scaletexture(uchar * RESTRICT src, uint sw, uint sh, uint stride, uchar * RESTRICT dst, uint dw, uint dh) -{ +template static void scaletexture(uchar * RESTRICT src, uint sw, uint sh, uint stride, uchar * RESTRICT dst, uint dw, uint dh) { uint wfrac = (sw<<12)/dw, hfrac = (sh<<12)/dh, darea = dw*dh, sarea = sw*sh; int over, under; for(over = 0; (darea>>over) > sarea; over++); @@ -56,24 +48,20 @@ template static void scaletexture(uchar * RESTRICT src, uint sw, uint s area = ((ullong)darea<>12, h = (yn>>12) - yi, ylow = ((yn|(-int(h)>>24))&0xFFFU) + 1 - (y&0xFFFU), yhigh = (yn&0xFFFU) + 1; const uchar *ysrc = &src[yi*stride]; - for(uint x = 0; x < dw; x += wfrac, dst += BPP) - { + for(uint x = 0; x < dw; x += wfrac, dst += BPP) { const uint xn = x + wfrac - 1, xi = x>>12, w = (xn>>12) - xi, xlow = ((w+0xFFFU)&0x1000U) - (x&0xFFFU), xhigh = (xn&0xFFFU) + 1; const uchar *xsrc = &ysrc[xi*BPP], *xend = &xsrc[w*BPP]; uint t[BPP] = {0}; for(const uchar *xcur = &xsrc[BPP]; xcur < xend; xcur += BPP) loopi(BPP) t[i] += xcur[i]; loopi(BPP) t[i] = (ylow*(t[i] + ((xsrc[i]*xlow + xend[i]*xhigh)>>12)))>>cscale; - if(h) - { + if(h) { xsrc += stride; xend += stride; - for(uint hcur = h; --hcur; xsrc += stride, xend += stride) - { + for(uint hcur = h; --hcur; xsrc += stride, xend += stride) { uint c[BPP] = {0}; for(const uchar *xcur = &xsrc[BPP]; xcur < xend; xcur += BPP) loopi(BPP) c[i] += xcur[i]; @@ -89,32 +77,25 @@ template static void scaletexture(uchar * RESTRICT src, uint sw, uint s } } -static void scaletexture(uchar * RESTRICT src, uint sw, uint sh, uint bpp, uint pitch, uchar * RESTRICT dst, uint dw, uint dh) -{ - if(sw == dw*2 && sh == dh*2) - { - switch(bpp) - { +static void scaletexture(uchar * RESTRICT src, uint sw, uint sh, uint bpp, uint pitch, uchar * RESTRICT dst, uint dw, uint dh) { + if(sw == dw*2 && sh == dh*2) { + switch(bpp) { case 1: return halvetexture<1>(src, sw, sh, pitch, dst); case 2: return halvetexture<2>(src, sw, sh, pitch, dst); case 3: return halvetexture<3>(src, sw, sh, pitch, dst); case 4: return halvetexture<4>(src, sw, sh, pitch, dst); } } - else if(sw < dw || sh < dh || sw&(sw-1) || sh&(sh-1) || dw&(dw-1) || dh&(dh-1)) - { - switch(bpp) - { + else if(sw < dw || sh < dh || sw&(sw-1) || sh&(sh-1) || dw&(dw-1) || dh&(dh-1)) { + switch(bpp) { case 1: return scaletexture<1>(src, sw, sh, pitch, dst, dw, dh); case 2: return scaletexture<2>(src, sw, sh, pitch, dst, dw, dh); case 3: return scaletexture<3>(src, sw, sh, pitch, dst, dw, dh); case 4: return scaletexture<4>(src, sw, sh, pitch, dst, dw, dh); } } - else - { - switch(bpp) - { + else { + switch(bpp) { case 1: return shifttexture<1>(src, sw, sh, pitch, dst, dw, dh); case 2: return shifttexture<2>(src, sw, sh, pitch, dst, dw, dh); case 3: return shifttexture<3>(src, sw, sh, pitch, dst, dw, dh); @@ -123,17 +104,14 @@ static void scaletexture(uchar * RESTRICT src, uint sw, uint sh, uint bpp, uint } } -static void reorientnormals(uchar * RESTRICT src, int sw, int sh, int bpp, int stride, uchar * RESTRICT dst, bool flipx, bool flipy, bool swapxy) -{ +static void reorientnormals(uchar * RESTRICT src, int sw, int sh, int bpp, int stride, uchar * RESTRICT dst, bool flipx, bool flipy, bool swapxy) { int stridex = bpp, stridey = bpp; if(swapxy) stridex *= sh; else stridey *= sw; if(flipx) { dst += (sw-1)*stridex; stridex = -stridex; } if(flipy) { dst += (sh-1)*stridey; stridey = -stridey; } uchar *srcrow = src; - loopi(sh) - { - for(uchar *curdst = dst, *src = srcrow, *end = &srcrow[sw*bpp]; src < end;) - { + loopi(sh) { + for(uchar *curdst = dst, *src = srcrow, *end = &srcrow[sw*bpp]; src < end;) { uchar nx = *src++, ny = *src++; if(flipx) nx = 255-nx; if(flipy) ny = 255-ny; @@ -150,17 +128,14 @@ static void reorientnormals(uchar * RESTRICT src, int sw, int sh, int bpp, int s } template -static inline void reorienttexture(uchar * RESTRICT src, int sw, int sh, int stride, uchar * RESTRICT dst, bool flipx, bool flipy, bool swapxy) -{ +static inline void reorienttexture(uchar * RESTRICT src, int sw, int sh, int stride, uchar * RESTRICT dst, bool flipx, bool flipy, bool swapxy) { int stridex = BPP, stridey = BPP; if(swapxy) stridex *= sh; else stridey *= sw; if(flipx) { dst += (sw-1)*stridex; stridex = -stridex; } if(flipy) { dst += (sh-1)*stridey; stridey = -stridey; } uchar *srcrow = src; - loopi(sh) - { - for(uchar *curdst = dst, *src = srcrow, *end = &srcrow[sw*BPP]; src < end;) - { + loopi(sh) { + for(uchar *curdst = dst, *src = srcrow, *end = &srcrow[sw*BPP]; src < end;) { loopk(BPP) curdst[k] = *src++; curdst += stridex; } @@ -169,10 +144,8 @@ static inline void reorienttexture(uchar * RESTRICT src, int sw, int sh, int str } } -static void reorienttexture(uchar * RESTRICT src, int sw, int sh, int bpp, int stride, uchar * RESTRICT dst, bool flipx, bool flipy, bool swapxy) -{ - switch(bpp) - { +static void reorienttexture(uchar * RESTRICT src, int sw, int sh, int bpp, int stride, uchar * RESTRICT dst, bool flipx, bool flipy, bool swapxy) { + switch(bpp) { case 1: return reorienttexture<1>(src, sw, sh, stride, dst, flipx, flipy, swapxy); case 2: return reorienttexture<2>(src, sw, sh, stride, dst, flipx, flipy, swapxy); case 3: return reorienttexture<3>(src, sw, sh, stride, dst, flipx, flipy, swapxy); @@ -180,23 +153,18 @@ static void reorienttexture(uchar * RESTRICT src, int sw, int sh, int bpp, int s } } -static void reorients3tc(GLenum format, int blocksize, int w, int h, uchar *src, uchar *dst, bool flipx, bool flipy, bool swapxy, bool normals = false) -{ +static void reorients3tc(GLenum format, int blocksize, int w, int h, uchar *src, uchar *dst, bool flipx, bool flipy, bool swapxy, bool normals = false) { int bx1 = 0, by1 = 0, bx2 = min(w, 4), by2 = min(h, 4), bw = (w+3)/4, bh = (h+3)/4, stridex = blocksize, stridey = blocksize; if(swapxy) stridex *= bw; else stridey *= bh; if(flipx) { dst += (bw-1)*stridex; stridex = -stridex; bx1 += 4-bx2; bx2 = 4; } if(flipy) { dst += (bh-1)*stridey; stridey = -stridey; by1 += 4-by2; by2 = 4; } - loopi(bh) - { - for(uchar *curdst = dst, *end = &src[bw*blocksize]; src < end; src += blocksize, curdst += stridex) - { - if(format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) - { + loopi(bh) { + for(uchar *curdst = dst, *end = &src[bw*blocksize]; src < end; src += blocksize, curdst += stridex) { + if(format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) { ullong salpha = lilswap(*(const ullong *)src), dalpha = 0; uint xmask = flipx ? 15 : 0, ymask = flipy ? 15 : 0, xshift = 2, yshift = 4; if(swapxy) swap(xshift, yshift); - for(int y = by1; y < by2; y++) for(int x = bx1; x < bx2; x++) - { + for(int y = by1; y < by2; y++) for(int x = bx1; x < bx2; x++) { dalpha |= ((salpha&15) << (((xmask^x)<>= 4; } @@ -204,14 +172,12 @@ static void reorients3tc(GLenum format, int blocksize, int w, int h, uchar *src, src += 8; curdst += 8; } - else if(format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) - { + else if(format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) { uchar alpha1 = src[0], alpha2 = src[1]; ullong salpha = lilswap(*(const ushort *)&src[2]) + ((ullong)lilswap(*(const uint *)&src[4]) << 16), dalpha = 0; uint xmask = flipx ? 7 : 0, ymask = flipy ? 7 : 0, xshift = 0, yshift = 2; if(swapxy) swap(xshift, yshift); - for(int y = by1; y < by2; y++) for(int x = bx1; x < bx2; x++) - { + for(int y = by1; y < by2; y++) for(int x = bx1; x < bx2; x++) { dalpha |= ((salpha&7) << (3*((xmask^x)<>= 3; } @@ -223,24 +189,19 @@ static void reorients3tc(GLenum format, int blocksize, int w, int h, uchar *src, src += 8; curdst += 8; } - ushort color1 = lilswap(*(const ushort *)src), color2 = lilswap(*(const ushort *)&src[2]); uint sbits = lilswap(*(const uint *)&src[4]); - if(normals) - { + if(normals) { ushort ncolor1 = color1, ncolor2 = color2; - if(flipx) - { + if(flipx) { ncolor1 = (ncolor1 & ~0xF800) | (0xF800 - (ncolor1 & 0xF800)); ncolor2 = (ncolor2 & ~0xF800) | (0xF800 - (ncolor2 & 0xF800)); } - if(flipy) - { + if(flipy) { ncolor1 = (ncolor1 & ~0x7E0) | (0x7E0 - (ncolor1 & 0x7E0)); ncolor2 = (ncolor2 & ~0x7E0) | (0x7E0 - (ncolor2 & 0x7E0)); } - if(swapxy) - { + if(swapxy) { ncolor1 = (ncolor1 & 0x1F) | (((((ncolor1 >> 11) & 0x1F) * 0x3F) / 0x1F) << 5) | (((((ncolor1 >> 5) & 0x3F) * 0x1F) / 0x3F) << 11); ncolor2 = (ncolor2 & 0x1F) | (((((ncolor2 >> 11) & 0x1F) * 0x3F) / 0x1F) << 5) | (((((ncolor2 >> 5) & 0x3F) * 0x1F) / 0x3F) << 11); } @@ -249,40 +210,33 @@ static void reorients3tc(GLenum format, int blocksize, int w, int h, uchar *src, } uint dbits = 0, xmask = flipx ? 3 : 0, ymask = flipy ? 3 : 0, xshift = 1, yshift = 3; if(swapxy) swap(xshift, yshift); - for(int y = by1; y < by2; y++) for(int x = bx1; x < bx2; x++) - { + for(int y = by1; y < by2; y++) for(int x = bx1; x < bx2; x++) { dbits |= ((sbits&3) << (((xmask^x)<>= 2; } *(ushort *)curdst = lilswap(color1); *(ushort *)&curdst[2] = lilswap(color2); *(uint *)&curdst[4] = lilswap(dbits); - if(blocksize > 8) { src -= 8; curdst -= 8; } } dst += stridey; } } -static void reorientrgtc(GLenum format, int blocksize, int w, int h, uchar *src, uchar *dst, bool flipx, bool flipy, bool swapxy) -{ +static void reorientrgtc(GLenum format, int blocksize, int w, int h, uchar *src, uchar *dst, bool flipx, bool flipy, bool swapxy) { int bx1 = 0, by1 = 0, bx2 = min(w, 4), by2 = min(h, 4), bw = (w+3)/4, bh = (h+3)/4, stridex = blocksize, stridey = blocksize; if(swapxy) stridex *= bw; else stridey *= bh; if(flipx) { dst += (bw-1)*stridex; stridex = -stridex; bx1 += 4-bx2; bx2 = 4; } if(flipy) { dst += (bh-1)*stridey; stridey = -stridey; by1 += 4-by2; by2 = 4; } stridex -= blocksize; - loopi(bh) - { - for(uchar *curdst = dst, *end = &src[bw*blocksize]; src < end; curdst += stridex) - { - loopj(blocksize/8) - { + loopi(bh) { + for(uchar *curdst = dst, *end = &src[bw*blocksize]; src < end; curdst += stridex) { + loopj(blocksize/8) { uchar val1 = src[0], val2 = src[1]; ullong sval = lilswap(*(const ushort *)&src[2]) + ((ullong)lilswap(*(const uint *)&src[4] )<< 16), dval = 0; uint xmask = flipx ? 7 : 0, ymask = flipy ? 7 : 0, xshift = 0, yshift = 2; if(swapxy) swap(xshift, yshift); - for(int y = by1; y < by2; y++) for(int x = bx1; x < bx2; x++) - { + for(int y = by1; y < by2; y++) for(int x = bx1; x < bx2; x++) { dval |= ((sval&7) << (3*((xmask^x)<>= 3; } @@ -299,26 +253,26 @@ static void reorientrgtc(GLenum format, int blocksize, int w, int h, uchar *src, } } -#define writetex(t, body) do \ - { \ +#define writetex(t, body) do { \ + \ uchar *dstrow = t.data; \ - loop(y, t.h) \ - { \ - for(uchar *dst = dstrow, *end = &dstrow[t.w*t.bpp]; dst < end; dst += t.bpp) \ - { \ + loop(y, t.h) { \ + \ + for(uchar *dst = dstrow, *end = &dstrow[t.w*t.bpp]; dst < end; dst += t.bpp) { \ + \ body; \ } \ dstrow += t.pitch; \ } \ } while(0) -#define readwritetex(t, s, body) do \ - { \ +#define readwritetex(t, s, body) do { \ + \ uchar *dstrow = t.data, *srcrow = s.data; \ - loop(y, t.h) \ - { \ - for(uchar *dst = dstrow, *src = srcrow, *end = &srcrow[s.w*s.bpp]; src < end; dst += t.bpp, src += s.bpp) \ - { \ + loop(y, t.h) { \ + \ + for(uchar *dst = dstrow, *src = srcrow, *end = &srcrow[s.w*s.bpp]; src < end; dst += t.bpp, src += s.bpp) { \ + \ body; \ } \ dstrow += t.pitch; \ @@ -326,13 +280,13 @@ static void reorientrgtc(GLenum format, int blocksize, int w, int h, uchar *src, } \ } while(0) -#define read2writetex(t, s1, src1, s2, src2, body) do \ - { \ +#define read2writetex(t, s1, src1, s2, src2, body) do { \ + \ uchar *dstrow = t.data, *src1row = s1.data, *src2row = s2.data; \ - loop(y, t.h) \ - { \ - for(uchar *dst = dstrow, *end = &dstrow[t.w*t.bpp], *src1 = src1row, *src2 = src2row; dst < end; dst += t.bpp, src1 += s1.bpp, src2 += s2.bpp) \ - { \ + loop(y, t.h) { \ + \ + for(uchar *dst = dstrow, *end = &dstrow[t.w*t.bpp], *src1 = src1row, *src2 = src2row; dst < end; dst += t.bpp, src1 += s1.bpp, src2 += s2.bpp) { \ + \ body; \ } \ dstrow += t.pitch; \ @@ -341,30 +295,29 @@ static void reorientrgtc(GLenum format, int blocksize, int w, int h, uchar *src, } \ } while(0) -#define readwritergbtex(t, s, body) \ - { \ +#define readwritergbtex(t, s, body) { \ + \ if(t.bpp >= 3) readwritetex(t, s, body); \ - else \ - { \ + else { \ + \ ImageData rgb(t.w, t.h, 3); \ read2writetex(rgb, t, orig, s, src, { dst[0] = dst[1] = dst[2] = orig[0]; body; }); \ t.replace(rgb); \ } \ } -void forcergbimage(ImageData &s) -{ +void forcergbimage(ImageData &s) { if(s.bpp >= 3) return; ImageData d(s.w, s.h, 3); readwritetex(d, s, { dst[0] = dst[1] = dst[2] = src[0]; }); s.replace(d); } -#define readwritergbatex(t, s, body) \ - { \ +#define readwritergbatex(t, s, body) { \ + \ if(t.bpp >= 4) { readwritetex(t, s, body); } \ - else \ - { \ + else { \ + \ ImageData rgba(t.w, t.h, 4); \ if(t.bpp==3) read2writetex(rgba, t, orig, s, src, { dst[0] = orig[0]; dst[1] = orig[1]; dst[2] = orig[2]; body; }); \ else read2writetex(rgba, t, orig, s, src, { dst[0] = dst[1] = dst[2] = orig[0]; body; }); \ @@ -372,8 +325,7 @@ void forcergbimage(ImageData &s) } \ } -void forcergbaimage(ImageData &s) -{ +void forcergbaimage(ImageData &s) { if(s.bpp >= 4) return; ImageData d(s.w, s.h, 4); if(s.bpp==3) readwritetex(d, s, { dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; }); @@ -381,38 +333,31 @@ void forcergbaimage(ImageData &s) s.replace(d); } -void swizzleimage(ImageData &s) -{ - if(s.bpp==2) - { +void swizzleimage(ImageData &s) { + if(s.bpp==2) { ImageData d(s.w, s.h, 4); readwritetex(d, s, { dst[0] = dst[1] = dst[2] = src[0]; dst[3] = src[1]; }); s.replace(d); } - else if(s.bpp==1) - { + else if(s.bpp==1) { ImageData d(s.w, s.h, 3); readwritetex(d, s, { dst[0] = dst[1] = dst[2] = src[0]; }); s.replace(d); } } -void texreorient(ImageData &s, bool flipx, bool flipy, bool swapxy, int type = TEX_DIFFUSE) -{ +void texreorient(ImageData &s, bool flipx, bool flipy, bool swapxy, int type = TEX_DIFFUSE) { ImageData d(swapxy ? s.h : s.w, swapxy ? s.w : s.h, s.bpp, s.levels, s.align, s.compressed); - switch(s.compressed) - { + switch(s.compressed) { case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: [[fallthrough]]; case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: [[fallthrough]]; case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: [[fallthrough]]; - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - { + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: { uchar *dst = d.data, *src = s.data; - loopi(s.levels) - { + loopi(s.levels) { reorients3tc(s.compressed, s.bpp, max(s.w>>i, 1), max(s.h>>i, 1), src, dst, flipx, flipy, swapxy, type==TEX_NORMAL); src += s.calclevelsize(i); dst += d.calclevelsize(i); @@ -425,11 +370,9 @@ void texreorient(ImageData &s, bool flipx, bool flipy, bool swapxy, int type = T [[fallthrough]]; case GL_COMPRESSED_LUMINANCE_LATC1_EXT: [[fallthrough]]; - case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: - { + case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: { uchar *dst = d.data, *src = s.data; - loopi(s.levels) - { + loopi(s.levels) { reorientrgtc(s.compressed, s.bpp, max(s.w>>i, 1), max(s.h>>i, 1), src, dst, flipx, flipy, swapxy); src += s.calclevelsize(i); dst += d.calclevelsize(i); @@ -444,29 +387,25 @@ void texreorient(ImageData &s, bool flipx, bool flipy, bool swapxy, int type = T s.replace(d); } -extern const texrotation texrotations[8] = -{ - { false, false, false }, // 0: default - { false, true, true }, // 1: 90 degrees - { true, true, false }, // 2: 180 degrees - { true, false, true }, // 3: 270 degrees - { true, false, false }, // 4: flip X - { false, true, false }, // 5: flip Y - { false, false, true }, // 6: transpose +extern const texrotation texrotations[8] = { + { false, false, false }, // 0: default { + { false, true, true }, // 1: 90 degrees { + { true, true, false }, // 2: 180 degrees { + { true, false, true }, // 3: 270 degrees { + { true, false, false }, // 4: flip X { + { false, true, false }, // 5: flip Y { + { false, false, true }, // 6: transpose { { true, true, true }, // 7: flipped transpose }; -void texrotate(ImageData &s, int numrots, int type = TEX_DIFFUSE) -{ - if(numrots>=1 && numrots<=7) - { +void texrotate(ImageData &s, int numrots, int type = TEX_DIFFUSE) { + if(numrots>=1 && numrots<=7) { const texrotation &r = texrotations[numrots]; texreorient(s, r.flipx, r.flipy, r.swapxy, type); } } -void texoffset(ImageData &s, int xoffset, int yoffset) -{ +void texoffset(ImageData &s, int xoffset, int yoffset) { xoffset = max(xoffset, 0); xoffset %= s.w; yoffset = max(yoffset, 0); @@ -474,8 +413,7 @@ void texoffset(ImageData &s, int xoffset, int yoffset) if(!xoffset && !yoffset) return; ImageData d(s.w, s.h, s.bpp); uchar *src = s.data; - loop(y, s.h) - { + loop(y, s.h) { uchar *dst = (uchar *)d.data+((y+yoffset)%d.h)*d.pitch; memcpy(dst+xoffset*s.bpp, src, (s.w-xoffset)*s.bpp); memcpy(dst, src+(s.w-xoffset)*s.bpp, xoffset*s.bpp); @@ -484,8 +422,7 @@ void texoffset(ImageData &s, int xoffset, int yoffset) s.replace(d); } -void texmad(ImageData &s, const vec &mul, const vec &add) -{ +void texmad(ImageData &s, const vec &mul, const vec &add) { if(s.bpp < 3 && (mul.x != mul.y || mul.y != mul.z || add.x != add.y || add.y != add.z)) swizzleimage(s); int maxk = min(int(s.bpp), 3); @@ -494,8 +431,7 @@ void texmad(ImageData &s, const vec &mul, const vec &add) ); } -void texcolorify(ImageData &s, const vec &color, vec weights) -{ +void texcolorify(ImageData &s, const vec &color, vec weights) { if(s.bpp < 3) return; if(weights.iszero()) weights = vec(0.21f, 0.72f, 0.07f); writetex(s, @@ -504,8 +440,7 @@ void texcolorify(ImageData &s, const vec &color, vec weights) ); } -void texcolormask(ImageData &s, const vec &color1, const vec &color2) -{ +void texcolormask(ImageData &s, const vec &color1, const vec &color2) { if(s.bpp < 4) return; ImageData d(s.w, s.h, 3); readwritetex(d, s, @@ -516,20 +451,17 @@ void texcolormask(ImageData &s, const vec &color1, const vec &color2) s.replace(d); } -void texdup(ImageData &s, int srcchan, int dstchan) -{ +void texdup(ImageData &s, int srcchan, int dstchan) { if(srcchan==dstchan || max(srcchan, dstchan) >= s.bpp) return; writetex(s, dst[dstchan] = dst[srcchan]); } -void texmix(ImageData &s, int c1, int c2, int c3, int c4) -{ +void texmix(ImageData &s, int c1, int c2, int c3, int c4) { int numchans = c1 < 0 ? 0 : (c2 < 0 ? 1 : (c3 < 0 ? 2 : (c4 < 0 ? 3 : 4))); if(numchans <= 0) return; ImageData d(s.w, s.h, numchans); readwritetex(d, s, - switch(numchans) - { + switch(numchans) { case 4: dst[3] = src[c4]; [[fallthrough]]; case 3: dst[2] = src[c3]; @@ -543,28 +475,23 @@ void texmix(ImageData &s, int c1, int c2, int c3, int c4) s.replace(d); } -void texgrey(ImageData &s) -{ +void texgrey(ImageData &s) { if(s.bpp <= 2) return; ImageData d(s.w, s.h, s.bpp >= 4 ? 2 : 1); - if(s.bpp >= 4) - { + if(s.bpp >= 4) { readwritetex(d, s, dst[0] = src[0]; dst[1] = src[3]; ); } - else - { + else { readwritetex(d, s, dst[0] = src[0]); } s.replace(d); } -void texpremul(ImageData &s) -{ - switch(s.bpp) - { +void texpremul(ImageData &s) { + switch(s.bpp) { case 2: writetex(s, dst[0] = uchar((uint(dst[0])*uint(dst[1]))/255); @@ -581,30 +508,25 @@ void texpremul(ImageData &s) } } -void texagrad(ImageData &s, float x2, float y2, float x1, float y1) -{ +void texagrad(ImageData &s, float x2, float y2, float x1, float y1) { if(s.bpp != 2 && s.bpp != 4) return; y1 = 1 - y1; y2 = 1 - y2; float minx = 1, miny = 1, maxx = 1, maxy = 1; - if(x1 != x2) - { + if(x1 != x2) { minx = (0 - x1) / (x2 - x1); maxx = (1 - x1) / (x2 - x1); } - if(y1 != y2) - { + if(y1 != y2) { miny = (0 - y1) / (y2 - y1); maxy = (1 - y1) / (y2 - y1); } float dx = (maxx - minx)/max(s.w-1, 1), dy = (maxy - miny)/max(s.h-1, 1), cury = miny; - for(uchar *dstrow = s.data + s.bpp - 1, *endrow = dstrow + s.h*s.pitch; dstrow < endrow; dstrow += s.pitch) - { + for(uchar *dstrow = s.data + s.bpp - 1, *endrow = dstrow + s.h*s.pitch; dstrow < endrow; dstrow += s.pitch) { float curx = minx; - for(uchar *dst = dstrow, *end = &dstrow[s.w*s.bpp]; dst < end; dst += s.bpp) - { + for(uchar *dst = dstrow, *end = &dstrow[s.w*s.bpp]; dst < end; dst += s.bpp) { dst[0] = uchar(dst[0]*clamp(curx, 0.0f, 1.0f)*clamp(cury, 0.0f, 1.0f)); curx += dx; } @@ -626,23 +548,18 @@ VARFP(aniso, 0, 0, 16, initwarning("texture filtering", INIT_LOAD)); extern int usetexcompress; -void setuptexcompress() -{ +void setuptexcompress() { if(!usetexcompress) return; - GLenum hint = GL_DONT_CARE; - switch(texcompressquality) - { + switch(texcompressquality) { case 1: hint = GL_NICEST; break; case 0: hint = GL_FASTEST; break; } glHint(GL_TEXTURE_COMPRESSION_HINT, hint); } -GLenum compressedformat(GLenum format, int w, int h, int force = 0) -{ - if(usetexcompress && texcompress && force >= 0 && (force || max(w, h) >= texcompress)) switch(format) - { +GLenum compressedformat(GLenum format, int w, int h, int force = 0) { + if(usetexcompress && texcompress && force >= 0 && (force || max(w, h) >= texcompress)) switch(format) { case GL_RGB5: case GL_RGB8: case GL_RGB: return usetexcompress > 1 ? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGB; @@ -660,10 +577,8 @@ GLenum compressedformat(GLenum format, int w, int h, int force = 0) return format; } -GLenum uncompressedformat(GLenum format) -{ - switch(format) - { +GLenum uncompressedformat(GLenum format) { + switch(format) { case GL_COMPRESSED_ALPHA: return GL_ALPHA; case GL_COMPRESSED_LUMINANCE: @@ -690,10 +605,8 @@ GLenum uncompressedformat(GLenum format) return GL_FALSE; } -int formatsize(GLenum format) -{ - switch(format) - { +int formatsize(GLenum format) { + switch(format) { case GL_RED: case GL_LUMINANCE: case GL_ALPHA: return 1; @@ -707,61 +620,51 @@ int formatsize(GLenum format) VARFP(usenp2, 0, 0, 1, initwarning("texture quality", INIT_LOAD)); -void resizetexture(int w, int h, bool mipmap, bool canreduce, GLenum target, int compress, int &tw, int &th) -{ +void resizetexture(int w, int h, bool mipmap, bool canreduce, GLenum target, int compress, int &tw, int &th) { int hwlimit = target==GL_TEXTURE_CUBE_MAP ? hwcubetexsize : hwtexsize, sizelimit = mipmap && maxtexsize ? min(maxtexsize, hwlimit) : hwlimit; - if(compress > 0 && !usetexcompress) - { + if(compress > 0 && !usetexcompress) { w = max(w/compress, 1); h = max(h/compress, 1); } - if(canreduce && texreduce) - { + if(canreduce && texreduce) { w = max(w>>texreduce, 1); h = max(h>>texreduce, 1); } w = min(w, sizelimit); h = min(h, sizelimit); - if(!usenp2 && (w&(w-1) || h&(h-1))) - { + if(!usenp2 && (w&(w-1) || h&(h-1))) { tw = th = 1; while(tw < w) tw *= 2; while(th < h) th *= 2; if(w < tw - tw/4) tw /= 2; if(h < th - th/4) th /= 2; } - else - { + else { tw = w; th = h; } } -void uploadtexture(int tnum, GLenum target, GLenum internal, int tw, int th, GLenum format, GLenum type, void *pixels, int pw, int ph, int pitch, bool mipmap) -{ +void uploadtexture(int tnum, GLenum target, GLenum internal, int tw, int th, GLenum format, GLenum type, void *pixels, int pw, int ph, int pitch, bool mipmap) { int bpp = formatsize(format), row = 0, rowalign = 0; if(!pitch) pitch = pw*bpp; uchar *buf = NULL; - if(pw!=tw || ph!=th) - { + if(pw!=tw || ph!=th) { buf = new uchar[tw*th*bpp]; scaletexture((uchar *)pixels, pw, ph, bpp, pitch, buf, tw, th); } - else if(tw*bpp != pitch) - { + else if(tw*bpp != pitch) { row = pitch/bpp; rowalign = texalign(pixels, pitch, 1); while(rowalign > 0 && ((row*bpp + rowalign - 1)/rowalign)*rowalign != pitch) rowalign >>= 1; - if(!rowalign) - { + if(!rowalign) { row = 0; buf = new uchar[tw*th*bpp]; loopi(th) memcpy(&buf[i*tw*bpp], &((uchar *)pixels)[i*pitch], tw*bpp); } } - for(int level = 0, align = 0, mw = tw, mh = th;; level++) - { + for(int level = 0, align = 0, mw = tw, mh = th;; level++) { uchar *src = buf ? buf : (uchar *)pixels; if(buf) pitch = mw*bpp; int srcalign = row > 0 ? rowalign : texalign(src, pitch, 1); @@ -773,8 +676,7 @@ void uploadtexture(int tnum, GLenum target, GLenum internal, int tw, int th, GLe int srcw = mw, srch = mh; if(mw > 1) mw /= 2; if(mh > 1) mh /= 2; - if(src) - { + if(src) { if(!buf) buf = new uchar[mw*mh*bpp]; scaletexture(src, srcw, srch, bpp, pitch, buf, mw, mh); } @@ -782,16 +684,13 @@ void uploadtexture(int tnum, GLenum target, GLenum internal, int tw, int th, GLe if(buf) delete[] buf; } -void uploadcompressedtexture(GLenum target, GLenum subtarget, GLenum format, int w, int h, uchar *data, int align, int blocksize, int levels, bool mipmap) -{ +void uploadcompressedtexture(GLenum target, GLenum subtarget, GLenum format, int w, int h, uchar *data, int align, int blocksize, int levels, bool mipmap) { int hwlimit = target==GL_TEXTURE_CUBE_MAP ? hwcubetexsize : hwtexsize, sizelimit = levels > 1 && maxtexsize ? min(maxtexsize, hwlimit) : hwlimit; int level = 0; - loopi(levels) - { + loopi(levels) { int size = ((w + align-1)/align) * ((h + align-1)/align) * blocksize; - if(w <= sizelimit && h <= sizelimit) - { + if(w <= sizelimit && h <= sizelimit) { glCompressedTexImage2D_(subtarget, level, format, w, h, 0, size, data); level++; if(!mipmap) break; @@ -803,10 +702,8 @@ void uploadcompressedtexture(GLenum target, GLenum subtarget, GLenum format, int } } -GLenum textarget(GLenum subtarget) -{ - switch(subtarget) - { +GLenum textarget(GLenum subtarget) { + switch(subtarget) { case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: @@ -818,20 +715,17 @@ GLenum textarget(GLenum subtarget) return subtarget; } -const GLint *swizzlemask(GLenum format) -{ +const GLint *swizzlemask(GLenum format) { static const GLint luminance[4] = { GL_RED, GL_RED, GL_RED, GL_ONE }; static const GLint luminancealpha[4] = { GL_RED, GL_RED, GL_RED, GL_GREEN }; - switch(format) - { + switch(format) { case GL_RED: return luminance; case GL_RG: return luminancealpha; } return NULL; } -void setuptexparameters(int tnum, void *pixels, int clamp, int filter, GLenum format, GLenum target, bool swizzle) -{ +void setuptexparameters(int tnum, void *pixels, int clamp, int filter, GLenum format, GLenum target, bool swizzle) { glBindTexture(target, tnum); glTexParameteri(target, GL_TEXTURE_WRAP_S, clamp&1 ? GL_CLAMP_TO_EDGE : (clamp&0x100 ? GL_MIRRORED_REPEAT : GL_REPEAT)); glTexParameteri(target, GL_TEXTURE_WRAP_T, clamp&2 ? GL_CLAMP_TO_EDGE : (clamp&0x200 ? GL_MIRRORED_REPEAT : GL_REPEAT)); @@ -843,48 +737,40 @@ void setuptexparameters(int tnum, void *pixels, int clamp, int filter, GLenum fo (bilinear ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_LINEAR) : (bilinear ? GL_LINEAR_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_NEAREST)) : (filter && bilinear ? GL_LINEAR : GL_NEAREST)); - if(swizzle && hasTRG && hasTSW) - { + if(swizzle && hasTRG && hasTSW) { const GLint *mask = swizzlemask(format); if(mask) glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, mask); } } -static GLenum textype(GLenum &component, GLenum &format) -{ +static GLenum textype(GLenum &component, GLenum &format) { GLenum type = GL_UNSIGNED_BYTE; - switch(component) - { + switch(component) { case GL_R16F: case GL_R32F: if(!format) format = GL_RED; type = GL_FLOAT; break; - case GL_RG16F: case GL_RG32F: if(!format) format = GL_RG; type = GL_FLOAT; break; - case GL_RGB16F: case GL_RGB32F: if(!format) format = GL_RGB; type = GL_FLOAT; break; - case GL_RGBA16F: case GL_RGBA32F: if(!format) format = GL_RGBA; type = GL_FLOAT; break; - case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT32: if(!format) format = GL_DEPTH_COMPONENT; break; - case GL_RGB5: case GL_RGB8: case GL_RGB10: @@ -893,7 +779,6 @@ static GLenum textype(GLenum &component, GLenum &format) case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: if(!format) format = GL_RGB; break; - case GL_RGB5_A1: case GL_RGBA8: case GL_RGB10_A2: @@ -904,41 +789,35 @@ static GLenum textype(GLenum &component, GLenum &format) case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: if(!format) format = GL_RGBA; break; - case GL_DEPTH_STENCIL: case GL_DEPTH24_STENCIL8: if(!format) format = GL_DEPTH_STENCIL; type = GL_UNSIGNED_INT_24_8; break; - case GL_R8: case GL_R16: case GL_COMPRESSED_RED: case GL_COMPRESSED_RED_RGTC1: if(!format) format = GL_RED; break; - case GL_RG8: case GL_RG16: case GL_COMPRESSED_RG: case GL_COMPRESSED_RG_RGTC2: if(!format) format = GL_RG; break; - case GL_LUMINANCE8: case GL_LUMINANCE16: case GL_COMPRESSED_LUMINANCE: case GL_COMPRESSED_LUMINANCE_LATC1_EXT: if(!format) format = GL_LUMINANCE; break; - case GL_LUMINANCE8_ALPHA8: case GL_LUMINANCE16_ALPHA16: case GL_COMPRESSED_LUMINANCE_ALPHA: case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: if(!format) format = GL_LUMINANCE_ALPHA; break; - case GL_ALPHA8: case GL_ALPHA16: case GL_COMPRESSED_ALPHA: @@ -949,24 +828,21 @@ static GLenum textype(GLenum &component, GLenum &format) return type; } -void createtexture(int tnum, int w, int h, void *pixels, int clamp, int filter, GLenum component, GLenum subtarget, int pw, int ph, int pitch, bool resize, GLenum format, bool swizzle) -{ +void createtexture(int tnum, int w, int h, void *pixels, int clamp, int filter, GLenum component, GLenum subtarget, int pw, int ph, int pitch, bool resize, GLenum format, bool swizzle) { GLenum target = textarget(subtarget), type = textype(component, format); if(filter >= 0 && clamp >= 0) setuptexparameters(tnum, pixels, clamp, filter, format, target, swizzle); if(!pw) pw = w; if(!ph) ph = h; int tw = w, th = h; bool mipmap = filter > 1 && pixels; - if(resize && pixels) - { + if(resize && pixels) { resizetexture(w, h, mipmap, false, target, 0, tw, th); if(mipmap) component = compressedformat(component, tw, th); } uploadtexture(tnum, subtarget, component, tw, th, format, type, pixels, pw, ph, pitch, mipmap); } -void createcompressedtexture(int tnum, int w, int h, uchar *data, int align, int blocksize, int levels, int clamp, int filter, GLenum format, GLenum subtarget, bool swizzle = false) -{ +void createcompressedtexture(int tnum, int w, int h, uchar *data, int align, int blocksize, int levels, int clamp, int filter, GLenum format, GLenum subtarget, bool swizzle = false) { GLenum target = textarget(subtarget); if(filter >= 0 && clamp >= 0) setuptexparameters(tnum, data, clamp, filter, format, target); uploadcompressedtexture(target, subtarget, format, w, h, data, align, blocksize, levels, filter > 1); @@ -976,10 +852,8 @@ hashnameset textures; Texture *notexture = NULL; // used as default, ensured to be loaded -static GLenum texformat(int bpp, bool swizzle = false) -{ - switch(bpp) - { +static GLenum texformat(int bpp, bool swizzle = false) { + switch(bpp) { case 1: return hasTRG && (hasTSW || !glcompat || !swizzle) ? GL_RED : GL_LUMINANCE; case 2: return hasTRG && (hasTSW || !glcompat || !swizzle) ? GL_RG : GL_LUMINANCE_ALPHA; case 3: return GL_RGB; @@ -988,10 +862,8 @@ static GLenum texformat(int bpp, bool swizzle = false) } } -static bool alphaformat(GLenum format) -{ - switch(format) - { +static bool alphaformat(GLenum format) { + switch(format) { case GL_ALPHA: case GL_LUMINANCE_ALPHA: case GL_RG: @@ -1002,49 +874,40 @@ static bool alphaformat(GLenum format) } } -int texalign(const void *data, int w, int bpp) -{ +int texalign(const void *data, int w, int bpp) { int stride = w*bpp; if(stride&1) return 1; if(stride&2) return 2; return 4; } -static Texture *newtexture(Texture *t, const char *rname, ImageData &s, int clamp = 0, bool mipit = true, bool canreduce = false, bool transient = false, int compress = 0) -{ - if(!t) - { +static Texture *newtexture(Texture *t, const char *rname, ImageData &s, int clamp = 0, bool mipit = true, bool canreduce = false, bool transient = false, int compress = 0) { + if(!t) { char *key = newstring(rname); t = &textures[key]; t->name = key; } - t->clamp = clamp; t->mipmap = mipit; t->type = Texture::IMAGE; if(transient) t->type |= Texture::TRANSIENT; if(clamp&0x300) t->type |= Texture::MIRROR; - if(!s.data) - { + if(!s.data) { t->type |= Texture::STUB; t->w = t->h = t->xs = t->ys = t->bpp = 0; return t; } - bool swizzle = !(clamp&0x10000); GLenum format; - if(s.compressed) - { + if(s.compressed) { format = uncompressedformat(s.compressed); t->bpp = formatsize(format); t->type |= Texture::COMPRESSED; } - else - { + else { format = texformat(s.bpp, swizzle); t->bpp = s.bpp; - if(swizzle && hasTRG && !hasTSW && swizzlemask(format)) - { + if(swizzle && hasTRG && !hasTSW && swizzlemask(format)) { swizzleimage(s); format = texformat(s.bpp, swizzle); t->bpp = s.bpp; @@ -1053,23 +916,19 @@ static Texture *newtexture(Texture *t, const char *rname, ImageData &s, int clam if(alphaformat(format)) t->type |= Texture::ALPHA; t->w = t->xs = s.w; t->h = t->ys = s.h; - int filter = !canreduce || reducefilter ? (mipit ? 2 : 1) : 0; glGenTextures(1, &t->id); - if(s.compressed) - { + if(s.compressed) { uchar *data = s.data; int levels = s.levels, level = 0; - if(canreduce && texreduce) loopi(min(texreduce, s.levels-1)) - { + if(canreduce && texreduce) loopi(min(texreduce, s.levels-1)) { data += s.calclevelsize(level++); levels--; if(t->w > 1) t->w /= 2; if(t->h > 1) t->h /= 2; } int sizelimit = mipit && maxtexsize ? min(maxtexsize, hwtexsize) : hwtexsize; - while(t->w > sizelimit || t->h > sizelimit) - { + while(t->w > sizelimit || t->h > sizelimit) { data += s.calclevelsize(level++); levels--; if(t->w > 1) t->w /= 2; @@ -1077,8 +936,7 @@ static Texture *newtexture(Texture *t, const char *rname, ImageData &s, int clam } createcompressedtexture(t->id, t->w, t->h, data, s.align, s.bpp, levels, clamp, filter, s.compressed, GL_TEXTURE_2D, swizzle); } - else - { + else { resizetexture(t->w, t->h, mipit, canreduce, GL_TEXTURE_2D, compress, t->w, t->h); GLenum component = compressedformat(format, t->w, t->h, compress); createtexture(t->id, t->w, t->h, s.data, clamp, filter, component, GL_TEXTURE_2D, t->xs, t->ys, s.pitch, false, format, swizzle); @@ -1094,29 +952,24 @@ static Texture *newtexture(Texture *t, const char *rname, ImageData &s, int clam #define RGBMASKS 0x0000ff, 0x00ff00, 0xff0000, 0 #endif -SDL_Surface *wrapsurface(void *data, int width, int height, int bpp) -{ - switch(bpp) - { +SDL_Surface *wrapsurface(void *data, int width, int height, int bpp) { + switch(bpp) { case 3: return SDL_CreateRGBSurfaceFrom(data, width, height, 8*bpp, bpp*width, RGBMASKS); case 4: return SDL_CreateRGBSurfaceFrom(data, width, height, 8*bpp, bpp*width, RGBAMASKS); } return NULL; } -SDL_Surface *creatergbsurface(SDL_Surface *os) -{ +SDL_Surface *creatergbsurface(SDL_Surface *os) { SDL_Surface *ns = SDL_CreateRGBSurface(SDL_SWSURFACE, os->w, os->h, 24, RGBMASKS); if(ns) SDL_BlitSurface(os, NULL, ns, NULL); SDL_FreeSurface(os); return ns; } -SDL_Surface *creatergbasurface(SDL_Surface *os) -{ +SDL_Surface *creatergbasurface(SDL_Surface *os) { SDL_Surface *ns = SDL_CreateRGBSurface(SDL_SWSURFACE, os->w, os->h, 32, RGBAMASKS); - if(ns) - { + if(ns) { SDL_SetSurfaceBlendMode(os, SDL_BLENDMODE_NONE); SDL_BlitSurface(os, NULL, ns, NULL); } @@ -1124,11 +977,9 @@ SDL_Surface *creatergbasurface(SDL_Surface *os) return ns; } -bool checkgrayscale(SDL_Surface *s) -{ +bool checkgrayscale(SDL_Surface *s) { // gray scale images have 256 levels, no colorkey, and the palette is a ramp - if(s->format->palette) - { + if(s->format->palette) { if(s->format->palette->ncolors != 256 || SDL_GetColorKey(s, NULL) >= 0) return false; const SDL_Color *colors = s->format->palette->colors; loopi(256) if(colors[i].r != i || colors[i].g != i || colors[i].b != i) return false; @@ -1136,17 +987,14 @@ bool checkgrayscale(SDL_Surface *s) return true; } -SDL_Surface *fixsurfaceformat(SDL_Surface *s) -{ +SDL_Surface *fixsurfaceformat(SDL_Surface *s) { if(!s) return NULL; - if(!s->pixels || min(s->w, s->h) <= 0 || s->format->BytesPerPixel <= 0) - { + if(!s->pixels || min(s->w, s->h) <= 0 || s->format->BytesPerPixel <= 0) { SDL_FreeSurface(s); return NULL; } static const uint rgbmasks[] = { RGBMASKS }, rgbamasks[] = { RGBAMASKS }; - switch(s->format->BytesPerPixel) - { + switch(s->format->BytesPerPixel) { case 1: if(!checkgrayscale(s)) return SDL_GetColorKey(s, NULL) >= 0 ? creatergbasurface(s) : creatergbsurface(s); break; @@ -1162,12 +1010,10 @@ SDL_Surface *fixsurfaceformat(SDL_Surface *s) return s; } -void texflip(ImageData &s) -{ +void texflip(ImageData &s) { ImageData d(s.w, s.h, s.bpp); uchar *dst = d.data, *src = &s.data[s.pitch*s.h]; - loopi(s.h) - { + loopi(s.h) { src -= s.pitch; memcpy(dst, src, s.bpp*s.w); dst += d.pitch; @@ -1175,12 +1021,10 @@ void texflip(ImageData &s) s.replace(d); } -void texnormal(ImageData &s, int emphasis) -{ +void texnormal(ImageData &s, int emphasis) { ImageData d(s.w, s.h, 3); uchar *src = s.data, *dst = d.data; - loop(y, s.h) loop(x, s.w) - { + loop(y, s.h) loop(x, s.w) { vec normal(0.0f, 0.0f, 255.0f/emphasis); normal.x += src[y*s.pitch + ((x+s.w-1)%s.w)*s.bpp]; normal.x -= src[y*s.pitch + ((x+1)%s.w)*s.bpp]; @@ -1195,16 +1039,13 @@ void texnormal(ImageData &s, int emphasis) } template -static void blurtexture(int w, int h, uchar *dst, const uchar *src, int margin) -{ - static const int weights3x3[9] = - { +static void blurtexture(int w, int h, uchar *dst, const uchar *src, int margin) { + static const int weights3x3[9] = { 0x10, 0x20, 0x10, 0x20, 0x40, 0x20, 0x10, 0x20, 0x10 }; - static const int weights5x5[25] = - { + static const int weights5x5[25] = { 0x05, 0x05, 0x09, 0x05, 0x05, 0x05, 0x0A, 0x14, 0x0A, 0x05, 0x09, 0x14, 0x28, 0x14, 0x09, @@ -1219,15 +1060,12 @@ static void blurtexture(int w, int h, uchar *dst, const uchar *src, int margin) nextoffset1 = stride + mstride*bpp, nextoffset2 = stride - mstride*bpp; src += margin*(stride + bpp); - for(int y = margin; y < h-margin; y++) - { - for(int x = margin; x < w-margin; x++) - { + for(int y = margin; y < h-margin; y++) { + for(int x = margin; x < w-margin; x++) { int dr = 0, dg = 0, db = 0; const uchar *p = src - startoffset; const int *m = mat + mstartoffset; - for(int t = y; t >= y-n; t--, p -= nextoffset1, m -= mstride) - { + for(int t = y; t >= y-n; t--, p -= nextoffset1, m -= mstride) { if(t < 0) p += stride; int a = 0; if(n > 1) { a += m[-2]; if(x >= 2) { dr += p[0] * a; dg += p[1] * a; db += p[2] * a; a = 0; } p += bpp; } @@ -1238,8 +1076,7 @@ static void blurtexture(int w, int h, uchar *dst, const uchar *src, int margin) } p = src - startoffset + stride; m = mat + mstartoffset + mstride; - for(int t = y+1; t <= y+n; t++, p += nextoffset2, m += mstride) - { + for(int t = y+1; t <= y+n; t++, p += nextoffset2, m += mstride) { if(t >= h) p -= stride; int a = 0; if(n > 1) { a += m[-2]; if(x >= 2) { dr += p[0] * a; dg += p[1] * a; db += p[2] * a; a = 0; } p += bpp; } @@ -1248,16 +1085,14 @@ static void blurtexture(int w, int h, uchar *dst, const uchar *src, int margin) if(x+1 < w) { cr = p[0]; cg = p[1]; cb = p[2]; } dr += cr * m[1]; dg += cg * m[1]; db += cb * m[1]; p += bpp; if(n > 1) { if(x+2 < w) { cr = p[0]; cg = p[1]; cb = p[2]; } dr += cr * m[2]; dg += cg * m[2]; db += cb * m[2]; p += bpp; } } - if(normals) - { + if(normals) { vec v(dr-0x7F80, dg-0x7F80, db-0x7F80); float mag = 127.5f/v.magnitude(); dst[0] = uchar(v.x*mag + 127.5f); dst[1] = uchar(v.y*mag + 127.5f); dst[2] = uchar(v.z*mag + 127.5f); } - else - { + else { dst[0] = dr>>8; dst[1] = dg>>8; dst[2] = db>>8; @@ -1270,10 +1105,8 @@ static void blurtexture(int w, int h, uchar *dst, const uchar *src, int margin) } } -void blurtexture(int n, int bpp, int w, int h, uchar *dst, const uchar *src, int margin) -{ - switch((clamp(n, 1, 2)<<4) | bpp) - { +void blurtexture(int n, int bpp, int w, int h, uchar *dst, const uchar *src, int margin) { + switch((clamp(n, 1, 2)<<4) | bpp) { case 0x13: blurtexture<1, 3, false>(w, h, dst, src, margin); break; case 0x23: blurtexture<2, 3, false>(w, h, dst, src, margin); break; case 0x14: blurtexture<1, 4, false>(w, h, dst, src, margin); break; @@ -1281,50 +1114,41 @@ void blurtexture(int n, int bpp, int w, int h, uchar *dst, const uchar *src, int } } -void blurnormals(int n, int w, int h, bvec *dst, const bvec *src, int margin) -{ - switch(clamp(n, 1, 2)) - { +void blurnormals(int n, int w, int h, bvec *dst, const bvec *src, int margin) { + switch(clamp(n, 1, 2)) { case 1: blurtexture<1, 3, true>(w, h, dst->v, src->v, margin); break; case 2: blurtexture<2, 3, true>(w, h, dst->v, src->v, margin); break; } } -void texblur(ImageData &s, int n, int r) -{ +void texblur(ImageData &s, int n, int r) { if(s.bpp < 3) return; - loopi(r) - { + loopi(r) { ImageData d(s.w, s.h, s.bpp); blurtexture(n, s.bpp, s.w, s.h, d.data, s.data); s.replace(d); } } -void scaleimage(ImageData &s, int w, int h) -{ +void scaleimage(ImageData &s, int w, int h) { ImageData d(w, h, s.bpp); scaletexture(s.data, s.w, s.h, s.bpp, s.pitch, d.data, w, h); s.replace(d); } -bool canloadsurface(const char *name) -{ +bool canloadsurface(const char *name) { stream *f = openfile(name, "rb"); if(!f) return false; delete f; return true; } -SDL_Surface *loadsurface(const char *name) -{ +SDL_Surface *loadsurface(const char *name) { SDL_Surface *s = NULL; stream *z = openzipfile(name, "rb"); - if(z) - { + if(z) { SDL_RWops *rw = z->rwops(); - if(rw) - { + if(rw) { char *ext = (char *)strrchr(name, '.'); if(ext) ++ext; s = IMG_LoadTyped_RW(rw, 0, ext); @@ -1336,12 +1160,10 @@ SDL_Surface *loadsurface(const char *name) return fixsurfaceformat(s); } -static vec parsevec(const char *arg) -{ +static vec parsevec(const char *arg) { vec v(0, 0, 0); int i = 0; - for(; arg[0] && (!i || arg[0]=='/') && i<3; arg += strcspn(arg, "/,><"), i++) - { + for(; arg[0] && (!i || arg[0]=='/') && i<3; arg += strcspn(arg, "/,><"), i++) { if(i) arg++; v[i] = atof(arg); } @@ -1349,38 +1171,30 @@ static vec parsevec(const char *arg) return v; } -static bool texturedata(ImageData &d, const char *tname, Slot::Tex *tex = NULL, bool msg = true, int *compress = NULL, int *wrap = NULL) -{ +static bool texturedata(ImageData &d, const char *tname, Slot::Tex *tex = NULL, bool msg = true, int *compress = NULL, int *wrap = NULL) { const char *cmds = NULL, *file = tname; - - if(!tname) - { + if(!tname) { if(!tex) return false; - if(tex->name[0]=='<') - { + if(tex->name[0]=='<') { cmds = tex->name; file = strrchr(tex->name, '>'); if(!file) { if(msg) conoutf(CON_ERROR, "could not load texture packages/%s", tex->name); return false; } file++; } else file = tex->name; - static string pname; formatstring(pname, "packages/%s", file); file = path(pname); } - else if(tname[0]=='<') - { + else if(tname[0]=='<') { cmds = tname; file = strrchr(tname, '>'); if(!file) { if(msg) conoutf(CON_ERROR, "could not load texture %s", tname); return false; } file++; } - int flen = strlen(file); - bool raw = !compress, guess = false; - for(const char *pcmds = cmds; pcmds;) - { + bool guess = false; + for(const char *pcmds = cmds; pcmds;) { #define PARSETEXCOMMANDS(cmds) \ const char *cmd = NULL, *end = NULL, *arg[4] = { NULL, NULL, NULL, NULL }; \ cmd = &cmds[1]; \ @@ -1388,32 +1202,25 @@ static bool texturedata(ImageData &d, const char *tname, Slot::Tex *tex = NULL, if(!end) break; \ cmds = strchr(cmd, '<'); \ size_t len = strcspn(cmd, ":,><"); \ - loopi(4) \ - { \ + loopi(4) { \ + \ arg[i] = strchr(i ? arg[i-1] : cmd, i ? ',' : ':'); \ if(!arg[i] || arg[i] >= end) arg[i] = ""; \ else arg[i]++; \ } PARSETEXCOMMANDS(pcmds); - if(matchstring(cmd, len, "thumbnail")) - { - raw = true; + if(matchstring(cmd, len, "thumbnail")) { guess = flen >= 4 && !strchr(file+flen-4, '.'); } else if(matchstring(cmd, len, "stub")) return canloadsurface(file); } - if(msg) renderprogress(loadprogress, file); - - if(!d.data) - { + if(!d.data) { SDL_Surface *s = NULL; - if(guess) - { + if(guess) { static const char *exts[] = {".jpg", ".png"}; string ext; - loopi(sizeof(exts)/sizeof(exts[0])) - { + loopi(sizeof(exts)/sizeof(exts[0])) { copystring(ext, file); concatstring(ext, exts[i]); s = loadsurface(ext); @@ -1427,16 +1234,13 @@ static bool texturedata(ImageData &d, const char *tname, Slot::Tex *tex = NULL, if(max(s->w, s->h) > (1<<12)) { SDL_FreeSurface(s); conoutf(CON_ERROR, "texture size exceeded %dx%d pixels: %s", 1<<12, 1<<12, file); return false; } d.wrap(s); } - - while(cmds) - { + while(cmds) { PARSETEXCOMMANDS(cmds); if(d.compressed) goto compressed; if(matchstring(cmd, len, "mad")) texmad(d, parsevec(arg[0]), parsevec(arg[1])); else if(matchstring(cmd, len, "colorify")) texcolorify(d, parsevec(arg[0]), parsevec(arg[1])); else if(matchstring(cmd, len, "colormask")) texcolormask(d, parsevec(arg[0]), *arg[1] ? parsevec(arg[1]) : vec(1, 1, 1)); - else if(matchstring(cmd, len, "normal")) - { + else if(matchstring(cmd, len, "normal")) { int emphasis = atoi(arg[0]); texnormal(d, emphasis > 0 ? emphasis : 3); } @@ -1446,25 +1250,21 @@ static bool texturedata(ImageData &d, const char *tname, Slot::Tex *tex = NULL, else if(matchstring(cmd, len, "reorient")) texreorient(d, atoi(arg[0])>0, atoi(arg[1])>0, atoi(arg[2])>0, tex ? tex->type : TEX_DIFFUSE); else if(matchstring(cmd, len, "mix")) texmix(d, *arg[0] ? atoi(arg[0]) : -1, *arg[1] ? atoi(arg[1]) : -1, *arg[2] ? atoi(arg[2]) : -1, *arg[3] ? atoi(arg[3]) : -1); else if(matchstring(cmd, len, "grey")) texgrey(d); - else if(matchstring(cmd, len, "blur")) - { + else if(matchstring(cmd, len, "blur")) { int emphasis = atoi(arg[0]), repeat = atoi(arg[1]); texblur(d, emphasis > 0 ? clamp(emphasis, 1, 2) : 1, repeat > 0 ? repeat : 1); } else if(matchstring(cmd, len, "premul")) texpremul(d); else if(matchstring(cmd, len, "agrad")) texagrad(d, atof(arg[0]), atof(arg[1]), atof(arg[2]), atof(arg[3])); - else if(matchstring(cmd, len, "compress")) - { + else if(matchstring(cmd, len, "compress")) { int scale = atoi(arg[0]); if(scale <= 0) scale = 2; if(compress) *compress = scale; } - else if(matchstring(cmd, len, "nocompress")) - { + else if(matchstring(cmd, len, "nocompress")) { if(compress) *compress = -1; } - else if(matchstring(cmd, len, "thumbnail")) - { + else if(matchstring(cmd, len, "thumbnail")) { int w = atoi(arg[0]), h = atoi(arg[1]); if(w <= 0 || w > (1<<12)) w = 64; if(h <= 0 || h > (1<<12)) h = w; @@ -1472,32 +1272,26 @@ static bool texturedata(ImageData &d, const char *tname, Slot::Tex *tex = NULL, } else compressed: - if(matchstring(cmd, len, "mirror")) - { + if(matchstring(cmd, len, "mirror")) { if(wrap) *wrap |= 0x300; } - else if(matchstring(cmd, len, "noswizzle")) - { + else if(matchstring(cmd, len, "noswizzle")) { if(wrap) *wrap |= 0x10000; } } - return true; } -uchar *loadalphamask(Texture *t) -{ +uchar *loadalphamask(Texture *t) { if(t->alphamask) return t->alphamask; if(!(t->type&Texture::ALPHA)) return NULL; ImageData s; if(!texturedata(s, t->name, NULL, false) || !s.data || s.compressed) return NULL; t->alphamask = new uchar[s.h * ((s.w+7)/8)]; uchar *srcrow = s.data, *dst = t->alphamask-1; - loop(y, s.h) - { + loop(y, s.h) { uchar *src = srcrow+s.bpp-1; - loop(x, s.w) - { + loop(x, s.w) { int offset = x%8; if(!offset) *++dst = 0; if(*src) *dst |= 1<alphamask; } -Texture *textureload(const char *name, int clamp, bool mipit, bool msg) -{ +Texture *textureload(const char *name, int clamp, bool mipit, bool msg) { string tname; copystring(tname, name); Texture *t = textures.access(path(tname)); @@ -1520,8 +1313,7 @@ Texture *textureload(const char *name, int clamp, bool mipit, bool msg) return notexture; } -bool settexture(const char *name, int clamp) -{ +bool settexture(const char *name, int clamp) { Texture *t = textureload(name, clamp, true, false); glBindTexture(GL_TEXTURE_2D, t->id); return t != notexture; @@ -1532,20 +1324,17 @@ vector slots; Slot dummyslot; VSlot dummyvslot(&dummyslot); -void texturereset(int *n) -{ +void texturereset(int *n) { if(!(identflags&IDF_OVERRIDDEN) && !game::allowedittoggle()) return; resetslotshader(); int limit = clamp(*n, 0, slots.length()); - for(int i = limit; i < slots.length(); i++) - { + for(int i = limit; i < slots.length(); i++) { Slot *s = slots[i]; for(VSlot *vs = s->variants; vs; vs = vs->next) vs->slot = &dummyslot; delete s; } slots.setsize(limit); - while(vslots.length()) - { + while(vslots.length()) { VSlot *vs = vslots.last(); if(vs->slot != &dummyslot || vs->changed) break; delete vslots.pop(); @@ -1557,8 +1346,7 @@ COMMAND(texturereset, "i"); static int compactedvslots = 0, compactvslotsprogress = 0, clonedvslots = 0; static bool markingvslots = false; -void clearslots() -{ +void clearslots() { resetslotshader(); slots.deletecontents(); vslots.deletecontents(); @@ -1567,44 +1355,35 @@ void clearslots() static void assignvslot(VSlot &vs); -static inline void assignvslotlayer(VSlot &vs) -{ - if(vs.layer && vslots.inrange(vs.layer)) - { +static inline void assignvslotlayer(VSlot &vs) { + if(vs.layer && vslots.inrange(vs.layer)) { VSlot &layer = *vslots[vs.layer]; if(layer.index < 0) assignvslot(layer); } } -static void assignvslot(VSlot &vs) -{ +static void assignvslot(VSlot &vs) { vs.index = compactedvslots++; assignvslotlayer(vs); } -void compactvslot(int &index) -{ - if(vslots.inrange(index)) - { +void compactvslot(int &index) { + if(vslots.inrange(index)) { VSlot &vs = *vslots[index]; if(vs.index < 0) assignvslot(vs); if(!markingvslots) index = vs.index; } } -void compactvslot(VSlot &vs) -{ +void compactvslot(VSlot &vs) { if(vs.index < 0) assignvslot(vs); } -void compactvslots(cube *c, int n) -{ +void compactvslots(cube *c, int n) { if((compactvslotsprogress++&0xFFF)==0) renderprogress(min(float(compactvslotsprogress)/allocnodes, 1.0f), markingvslots ? "marking slots..." : "compacting slots..."); - loopi(n) - { + loopi(n) { if(c[i].children) compactvslots(c[i].children); - else loopj(6) if(vslots.inrange(c[i].texture[j])) - { + else loopj(6) if(vslots.inrange(c[i].texture[j])) { VSlot &vs = *vslots[c[i].texture[j]]; if(vs.index < 0) assignvslot(vs); if(!markingvslots) c[i].texture[j] = vs.index; @@ -1612,8 +1391,7 @@ void compactvslots(cube *c, int n) } } -int compactvslots() -{ +int compactvslots() { clonedvslots = 0; markingvslots = false; compactedvslots = 0; @@ -1621,38 +1399,31 @@ int compactvslots() loopv(vslots) vslots[i]->index = -1; loopv(slots) slots[i]->variants->index = compactedvslots++; loopv(slots) assignvslotlayer(*slots[i]->variants); - loopv(vslots) - { + loopv(vslots) { VSlot &vs = *vslots[i]; if(!vs.changed && vs.index < 0) { markingvslots = true; break; } } compactvslots(worldroot); int total = compactedvslots; compacteditvslots(); - loopv(vslots) - { + loopv(vslots) { VSlot *vs = vslots[i]; if(vs->changed) continue; - while(vs->next) - { + while(vs->next) { if(vs->next->index < 0) vs->next = vs->next->next; else vs = vs->next; } } - if(markingvslots) - { + if(markingvslots) { markingvslots = false; compactedvslots = 0; compactvslotsprogress = 0; int lastdiscard = 0; - loopv(vslots) - { + loopv(vslots) { VSlot &vs = *vslots[i]; if(vs.changed || (vs.index < 0 && !vs.next)) vs.index = -1; - else - { - while(lastdiscard < i) - { + else { + while(lastdiscard < i) { VSlot &ds = *vslots[lastdiscard++]; if(!ds.changed && ds.index < 0) ds.index = compactedvslots++; } @@ -1664,13 +1435,11 @@ int compactvslots() compacteditvslots(); } compactmruvslots(); - loopv(vslots) - { + loopv(vslots) { VSlot &vs = *vslots[i]; if(vs.index >= 0 && vs.layer && vslots.inrange(vs.layer)) vs.layer = vslots[vs.layer]->index; } - loopv(vslots) - { + loopv(vslots) { while(vslots[i]->index >= 0 && vslots[i]->index != i) swap(vslots[i], vslots[vslots[i]->index]); } @@ -1679,8 +1448,7 @@ int compactvslots() return total; } -ICOMMAND(compactvslots, "", (), -{ +ICOMMAND(compactvslots, "", (), { extern int nompedit; if(nompedit && multiplayer()) return; compactvslots(); @@ -1689,11 +1457,9 @@ ICOMMAND(compactvslots, "", (), static Slot &loadslot(Slot &s, bool forceload); -static void clampvslotoffset(VSlot &dst, Slot *slot = NULL) -{ +static void clampvslotoffset(VSlot &dst, Slot *slot = NULL) { if(!slot) slot = dst.slot; - if(slot && slot->sts.inrange(0)) - { + if(slot && slot->sts.inrange(0)) { if(!slot->loaded) loadslot(*slot, false); Texture *t = slot->sts[0].t; int xs = t->xs, ys = t->ys; @@ -1705,49 +1471,39 @@ static void clampvslotoffset(VSlot &dst, Slot *slot = NULL) else dst.offset.max(0); } -static void propagatevslot(VSlot &dst, const VSlot &src, int diff, bool edit = false) -{ +static void propagatevslot(VSlot &dst, const VSlot &src, int diff, bool edit = false) { if(diff & (1<next; vs; vs = vs->next) - { +static void propagatevslot(VSlot *root, int changed) { + for(VSlot *vs = root->next; vs; vs = vs->next) { int diff = changed & ~vs->changed; if(diff) propagatevslot(*vs, *root, diff); } } -static void mergevslot(VSlot &dst, const VSlot &src, int diff, Slot *slot = NULL) -{ - if(diff & (1<slot = &owner; vs->linked = false; vs = vs->next; @@ -1798,21 +1547,17 @@ static VSlot *reassignvslot(Slot &owner, VSlot *vs) return owner.variants; } -static VSlot *emptyvslot(Slot &owner) -{ +static VSlot *emptyvslot(Slot &owner) { int offset = 0; loopvrev(slots) if(slots[i]->variants) { offset = slots[i]->variants->index + 1; break; } for(int i = offset; i < vslots.length(); i++) if(!vslots[i]->changed) return reassignvslot(owner, vslots[i]); return vslots.add(new VSlot(&owner, vslots.length())); } -static bool comparevslot(const VSlot &dst, const VSlot &src, int diff) -{ - if(diff & (1< &buf, const VSlot &src) -{ - if(src.changed & (1< &buf, const VSlot &src) { + if(src.changed & (1<changed ? src.layer : 0); } - if(src.changed & (1< &buf, const VSlot &src) buf.put(0xFF); } -void packvslot(vector &buf, int index) -{ +void packvslot(vector &buf, int index) { if(vslots.inrange(index)) packvslot(buf, *vslots[index]); else buf.put(0xFF); } -void packvslot(vector &buf, const VSlot *vs) -{ +void packvslot(vector &buf, const VSlot *vs) { if(vs) packvslot(buf, *vs); else buf.put(0xFF); } -bool unpackvslot(ucharbuf &buf, VSlot &dst, bool delta) -{ - while(buf.remaining()) - { +bool unpackvslot(ucharbuf &buf, VSlot &dst, bool delta) { + while(buf.remaining()) { int changed = buf.get(); if(changed >= 0x80) break; - switch(changed) - { - case VSLOT_SHPARAM: - { + switch(changed) { + case VSLOT_SHPARAM: { string name; getstring(name, buf); SlotShaderParam p = { name[0] ? getshaderparamname(name) : NULL, -1, { 0, 0, 0, 0 } }; @@ -1929,8 +1658,7 @@ bool unpackvslot(ucharbuf &buf, VSlot &dst, bool delta) dst.scroll.x = getfloat(buf); dst.scroll.y = getfloat(buf); break; - case VSLOT_LAYER: - { + case VSLOT_LAYER: { int tex = getuint(buf); dst.layer = vslots.inrange(tex) ? tex : 0; break; @@ -1953,10 +1681,8 @@ bool unpackvslot(ucharbuf &buf, VSlot &dst, bool delta) return true; } -VSlot *findvslot(Slot &slot, const VSlot &src, const VSlot &delta) -{ - for(VSlot *dst = slot.variants; dst; dst = dst->next) - { +VSlot *findvslot(Slot &slot, const VSlot &src, const VSlot &delta) { + for(VSlot *dst = slot.variants; dst; dst = dst->next) { if((!dst->changed || dst->changed == (src.changed | delta.changed)) && comparevslot(*dst, src, src.changed & ~delta.changed) && comparevslot(*dst, delta, delta.changed)) @@ -1965,8 +1691,7 @@ VSlot *findvslot(Slot &slot, const VSlot &src, const VSlot &delta) return NULL; } -static VSlot *clonevslot(const VSlot &src, const VSlot &delta) -{ +static VSlot *clonevslot(const VSlot &src, const VSlot &delta) { VSlot *dst = vslots.add(new VSlot(src.slot, vslots.length())); dst->changed = src.changed | delta.changed; propagatevslot(*dst, src, ((1<=0x10000) - { + if(vslots.length()>=0x10000) { compactvslots(); allchanged(); if(vslots.length()>=0x10000) return NULL; } - if(autocompactvslots && ++clonedvslots >= autocompactvslots) - { + if(autocompactvslots && ++clonedvslots >= autocompactvslots) { compactvslots(); allchanged(); } return clonevslot(src, delta); } -static void fixinsidefaces(cube *c, const ivec &o, int size, int tex) -{ - loopi(8) - { +static void fixinsidefaces(cube *c, const ivec &o, int size, int tex) { + loopi(8) { ivec co(i, o, size); if(c[i].children) fixinsidefaces(c[i].children, co, size>>1, tex); else loopj(6) if(!visibletris(c[i], j, co, size)) @@ -2005,40 +1725,35 @@ static void fixinsidefaces(cube *c, const ivec &o, int size, int tex) } } -ICOMMAND(fixinsidefaces, "i", (int *tex), -{ +ICOMMAND(fixinsidefaces, "i", (int *tex), { extern int nompedit; if(noedit(true) || (nompedit && multiplayer())) return; fixinsidefaces(worldroot, ivec(0, 0, 0), worldsize>>1, *tex && vslots.inrange(*tex) ? *tex : DEFAULT_GEOM); allchanged(); }); -const struct slottex -{ +const struct slottex { const char *name; int id; -} slottexs[] = -{ - {"c", TEX_DIFFUSE}, - {"u", TEX_UNKNOWN}, - {"d", TEX_DECAL}, - {"n", TEX_NORMAL}, - {"s", TEX_SPEC}, - {"z", TEX_DEPTH}, - {"a", TEX_ALPHA} +} slottexs[] = { + { + "c", TEX_DIFFUSE}, { + "u", TEX_UNKNOWN}, { + "d", TEX_DECAL}, { + "n", TEX_NORMAL}, { + "s", TEX_SPEC}, { + "z", TEX_DEPTH}, { + "a", TEX_ALPHA} }; -int findslottex(const char *name) -{ - loopi(sizeof(slottexs)/sizeof(slottex)) - { +int findslottex(const char *name) { + loopi(sizeof(slottexs)/sizeof(slottex)) { if(!strcmp(slottexs[i].name, name)) return slottexs[i].id; } return -1; } -void texture(char *type, char *name, int *rot, int *xoffset, int *yoffset, float *scale) -{ +void texture(char *type, char *name, int *rot, int *xoffset, int *yoffset, float *scale) { if(slots.length()>=0x10000) return; int tnum = findslottex(type); if(tnum<0) tnum = atoi(type); @@ -2052,8 +1767,7 @@ void texture(char *type, char *name, int *rot, int *xoffset, int *yoffset, float st.t = NULL; copystring(st.name, name); path(st.name); - if(tnum==TEX_DIFFUSE) - { + if(tnum==TEX_DIFFUSE) { setslotshader(s); VSlot &vs = *emptyvslot(s); vs.reset(); @@ -2066,8 +1780,7 @@ void texture(char *type, char *name, int *rot, int *xoffset, int *yoffset, float COMMAND(texture, "ssiiif"); -void texscroll(float *scrollS, float *scrollT) -{ +void texscroll(float *scrollS, float *scrollT) { if(slots.empty()) return; Slot &s = *slots.last(); s.variants->scroll = vec2(*scrollS, *scrollT).div(1000.0f); @@ -2075,8 +1788,7 @@ void texscroll(float *scrollS, float *scrollT) } COMMAND(texscroll, "ff"); -void texoffset_(int *xoffset, int *yoffset) -{ +void texoffset_(int *xoffset, int *yoffset) { if(slots.empty()) return; Slot &s = *slots.last(); s.variants->offset = ivec2(*xoffset, *yoffset).max(0); @@ -2084,8 +1796,7 @@ void texoffset_(int *xoffset, int *yoffset) } COMMANDN(texoffset, texoffset_, "ii"); -void texrotate_(int *rot) -{ +void texrotate_(int *rot) { if(slots.empty()) return; Slot &s = *slots.last(); s.variants->rotation = clamp(*rot, 0, 7); @@ -2093,8 +1804,7 @@ void texrotate_(int *rot) } COMMANDN(texrotate, texrotate_, "i"); -void texscale(float *scale) -{ +void texscale(float *scale) { if(slots.empty()) return; Slot &s = *slots.last(); s.variants->scale = *scale <= 0 ? 1 : *scale; @@ -2102,8 +1812,7 @@ void texscale(float *scale) } COMMAND(texscale, "f"); -void texlayer(int *layer, char *name, int *mode, float *scale) -{ +void texlayer(int *layer, char *name, int *mode, float *scale) { if(slots.empty()) return; Slot &s = *slots.last(); s.variants->layer = *layer < 0 ? max(slots.length()-1+*layer, 0) : *layer; @@ -2114,8 +1823,7 @@ void texlayer(int *layer, char *name, int *mode, float *scale) } COMMAND(texlayer, "isif"); -void texalpha(float *front, float *back) -{ +void texalpha(float *front, float *back) { if(slots.empty()) return; Slot &s = *slots.last(); s.variants->alphafront = clamp(*front, 0.0f, 1.0f); @@ -2124,8 +1832,7 @@ void texalpha(float *front, float *back) } COMMAND(texalpha, "ff"); -void texcolor(float *r, float *g, float *b) -{ +void texcolor(float *r, float *g, float *b) { if(slots.empty()) return; Slot &s = *slots.last(); s.variants->colorscale = vec(clamp(*r, 0.0f, 1.0f), clamp(*g, 0.0f, 1.0f), clamp(*b, 0.0f, 1.0f)); @@ -2133,48 +1840,40 @@ void texcolor(float *r, float *g, float *b) } COMMAND(texcolor, "fff"); -static int findtextype(Slot &s, int type, int last = -1) -{ +static int findtextype(Slot &s, int type, int last = -1) { for(int i = last+1; i &key, Slot &slot, Slot::Tex &t, bool combined = false, const char *prefix = NULL) -{ +static void addname(vector &key, Slot &slot, Slot::Tex &t, bool combined = false, const char *prefix = NULL) { if(combined) key.add('&'); if(prefix) { while(*prefix) key.add(*prefix++); } defformatstring(tname, "packages/%s", t.name); for(const char *s = path(tname); *s; key.add(*s++)); } -static void texcombine(Slot &s, int index, Slot::Tex &t, bool forceload = false) -{ +static void texcombine(Slot &s, int index, Slot::Tex &t, bool forceload = false) { vector key; addname(key, s, t); int texmask = 0; - if(!forceload) switch(t.type) - { + if(!forceload) switch(t.type) { case TEX_DIFFUSE: - case TEX_NORMAL: - { + case TEX_NORMAL: { int i = findtextype(s, t.type==TEX_DIFFUSE ? (s.texmask&(1<= 0) continue; - switch(t.type) - { + switch(t.type) { default: texcombine(s, i, t, forceload); break; @@ -2232,17 +1925,14 @@ static Slot &loadslot(Slot &s, bool forceload) return s; } -Slot &lookupslot(int index, bool load) -{ +Slot &lookupslot(int index, bool load) { Slot &s = slots.inrange(index) ? *slots[index] : (slots.inrange(DEFAULT_GEOM) ? *slots[DEFAULT_GEOM] : dummyslot); return s.loaded || !load ? s : loadslot(s, false); } -VSlot &lookupvslot(int index, bool load) -{ +VSlot &lookupvslot(int index, bool load) { VSlot &s = vslots.inrange(index) && vslots[index]->slot ? *vslots[index] : (slots.inrange(DEFAULT_GEOM) && slots[DEFAULT_GEOM]->variants ? *slots[DEFAULT_GEOM]->variants : dummyvslot); - if(load && !s.linked) - { + if(load && !s.linked) { if(!s.slot->loaded) loadslot(*s.slot, false); linkvslotshader(s); s.linked = true; @@ -2250,17 +1940,14 @@ VSlot &lookupvslot(int index, bool load) return s; } -void linkslotshaders() -{ +void linkslotshaders() { loopv(slots) if(slots[i]->loaded) linkslotshader(*slots[i]); loopv(vslots) if(vslots[i]->linked) linkvslotshader(*vslots[i]); } -Texture *loadthumbnail(Slot &slot) -{ +Texture *loadthumbnail(Slot &slot) { if(slot.thumbnail) return slot.thumbnail; - if(!slot.variants) - { + if(!slot.variants) { slot.thumbnail = notexture; return slot.thumbnail; } @@ -2269,17 +1956,14 @@ Texture *loadthumbnail(Slot &slot) linkvslotshader(vslot, false); vector name; if(vslot.colorscale == vec(1, 1, 1)) addname(name, slot, slot.sts[0], false, ""); - else - { + else { defformatstring(prefix, "", vslot.colorscale.x, vslot.colorscale.y, vslot.colorscale.z); addname(name, slot, slot.sts[0], false, prefix); } VSlot *layer = vslot.layer ? &lookupvslot(vslot.layer, false) : NULL; - if(layer) - { + if(layer) { if(layer->colorscale == vec(1, 1, 1)) addname(name, *layer->slot, layer->slot->sts[0], true, ""); - else - { + else { defformatstring(prefix, "", vslot.colorscale.x, vslot.colorscale.y, vslot.colorscale.z); addname(name, *layer->slot, layer->slot->sts[0], true, prefix); } @@ -2287,30 +1971,25 @@ Texture *loadthumbnail(Slot &slot) name.add('\0'); Texture *t = textures.access(path(name.getbuf())); if(t) slot.thumbnail = t; - else - { + else { ImageData s, g, l; texturedata(s, NULL, &slot.sts[0], false); if(layer) texturedata(l, NULL, &layer->slot->sts[0], false); if(!s.data) t = slot.thumbnail = notexture; - else - { + else { if(vslot.colorscale != vec(1, 1, 1)) texmad(s, vslot.colorscale, vec(0, 0, 0)); int xs = s.w, ys = s.h; if(s.w > 64 || s.h > 64) scaleimage(s, min(s.w, 64), min(s.h, 64)); - if(g.data) - { + if(g.data) { if(g.w != s.w || g.h != s.h) scaleimage(g, s.w, s.h); } - if(l.data) - { + if(l.data) { if(layer->colorscale != vec(1, 1, 1)) texmad(l, layer->colorscale, vec(0, 0, 0)); if(l.w != s.w/2 || l.h != s.h/2) scaleimage(l, s.w/2, s.h/2); forcergbimage(s); forcergbimage(l); uchar *dstrow = &s.data[s.pitch*l.h + s.bpp*l.w], *srcrow = l.data; - loop(y, l.h) - { + loop(y, l.h) { for(uchar *dst = dstrow, *src = srcrow, *end = &srcrow[l.w*l.bpp]; src < end; dst += s.bpp, src += l.bpp) loopk(3) dst[k] = src[k]; dstrow += s.pitch; @@ -2327,13 +2006,10 @@ Texture *loadthumbnail(Slot &slot) return t; } -void loadlayermasks() -{ - loopv(slots) - { +void loadlayermasks() { + loopv(slots) { Slot &slot = *slots[i]; - if(slot.loaded && slot.layermaskname && !slot.layermask) - { + if(slot.loaded && slot.layermaskname && !slot.layermask) { slot.layermask = new ImageData; texturedata(*slot.layermask, slot.layermaskname); if(!slot.layermask->data) DELETEP(slot.layermask); @@ -2341,34 +2017,28 @@ void loadlayermasks() } } -void cleanuptexture(Texture *t) -{ +void cleanuptexture(Texture *t) { DELETEA(t->alphamask); if(t->id) { glDeleteTextures(1, &t->id); t->id = 0; } if(t->type&Texture::TRANSIENT) textures.remove(t->name); } -void cleanuptextures() -{ +void cleanuptextures() { loopv(slots) slots[i]->cleanup(); loopv(vslots) vslots[i]->cleanup(); enumerate(textures, Texture, tex, cleanuptexture(&tex)); } -bool reloadtexture(const char *name) -{ +bool reloadtexture(const char *name) { Texture *t = textures.access(path(name, true)); if(t) return reloadtexture(*t); return true; } -bool reloadtexture(Texture &tex) -{ +bool reloadtexture(Texture &tex) { if(tex.id) return true; - switch(tex.type&Texture::TYPE) - { - case Texture::IMAGE: - { + switch(tex.type&Texture::TYPE) { + case Texture::IMAGE: { int compress = 0; ImageData s; if(!texturedata(s, tex.name, NULL, true, &compress) || !newtexture(&tex, NULL, s, tex.clamp, tex.mipmap, false, false, compress)) return false; @@ -2378,16 +2048,14 @@ bool reloadtexture(Texture &tex) return true; } -void reloadtex(char *name) -{ +void reloadtex(char *name) { Texture *t = textures.access(path(name, true)); if(!t) { conoutf(CON_ERROR, "texture %s is not loaded", name); return; } if(t->type&Texture::TRANSIENT) { conoutf(CON_ERROR, "can't reload transient texture %s", name); return; } DELETEA(t->alphamask); Texture oldtex = *t; t->id = 0; - if(!reloadtexture(*t)) - { + if(!reloadtexture(*t)) { if(t->id) glDeleteTextures(1, &t->id); *t = oldtex; conoutf(CON_ERROR, "failed to reload texture %s", name); @@ -2396,23 +2064,19 @@ void reloadtex(char *name) COMMAND(reloadtex, "s"); -void reloadtextures() -{ +void reloadtextures() { int reloaded = 0; - enumerate(textures, Texture, tex, - { + enumerate(textures, Texture, tex, { loadprogress = float(++reloaded)/textures.numelems; reloadtexture(tex); }); loadprogress = 0; } -void writepngchunk(stream *f, const char *type, uchar *data = NULL, uint len = 0) -{ +void writepngchunk(stream *f, const char *type, uchar *data = NULL, uint len = 0) { f->putbig(len); f->write(type, 4); f->write(data, len); - uint crc = crc32(0, Z_NULL, 0); crc = crc32(crc, (const Bytef *)type, 4); if(data) crc = crc32(crc, data, len); @@ -2421,11 +2085,9 @@ void writepngchunk(stream *f, const char *type, uchar *data = NULL, uint len = 0 VARP(compresspng, 0, 9, 9); -void savepng(const char *filename, ImageData &image, bool flip) -{ +void savepng(const char *filename, ImageData &image, bool flip) { uchar ctype = 0; - switch(image.bpp) - { + switch(image.bpp) { case 1: ctype = 0; break; case 2: ctype = 4; break; case 3: ctype = 2; break; @@ -2434,44 +2096,33 @@ void savepng(const char *filename, ImageData &image, bool flip) } stream *f = openfile(filename, "wb"); if(!f) { conoutf(CON_ERROR, "could not write to %s", filename); return; } - uchar signature[] = { 137, 80, 78, 71, 13, 10, 26, 10 }; f->write(signature, sizeof(signature)); - - struct pngihdr - { + struct pngihdr { uint width, height; uchar bitdepth, colortype, compress, filter, interlace; } ihdr = { bigswap(image.w), bigswap(image.h), 8, ctype, 0, 0, 0 }; writepngchunk(f, "IHDR", (uchar *)&ihdr, 13); - stream::offset idat = f->tell(); uint len = 0; f->write("\0\0\0\0IDAT", 8); uint crc = crc32(0, Z_NULL, 0); crc = crc32(crc, (const Bytef *)"IDAT", 4); - z_stream z; z.zalloc = NULL; z.zfree = NULL; z.opaque = NULL; - if(deflateInit(&z, compresspng) != Z_OK) goto error; - uchar buf[1<<12]; z.next_out = (Bytef *)buf; z.avail_out = sizeof(buf); - - loopi(image.h) - { + loopi(image.h) { uchar filter = 0; - loopj(2) - { + loopj(2) { z.next_in = j ? (Bytef *)image.data + (flip ? image.h-i-1 : i)*image.pitch : (Bytef *)&filter; z.avail_in = j ? image.w*image.bpp : 1; - while(z.avail_in > 0) - { + while(z.avail_in > 0) { if(deflate(&z, Z_NO_FLUSH) != Z_OK) goto cleanuperror; #define FLUSHZ do { \ int flush = sizeof(buf) - z.avail_out; \ @@ -2485,24 +2136,18 @@ void savepng(const char *filename, ImageData &image, bool flip) } } } - - for(;;) - { + for(;;) { int err = deflate(&z, Z_FINISH); if(err != Z_OK && err != Z_STREAM_END) goto cleanuperror; FLUSHZ; if(err == Z_STREAM_END) break; } - deflateEnd(&z); - f->seek(idat, SEEK_SET); f->putbig(len); f->seek(0, SEEK_END); f->putbig(crc); - writepngchunk(f, "IEND"); - delete f; return; @@ -2511,7 +2156,6 @@ cleanuperror: error: delete f; - conoutf(CON_ERROR, "failed saving png to %s", filename); } @@ -2522,31 +2166,25 @@ VARP(screenshotformat, 0, IMG_PNG, NUMIMG-1); const char *imageexts[NUMIMG] = { ".bmp", ".png", ".jpg" }; -int guessimageformat(const char *filename, int format = IMG_BMP) -{ +int guessimageformat(const char *filename, int format = IMG_BMP) { int len = strlen(filename); - loopi(NUMIMG) - { + loopi(NUMIMG) { int extlen = strlen(imageexts[i]); if(len >= extlen && !strcasecmp(&filename[len-extlen], imageexts[i])) return i; } return format; } -void saveimage(const char *filename, int format, ImageData &image, bool flip = false) -{ - switch(format) - { +void saveimage(const char *filename, int format, ImageData &image, bool flip = false) { + switch(format) { case IMG_PNG: savepng(filename, image, flip); break; - default: - { + default: { ImageData flipped(image.w, image.h, image.bpp, image.data); if(flip) texflip(flipped); SDL_Surface *s = wrapsurface(flipped.data, flipped.w, flipped.h, flipped.bpp); if(!s) break; stream *f = openfile(filename, "wb"); - if(f) - { + if(f) { switch(format) { case IMG_JPG: #if SDL_IMAGE_VERSION_ATLEAST(2, 0, 2) @@ -2565,8 +2203,7 @@ void saveimage(const char *filename, int format, ImageData &image, bool flip = f } } -bool loadimage(const char *filename, ImageData &image) -{ +bool loadimage(const char *filename, ImageData &image) { SDL_Surface *s = loadsurface(path(filename, true)); if(!s) return false; image.wrap(s); @@ -2575,51 +2212,41 @@ bool loadimage(const char *filename, ImageData &image) SVARP(screenshotdir, "screenshot"); -void screenshot(char *filename) -{ +void screenshot(char *filename) { static string buf; int format = -1, dirlen = 0; copystring(buf, screenshotdir); - if(screenshotdir[0]) - { + if(screenshotdir[0]) { dirlen = strlen(buf); if(buf[dirlen] != '/' && buf[dirlen] != '\\' && dirlen+1 < (int)sizeof(buf)) { buf[dirlen++] = '/'; buf[dirlen] = '\0'; } const char *dir = findfile(buf, "w"); if(!fileexists(dir, "w")) createdir(dir); } - if(filename[0]) - { + if(filename[0]) { concatstring(buf, filename); format = guessimageformat(buf, -1); } - else - { + else { string sstime; time_t t = time(NULL); size_t len = strftime(sstime, sizeof(sstime), "%Y-%m-%d_%H.%M.%S", localtime(&t)); sstime[min(len, sizeof(sstime)-1)] = '\0'; concatstring(buf, sstime); - const char *map = game::getclientmap(), *ssinfo = game::getscreenshotinfo(); - if(map && map[0]) - { + if(map && map[0]) { concatstring(buf, "_"); concatstring(buf, map); } - if(ssinfo && ssinfo[0]) - { + if(ssinfo && ssinfo[0]) { concatstring(buf, "_"); concatstring(buf, ssinfo); } - for(char *s = &buf[dirlen]; *s; s++) if(iscubespace(*s) || *s == '/' || *s == '\\') *s = '-'; } - if(format < 0) - { + if(format < 0) { format = screenshotformat; concatstring(buf, imageexts[format]); } - ImageData image(screenw, screenh, 3); glPixelStorei(GL_PACK_ALIGNMENT, texalign(image.data, screenw, 3)); glReadPixels(0, 0, screenw, screenh, GL_RGB, GL_UNSIGNED_BYTE, image.data); diff --git a/src/engine/texture.h b/src/engine/texture.h index 3679931..ef5a57b 100644 --- a/src/engine/texture.h +++ b/src/engine/texture.h @@ -1,43 +1,31 @@ -struct GlobalShaderParamState -{ +struct GlobalShaderParamState { const char *name; - union - { + union { float fval[32]; int ival[32]; uint uval[32]; uchar buf[32*sizeof(float)]; }; int version; - static int nextversion; - void resetversions(); - - void changed() - { + void changed() { if(++nextversion < 0) resetversions(); version = nextversion; } }; -struct ShaderParamBinding -{ +struct ShaderParamBinding { int loc, size; GLenum format; }; -struct GlobalShaderParamUse : ShaderParamBinding -{ - +struct GlobalShaderParamUse : ShaderParamBinding { GlobalShaderParamState *param; int version; - - void flush() - { + void flush() { if(version == param->version) return; - switch(format) - { + switch(format) { case GL_BOOL: case GL_FLOAT: glUniform1fv_(loc, size, param->fval); break; case GL_BOOL_VEC2: @@ -58,25 +46,20 @@ struct GlobalShaderParamUse : ShaderParamBinding } }; -struct LocalShaderParamState : ShaderParamBinding -{ +struct LocalShaderParamState : ShaderParamBinding { const char *name; }; -struct SlotShaderParam -{ +struct SlotShaderParam { const char *name; int loc; float val[4]; }; -struct SlotShaderParamState : LocalShaderParamState -{ +struct SlotShaderParamState : LocalShaderParamState { float val[4]; - SlotShaderParamState() {} - SlotShaderParamState(const SlotShaderParam &p) - { + SlotShaderParamState(const SlotShaderParam &p) { name = p.name; loc = -1; size = 1; @@ -85,12 +68,10 @@ struct SlotShaderParamState : LocalShaderParamState } }; -enum -{ +enum { SHADER_DEFAULT = 0, SHADER_NORMALSLMS = 1<<0, SHADER_OPTION = 1<<3, - SHADER_INVALID = 1<<8, SHADER_DEFERRED = 1<<9 }; @@ -103,25 +84,21 @@ extern int shaderdetail; struct Slot; struct VSlot; -struct UniformLoc -{ +struct UniformLoc { const char *name, *blockname; int loc, version, binding, stride, offset, size; void *data; UniformLoc(const char *name = NULL, const char *blockname = NULL, int binding = -1, int stride = -1) : name(name), blockname(blockname), loc(-1), version(-1), binding(binding), stride(stride), offset(-1), size(-1), data(NULL) {} }; -struct AttribLoc -{ +struct AttribLoc { const char *name; int loc; AttribLoc(const char *name = NULL, int loc = -1) : name(name), loc(loc) {} }; -struct Shader -{ +struct Shader { static Shader *lastshader; - char *name, *vsstr, *psstr, *defer; int type; GLuint program, vsobj, psobj; @@ -137,161 +114,115 @@ struct Shader vector uniformlocs; vector attriblocs; const void *owner; - - Shader() : name(NULL), vsstr(NULL), psstr(NULL), defer(NULL), type(SHADER_DEFAULT), program(0), vsobj(0), psobj(0), detailshader(NULL), variantshader(NULL), altshader(NULL), variantrows(NULL), standard(false), forced(false), used(false), reusevs(NULL), reuseps(NULL), owner(NULL) - { + Shader() : name(NULL), vsstr(NULL), psstr(NULL), defer(NULL), type(SHADER_DEFAULT), program(0), vsobj(0), psobj(0), detailshader(NULL), variantshader(NULL), altshader(NULL), variantrows(NULL), standard(false), forced(false), used(false), reusevs(NULL), reuseps(NULL), owner(NULL) { loopi(MAXSHADERDETAIL) fastshader[i] = this; } - - ~Shader() - { + ~Shader() { DELETEA(name); DELETEA(vsstr); DELETEA(psstr); DELETEA(defer); DELETEA(variantrows); } - void fixdetailshader(bool force = true, bool recurse = true); void allocparams(Slot *slot = NULL); void setslotparams(Slot &slot); void setslotparams(Slot &slot, VSlot &vslot); void bindprograms(); - - void flushparams(Slot *slot = NULL) - { + void flushparams(Slot *slot = NULL) { if(!used) { allocparams(slot); used = true; } loopv(globalparams) globalparams[i].flush(); } - void force(); - bool invalid() const { return (type&SHADER_INVALID)!=0; } bool deferred() const { return (type&SHADER_DEFERRED)!=0; } bool loaded() const { return detailshader!=NULL; } - static bool isnull(const Shader *s); - bool isnull() const { return isnull(this); } - - int numvariants(int row) const - { + int numvariants(int row) const { if(row < 0 || row >= MAXVARIANTROWS || !variantrows) return 0; return variantrows[row+1] - variantrows[row]; } - - Shader *getvariant(int col, int row) const - { + Shader *getvariant(int col, int row) const { if(row < 0 || row >= MAXVARIANTROWS || col < 0 || !variantrows) return NULL; int start = variantrows[row], end = variantrows[row+1]; return col < end - start ? variants[start + col] : NULL; } - - bool hasoption(int row) - { - if(detailshader) - { + bool hasoption(int row) { + if(detailshader) { Shader *s = getvariant(0, row); if(s) return (s->type&SHADER_OPTION)!=0; } return false; } - - void addvariant(int row, Shader *s) - { + void addvariant(int row, Shader *s) { if(row < 0 || row >= MAXVARIANTROWS || variants.length() >= USHRT_MAX) return; if(!variantrows) { variantrows = new ushort[MAXVARIANTROWS+1]; memset(variantrows, 0, (MAXVARIANTROWS+1)*sizeof(ushort)); } variants.insert(variantrows[row+1], s); for(int i = row+1; i <= MAXVARIANTROWS; ++i) ++variantrows[i]; } - - void setvariant_(int col, int row, Shader *fallbackshader) - { + void setvariant_(int col, int row, Shader *fallbackshader) { Shader *s = fallbackshader; - if(detailshader->variantrows) - { + if(detailshader->variantrows) { int start = detailshader->variantrows[row], end = detailshader->variantrows[row+1]; - for(col = min(start + col, end-1); col >= start; --col) - { + for(col = min(start + col, end-1); col >= start; --col) { if(!detailshader->variants[col]->invalid()) { s = detailshader->variants[col]; break; } } } if(lastshader!=s) s->bindprograms(); } - - void setvariant(int col, int row, Shader *fallbackshader) - { + void setvariant(int col, int row, Shader *fallbackshader) { if(isnull() || !loaded()) return; setvariant_(col, row, fallbackshader); lastshader->flushparams(); } - - void setvariant(int col, int row) - { + void setvariant(int col, int row) { if(isnull() || !loaded()) return; setvariant_(col, row, detailshader); lastshader->flushparams(); } - - void setvariant(int col, int row, Slot &slot, VSlot &vslot, Shader *fallbackshader) - { + void setvariant(int col, int row, Slot &slot, VSlot &vslot, Shader *fallbackshader) { if(isnull() || !loaded()) return; setvariant_(col, row, fallbackshader); lastshader->flushparams(&slot); lastshader->setslotparams(slot, vslot); } - - void setvariant(int col, int row, Slot &slot, VSlot &vslot) - { + void setvariant(int col, int row, Slot &slot, VSlot &vslot) { if(isnull() || !loaded()) return; setvariant_(col, row, detailshader); lastshader->flushparams(&slot); lastshader->setslotparams(slot, vslot); } - - void set_() - { + void set_() { if(lastshader!=detailshader) detailshader->bindprograms(); } - - void set() - { + void set() { if(isnull() || !loaded()) return; set_(); lastshader->flushparams(); } - - void set(Slot &slot, VSlot &vslot) - { + void set(Slot &slot, VSlot &vslot) { if(isnull() || !loaded()) return; set_(); lastshader->flushparams(&slot); lastshader->setslotparams(slot, vslot); } - bool compile(); void cleanup(bool invalid = false); - static int uniformlocversion(); }; -struct GlobalShaderParam -{ +struct GlobalShaderParam { const char *name; GlobalShaderParamState *param; - GlobalShaderParam(const char *name) : name(name), param(NULL) {} - - GlobalShaderParamState *resolve() - { + GlobalShaderParamState *resolve() { extern GlobalShaderParamState *getglobalparam(const char *name); if(!param) param = getglobalparam(name); param->changed(); return param; } - - void setf(float x = 0, float y = 0, float z = 0, float w = 0) - { + void setf(float x = 0, float y = 0, float z = 0, float w = 0) { GlobalShaderParamState *g = resolve(); g->fval[0] = x; g->fval[1] = y; @@ -305,12 +236,9 @@ struct GlobalShaderParam void set(const matrix2 &m) { memcpy(resolve()->fval, m.a.v, sizeof(m)); } void set(const matrix3 &m) { memcpy(resolve()->fval, m.a.v, sizeof(m)); } void set(const matrix4 &m) { memcpy(resolve()->fval, m.a.v, sizeof(m)); } - template void setv(const T *v, int n = 1) { memcpy(resolve()->buf, v, n*sizeof(T)); } - - void seti(int x = 0, int y = 0, int z = 0, int w = 0) - { + void seti(int x = 0, int y = 0, int z = 0, int w = 0) { GlobalShaderParamState *g = resolve(); g->ival[0] = x; g->ival[1] = y; @@ -320,33 +248,25 @@ struct GlobalShaderParam void set(const ivec &v, int w = 0) { seti(v.x, v.y, v.z, w); } void set(const ivec2 &v, int z = 0, int w = 0) { seti(v.x, v.y, z, w); } void set(const ivec4 &v) { seti(v.x, v.y, v.z, v.w); } - - void setu(uint x = 0, uint y = 0, uint z = 0, uint w = 0) - { + void setu(uint x = 0, uint y = 0, uint z = 0, uint w = 0) { GlobalShaderParamState *g = resolve(); g->uval[0] = x; g->uval[1] = y; g->uval[2] = z; g->uval[3] = w; } - template T *reserve(int n = 1) { return (T *)resolve()->buf; } }; -struct LocalShaderParam -{ +struct LocalShaderParam { const char *name; int loc; - LocalShaderParam(const char *name) : name(name), loc(-1) {} - - LocalShaderParamState *resolve() - { + LocalShaderParamState *resolve() { Shader *s = Shader::lastshader; if(!s) return NULL; - if(!s->localparamremap.inrange(loc)) - { + if(!s->localparamremap.inrange(loc)) { extern int getlocalparam(const char *name); if(loc == -1) loc = getlocalparam(name); if(!s->localparamremap.inrange(loc)) return NULL; @@ -354,12 +274,9 @@ struct LocalShaderParam uchar remap = s->localparamremap[loc]; return s->localparams.inrange(remap) ? &s->localparams[remap] : NULL; } - - void setf(float x = 0, float y = 0, float z = 0, float w = 0) - { + void setf(float x = 0, float y = 0, float z = 0, float w = 0) { ShaderParamBinding *b = resolve(); - if(b) switch(b->format) - { + if(b) switch(b->format) { case GL_BOOL: case GL_FLOAT: glUniform1f_(b->loc, x); break; case GL_BOOL_VEC2: @@ -389,13 +306,10 @@ struct LocalShaderParam void set(const matrix2 &m) { setv(&m); } void set(const matrix3 &m) { setv(&m); } void set(const matrix4 &m) { setv(&m); } - template - void sett(T x, T y, T z, T w) - { + void sett(T x, T y, T z, T w) { ShaderParamBinding *b = resolve(); - if(b) switch(b->format) - { + if(b) switch(b->format) { case GL_FLOAT: glUniform1f_(b->loc, x); break; case GL_FLOAT_VEC2: glUniform2f_(b->loc, x, y); break; case GL_FLOAT_VEC3: glUniform3f_(b->loc, x, y, z); break; @@ -442,35 +356,26 @@ struct LocalShaderParam name##shader->setvariant(__VA_ARGS__); \ } while(0) -struct ImageData -{ +struct ImageData { int w, h, bpp, levels, align, pitch; GLenum compressed; uchar *data; void *owner; void (*freefunc)(void *); - ImageData() - : data(NULL), owner(NULL), freefunc(NULL) - {} - + : data(NULL), owner(NULL), freefunc(NULL) { + } - ImageData(int nw, int nh, int nbpp, int nlevels = 1, int nalign = 0, GLenum ncompressed = GL_FALSE) - { + ImageData(int nw, int nh, int nbpp, int nlevels = 1, int nalign = 0, GLenum ncompressed = GL_FALSE) { setdata(NULL, nw, nh, nbpp, nlevels, nalign, ncompressed); } - ImageData(int nw, int nh, int nbpp, uchar *data) - : owner(NULL), freefunc(NULL) - { + : owner(NULL), freefunc(NULL) { setdata(data, nw, nh, nbpp); } - ImageData(SDL_Surface *s) { wrap(s); } ~ImageData() { cleanup(); } - - void setdata(uchar *ndata, int nw, int nh, int nbpp, int nlevels = 1, int nalign = 0, GLenum ncompressed = GL_FALSE) - { + void setdata(uchar *ndata, int nw, int nh, int nbpp, int nlevels = 1, int nalign = 0, GLenum ncompressed = GL_FALSE) { w = nw; h = nh; bpp = nbpp; @@ -481,16 +386,12 @@ struct ImageData data = ndata ? ndata : new uchar[calcsize()]; if(!ndata) { owner = this; freefunc = NULL; } } - int calclevelsize(int level) const { return ((max(w>>level, 1)+align-1)/align)*((max(h>>level, 1)+align-1)/align)*bpp; } - - int calcsize() const - { + int calcsize() const { if(!align) return w*h*bpp; int lw = w, lh = h, size = 0; - loopi(levels) - { + loopi(levels) { if(lw<=0) lw = 1; if(lh<=0) lh = 1; size += ((lw+align-1)/align)*((lh+align-1)/align)*bpp; @@ -500,31 +401,23 @@ struct ImageData } return size; } - - void disown() - { + void disown() { data = NULL; owner = NULL; freefunc = NULL; } - - void cleanup() - { + void cleanup() { if(owner==this) delete[] data; else if(freefunc) (*freefunc)(owner); disown(); } - - void replace(ImageData &d) - { + void replace(ImageData &d) { cleanup(); *this = d; if(owner == &d) owner = this; d.disown(); } - - void wrap(SDL_Surface *s) - { + void wrap(SDL_Surface *s) { setdata((uchar *)s->pixels, s->w, s->h, s->format->BytesPerPixel); pitch = s->pitch; owner = s; @@ -536,14 +429,11 @@ struct ImageData // each texture slot can have multiple texture frames, of which currently only the first is used // additional frames can be used for various shaders -struct Texture -{ - enum - { +struct Texture { + enum { IMAGE = 0, CUBEMAP = 1, TYPE = 0xFF, - STUB = 1<<8, TRANSIENT = 1<<9, COMPRESSED = 1<<10, @@ -551,18 +441,15 @@ struct Texture MIRROR = 1<<12, FLAGS = 0xFF00 }; - char *name; int type, w, h, xs, ys, bpp, clamp; bool mipmap, canreduce; GLuint id; uchar *alphamask; - Texture() : alphamask(NULL) {} }; -enum -{ +enum { TEX_DIFFUSE = 0, TEX_UNKNOWN, TEX_DECAL, @@ -572,8 +459,7 @@ enum TEX_ALPHA }; -enum -{ +enum { VSLOT_SHPARAM = 0, VSLOT_SCALE, VSLOT_ROTATION, @@ -585,8 +471,7 @@ enum VSLOT_NUM }; -struct VSlot -{ +struct VSlot { Slot *slot; VSlot *next; int index, changed; @@ -599,17 +484,12 @@ struct VSlot int layer; float alphafront, alphaback; vec colorscale; - - VSlot(Slot *slot = NULL, int index = -1) : slot(slot), next(NULL), index(index), changed(0) - { + VSlot(Slot *slot = NULL, int index = -1) : slot(slot), next(NULL), index(index), changed(0) { reset(); if(slot) addvariant(slot); } - void addvariant(Slot *slot); - - void reset() - { + void reset() { params.shrink(0); linked = false; scale = 1; @@ -621,23 +501,18 @@ struct VSlot alphaback = 0; colorscale = vec(1, 1, 1); } - - void cleanup() - { + void cleanup() { linked = false; } }; -struct Slot -{ - struct Tex - { +struct Slot { + struct Tex { int type; Texture *t; string name; int combined; }; - int index; vector sts; Shader *shader; @@ -650,11 +525,8 @@ struct Slot int layermaskmode; float layermaskscale; ImageData *layermask; - Slot(int index = -1) : index(index), variants(NULL), layermaskname(NULL), layermask(NULL) { reset(); } - - void reset() - { + void reset() { sts.shrink(0); shader = NULL; params.shrink(0); @@ -666,13 +538,10 @@ struct Slot layermaskscale = 1; if(layermask) DELETEP(layermask); } - - void cleanup() - { + void cleanup() { loaded = false; thumbnail = NULL; - loopv(sts) - { + loopv(sts) { Tex &t = sts[i]; t.t = NULL; t.combined = -1; @@ -680,41 +549,32 @@ struct Slot } }; -inline void VSlot::addvariant(Slot *slot) -{ +inline void VSlot::addvariant(Slot *slot) { if(!slot->variants) slot->variants = this; - else - { + else { VSlot *prev = slot->variants; while(prev->next) prev = prev->next; prev->next = this; } } -struct MSlot : Slot, VSlot -{ +struct MSlot : Slot, VSlot { MSlot() : VSlot(this) {} - - void reset() - { + void reset() { Slot::reset(); VSlot::reset(); } - - void cleanup() - { + void cleanup() { Slot::cleanup(); VSlot::cleanup(); } }; -struct texrotation -{ +struct texrotation { bool flipx, flipy, swapxy; }; -struct cubemapside -{ +struct cubemapside { GLenum target; const char *name; bool flipx, flipy, swapxy; diff --git a/src/engine/vertmodel.h b/src/engine/vertmodel.h deleted file mode 100644 index e9af1b0..0000000 --- a/src/engine/vertmodel.h +++ /dev/null @@ -1,490 +0,0 @@ -struct vertmodel : animmodel -{ - struct vert { vec pos, norm; }; - struct vvert { vec pos; vec2 tc; }; - struct vvertn : vvert { vec norm; }; - struct vvertbump : vvert { squat tangent; }; - struct tcvert { vec2 tc; }; - struct bumpvert { vec4 tangent; }; - struct tri { ushort vert[3]; }; - - struct vbocacheentry - { - GLuint vbuf; - animstate as; - int millis; - - vbocacheentry() : vbuf(0) { as.cur.fr1 = as.prev.fr1 = -1; } - }; - - struct vertmesh : mesh - { - vert *verts; - tcvert *tcverts; - bumpvert *bumpverts; - tri *tris; - int numverts, numtris; - - int voffset, eoffset, elen; - ushort minvert, maxvert; - - vertmesh() : verts(0), tcverts(0), bumpverts(0), tris(0) - { - } - - virtual ~vertmesh() - { - DELETEA(verts); - DELETEA(tcverts); - DELETEA(bumpverts); - DELETEA(tris); - } - - void smoothnorms(float limit = 0, bool areaweight = true) - { - if(((vertmeshgroup *)group)->numframes == 1) mesh::smoothnorms(verts, numverts, tris, numtris, limit, areaweight); - else buildnorms(areaweight); - } - - void buildnorms(bool areaweight = true) - { - mesh::buildnorms(verts, numverts, tris, numtris, areaweight, ((vertmeshgroup *)group)->numframes); - } - - void calctangents(bool areaweight = true) - { - if(bumpverts) return; - bumpverts = new bumpvert[((vertmeshgroup *)group)->numframes*numverts]; - mesh::calctangents(bumpverts, verts, tcverts, numverts, tris, numtris, areaweight, ((vertmeshgroup *)group)->numframes); - } - - void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) - { - loopj(numverts) - { - vec v = m.transform(verts[j].pos); - loopi(3) - { - bbmin[i] = min(bbmin[i], v[i]); - bbmax[i] = max(bbmax[i], v[i]); - } - } - } - - void genBIH(BIH::mesh &m) - { - m.tris = (const BIH::tri *)tris; - m.numtris = numtris; - m.pos = (const uchar *)&verts->pos; - m.posstride = sizeof(vert); - m.tc = (const uchar *)&tcverts->tc; - m.tcstride = sizeof(tcvert); - } - - static inline void assignvert(vvertn &vv, int j, tcvert &tc, vert &v) - { - vv.pos = v.pos; - vv.norm = v.norm; - vv.tc = tc.tc; - } - - inline void assignvert(vvertbump &vv, int j, tcvert &tc, vert &v) - { - vv.pos = v.pos; - vv.tc = tc.tc; - vv.tangent = bumpverts[j].tangent; - } - - template - int genvbo(vector &idxs, int offset, vector &vverts, int *htdata, int htlen) - { - voffset = offset; - eoffset = idxs.length(); - minvert = 0xFFFF; - loopi(numtris) - { - tri &t = tris[i]; - loopj(3) - { - int index = t.vert[j]; - tcvert &tc = tcverts[index]; - vert &v = verts[index]; - T vv; - assignvert(vv, index, tc, v); - int htidx = hthash(v.pos)&(htlen-1); - loopk(htlen) - { - int &vidx = htdata[(htidx+k)&(htlen-1)]; - if(vidx < 0) { vidx = idxs.add(ushort(vverts.length())); vverts.add(vv); break; } - else if(!memcmp(&vverts[vidx], &vv, sizeof(vv))) { minvert = min(minvert, idxs.add(ushort(vidx))); break; } - } - } - } - minvert = min(minvert, ushort(voffset)); - maxvert = max(minvert, ushort(vverts.length()-1)); - elen = idxs.length()-eoffset; - return vverts.length()-voffset; - } - - int genvbo(vector &idxs, int offset) - { - voffset = offset; - eoffset = idxs.length(); - loopi(numtris) - { - tri &t = tris[i]; - loopj(3) idxs.add(voffset+t.vert[j]); - } - minvert = voffset; - maxvert = voffset + numverts-1; - elen = idxs.length()-eoffset; - return numverts; - } - - template - static inline void fillvert(T &vv, int j, tcvert &tc, vert &v) - { - vv.tc = tc.tc; - } - - template - void fillverts(T *vdata) - { - vdata += voffset; - loopi(numverts) fillvert(vdata[i], i, tcverts[i], verts[i]); - } - - void interpverts(const animstate &as, bool tangents, void * RESTRICT vdata, skin &s) - { - const vert * RESTRICT vert1 = &verts[as.cur.fr1 * numverts], - * RESTRICT vert2 = &verts[as.cur.fr2 * numverts], - * RESTRICT pvert1 = as.interp<1 ? &verts[as.prev.fr1 * numverts] : NULL, - * RESTRICT pvert2 = as.interp<1 ? &verts[as.prev.fr2 * numverts] : NULL; - #define ipvert(attrib) v.attrib.lerp(vert1[i].attrib, vert2[i].attrib, as.cur.t) - #define ipbvert(attrib, type) v.attrib.lerp(bvert1[i].attrib, bvert2[i].attrib, as.cur.t) - #define ipvertp(attrib) v.attrib.lerp(pvert1[i].attrib, pvert2[i].attrib, as.prev.t).lerp(vec().lerp(vert1[i].attrib, vert2[i].attrib, as.cur.t), as.interp) - #define ipbvertp(attrib, type) v.attrib.lerp(type().lerp(bpvert1[i].attrib, bpvert2[i].attrib, as.prev.t), type().lerp(bvert1[i].attrib, bvert2[i].attrib, as.cur.t), as.interp) - #define iploop(type, body) \ - loopi(numverts) \ - { \ - type &v = ((type * RESTRICT)vdata)[i]; \ - body; \ - } - if(tangents) - { - const bumpvert * RESTRICT bvert1 = &bumpverts[as.cur.fr1 * numverts], - * RESTRICT bvert2 = &bumpverts[as.cur.fr2 * numverts], - * RESTRICT bpvert1 = as.interp<1 ? &bumpverts[as.prev.fr1 * numverts] : NULL, - * RESTRICT bpvert2 = as.interp<1 ? &bumpverts[as.prev.fr2 * numverts] : NULL; - if(as.interp<1) iploop(vvertbump, { ipvertp(pos); ipbvertp(tangent, vec4); }) - else iploop(vvertbump, { ipvert(pos); ipbvert(tangent, vec4); }) - } - else - { - if(as.interp<1) iploop(vvertn, { ipvertp(pos); ipvertp(norm); }) - else iploop(vvertn, { ipvert(pos); ipvert(norm); }) - } - #undef iploop - #undef ipvert - #undef ipbvert - #undef ipvertp - #undef ipbvertp - } - - void render(const animstate *as, skin &s, vbocacheentry &vc) - { - if(!Shader::lastshader) return; - glDrawRangeElements_(GL_TRIANGLES, minvert, maxvert, elen, GL_UNSIGNED_SHORT, &((vertmeshgroup *)group)->edata[eoffset]); - glde++; - xtravertsva += numverts; - } - }; - - struct tag - { - char *name; - matrix4x3 transform; - - tag() : name(NULL) {} - ~tag() { DELETEA(name); } - }; - - struct vertmeshgroup : meshgroup - { - int numframes; - tag *tags; - int numtags; - - static const int MAXVBOCACHE = 16; - vbocacheentry vbocache[MAXVBOCACHE]; - - ushort *edata; - GLuint ebuf; - bool vtangents; - int vlen, vertsize; - uchar *vdata; - - vertmeshgroup() : numframes(0), tags(NULL), numtags(0), edata(NULL), ebuf(0), vtangents(false), vlen(0), vertsize(0), vdata(NULL) - { - } - - virtual ~vertmeshgroup() - { - DELETEA(tags); - if(ebuf) glDeleteBuffers_(1, &ebuf); - loopi(MAXVBOCACHE) - { - if(vbocache[i].vbuf) glDeleteBuffers_(1, &vbocache[i].vbuf); - } - DELETEA(vdata); - } - - int findtag(const char *name) - { - loopi(numtags) if(!strcmp(tags[i].name, name)) return i; - return -1; - } - - int totalframes() const { return numframes; } - - void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) - { - n.mul(m, tags[numtags + i].transform); - n.posttranslate(m.transformnormal(p->translate), p->model->scale); - } - - void calctagmatrix(part *p, int i, const animstate &as, matrix4 &matrix) - { - const matrix4x3 &tag1 = tags[as.cur.fr1*numtags + i].transform, - &tag2 = tags[as.cur.fr2*numtags + i].transform; - matrix4x3 tag; - tag.lerp(tag1, tag2, as.cur.t); - if(as.interp<1) - { - const matrix4x3 &tag1p = tags[as.prev.fr1*numtags + i].transform, - &tag2p = tags[as.prev.fr2*numtags + i].transform; - matrix4x3 tagp; - tagp.lerp(tag1p, tag2p, as.prev.t); - tag.lerp(tagp, tag, as.interp); - } - tag.d.add(p->translate).mul(p->model->scale); - matrix = matrix4(tag); - } - - void genvbo(bool tangents, vbocacheentry &vc) - { - if(!vc.vbuf) glGenBuffers_(1, &vc.vbuf); - if(ebuf) return; - - vector idxs; - - if(tangents) loopv(meshes) ((vertmesh *)meshes[i])->calctangents(); - - vtangents = tangents; - vertsize = tangents ? sizeof(vvertbump) : sizeof(vvertn); - vlen = 0; - if(numframes>1) - { - loopv(meshes) vlen += ((vertmesh *)meshes[i])->genvbo(idxs, vlen); - DELETEA(vdata); - vdata = new uchar[vlen*vertsize]; - #define FILLVDATA(type) do { \ - loopv(meshes) ((vertmesh *)meshes[i])->fillverts((type *)vdata); \ - } while(0) - if(tangents) FILLVDATA(vvertbump); - else FILLVDATA(vvertn); - #undef FILLVDATA - } - else - { - gle::bindvbo(vc.vbuf); - #define GENVBO(type) do { \ - vector vverts; \ - loopv(meshes) vlen += ((vertmesh *)meshes[i])->genvbo(idxs, vlen, vverts, htdata, htlen); \ - glBufferData_(GL_ARRAY_BUFFER, vverts.length()*sizeof(type), vverts.getbuf(), GL_STATIC_DRAW); \ - } while(0) - int numverts = 0, htlen = 128; - loopv(meshes) numverts += ((vertmesh *)meshes[i])->numverts; - while(htlen < numverts) htlen *= 2; - if(numverts*4 > htlen*3) htlen *= 2; - int *htdata = new int[htlen]; - memset(htdata, -1, htlen*sizeof(int)); - if(tangents) GENVBO(vvertbump); - else GENVBO(vvertn); - delete[] htdata; - #undef GENVBO - gle::clearvbo(); - } - - glGenBuffers_(1, &ebuf); - gle::bindebo(ebuf); - glBufferData_(GL_ELEMENT_ARRAY_BUFFER, idxs.length()*sizeof(ushort), idxs.getbuf(), GL_STATIC_DRAW); - gle::clearebo(); - } - - void bindvbo(const animstate *as, vbocacheentry &vc) - { - vvert *vverts = 0; - bindpos(ebuf, vc.vbuf, &vverts->pos, vertsize); - if(as->cur.anim&ANIM_NOSKIN) - { - if(enabletc) disabletc(); - if(enablenormals) disablenormals(); - if(enabletangents) disabletangents(); - } - else - { - if(vtangents) - { - if(enablenormals) disablenormals(); - vvertbump *vvertbumps = 0; - bindtangents(&vvertbumps->tangent, vertsize); - } - else - { - if(enabletangents) disabletangents(); - vvertn *vvertns = 0; - bindnormals(&vvertns->norm, vertsize); - } - - bindtc(&vverts->tc, vertsize); - } - if(enablebones) disablebones(); - } - - void cleanup() - { - loopi(MAXVBOCACHE) - { - vbocacheentry &c = vbocache[i]; - if(c.vbuf) { glDeleteBuffers_(1, &c.vbuf); c.vbuf = 0; } - c.as.cur.fr1 = -1; - } - if(ebuf) { glDeleteBuffers_(1, &ebuf); ebuf = 0; } - } - - void preload(part *p) - { - if(numframes > 1) return; - bool tangents = p->tangents(); - if(tangents!=vtangents) cleanup(); - if(!vbocache->vbuf) genvbo(tangents, *vbocache); - } - - void render(const animstate *as, float pitch, const vec &axis, const vec &forward, dynent *d, part *p) - { - if(as->cur.anim&ANIM_NORENDER) - { - loopv(p->links) calctagmatrix(p, p->links[i].tag, *as, p->links[i].matrix); - return; - } - - bool tangents = p->tangents(); - if(tangents!=vtangents) { cleanup(); disablevbo(); } - vbocacheentry *vc = NULL; - if(numframes<=1) vc = vbocache; - else - { - loopi(MAXVBOCACHE) - { - vbocacheentry &c = vbocache[i]; - if(!c.vbuf) continue; - if(c.as==*as) { vc = &c; break; } - } - if(!vc) loopi(MAXVBOCACHE) { vc = &vbocache[i]; if(!vc->vbuf || vc->millis < lastmillis) break; } - } - if(!vc->vbuf) genvbo(tangents, *vc); - if(numframes>1) - { - if(vc->as!=*as) - { - vc->as = *as; - vc->millis = lastmillis; - loopv(meshes) - { - vertmesh &m = *(vertmesh *)meshes[i]; - m.interpverts(*as, tangents, vdata + m.voffset*vertsize, p->skins[i]); - } - gle::bindvbo(vc->vbuf); - glBufferData_(GL_ARRAY_BUFFER, vlen*vertsize, vdata, GL_STREAM_DRAW); - } - vc->millis = lastmillis; - } - - bindvbo(as, *vc); - loopv(meshes) - { - vertmesh *m = (vertmesh *)meshes[i]; - p->skins[i].bind(m, as); - m->render(as, p->skins[i], *vc); - } - - loopv(p->links) calctagmatrix(p, p->links[i].tag, *as, p->links[i].matrix); - } - }; - - vertmodel(const char *name) : animmodel(name) - { - } -}; - -template struct vertloader : modelloader -{ - vertloader(const char *name) : modelloader(name) {} -}; - -template struct vertcommands : modelcommands -{ - typedef struct MDL::part part; - typedef struct MDL::skin skin; - - static void loadpart(char *model, float *smooth) - { - if(!MDL::loading) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } - defformatstring(filename, "%s/%s", MDL::dir, model); - part &mdl = MDL::loading->addpart(); - if(mdl.index) mdl.pitchscale = mdl.pitchoffset = mdl.pitchmin = mdl.pitchmax = 0; - mdl.meshes = MDL::loading->sharemeshes(path(filename), double(*smooth > 0 ? cos(clamp(*smooth, 0.0f, 180.0f)*RAD) : 2)); - if(!mdl.meshes) conoutf(CON_ERROR, "could not load %s", filename); - else mdl.initskins(); - } - - static void setpitch(float *pitchscale, float *pitchoffset, float *pitchmin, float *pitchmax) - { - if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } - part &mdl = *MDL::loading->parts.last(); - - mdl.pitchscale = *pitchscale; - mdl.pitchoffset = *pitchoffset; - if(*pitchmin || *pitchmax) - { - mdl.pitchmin = *pitchmin; - mdl.pitchmax = *pitchmax; - } - else - { - mdl.pitchmin = -360*fabs(mdl.pitchscale) + mdl.pitchoffset; - mdl.pitchmax = 360*fabs(mdl.pitchscale) + mdl.pitchoffset; - } - } - - static void setanim(char *anim, int *frame, int *range, float *speed, int *priority) - { - if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } - vector anims; - findanims(anim, anims); - if(anims.empty()) conoutf(CON_ERROR, "could not find animation %s", anim); - else loopv(anims) - { - MDL::loading->parts.last()->setanim(0, anims[i], *frame, *range, *speed, *priority); - } - } - - vertcommands() - { - if(MDL::multiparted()) this->modelcommand(loadpart, "load", "sf"); - this->modelcommand(setpitch, "pitch", "ffff"); - if(MDL::animated()) this->modelcommand(setanim, "anim", "siiff"); - } -}; - diff --git a/src/engine/world.cpp b/src/engine/world.cpp index 46aaa0f..489ea65 100644 --- a/src/engine/world.cpp +++ b/src/engine/world.cpp @@ -10,29 +10,23 @@ SVARR(maptitle, "Untitled Map by Unknown"); VAR(octaentsize, 0, 64, 1024); VAR(entselradius, 0, 2, 10); -static inline void mmboundbox(const entity &e, model *m, vec ¢er, vec &radius) -{ +static inline void mmboundbox(const entity &e, model *m, vec ¢er, vec &radius) { m->boundbox(center, radius); rotatebb(center, radius, e.attr1); } -static inline void mmcollisionbox(const entity &e, model *m, vec ¢er, vec &radius) -{ +static inline void mmcollisionbox(const entity &e, model *m, vec ¢er, vec &radius) { m->collisionbox(center, radius); rotatebb(center, radius, e.attr1); } -bool getentboundingbox(const extentity &e, ivec &o, ivec &r) -{ - switch(e.type) - { +bool getentboundingbox(const extentity &e, ivec &o, ivec &r) { + switch(e.type) { case ET_EMPTY: return false; - case ET_MAPMODEL: - { + case ET_MAPMODEL: { model *m = loadmapmodel(e.attr2); - if(m) - { + if(m) { vec center, radius; mmboundbox(e, m, center, radius); center.add(e.o); @@ -52,32 +46,25 @@ bool getentboundingbox(const extentity &e, ivec &o, ivec &r) return true; } -enum -{ +enum { MODOE_ADD = 1<<0, MODOE_UPDATEBB = 1<<1, MODOE_LIGHTENT = 1<<2 }; -void modifyoctaentity(int flags, int id, extentity &e, cube *c, const ivec &cor, int size, const ivec &bo, const ivec &br, int leafsize, vtxarray *lastva = NULL) -{ - loopoctabox(cor, size, bo, br) - { +void modifyoctaentity(int flags, int id, extentity &e, cube *c, const ivec &cor, int size, const ivec &bo, const ivec &br, int leafsize, vtxarray *lastva = NULL) { + loopoctabox(cor, size, bo, br) { ivec o(i, cor, size); vtxarray *va = c[i].ext && c[i].ext->va ? c[i].ext->va : lastva; if(c[i].children != NULL && size > leafsize) modifyoctaentity(flags, id, e, c[i].children, o, size>>1, bo, br, leafsize, va); - else if(flags&MODOE_ADD) - { + else if(flags&MODOE_ADD) { if(!c[i].ext || !c[i].ext->ents) ext(c[i]).ents = new octaentities(o, size); octaentities &oe = *c[i].ext->ents; - switch(e.type) - { + switch(e.type) { case ET_MAPMODEL: - if(loadmapmodel(e.attr2)) - { - if(va) - { + if(loadmapmodel(e.attr2)) { + if(va) { va->bbmin.x = -1; if(oe.mapmodels.empty()) va->mapmodels.add(&oe); } @@ -92,26 +79,20 @@ void modifyoctaentity(int flags, int id, extentity &e, cube *c, const ivec &cor, oe.other.add(id); break; } - } - else if(c[i].ext && c[i].ext->ents) - { + else if(c[i].ext && c[i].ext->ents) { octaentities &oe = *c[i].ext->ents; - switch(e.type) - { + switch(e.type) { case ET_MAPMODEL: - if(loadmapmodel(e.attr2)) - { + if(loadmapmodel(e.attr2)) { oe.mapmodels.removeobj(id); - if(va) - { + if(va) { va->bbmin.x = -1; if(oe.mapmodels.empty()) va->mapmodels.removeobj(&oe); } oe.bbmin = oe.bbmax = oe.o; oe.bbmin.add(oe.size); - loopvj(oe.mapmodels) - { + loopvj(oe.mapmodels) { extentity &e = *entities::getents()[oe.mapmodels[j]]; ivec eo, er; if(getentboundingbox(e, eo, er)) @@ -134,10 +115,8 @@ void modifyoctaentity(int flags, int id, extentity &e, cube *c, const ivec &cor, freeoctaentities(c[i]); } if(c[i].ext && c[i].ext->ents) c[i].ext->ents->query = NULL; - if(va && va!=lastva) - { - if(lastva) - { + if(va && va!=lastva) { + if(lastva) { if(va->bbmin.x < 0) lastva->bbmin.x = -1; } else if(flags&MODOE_UPDATEBB) updatevabb(va); @@ -147,24 +126,18 @@ void modifyoctaentity(int flags, int id, extentity &e, cube *c, const ivec &cor, vector outsideents; -static bool modifyoctaent(int flags, int id, extentity &e) -{ +static bool modifyoctaent(int flags, int id, extentity &e) { if(flags&MODOE_ADD ? e.flags&EF_OCTA : !(e.flags&EF_OCTA)) return false; - ivec o, r; if(!getentboundingbox(e, o, r)) return false; - - if(!insideworld(e.o)) - { + if(!insideworld(e.o)) { int idx = outsideents.find(id); - if(flags&MODOE_ADD) - { + if(flags&MODOE_ADD) { if(idx < 0) outsideents.add(id); } else if(idx >= 0) outsideents.removeunordered(idx); } - else - { + else { int leafsize = octaentsize, limit = max(r.x - o.x, max(r.y - o.y, r.z - o.z)); while(leafsize < limit) leafsize *= 2; int diff = ~(leafsize-1) & ((o.x^r.x)|(o.y^r.y)|(o.z^r.z)); @@ -178,8 +151,7 @@ static bool modifyoctaent(int flags, int id, extentity &e) return true; } -static inline bool modifyoctaent(int flags, int id) -{ +static inline bool modifyoctaent(int flags, int id) { vector &ents = entities::getents(); return ents.inrange(id) && modifyoctaent(flags, id, *ents[id]); } @@ -187,68 +159,56 @@ static inline bool modifyoctaent(int flags, int id) static inline void addentity(int id) { modifyoctaent(MODOE_ADD|MODOE_UPDATEBB|MODOE_LIGHTENT, id); } static inline void removeentity(int id) { modifyoctaent(MODOE_UPDATEBB, id); } -void freeoctaentities(cube &c) -{ +void freeoctaentities(cube &c) { if(!c.ext) return; - if(entities::getents().length()) - { + if(entities::getents().length()) { while(c.ext->ents && !c.ext->ents->mapmodels.empty()) removeentity(c.ext->ents->mapmodels.pop()); while(c.ext->ents && !c.ext->ents->other.empty()) removeentity(c.ext->ents->other.pop()); } - if(c.ext->ents) - { + if(c.ext->ents) { delete c.ext->ents; c.ext->ents = NULL; } } -void entitiesinoctanodes() -{ +void entitiesinoctanodes() { vector &ents = entities::getents(); loopv(ents) modifyoctaent(MODOE_ADD, i, *ents[i]); } -static inline void findents(octaentities &oe, int low, int high, bool notspawned, const vec &pos, const vec &invradius, vector &found) -{ +static inline void findents(octaentities &oe, int low, int high, bool notspawned, const vec &pos, const vec &invradius, vector &found) { vector &ents = entities::getents(); - loopv(oe.other) - { + loopv(oe.other) { int id = oe.other[i]; extentity &e = *ents[id]; if(e.type >= low && e.type <= high && (e.spawned() || notspawned) && vec(e.o).sub(pos).mul(invradius).squaredlen() <= 1) found.add(id); } } -static inline void findents(cube *c, const ivec &o, int size, const ivec &bo, const ivec &br, int low, int high, bool notspawned, const vec &pos, const vec &invradius, vector &found) -{ - loopoctabox(o, size, bo, br) - { +static inline void findents(cube *c, const ivec &o, int size, const ivec &bo, const ivec &br, int low, int high, bool notspawned, const vec &pos, const vec &invradius, vector &found) { + loopoctabox(o, size, bo, br) { if(c[i].ext && c[i].ext->ents) findents(*c[i].ext->ents, low, high, notspawned, pos, invradius, found); - if(c[i].children && size > octaentsize) - { + if(c[i].children && size > octaentsize) { ivec co(i, o, size); findents(c[i].children, co, size>>1, bo, br, low, high, notspawned, pos, invradius, found); } } } -void findents(int low, int high, bool notspawned, const vec &pos, const vec &radius, vector &found) -{ +void findents(int low, int high, bool notspawned, const vec &pos, const vec &radius, vector &found) { vec invradius(1/radius.x, 1/radius.y, 1/radius.z); ivec bo(vec(pos).sub(radius).sub(1)), br(vec(pos).add(radius).add(1)); int diff = (bo.x^br.x) | (bo.y^br.y) | (bo.z^br.z) | octaentsize, scale = worldscale-1; - if(diff&~((1<= uint(worldsize)) - { + if(diff&~((1<= uint(worldsize)) { findents(worldroot, ivec(0, 0, 0), 1<ext && c->ext->ents) findents(*c->ext->ents, low, high, notspawned, pos, invradius, found); scale--; - while(c->children && !(diff&(1<children && !(diff&(1<children[octastep(bo.x, bo.y, bo.z, scale)]; if(c->ext && c->ext->ents) findents(*c->ext->ents, low, high, notspawned, pos, invradius, found); scale--; @@ -256,13 +216,11 @@ void findents(int low, int high, bool notspawned, const vec &pos, const vec &rad if(c->children && 1<= octaentsize) findents(c->children, ivec(bo).mask(~((2<= sel.o.x && o.y <= sel.o.y+sel.s.y*sel.grid @@ -295,31 +251,26 @@ bool pointinsel(const selinfo &sel, const vec &o) vector entgroup; -bool haveselent() -{ +bool haveselent() { return entgroup.length() > 0; } -void entcancel() -{ +void entcancel() { entgroup.shrink(0); } -void entadd(int id) -{ +void entadd(int id) { undonext = true; entgroup.add(id); } -undoblock *newundoent() -{ +undoblock *newundoent() { int numents = entgroup.length(); if(numents <= 0) return NULL; undoblock *u = (undoblock *)new uchar[sizeof(undoblock) + numents*sizeof(undoent)]; u->numents = numents; undoent *e = (undoent *)(u + 1); - loopv(entgroup) - { + loopv(entgroup) { e->i = entgroup[i]; e->e = *entities::getents()[entgroup[i]]; e++; @@ -327,8 +278,7 @@ undoblock *newundoent() return u; } -void makeundoent() -{ +void makeundoent() { if(!undonext) return; undonext = false; oldhover = enthover; @@ -336,8 +286,7 @@ void makeundoent() if(u) addundo(u); } -void detachentity(extentity &e) -{ +void detachentity(extentity &e) { if(!e.attached) return; e.attached->attached = NULL; e.attached = NULL; @@ -345,40 +294,31 @@ void detachentity(extentity &e) VAR(attachradius, 1, 100, 1000); -void attachentity(extentity &e) -{ - switch(e.type) - { +void attachentity(extentity &e) { + switch(e.type) { case ET_SPOTLIGHT: break; - default: if(e.type &ents = entities::getents(); int closest = -1; float closedist = 1e10f; - loopv(ents) - { + loopv(ents) { extentity *a = ents[i]; if(a->attached) continue; - switch(e.type) - { + switch(e.type) { case ET_SPOTLIGHT: if(a->type!=ET_LIGHT) continue; break; - default: if(e.typeo); - if(dist < closedist) - { + if(dist < closedist) { closest = i; closedist = dist; } @@ -388,8 +328,7 @@ void attachentity(extentity &e) ents[closest]->attached = &e; } -void attachentities() -{ +void attachentities() { vector &ents = entities::getents(); loopv(ents) attachentity(*ents[i]); } @@ -400,10 +339,10 @@ void attachentities() #define addimplicit(f) { if(entgroup.empty() && enthover>=0) { entadd(enthover); undonext = (enthover != oldhover); f; entgroup.drop(); } else f; } #define entfocusv(i, f, v){ int n = efocus = (i); if(n>=0) { extentity &e = *v[n]; f; } } #define entfocus(i, f) entfocusv(i, f, entities::getents()) -#define enteditv(i, f, v) \ -{ \ - entfocusv(i, \ - { \ +#define enteditv(i, f, v) { \ + \ + entfocusv(i, { \ + \ int oldtype = e.type; \ removeentity(n); \ f; \ @@ -413,23 +352,21 @@ void attachentities() }, v); \ } #define entedit(i, f) enteditv(i, f, entities::getents()) -#define addgroup(exp) { vector &ents = entities::getents(); loopv(ents) entfocusv(i, if(exp) entadd(n), ents); } -#define setgroup(exp) { entcancel(); addgroup(exp); } +#define addgroup(exp) { vector &ents = entities::getents(); loopv(ents) entfocusv(i, if(exp) entadd(n), ents); } +#define setgroup(exp) { entcancel(); addgroup(exp); } #define groupeditloop(f){ vector &ents = entities::getents(); entlooplevel++; int _ = efocus; loopv(entgroup) enteditv(entgroup[i], f, ents); efocus = _; entlooplevel--; } #define groupeditpure(f){ if(entlooplevel>0) { entedit(efocus, f); } else groupeditloop(f); } #define groupeditundo(f){ makeundoent(); groupeditpure(f); } #define groupedit(f) { addimplicit(groupeditundo(f)); } -vec getselpos() -{ +vec getselpos() { vector &ents = entities::getents(); if(entgroup.length() && ents.inrange(entgroup[0])) return ents[entgroup[0]]->o; if(ents.inrange(enthover)) return ents[enthover]->o; return vec(sel.o); } -undoblock *copyundoents(undoblock *u) -{ +undoblock *copyundoents(undoblock *u) { entcancel(); undoent *e = u->ents(); loopi(u->numents) @@ -440,8 +377,7 @@ undoblock *copyundoents(undoblock *u) return c; } -void pasteundoent(int idx, const entity &ue) -{ +void pasteundoent(int idx, const entity &ue) { if(idx < 0 || idx >= MAXENTS) return; vector &ents = entities::getents(); while(ents.length() < idx) ents.add(entities::newentity())->type = ET_EMPTY; @@ -449,23 +385,20 @@ void pasteundoent(int idx, const entity &ue) entedit(idx, (entity &)e = ue); } -void pasteundoents(undoblock *u) -{ +void pasteundoents(undoblock *u) { undoent *ue = u->ents(); loopi(u->numents) entedit(ue[i].i, (entity &)e = ue[i].e); } -void entflip() -{ +void entflip() { if(noentedit()) return; int d = dimension(sel.orient); float mid = sel.s[d]*sel.grid/2+sel.o[d]; groupeditundo(e.o[d] -= (e.o[d]-mid)*2); } -void entrotate(int *cw) -{ +void entrotate(int *cw) { if(noentedit()) return; int d = dimension(sel.orient); int dd = (*cw<0) == dimcoord(sel.orient) ? R[d] : C[d]; @@ -479,12 +412,10 @@ void entrotate(int *cw) ); } -void entselectionbox(const entity &e, vec &eo, vec &es) -{ +void entselectionbox(const entity &e, vec &eo, vec &es) { model *m = NULL; const char *mname = entities::entmodel(e); - if(mname && (m = loadmodel(mname))) - { + if(mname && (m = loadmodel(mname))) { m->collisionbox(eo, es); if(es.x > es.y) es.y = es.x; else es.x = es.y; // square es.z = (es.z + eo.z + 1 + entselradius)/2; // enclose ent radius box and model box @@ -492,14 +423,12 @@ void entselectionbox(const entity &e, vec &eo, vec &es) eo.y += e.o.y; eo.z = e.o.z - entselradius + es.z; } - else if(e.type == ET_MAPMODEL && (m = loadmapmodel(e.attr2))) - { + else if(e.type == ET_MAPMODEL && (m = loadmapmodel(e.attr2))) { mmcollisionbox(e, m, eo, es); es.max(entselradius); eo.add(e.o); } - else - { + else { es = vec(entselradius); eo = e.o; } @@ -517,31 +446,24 @@ extern bool editmoveplane(const vec &o, const vec &ray, int d, float off, vec &h int entmoving = 0; -void entdrag(const vec &ray) -{ +void entdrag(const vec &ray) { if(noentedit() || !haveselent()) return; - float r = 0, c = 0; static vec v, handle; vec eo, es; int d = dimension(entorient), dc= dimcoord(entorient); - entfocus(entgroup.last(), entselectionbox(e, eo, es); - if(!editmoveplane(e.o, ray, d, eo[d] + (dc ? es[d] : 0), handle, v, entmoving==1)) return; - ivec g(v); int z = g[d]&(~(sel.grid-1)); g.add(sel.grid/2).mask(~(sel.grid-1)); g[d] = z; - r = (entselsnap ? g[R[d]] : v[R[d]]) - e.o[R[d]]; c = (entselsnap ? g[C[d]] : v[C[d]]) - e.o[C[d]]; ); - if(entmoving==1) makeundoent(); groupeditpure(e.o[R[d]] += r; e.o[C[d]] += c); entmoving = 2; @@ -549,13 +471,11 @@ void entdrag(const vec &ray) VAR(showentradius, 0, 1, 1); -void renderentring(const extentity &e, float radius, int axis) -{ +void renderentring(const extentity &e, float radius, int axis) { if(radius <= 0) return; gle::defvertex(); gle::begin(GL_LINE_LOOP); - loopi(15) - { + loopi(15) { vec p(e.o); const vec2 &sc = sincos360[i*(360/15)]; p[axis>=2 ? 1 : 0] += radius*sc.x; @@ -565,14 +485,12 @@ void renderentring(const extentity &e, float radius, int axis) xtraverts += gle::end(); } -void renderentsphere(const extentity &e, float radius) -{ +void renderentsphere(const extentity &e, float radius) { if(radius <= 0) return; loopk(3) renderentring(e, radius, k); } -void renderentattachment(const extentity &e) -{ +void renderentattachment(const extentity &e) { if(!e.attached) return; gle::defvertex(); gle::begin(GL_LINES); @@ -581,63 +499,50 @@ void renderentattachment(const extentity &e) xtraverts += gle::end(); } -void renderentarrow(const extentity &e, const vec &dir, float radius) -{ +void renderentarrow(const extentity &e, const vec &dir, float radius) { if(radius <= 0) return; float arrowsize = min(radius/8, 0.5f); vec target = vec(dir).mul(radius).add(e.o), arrowbase = vec(dir).mul(radius - arrowsize).add(e.o), spoke; spoke.orthogonal(dir); spoke.normalize(); spoke.mul(arrowsize); - gle::defvertex(); - gle::begin(GL_LINES); gle::attrib(e.o); gle::attrib(target); xtraverts += gle::end(); - gle::begin(GL_TRIANGLE_FAN); gle::attrib(target); loopi(5) gle::attrib(vec(spoke).rotate(2*M_PI*i/4.0f, dir).add(arrowbase)); xtraverts += gle::end(); } -void renderentcone(const extentity &e, const vec &dir, float radius, float angle) -{ +void renderentcone(const extentity &e, const vec &dir, float radius, float angle) { if(radius <= 0) return; vec spot = vec(dir).mul(radius*cosf(angle*RAD)).add(e.o), spoke; spoke.orthogonal(dir); spoke.normalize(); spoke.mul(radius*sinf(angle*RAD)); - gle::defvertex(); - gle::begin(GL_LINES); - loopi(8) - { + loopi(8) { gle::attrib(e.o); gle::attrib(vec(spoke).rotate(2*M_PI*i/8.0f, dir).add(spot)); } xtraverts += gle::end(); - gle::begin(GL_LINE_LOOP); loopi(8) gle::attrib(vec(spoke).rotate(2*M_PI*i/8.0f, dir).add(spot)); xtraverts += gle::end(); } -void renderentradius(extentity &e, bool color) -{ - switch(e.type) - { +void renderentradius(extentity &e, bool color) { + switch(e.type) { case ET_LIGHT: if(color) gle::colorf(e.attr2/255.0f, e.attr3/255.0f, e.attr4/255.0f); renderentsphere(e, e.attr1); break; - case ET_SPOTLIGHT: - if(e.attached) - { + if(e.attached) { if(color) gle::colorf(0, 1, 1); float radius = e.attached->attr1; if(!radius) radius = 2*e.o.dist(e.attached->o); @@ -647,15 +552,12 @@ void renderentradius(extentity &e, bool color) renderentcone(*e.attached, dir, radius, angle); } break; - case ET_SOUND: if(color) gle::colorf(0, 1, 1); renderentsphere(e, e.attr2); break; - case ET_MAPMODEL: - case ET_PLAYERSTART: - { + case ET_PLAYERSTART: { if(color) gle::colorf(0, 1, 1); entities::entradius(e, color); vec dir; @@ -663,10 +565,8 @@ void renderentradius(extentity &e, bool color) renderentarrow(e, dir, 4); break; } - default: - if(e.type>=ET_GAMESPECIFIC) - { + if(e.type>=ET_GAMESPECIFIC) { if(color) gle::colorf(0, 1, 1); entities::entradius(e, color); } @@ -674,22 +574,18 @@ void renderentradius(extentity &e, bool color) } } -static void renderentbox(const vec &eo, vec es) -{ +static void renderentbox(const vec &eo, vec es) { es.add(eo); - // bottom quad gle::attrib(eo.x, eo.y, eo.z); gle::attrib(es.x, eo.y, eo.z); gle::attrib(es.x, eo.y, eo.z); gle::attrib(es.x, es.y, eo.z); gle::attrib(es.x, es.y, eo.z); gle::attrib(eo.x, es.y, eo.z); gle::attrib(eo.x, es.y, eo.z); gle::attrib(eo.x, eo.y, eo.z); - // top quad gle::attrib(eo.x, eo.y, es.z); gle::attrib(es.x, eo.y, es.z); gle::attrib(es.x, eo.y, es.z); gle::attrib(es.x, es.y, es.z); gle::attrib(es.x, es.y, es.z); gle::attrib(eo.x, es.y, es.z); gle::attrib(eo.x, es.y, es.z); gle::attrib(eo.x, eo.y, es.z); - // sides gle::attrib(eo.x, eo.y, eo.z); gle::attrib(eo.x, eo.y, es.z); gle::attrib(es.x, eo.y, eo.z); gle::attrib(es.x, eo.y, es.z); @@ -697,13 +593,10 @@ static void renderentbox(const vec &eo, vec es) gle::attrib(eo.x, es.y, eo.z); gle::attrib(eo.x, es.y, es.z); } -void renderentselection(const vec &o, const vec &ray, bool entmoving) -{ +void renderentselection(const vec &o, bool entmoving) { if(noentedit()) return; vec eo, es; - - if(entgroup.length()) - { + if(entgroup.length()) { gle::colorub(0, 40, 0); gle::defvertex(); gle::begin(GL_LINES, entgroup.length()*24); @@ -713,14 +606,11 @@ void renderentselection(const vec &o, const vec &ray, bool entmoving) ); xtraverts += gle::end(); } - - if(enthover >= 0) - { + if(enthover >= 0) { gle::colorub(0, 40, 0); entfocus(enthover, entselectionbox(e, eo, es)); // also ensures enthover is back in focus boxs3D(eo, es, 1); - if(entmoving && entmovingshadow==1) - { + if(entmoving && entmovingshadow==1) { vec a, b; gle::colorub(20, 20, 20); (a = eo).x = eo.x - fmod(eo.x, worldsize); (b = es).x = a.x + worldsize; boxs3D(a, b, 1); @@ -731,9 +621,7 @@ void renderentselection(const vec &o, const vec &ray, bool entmoving) boxs(entorient, eo, es); boxs(entorient, eo, es, clamp(0.015f*camera1->o.dist(eo)*tan(fovy*0.5f*RAD), 0.1f, 1.0f)); } - - if(showentradius && (entgroup.length() || enthover >= 0)) - { + if(showentradius && (entgroup.length() || enthover >= 0)) { glDepthFunc(GL_GREATER); gle::colorf(0.25f, 0.25f, 0.25f); loopv(entgroup) entfocus(entgroup[i], renderentradius(e, false)); @@ -744,8 +632,7 @@ void renderentselection(const vec &o, const vec &ray, bool entmoving) } } -bool enttoggle(int id) -{ +bool enttoggle(int id) { undonext = true; int i = entgroup.find(id); if(i < 0) @@ -755,8 +642,7 @@ bool enttoggle(int id) return i < 0; } -bool hoveringonent(int ent, int orient) -{ +bool hoveringonent(int ent, int orient) { if(noentedit()) return false; entorient = orient; if((efocus = enthover = ent) >= 0) @@ -768,28 +654,22 @@ bool hoveringonent(int ent, int orient) VAR(entitysurf, 0, 0, 1); -ICOMMAND(entadd, "", (), -{ - if(enthover >= 0 && !noentedit()) - { +ICOMMAND(entadd, "", (), { + if(enthover >= 0 && !noentedit()) { if(entgroup.find(enthover) < 0) entadd(enthover); if(entmoving > 1) entmoving = 1; } }); -ICOMMAND(enttoggle, "", (), -{ +ICOMMAND(enttoggle, "", (), { if(enthover < 0 || noentedit() || !enttoggle(enthover)) { entmoving = 0; intret(0); } else { if(entmoving > 1) entmoving = 1; intret(1); } }); -ICOMMAND(entmoving, "b", (int *n), -{ - if(*n >= 0) - { +ICOMMAND(entmoving, "b", (int *n), { + if(*n >= 0) { if(!*n || enthover < 0 || noentedit()) entmoving = 0; - else - { + else { if(entgroup.find(enthover) < 0) { entadd(enthover); entmoving = 1; } else if(!entmoving) entmoving = 1; } @@ -797,27 +677,23 @@ ICOMMAND(entmoving, "b", (int *n), intret(entmoving); }); -void entpush(int *dir) -{ +void entpush(int *dir) { if(noentedit()) return; int d = dimension(entorient); int s = dimcoord(entorient) ? -*dir : *dir; - if(entmoving) - { + if(entmoving) { groupeditpure(e.o[d] += float(s*sel.grid)); // editdrag supplies the undo } else groupedit(e.o[d] += float(s*sel.grid)); - if(entitysurf==1) - { + if(entitysurf==1) { player->o[d] += float(s*sel.grid); player->resetinterp(); } } VAR(entautoviewdist, 0, 25, 100); -void entautoview(int *dir) -{ +void entautoview(int *dir) { if(!haveselent()) return; static int s = 0; vec v(player->o); @@ -839,15 +715,13 @@ COMMAND(entflip, ""); COMMAND(entrotate, "i"); COMMAND(entpush, "i"); -void delent() -{ +void delent() { if(noentedit()) return; groupedit(e.type = ET_EMPTY;); entcancel(); } -int findtype(char *what) -{ +int findtype(char *what) { for(int i = 0; *entities::entname(i); i++) if(strcmp(what, entities::entname(i))==0) return i; conoutf(CON_ERROR, "unknown entity type \"%s\"", what); return ET_EMPTY; @@ -855,15 +729,12 @@ int findtype(char *what) VAR(entdrop, 0, 2, 3); -bool dropentity(entity &e, int drop = -1) -{ +bool dropentity(entity &e, int drop = -1) { vec radius(4.0f, 4.0f, 4.0f); if(drop<0) drop = entdrop; - if(e.type == ET_MAPMODEL) - { + if(e.type == ET_MAPMODEL) { model *m = loadmapmodel(e.attr2); - if(m) - { + if(m) { vec center; mmboundbox(e, m, center, radius); radius.x += fabs(center.x); @@ -871,8 +742,7 @@ bool dropentity(entity &e, int drop = -1) } radius.z = 0.0f; } - switch(drop) - { + switch(drop) { case 1: if(e.type != ET_LIGHT && e.type != ET_SPOTLIGHT) dropenttofloor(&e); @@ -880,8 +750,7 @@ bool dropentity(entity &e, int drop = -1) case 2: case 3: int cx = 0, cy = 0; - if(sel.cxs == 1 && sel.cys == 1) - { + if(sel.cxs == 1 && sel.cys == 1) { cx = (sel.cx ? 1 : -1) * sel.grid / 2; cy = (sel.cy ? 1 : -1) * sel.grid / 2; } @@ -893,7 +762,6 @@ bool dropentity(entity &e, int drop = -1) e.o[D[d]] -= radius[D[d]]; else e.o[D[d]] += sel.grid + radius[D[d]]; - if(drop == 3) dropenttofloor(&e); break; @@ -901,14 +769,12 @@ bool dropentity(entity &e, int drop = -1) return true; } -void dropent() -{ +void dropent() { if(noentedit()) return; groupedit(dropentity(e)); } -void attachent() -{ +void attachent() { if(noentedit()) return; groupedit(attachentity(e)); } @@ -919,11 +785,9 @@ VARP(entcamdir, 0, 1, 1); static int keepents = 0; -extentity *newentity(bool local, const vec &o, int type, int v1, int v2, int v3, int v4, int v5, int &idx) -{ +extentity *newentity(bool local, const vec &o, int type, int v1, int v2, int v3, int v4, int v5, int &idx) { vector &ents = entities::getents(); - if(local) - { + if(local) { idx = -1; for(int i = keepents; i < ents.length(); i++) if(ents[i]->type == ET_EMPTY) { idx = i; break; } if(idx < 0 && ents.length() >= MAXENTS) { conoutf(CON_ERROR, "too many entities"); return NULL; } @@ -940,10 +804,8 @@ extentity *newentity(bool local, const vec &o, int type, int v1, int v2, int v3, e.reserved = 0; e.light.color = vec(1, 1, 1); e.light.dir = vec(0, 0, 1); - if(local) - { - if(entcamdir) switch(type) - { + if(local) { + if(entcamdir) switch(type) { case ET_MAPMODEL: case ET_PLAYERSTART: e.attr5 = e.attr4; @@ -960,8 +822,7 @@ extentity *newentity(bool local, const vec &o, int type, int v1, int v2, int v3, return &e; } -void newentity(int type, int a1, int a2, int a3, int a4, int a5) -{ +void newentity(int type, int a1, int a2, int a3, int a4, int a5) { int idx; extentity *t = newentity(true, player->o, type, a1, a2, a3, a4, a5, idx); if(!t) return; @@ -972,8 +833,7 @@ void newentity(int type, int a1, int a2, int a3, int a4, int a5) entedit(idx, e.type = type); } -void newent(char *what, int *a1, int *a2, int *a3, int *a4, int *a5) -{ +void newent(char *what, int *a1, int *a2, int *a3, int *a4, int *a5) { if(noentedit()) return; int type = findtype(what); if(type != ET_EMPTY) @@ -983,8 +843,7 @@ void newent(char *what, int *a1, int *a2, int *a3, int *a4, int *a5) int entcopygrid; vector entcopybuf; -void entcopy() -{ +void entcopy() { if(noentedit()) return; entcopygrid = sel.grid; entcopybuf.shrink(0); @@ -992,14 +851,12 @@ void entcopy() entfocus(entgroup[i], entcopybuf.add(e).o.sub(vec(sel.o))); } -void entpaste() -{ +void entpaste() { if(noentedit()) return; if(entcopybuf.length()==0) return; entcancel(); float m = float(sel.grid)/float(entcopygrid); - loopv(entcopybuf) - { + loopv(entcopybuf) { entity &c = entcopybuf[i]; vec o(c.o); o.mul(m).add(vec(sel.o)); @@ -1020,8 +877,7 @@ COMMAND(dropent, ""); COMMAND(entcopy, ""); COMMAND(entpaste, ""); -void entset(char *what, int *a1, int *a2, int *a3, int *a4, int *a5) -{ +void entset(char *what, int *a1, int *a2, int *a3, int *a4, int *a5) { if(noentedit()) return; int type = findtype(what); if(type != ET_EMPTY) @@ -1033,14 +889,11 @@ void entset(char *what, int *a1, int *a2, int *a3, int *a4, int *a5) e.attr5=*a5); } -void printent(extentity &e, char *buf, int len) -{ - switch(e.type) - { +void printent(extentity &e, char *buf, int len) { + switch(e.type) { case ET_PARTICLES: if(printparticles(e, buf, len)) return; break; - default: if(e.type >= ET_GAMESPECIFIC && entities::printent(e, buf, len)) return; break; @@ -1048,19 +901,16 @@ void printent(extentity &e, char *buf, int len) nformatstring(buf, len, "%s %d %d %d %d %d", entities::entname(e.type), e.attr1, e.attr2, e.attr3, e.attr4, e.attr5); } -void nearestent() -{ +void nearestent() { if(noentedit()) return; int closest = -1; float closedist = 1e16f; vector &ents = entities::getents(); - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; if(e.type == ET_EMPTY) continue; float dist = e.o.dist(player->o); - if(dist < closedist) - { + if(dist < closedist) { closest = i; closedist = dist; } @@ -1077,27 +927,21 @@ ICOMMAND(entindex, "", (), intret(efocus)); COMMAND(entset, "siiiii"); COMMAND(nearestent, ""); -void enttype(char *type, int *numargs) -{ - if(*numargs >= 1) - { +void enttype(char *type, int *numargs) { + if(*numargs >= 1) { int typeidx = findtype(type); if(typeidx != ET_EMPTY) groupedit(e.type = typeidx); } - else entfocus(efocus, - { + else entfocus(efocus, { result(entities::entname(e.type)); }) } -void entattr(int *attr, int *val, int *numargs) -{ - if(*numargs >= 2) - { +void entattr(int *attr, int *val, int *numargs) { + if(*numargs >= 2) { if(*attr >= 0 && *attr <= 4) groupedit( - switch(*attr) - { + switch(*attr) { case 0: e.attr1 = *val; break; case 1: e.attr2 = *val; break; case 2: e.attr3 = *val; break; @@ -1106,10 +950,8 @@ void entattr(int *attr, int *val, int *numargs) } ); } - else entfocus(efocus, - { - switch(*attr) - { + else entfocus(efocus, { + switch(*attr) { case 0: intret(e.attr1); break; case 1: intret(e.attr2); break; case 2: intret(e.attr3); break; @@ -1122,18 +964,15 @@ void entattr(int *attr, int *val, int *numargs) COMMAND(enttype, "sN"); COMMAND(entattr, "iiN"); -int findentity(int type, int index, int attr1, int attr2) -{ +int findentity(int type, int index, int attr1, int attr2) { const vector &ents = entities::getents(); if(index > ents.length()) index = ents.length(); - else for(int i = index; i &spawninfos) -{ +float gatherspawninfos(dynent *d, int tag, vector &spawninfos) { const vector &ents = entities::getents(); float total = 0.0f; - loopv(ents) - { + loopv(ents) { const extentity &e = *ents[i]; if(e.type != ET_PLAYERSTART || e.attr2 != tag) continue; spawninfo &s = spawninfos.add(); @@ -1164,12 +1001,10 @@ float gatherspawninfos(dynent *d, int tag, vector &spawninfos) // Randomly picks a weighted spawn from the provided vector and removes it. // The probability of a given spawn being picked is proportional to its weight. // If all weights are zero, the index is picked uniformly. -static const extentity *poprandomspawn(vector &spawninfos, float &total) -{ +static const extentity *poprandomspawn(vector &spawninfos, float &total) { if(spawninfos.empty()) return NULL; int index = 0; - if(total > 0.0f) - { + if(total > 0.0f) { float x = rndscale(total); do x -= spawninfos[index].weight; while(x > 0 && ++index < spawninfos.length()-1); } @@ -1179,15 +1014,13 @@ static const extentity *poprandomspawn(vector &spawninfos, float &tot return s.e; } -static inline bool tryspawn(dynent *d, const extentity &e) -{ +static inline bool tryspawn(dynent *d, const extentity &e) { d->o = e.o; d->yaw = e.attr1; return entinmap(d, true); } -void findplayerspawn(dynent *d, int forceent, int tag) -{ +void findplayerspawn(dynent *d, int forceent, int tag) { const vector &ents = entities::getents(); d->pitch = 0; d->roll = 0; @@ -1200,18 +1033,15 @@ void findplayerspawn(dynent *d, int forceent, int tag) entinmap(d); } -void splitocta(cube *c, int size) -{ +void splitocta(cube *c, int size) { if(size <= 0x1000) return; - loopi(8) - { + loopi(8) { if(!c[i].children) c[i].children = newcubes(isempty(c[i]) ? F_EMPTY : F_SOLID); splitocta(c[i].children, size>>1); } } -void resetmap() -{ +void resetmap() { clearoverrides(); clearmapsounds(); resetlightmaps(); @@ -1222,101 +1052,74 @@ void resetmap() cancelsel(); pruneundos(); clearmapcrc(); - entities::clearents(); outsideents.setsize(0); } -void startmap(const char *name) -{ +void startmap(const char *name) { game::startmap(name); } -bool emptymap(int scale, bool force, const char *mname, bool usecfg) // main empty world creation routine -{ - if(!force && !editmode) - { +bool emptymap(int scale, bool force, const char *mname, bool usecfg) { // main empty world creation routine { + if(!force && !editmode) { conoutf(CON_ERROR, "newmap only allowed in edit mode"); return false; } - resetmap(); - setvar("mapscale", scale<10 ? 10 : (scale>16 ? 16 : scale), true, false); setvar("mapsize", 1< 0x1000) splitocta(worldroot, worldsize>>1); - clearmainmenu(); - - if(usecfg) - { + if(usecfg) { identflags |= IDF_OVERRIDDEN; execfile("data/default_map.cfg", false); identflags &= ~IDF_OVERRIDDEN; } - initlights(); allchanged(true); - startmap(mname); - return true; } -bool enlargemap(bool force) -{ - if(!force && !editmode) - { +bool enlargemap(bool force) { + if(!force && !editmode) { conoutf(CON_ERROR, "mapenlarge only allowed in edit mode"); return false; } if(worldsize >= 1<<16) return false; - while(outsideents.length()) removeentity(outsideents.pop()); - worldscale++; worldsize *= 2; cube *c = newcubes(F_EMPTY); c[0].children = worldroot; loopi(3) solidfaces(c[i+1]); worldroot = c; - if(worldsize > 0x1000) splitocta(worldroot, worldsize>>1); - allchanged(); - return true; } -static bool isallempty(cube &c) -{ +static bool isallempty(cube &c) { if(!c.children) return isempty(c); loopi(8) if(!isallempty(c.children[i])) return false; return true; } -void shrinkmap() -{ +void shrinkmap() { extern int nompedit; if(noedit(true) || (nompedit && multiplayer())) return; if(worldsize <= 1<<10) return; - int octant = -1; - loopi(8) if(!isallempty(worldroot[i])) - { + loopi(8) if(!isallempty(worldroot[i])) { if(octant >= 0) return; octant = i; } if(octant < 0) return; - while(outsideents.length()) removeentity(outsideents.pop()); - if(!worldroot[octant].children) subdividecube(worldroot[octant], false, false); cube *root = worldroot[octant].children; worldroot[octant].children = NULL; @@ -1324,13 +1127,10 @@ void shrinkmap() worldroot = root; worldscale--; worldsize /= 2; - ivec offset(octant, ivec(0, 0, 0), worldsize); vector &ents = entities::getents(); loopv(ents) ents[i]->o.sub(vec(offset)); - allchanged(); - conoutf("shrunk map to size %d", worldscale); } @@ -1340,26 +1140,22 @@ COMMAND(newmap, "i"); COMMAND(mapenlarge, ""); COMMAND(shrinkmap, ""); -void mapname() -{ +void mapname() { result(game::getclientmap()); } COMMAND(mapname, ""); -void mpeditent(int i, const vec &o, int type, int attr1, int attr2, int attr3, int attr4, int attr5, bool local) -{ +void mpeditent(int i, const vec &o, int type, int attr1, int attr2, int attr3, int attr4, int attr5, bool local) { if(i < 0 || i >= MAXENTS) return; vector &ents = entities::getents(); - if(ents.length()<=i) - { + if(ents.length()<=i) { extentity *e = newentity(local, o, type, attr1, attr2, attr3, attr4, attr5, i); if(!e) return; addentity(i); attachentity(*e); } - else - { + else { extentity &e = *ents[i]; removeentity(i); int oldtype = e.type; diff --git a/src/engine/world.h b/src/engine/world.h index 43ec470..91812b4 100644 --- a/src/engine/world.h +++ b/src/engine/world.h @@ -1,12 +1,10 @@ -enum // hardcoded texture numbers -{ +enum { // hardcoded texture numbers { DEFAULT_GEOM }; #define MAPVERSION 34 // bump if map format changes, see worldio.cpp -struct octaheader -{ +struct octaheader { char magic[4]; // "OCTA" int version; // any >8bit quantity is little endian int headersize; // sizeof(header) @@ -18,8 +16,7 @@ struct octaheader int numvslots; }; -enum -{ +enum { MATSURF_NOT_VISIBLE = 0, MATSURF_VISIBLE, MATSURF_EDIT_ONLY @@ -28,4 +25,3 @@ enum #define TEX_SCALE 8.0f struct vertex { vec pos; bvec4 norm; vec2 tc; svec2 lm; bvec4 tangent; }; - diff --git a/src/engine/worldio.cpp b/src/engine/worldio.cpp index 4e309a8..898b2bb 100644 --- a/src/engine/worldio.cpp +++ b/src/engine/worldio.cpp @@ -2,12 +2,10 @@ #include "engine.h" -void validmapname(char *dst, const char *src, const char *prefix = NULL, const char *alt = "untitled", size_t maxlen = 100) -{ +void validmapname(char *dst, const char *src, const char *prefix = NULL, const char *alt = "untitled", size_t maxlen = 100) { if(prefix) while(*prefix) *dst++ = *prefix++; const char *start = dst; - if(src) loopi(maxlen) - { + if(src) loopi(maxlen) { char c = *src++; if(iscubealnum(c) || c == '_' || c == '-' || c == '/' || c == '\\') *dst++ = c; else break; @@ -16,32 +14,27 @@ void validmapname(char *dst, const char *src, const char *prefix = NULL, const c else if(dst != alt) copystring(dst, alt, maxlen); } -void fixmapname(char *name) -{ +void fixmapname(char *name) { validmapname(name, name, NULL, ""); } -void getmapfilenames(const char *fname, const char *cname, char *pakname, char *mapname, char *cfgname) -{ +void getmapfilenames(const char *fname, const char *cname, char *pakname, char *mapname, char *cfgname) { if(!cname) cname = fname; string name; validmapname(name, cname); char *slash = strpbrk(name, "/\\"); - if(slash) - { + if(slash) { copystring(pakname, name, slash-name+1); copystring(cfgname, slash+1, MAXSTRLEN); } - else - { + else { copystring(pakname, "maps", MAXSTRLEN); copystring(cfgname, name, MAXSTRLEN); } validmapname(mapname, fname, strpbrk(fname, "/\\") ? NULL : "maps/"); } -bool loadents(const char *fname, vector &ents, uint *crc) -{ +bool loadents(const char *fname, vector &ents, uint *crc) { string pakname, mapname, mcfgname, ogzname; getmapfilenames(fname, NULL, pakname, mapname, mcfgname); formatstring(ogzname, "packages/%s.ogz", mapname); @@ -53,21 +46,16 @@ bool loadents(const char *fname, vector &ents, uint *crc) lilswap(&hdr.version, 6); if(memcmp(hdr.magic, "OCTA", 4) || hdr.worldsize <= 0|| hdr.numents < 0) { conoutf(CON_ERROR, "map %s has malformatted header", ogzname); delete f; return false; } if(hdr.version>MAPVERSION) { conoutf(CON_ERROR, "map %s requires a newer version of Cube 2: Sauerbraten", ogzname); delete f; return false; } - lilswap(&hdr.numvslots, 1); - - loopi(hdr.numvars) - { + loopi(hdr.numvars) { int type = f->getchar(), ilen = f->getlil(); f->seek(ilen, SEEK_CUR); - switch(type) - { + switch(type) { case ID_VAR: f->getlil(); break; case ID_FVAR: f->getlil(); break; case ID_SVAR: { int slen = f->getlil(); f->seek(slen, SEEK_CUR); break; } } } - string gametype; copystring(gametype, "fps"); int eif = 0; @@ -76,32 +64,24 @@ bool loadents(const char *fname, vector &ents, uint *crc) eif = f->getlil(); int extrasize = f->getlil(); f->seek(extrasize, SEEK_CUR); - ushort nummru = f->getlil(); f->seek(nummru*sizeof(ushort), SEEK_CUR); - - loopi(min(hdr.numents, MAXENTS)) - { + loopi(min(hdr.numents, MAXENTS)) { entity &e = ents.add(); f->read(&e, sizeof(entity)); lilswap(&e.o.x, 3); lilswap(&e.attr1, 5); if(eif > 0) f->seek(eif, SEEK_CUR); - if(e.type>=ET_GAMESPECIFIC) - { + if(e.type>=ET_GAMESPECIFIC) { ents.pop(); continue; } } - - if(crc) - { + if(crc) { f->seek(0, SEEK_END); *crc = f->getcrc(); } - delete f; - return true; } @@ -110,25 +90,21 @@ string ogzname, bakname, cfgname, picname; VARP(savebak, 0, 2, 2); -void setmapfilenames(const char *fname, const char *cname = NULL) -{ +void setmapfilenames(const char *fname, const char *cname = NULL) { string pakname, mapname, mcfgname; getmapfilenames(fname, cname, pakname, mapname, mcfgname); - formatstring(ogzname, "packages/%s.ogz", mapname); if(savebak==1) formatstring(bakname, "packages/%s.BAK", mapname); else formatstring(bakname, "packages/%s_%d.BAK", mapname, totalmillis); formatstring(cfgname, "packages/%s/%s.cfg", pakname, mcfgname); formatstring(picname, "packages/%s.png", mapname); - path(ogzname); path(bakname); path(cfgname); path(picname); } -void mapcfgname() -{ +void mapcfgname() { const char *mname = game::getclientmap(); string pakname, mapname, mcfgname; getmapfilenames(mname, NULL, pakname, mapname, mcfgname); @@ -139,8 +115,7 @@ void mapcfgname() COMMAND(mapcfgname, ""); -void backup(char *name, char *backupname) -{ +void backup(char *name, char *backupname) { string backupfile; copystring(backupfile, findfile(backupname, "wb")); remove(backupfile); @@ -151,30 +126,22 @@ enum { OCTSAV_CHILDREN = 0, OCTSAV_EMPTY, OCTSAV_SOLID, OCTSAV_NORMAL, OCTSAV_LO static int savemapprogress = 0; -void savec(cube *c, const ivec &o, int size, stream *f, bool nolms) -{ +void savec(cube *c, const ivec &o, int size, stream *f, bool nolms) { if((savemapprogress++&0xFFF)==0) renderprogress(float(savemapprogress)/allocnodes, "saving octree..."); - - loopi(8) - { + loopi(8) { ivec co(i, o, size); - if(c[i].children) - { + if(c[i].children) { f->putchar(OCTSAV_CHILDREN); savec(c[i].children, co, size>>1, f, nolms); } - else - { + else { int oflags = 0, surfmask = 0, totalverts = 0; if(c[i].material!=MAT_AIR) oflags |= 0x40; if(isempty(c[i])) f->putchar(oflags | OCTSAV_EMPTY); - else - { - if(!nolms) - { + else { + if(!nolms) { if(c[i].merged) oflags |= 0x80; - if(c[i].ext) loopj(6) - { + if(c[i].ext) loopj(6) { const surfaceinfo &surf = c[i].ext->surfaces[j]; if(!surf.used()) continue; oflags |= 0x20; @@ -182,34 +149,26 @@ void savec(cube *c, const ivec &o, int size, stream *f, bool nolms) totalverts += surf.totalverts(); } } - if(isentirelysolid(c[i])) f->putchar(oflags | OCTSAV_SOLID); - else - { + else { f->putchar(oflags | OCTSAV_NORMAL); f->write(c[i].edges, 12); } } - loopj(6) f->putlil(c[i].texture[j]); - if(oflags&0x40) f->putlil(c[i].material); if(oflags&0x80) f->putchar(c[i].merged); - if(oflags&0x20) - { + if(oflags&0x20) { f->putchar(surfmask); f->putchar(totalverts); - loopj(6) if(surfmask&(1<surfaces[j]; vertinfo *verts = c[i].ext->verts() + surf.verts; int layerverts = surf.numverts&MAXFACEVERTS, numverts = surf.totalverts(), vertmask = 0, vertorder = 0, uvorder = 0, dim = dimension(j), vc = C[dim], vr = R[dim]; - if(numverts) - { - if(c[i].merged&(1<write(&surf, sizeof(surfaceinfo)); bool hasxyz = (vertmask&0x04)!=0, hasuv = (vertmask&0x40)!=0, hasnorm = (vertmask&0x80)!=0; - if(layerverts == 4) - { - if(hasxyz && vertmask&0x01) - { + if(layerverts == 4) { + if(hasxyz && vertmask&0x01) { ivec v0 = verts[vertorder].getxyz(), v2 = verts[(vertorder+2)&3].getxyz(); f->putlil(v0[vc]); f->putlil(v0[vr]); f->putlil(v2[vc]); f->putlil(v2[vr]); hasxyz = false; } - if(hasuv && vertmask&0x02) - { + if(hasuv && vertmask&0x02) { const vertinfo &v0 = verts[uvorder], &v2 = verts[(uvorder+2)&3]; f->putlil(v0.u); f->putlil(v0.v); f->putlil(v2.u); f->putlil(v2.v); @@ -287,19 +240,16 @@ void savec(cube *c, const ivec &o, int size, stream *f, bool nolms) } } if(hasnorm && vertmask&0x08) { f->putlil(verts[0].norm); hasnorm = false; } - if(hasxyz || hasuv || hasnorm) loopk(layerverts) - { + if(hasxyz || hasuv || hasnorm) loopk(layerverts) { const vertinfo &v = verts[(k+vertorder)%layerverts]; - if(hasxyz) - { + if(hasxyz) { ivec xyz = v.getxyz(); f->putlil(xyz[vc]); f->putlil(xyz[vr]); } if(hasuv) { f->putlil(v.u); f->putlil(v.v); } if(hasnorm) f->putlil(v.norm); } - if(surf.numverts&LAYER_DUP) loopk(layerverts) - { + if(surf.numverts&LAYER_DUP) loopk(layerverts) { const vertinfo &v = verts[layerverts + (k+vertorder)%layerverts]; if(hasuv) { f->putlil(v.u); f->putlil(v.v); } } @@ -309,36 +259,30 @@ void savec(cube *c, const ivec &o, int size, stream *f, bool nolms) } } -struct surfacecompat -{ +struct surfacecompat { uchar texcoords[8]; uchar w, h; ushort x, y; uchar lmid, layer; }; -struct normalscompat -{ +struct normalscompat { bvec normals[4]; }; -struct mergecompat -{ +struct mergecompat { ushort u1, u2, v1, v2; }; cube *loadchildren(stream *f, const ivec &co, int size, bool &failed); -void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) -{ +void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) { bool haschildren = false; int octsav = f->getchar(); - switch(octsav&0x7) - { + switch(octsav&0x7) { case OCTSAV_CHILDREN: c.children = loadchildren(f, co, size>>1, failed); return; - case OCTSAV_LODCUBE: haschildren = true; break; case OCTSAV_EMPTY: emptyfaces(c); break; case OCTSAV_SOLID: solidfaces(c); break; @@ -346,12 +290,10 @@ void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) default: failed = true; return; } loopi(6) c.texture[i] = mapversion<14 ? f->getchar() : f->getlil(); - - { + { if(octsav&0x40) c.material = f->getlil(); if(octsav&0x80) c.merged = f->getchar(); - if(octsav&0x20) - { + if(octsav&0x20) { int surfmask, totalverts; surfmask = f->getchar(); totalverts = max(f->getchar(), 0); @@ -359,8 +301,7 @@ void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) memset(c.ext->surfaces, 0, sizeof(c.ext->surfaces)); memset(c.ext->verts(), 0, totalverts*sizeof(vertinfo)); int offset = 0; - loopi(6) if(surfmask&(1<surfaces[i]; f->read(&surf, sizeof(surfaceinfo)); int vertmask = surf.verts, numverts = surf.totalverts(); @@ -372,25 +313,21 @@ void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) int layerverts = surf.numverts&MAXFACEVERTS, dim = dimension(i), vc = C[dim], vr = R[dim], bias = 0; genfaceverts(c, i, v); bool hasxyz = (vertmask&0x04)!=0, hasuv = (vertmask&0x40)!=0, hasnorm = (vertmask&0x80)!=0; - if(hasxyz) - { + if(hasxyz) { ivec e1, e2, e3; n.cross((e1 = v[1]).sub(v[0]), (e2 = v[2]).sub(v[0])); if(n.iszero()) n.cross(e2, (e3 = v[3]).sub(v[0])); bias = -n.dot(ivec(v[0]).mul(size).add(vo)); } - else - { + else { int vis = layerverts < 4 ? (vertmask&0x02 ? 2 : 1) : 3, order = vertmask&0x01 ? 1 : 0, k = 0; verts[k++].setxyz(v[order].mul(size).add(vo)); if(vis&1) verts[k++].setxyz(v[order+1].mul(size).add(vo)); verts[k++].setxyz(v[order+2].mul(size).add(vo)); if(vis&2) verts[k++].setxyz(v[(order+3)&3].mul(size).add(vo)); } - if(layerverts == 4) - { - if(hasxyz && vertmask&0x01) - { + if(layerverts == 4) { + if(hasxyz && vertmask&0x01) { ushort c1 = f->getlil(), r1 = f->getlil(), c2 = f->getlil(), r2 = f->getlil(); ivec xyz; xyz[vc] = c1; xyz[vr] = r1; xyz[dim] = n[dim] ? -(bias + n[vc]*xyz[vc] + n[vr]*xyz[vr])/n[dim] : vo[dim]; @@ -403,16 +340,14 @@ void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) verts[3].setxyz(xyz); hasxyz = false; } - if(hasuv && vertmask&0x02) - { + if(hasuv && vertmask&0x02) { int uvorder = (vertmask&0x30)>>4; vertinfo &v0 = verts[uvorder], &v1 = verts[(uvorder+1)&3], &v2 = verts[(uvorder+2)&3], &v3 = verts[(uvorder+3)&3]; v0.u = f->getlil(); v0.v = f->getlil(); v2.u = f->getlil(); v2.v = f->getlil(); v1.u = v0.u; v1.v = v2.v; v3.u = v2.u; v3.v = v0.v; - if(surf.numverts&LAYER_DUP) - { + if(surf.numverts&LAYER_DUP) { vertinfo &b0 = verts[4+uvorder], &b1 = verts[4+((uvorder+1)&3)], &b2 = verts[4+((uvorder+2)&3)], &b3 = verts[4+((uvorder+3)&3)]; b0.u = f->getlil(); b0.v = f->getlil(); b2.u = f->getlil(); b2.v = f->getlil(); @@ -422,17 +357,14 @@ void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) hasuv = false; } } - if(hasnorm && vertmask&0x08) - { + if(hasnorm && vertmask&0x08) { ushort norm = f->getlil(); loopk(layerverts) verts[k].norm = norm; hasnorm = false; } - if(hasxyz || hasuv || hasnorm) loopk(layerverts) - { + if(hasxyz || hasuv || hasnorm) loopk(layerverts) { vertinfo &v = verts[k]; - if(hasxyz) - { + if(hasxyz) { ivec xyz; xyz[vc] = f->getlil(); xyz[vr] = f->getlil(); xyz[dim] = n[dim] ? -(bias + n[vc]*xyz[vc] + n[vr]*xyz[vr])/n[dim] : vo[dim]; @@ -441,8 +373,7 @@ void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) if(hasuv) { v.u = f->getlil(); v.v = f->getlil(); } if(hasnorm) v.norm = f->getlil(); } - if(surf.numverts&LAYER_DUP) loopk(layerverts) - { + if(surf.numverts&LAYER_DUP) loopk(layerverts) { vertinfo &v = verts[k+layerverts], &t = verts[k]; v.setxyz(t.x, t.y, t.z); if(hasuv) { v.u = f->getlil(); v.v = f->getlil(); } @@ -451,30 +382,24 @@ void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) } } } - c.children = (haschildren ? loadchildren(f, co, size>>1, failed) : NULL); } -cube *loadchildren(stream *f, const ivec &co, int size, bool &failed) -{ +cube *loadchildren(stream *f, const ivec &co, int size, bool &failed) { cube *c = newcubes(); - loopi(8) - { + loopi(8) { loadc(f, c[i], ivec(i, co, size), size, failed); if(failed) break; } return c; } -void savevslot(stream *f, VSlot &vs, int prev) -{ +void savevslot(stream *f, VSlot &vs, int prev) { f->putlil(vs.changed); f->putlil(prev); - if(vs.changed & (1<putlil(vs.params.length()); - loopv(vs.params) - { + loopv(vs.params) { SlotShaderParam &p = vs.params[i]; f->putlil(strlen(p.name)); f->write(p.name, strlen(p.name)); @@ -483,39 +408,32 @@ void savevslot(stream *f, VSlot &vs, int prev) } if(vs.changed & (1<putlil(vs.scale); if(vs.changed & (1<putlil(vs.rotation); - if(vs.changed & (1<putlil(vs.offset.x); f->putlil(vs.offset.y); } - if(vs.changed & (1<putlil(vs.scroll.x); f->putlil(vs.scroll.y); } if(vs.changed & (1<putlil(vs.layer); - if(vs.changed & (1<putlil(vs.alphafront); f->putlil(vs.alphaback); } - if(vs.changed & (1<putlil(vs.colorscale[k]); } } -void savevslots(stream *f, int numvslots) -{ +void savevslots(stream *f, int numvslots) { if(vslots.empty()) return; int *prev = new int[numvslots]; for(int i=0;ichanged) continue; - for(;;) - { + for(;;) { VSlot *cur = vs; do vs = vs->next; while(vs && vs->index >= numvslots); if(!vs) break; @@ -523,8 +441,7 @@ void savevslots(stream *f, int numvslots) } } int lastroot = 0; - loopi(numvslots) - { + loopi(numvslots) { VSlot &vs = *vslots[i]; if(!vs.changed) continue; if(lastroot < i) f->putlil(-(i - lastroot)); @@ -535,15 +452,12 @@ void savevslots(stream *f, int numvslots) delete[] prev; } -void loadvslot(stream *f, VSlot &vs, int changed) -{ +void loadvslot(stream *f, VSlot &vs, int changed) { vs.changed = changed; - if(vs.changed & (1<getlil(); string name; - loopi(numparams) - { + loopi(numparams) { SlotShaderParam &p = vs.params.add(); int nlen = f->getlil(); f->read(name, min(nlen, MAXSTRLEN-1)); @@ -556,43 +470,35 @@ void loadvslot(stream *f, VSlot &vs, int changed) } if(vs.changed & (1<getlil(); if(vs.changed & (1<getlil(), 0, 7); - if(vs.changed & (1<getlil(); vs.offset.y = f->getlil(); } - if(vs.changed & (1<getlil(); vs.scroll.y = f->getlil(); } if(vs.changed & (1<getlil(); - if(vs.changed & (1<getlil(); vs.alphaback = f->getlil(); } - if(vs.changed & (1<getlil(); } } -void loadvslots(stream *f, int numvslots) -{ +void loadvslots(stream *f, int numvslots) { int *prev = new (false) int[numvslots]; if(!prev) return; for(int i=0;i 0) - { + while(numvslots > 0) { int changed = f->getlil(); - if(changed < 0) - { + if(changed < 0) { loopi(-changed) vslots.add(new VSlot(NULL, vslots.length())); numvslots += changed; } - else - { + else { prev[vslots.length()] = f->getlil(); loadvslot(f, *vslots.add(new VSlot(NULL, vslots.length())), changed); numvslots--; @@ -602,24 +508,19 @@ void loadvslots(stream *f, int numvslots) delete[] prev; } -bool save_world(const char *mname, bool nolms) -{ +bool save_world(const char *mname, bool nolms) { if(!*mname) mname = game::getclientmap(); setmapfilenames(mname); if(savebak) backup(ogzname, bakname); stream *f = opengzfile(ogzname, "wb"); if(!f) { conoutf(CON_WARN, "could not write map to %s", ogzname); return false; } - int numvslots = vslots.length(); - if(!nolms && !multiplayer(false)) - { + if(!nolms && !multiplayer(false)) { numvslots = compactvslots(); allchanged(); } - savemapprogress = 0; renderprogress(0, "saving map..."); - octaheader hdr; memcpy(hdr.magic, "OCTA", 4); hdr.version = MAPVERSION; @@ -632,36 +533,29 @@ bool save_world(const char *mname, bool nolms) hdr.lightmaps = nolms ? 0 : lightmaps.length(); hdr.numvars = 0; hdr.numvslots = numvslots; - enumerate(idents, ident, id, - { + enumerate(idents, ident, id, { if((id.type == ID_VAR || id.type == ID_FVAR || id.type == ID_SVAR) && id.flags&IDF_OVERRIDE && !(id.flags&IDF_READONLY) && id.flags&IDF_OVERRIDDEN) hdr.numvars++; }); lilswap(&hdr.version, 9); f->write(&hdr, sizeof(hdr)); - - enumerate(idents, ident, id, - { + enumerate(idents, ident, id, { if((id.type!=ID_VAR && id.type!=ID_FVAR && id.type!=ID_SVAR) || !(id.flags&IDF_OVERRIDE) || id.flags&IDF_READONLY || !(id.flags&IDF_OVERRIDDEN)) continue; f->putchar(id.type); f->putlil(strlen(id.name)); f->write(id.name, strlen(id.name)); - switch(id.type) - { + switch(id.type) { case ID_VAR: f->putlil(*id.storage.i); break; - case ID_FVAR: f->putlil(*id.storage.f); break; - case ID_SVAR: f->putlil(strlen(*id.storage.s)); f->write(*id.storage.s, strlen(*id.storage.s)); break; } }); - f->putchar((int)strlen(game::gameident())); f->write(game::gameident(), (int)strlen(game::gameident())+1); f->putlil(entities::extraentinfosize()); @@ -669,14 +563,11 @@ bool save_world(const char *mname, bool nolms) game::writegamedata(extras); f->putlil(extras.length()); f->write(extras.getbuf(), extras.length()); - f->putlil(texmru.length()); loopv(texmru) f->putlil(texmru[i]); char *ebuf = new char[entities::extraentinfosize()]; - loopv(ents) - { - if(ents[i]->type!=ET_EMPTY || nolms) - { + loopv(ents) { + if(ents[i]->type!=ET_EMPTY || nolms) { entity tmp = *ents[i]; lilswap(&tmp.o.x, 3); lilswap(&tmp.attr1, 5); @@ -685,21 +576,15 @@ bool save_world(const char *mname, bool nolms) } } delete[] ebuf; - savevslots(f, numvslots); - renderprogress(0, "saving octree..."); savec(worldroot, ivec(0, 0, 0), worldsize>>1, f, nolms); - - if(!nolms) - { + if(!nolms) { if(lightmaps.length()) renderprogress(0, "saving lightmaps..."); - loopv(lightmaps) - { + loopv(lightmaps) { LightMap &lm = lightmaps[i]; f->putchar(lm.type | (lm.unlitx>=0 ? 0x80 : 0)); - if(lm.unlitx>=0) - { + if(lm.unlitx>=0) { f->putlil(ushort(lm.unlitx)); f->putlil(ushort(lm.unlity)); } @@ -707,7 +592,6 @@ bool save_world(const char *mname, bool nolms) renderprogress(float(i+1)/lightmaps.length(), "saving lightmaps..."); } } - delete f; conoutf("wrote map file %s", ogzname); return true; @@ -718,8 +602,7 @@ static uint mapcrc = 0; uint getmapcrc() { return mapcrc; } void clearmapcrc() { mapcrc = 0; } -bool load_world(const char *mname, const char *cname) // still supports all map formats that have existed since the earliest cube betas! -{ +bool load_world(const char *mname, const char *cname) { // still supports all map formats that have existed since the earliest cube betas! { int loadingstart = SDL_GetTicks(); setmapfilenames(mname, cname); stream *f = opengzfile(ogzname, "rb"); @@ -729,32 +612,21 @@ bool load_world(const char *mname, const char *cname) // still supports all map lilswap(&hdr.version, 6); if(memcmp(hdr.magic, "OCTA", 4) || hdr.worldsize <= 0|| hdr.numents < 0) { conoutf(CON_ERROR, "map %s has malformatted header", ogzname); delete f; return false; } if(hdr.version>MAPVERSION) { conoutf(CON_ERROR, "map %s requires a newer version of Cube 2: Sauerbraten", ogzname); delete f; return false; } - resetmap(); - Texture *mapshot = textureload(picname, 3, true, false); renderbackground("loading...", mapshot, mname, game::getmapinfo()); - game::loadingmap(cname ? cname : mname); - setvar("mapversion", hdr.version, true, false); - lilswap(&hdr.numvslots, 1); - renderprogress(0, "clearing world..."); - freeocta(worldroot); worldroot = NULL; - int worldscale = 0; while(1<getchar(), ilen = f->getlil(); string name; f->read(name, min(ilen, MAXSTRLEN-1)); @@ -762,24 +634,18 @@ bool load_world(const char *mname, const char *cname) // still supports all map if(ilen >= MAXSTRLEN) f->seek(ilen - (MAXSTRLEN-1), SEEK_CUR); ident *id = getident(name); bool exists = id && id->type == type && id->flags&IDF_OVERRIDE; - switch(type) - { - case ID_VAR: - { + switch(type) { + case ID_VAR: { int val = f->getlil(); if(exists && id->minval <= id->maxval) setvar(name, val); break; } - - case ID_FVAR: - { + case ID_FVAR: { float val = f->getlil(); if(exists && id->minvalf <= id->maxvalf) setfvar(name, val); break; } - - case ID_SVAR: - { + case ID_SVAR: { int slen = f->getlil(); string val; f->read(val, min(slen, MAXSTRLEN-1)); @@ -790,73 +656,54 @@ bool load_world(const char *mname, const char *cname) // still supports all map } } } - string gametype; copystring(gametype, "fps"); - int eif = 0; int len = f->getchar(); f->read(gametype, len+1); - eif = f->getlil(); int extrasize = f->getlil(); vector extras; f->read(extras.pad(extrasize), extrasize); game::readgamedata(extras); - texmru.shrink(0); ushort nummru = f->getlil(); loopi(nummru) texmru.add(f->getlil()); - renderprogress(0, "loading entities..."); - vector &ents = entities::getents(); int einfosize = entities::extraentinfosize(); char *ebuf = einfosize > 0 ? new char[einfosize] : NULL; - loopi(min(hdr.numents, MAXENTS)) - { + loopi(min(hdr.numents, MAXENTS)) { extentity &e = *entities::newentity(); ents.add(&e); f->read(&e, sizeof(entity)); lilswap(&e.o.x, 3); lilswap(&e.attr1, 5); if(einfosize > 0) f->read(ebuf, einfosize); - if(!insideworld(e.o)) - { - if(e.type != ET_LIGHT && e.type != ET_SPOTLIGHT) - { + if(!insideworld(e.o)) { + if(e.type != ET_LIGHT && e.type != ET_SPOTLIGHT) { conoutf(CON_WARN, "warning: ent outside of world: enttype[%s] index %d (%f, %f, %f)", entities::entname(e.type), i, e.o.x, e.o.y, e.o.z); } } } if(ebuf) delete[] ebuf; - - if(hdr.numents > MAXENTS) - { + if(hdr.numents > MAXENTS) { conoutf(CON_WARN, "warning: map has %d entities", hdr.numents); f->seek((hdr.numents-MAXENTS)*(sizeof(entity) + einfosize), SEEK_CUR); } - renderprogress(0, "loading slots..."); loadvslots(f, hdr.numvslots); - renderprogress(0, "loading octree..."); bool failed = false; worldroot = loadchildren(f, ivec(0, 0, 0), hdr.worldsize>>1, failed); if(failed) conoutf(CON_ERROR, "garbage in map"); - renderprogress(0, "validating..."); validatec(worldroot, hdr.worldsize>>1); - - if(!failed) - { - loopi(hdr.lightmaps) - { + if(!failed) { + loopi(hdr.lightmaps) { renderprogress(i/(float)hdr.lightmaps, "loading lightmaps..."); - LightMap &lm = lightmaps.add(); - { + LightMap &lm = lightmaps.add(); { int type = f->getchar(); lm.type = type&0x7F; - if(type&0x80) - { + if(type&0x80) { lm.unlitx = f->getlil(); lm.unlity = f->getlil(); } @@ -867,37 +714,25 @@ bool load_world(const char *mname, const char *cname) // still supports all map lm.finalize(); } } - mapcrc = f->getcrc(); delete f; - conoutf("read map %s (%.1f seconds)", ogzname, (SDL_GetTicks()-loadingstart)/1000.0f); - clearmainmenu(); - identflags |= IDF_OVERRIDDEN; execfile("data/default_map.cfg", false); execfile(cfgname, false); identflags &= ~IDF_OVERRIDDEN; - preloadusedmapmodels(true); - game::preload(); flushpreloadedmodels(); - preloadmapsounds(); - entitiesinoctanodes(); attachentities(); initlights(); allchanged(true); - renderbackground("loading...", mapshot, mname, game::getmapinfo()); - if(maptitle[0] && strcmp(maptitle, "Untitled Map by Unknown")) conoutf(CON_ECHO, "%s", maptitle); - startmap(cname ? cname : mname); - return true; } diff --git a/src/fpsgame/ai.cpp b/src/fpsgame/ai.cpp index 0886245..b4e631b 100644 --- a/src/fpsgame/ai.cpp +++ b/src/fpsgame/ai.cpp @@ -1,100 +1,68 @@ #include "game.h" -namespace ai -{ +namespace ai { using namespace game; - avoidset obstacles; int updatemillis = 0, iteration = 0, itermillis = 0, forcegun = -1; vec aitarget(0, 0, 0); - VAR(aidebug, 0, 0, 6); VAR(aiforcegun, -1, -1, NUMGUNS-1); - ICOMMAND(addbot, "s", (char *s), addmsg(N_ADDBOT, "ri", *s ? clamp(parseint(s), 1, 101) : -1)); ICOMMAND(delbot, "", (), addmsg(N_DELBOT, "r")); ICOMMAND(botlimit, "i", (int *n), addmsg(N_BOTLIMIT, "ri", *n)); ICOMMAND(botbalance, "i", (int *n), addmsg(N_BOTBALANCE, "ri", *n)); - - float viewdist(int x) - { + float viewdist(int x) { return x <= 100 ? clamp((SIGHTMIN+(SIGHTMAX-SIGHTMIN))/100.f*float(x), float(SIGHTMIN), 10000.0f) : 10000.0f; } - - float viewfieldx(int x) - { + float viewfieldx(int x) { return x <= 100 ? clamp((VIEWMIN+(VIEWMAX-VIEWMIN))/100.f*float(x), float(VIEWMIN), float(VIEWMAX)) : float(VIEWMAX); } - - float viewfieldy(int x) - { + float viewfieldy(int x) { return viewfieldx(x)*3.f/4.f; } - - bool canmove(fpsent *d) - { + bool canmove(fpsent *d) { return d->state != CS_DEAD && !intermission; } - - float weapmindist(int weap) - { + float weapmindist(int weap) { return max(int(guns[weap].exprad), 2); } - - float weapmaxdist(int weap) - { + float weapmaxdist(int weap) { return guns[weap].range + 4; } - - bool weaprange(fpsent *d, int weap, float dist) - { + bool weaprange(fpsent *d, int weap, float dist) { float mindist = weapmindist(weap), maxdist = weapmaxdist(weap); return dist >= mindist*mindist && dist <= maxdist*maxdist; } - - bool targetable(fpsent *d, fpsent *e) - { + bool targetable(fpsent *d, fpsent *e) { if(d == e || !canmove(d)) return false; return e->state == CS_ALIVE && !isteam(d->team, e->team); } - - bool getsight(vec &o, float yaw, float pitch, vec &q, vec &v, float mdist, float fovx, float fovy) - { + bool getsight(vec &o, float yaw, float pitch, vec &q, vec &v, float mdist, float fovx, float fovy) { float dist = o.dist(q); - - if(dist <= mdist) - { + if(dist <= mdist) { float x = fmod(fabs(asin((q.z-o.z)/dist)/RAD-pitch), 360); float y = fmod(fabs(-atan2(q.x-o.x, q.y-o.y)/RAD-yaw), 360); if(min(x, 360-x) <= fovx && min(y, 360-y) <= fovy) return raycubelos(o, q, v); } return false; } - - bool cansee(fpsent *d, vec &x, vec &y, vec &targ) - { + bool cansee(fpsent *d, vec &x, vec &y, vec &targ) { aistate &b = d->ai->getstate(); if(canmove(d) && b.type != AI_S_WAIT) return getsight(x, d->yaw, d->pitch, y, targ, d->ai->views[2], d->ai->views[0], d->ai->views[1]); return false; } - - bool canshoot(fpsent *d, fpsent *e) - { + bool canshoot(fpsent *d, fpsent *e) { if(weaprange(d, d->gunselect, e->o.squaredist(d->o)) && targetable(d, e)) return d->ammo[d->gunselect] > 0 && lastmillis - d->lastaction >= d->gunwait; return false; } - - bool canshoot(fpsent *d) - { + bool canshoot(fpsent *d) { return !d->ai->becareful && d->ammo[d->gunselect] > 0 && lastmillis - d->lastaction >= d->gunwait; } - - bool hastarget(fpsent *d, aistate &b, fpsent *e, float yaw, float pitch, float dist) - { // add margins of error - if(weaprange(d, d->gunselect, dist) || (d->skill <= 100 && !rnd(d->skill))) - { + bool hastarget(fpsent *d, aistate &b, fpsent *e, float yaw, float pitch, float dist) { + // add margins of error + if(weaprange(d, d->gunselect, dist) || (d->skill <= 100 && !rnd(d->skill))) { if(d->gunselect == GUN_FIST) return true; float skew = clamp(float(lastmillis-d->ai->enemymillis)/float((d->skill*guns[d->gunselect].attackdelay/200.f)), 0.f, guns[d->gunselect].projspeed ? 0.25f : 1e16f), offy = yaw-d->yaw, offp = pitch-d->pitch; @@ -104,16 +72,12 @@ namespace ai } return false; } - - vec getaimpos(fpsent *d, fpsent *e) - { + vec getaimpos(fpsent *d, fpsent *e) { vec o = e->o; if(d->gunselect == GUN_RL) o.z += (e->aboveeye*0.2f)-(0.8f*d->eyeheight); else if(d->gunselect != GUN_GL) o.z += (e->aboveeye-e->eyeheight)*0.5f; - if(d->skill <= 100) - { - if(lastmillis >= d->ai->lastaimrnd) - { + if(d->skill <= 100) { + if(lastmillis >= d->ai->lastaimrnd) { const int aiskew[NUMGUNS] = { 1, 10, 50, 5, 20, 1, 100 }; #define rndaioffset(r) ((rnd(int(r*aiskew[d->gunselect]*2)+1)-(r*aiskew[d->gunselect]))*(1.f/float(max(d->skill, 1)))) loopk(3) d->ai->aimrnd[k] = rndaioffset(e->radius); @@ -124,55 +88,39 @@ namespace ai } return o; } - - void create(fpsent *d) - { + void create(fpsent *d) { if(!d->ai) d->ai = new aiinfo; } - - void destroy(fpsent *d) - { + void destroy(fpsent *d) { if(d->ai) DELETEP(d->ai); } - - void init(fpsent *d, int at, int ocn, int sk, int bn, int pm, const char *name, const char *team) - { + void init(fpsent *d, int at, int ocn, int sk, int bn, int pm, const char *name, const char *team) { loadwaypoints(); - fpsent *o = newclient(ocn); - d->aitype = at; - bool resetthisguy = false; - if(!d->name[0]) - { + if(!d->name[0]) { if(aidebug) conoutf(CON_DEBUG, "%s assigned to %s at skill %d", colorname(d, name), o ? colorname(o) : "?", sk); else conoutf("\f0join:\f7 %s", colorname(d, name)); resetthisguy = true; } - else - { - if(d->ownernum != ocn) - { + else { + if(d->ownernum != ocn) { if(aidebug) conoutf(CON_DEBUG, "%s reassigned to %s", colorname(d, name), o ? colorname(o) : "?"); resetthisguy = true; } if(d->skill != sk && aidebug) conoutf(CON_DEBUG, "%s changed skill to %d", colorname(d, name), sk); } - copystring(d->name, name, MAXNAMELEN+1); copystring(d->team, team, MAXTEAMLEN+1); d->ownernum = ocn; d->plag = 0; d->skill = sk; d->playermodel = 0; - if(resetthisguy) removeweapons(d); - if(d->ownernum >= 0 && player1->clientnum == d->ownernum) - { + if(d->ownernum >= 0 && player1->clientnum == d->ownernum) { create(d); - if(d->ai) - { + if(d->ai) { d->ai->views[0] = viewfieldx(d->skill); d->ai->views[1] = viewfieldy(d->skill); d->ai->views[2] = viewdist(d->skill); @@ -180,20 +128,15 @@ namespace ai } else if(d->ai) destroy(d); } - - void update() - { + void update() { if(intermission) { loopv(players) if(players[i]->ai) players[i]->stopmoving(); } - else // fixed rate logic done out-of-sequence at 1 frame per second for each ai - { - if(totalmillis-updatemillis > 1000) - { + else { // fixed rate logic done out-of-sequence at 1 frame per second for each ai { + if(totalmillis-updatemillis > 1000) { avoid(); forcegun = multiplayer(false) ? -1 : aiforcegun; updatemillis = totalmillis; } - if(!iteration && totalmillis-itermillis > 1000) - { + if(!iteration && totalmillis-itermillis > 1000) { iteration = 1; itermillis = totalmillis; } @@ -202,12 +145,10 @@ namespace ai if(++iteration > count) iteration = 0; } } - - bool checkothers(vector &targets, fpsent *d, int state, int targtype, int target, bool teams, int *members) - { // checks the states of other ai for a match + bool checkothers(vector &targets, fpsent *d, int state, int targtype, int target, bool teams, int *members) { + // checks the states of other ai for a match targets.setsize(0); - loopv(players) - { + loopv(players) { fpsent *e = players[i]; if(targets.find(e->clientnum) >= 0) continue; if(teams && d && !isteam(d->team, e->team)) continue; @@ -221,13 +162,10 @@ namespace ai } return !targets.empty(); } - - bool makeroute(fpsent *d, aistate &b, int node, bool changed, int retries) - { + bool makeroute(fpsent *d, aistate &b, int node, bool changed, int retries) { if(!iswaypoint(d->lastnode)) return false; if(changed && d->ai->route.length() > 1 && d->ai->route[0] == node) return true; - if(route(d, d->lastnode, node, d->ai->route, obstacles, retries)) - { + if(route(d, d->lastnode, node, d->ai->route, obstacles, retries)) { b.override = false; return true; } @@ -235,51 +173,37 @@ namespace ai if(retries <= 1) return makeroute(d, b, node, false, retries+1); return false; } - - bool makeroute(fpsent *d, aistate &b, const vec &pos, bool changed, int retries) - { + bool makeroute(fpsent *d, aistate &b, const vec &pos, bool changed, int retries) { int node = closestwaypoint(pos, SIGHTMIN, true); return makeroute(d, b, node, changed, retries); } - - bool randomnode(fpsent *d, aistate &b, const vec &pos, float guard, float wander) - { + bool randomnode(fpsent *d, aistate &b, const vec &pos, float guard, float wander) { static vector candidates; candidates.setsize(0); findwaypointswithin(pos, guard, wander, candidates); - - while(!candidates.empty()) - { + while(!candidates.empty()) { int w = rnd(candidates.length()), n = candidates.removeunordered(w); if(n != d->lastnode && !d->ai->hasprevnode(n) && !obstacles.find(n, d) && makeroute(d, b, n)) return true; } return false; } - - bool randomnode(fpsent *d, aistate &b, float guard, float wander) - { + bool randomnode(fpsent *d, aistate &b, float guard, float wander) { return randomnode(d, b, d->feetpos(), guard, wander); } - - bool badhealth(fpsent *d) - { + bool badhealth(fpsent *d) { if(d->skill <= 100) return d->health <= (111-d->skill)/4; return false; } - - bool enemy(fpsent *d, aistate &b, const vec &pos, float guard = SIGHTMIN, int pursue = 0) - { + bool enemy(fpsent *d, aistate &b, const vec &pos, float guard = SIGHTMIN, int pursue = 0) { fpsent *t = NULL; vec dp = d->headpos(); float mindist = guard*guard, bestdist = 1e16f; - loopv(players) - { + loopv(players) { fpsent *e = players[i]; if(e == d || !targetable(d, e)) continue; vec ep = getaimpos(d, e); float dist = ep.squaredist(dp); - if(dist < bestdist && (cansee(d, dp, ep) || dist <= mindist)) - { + if(dist < bestdist && (cansee(d, dp, ep) || dist <= mindist)) { t = e; bestdist = dist; } @@ -287,21 +211,16 @@ namespace ai if(t && violence(d, b, t, pursue)) return true; return false; } - - bool patrol(fpsent *d, aistate &b, const vec &pos, float guard, float wander, int walk, bool retry) - { + bool patrol(fpsent *d, aistate &b, const vec &pos, float guard, float wander, int walk, bool retry) { vec feet = d->feetpos(); - if(walk == 2 || b.override || (walk && feet.squaredist(pos) <= guard*guard) || !makeroute(d, b, pos)) - { // run away and back to keep ourselves busy - if(!b.override && randomnode(d, b, pos, guard, wander)) - { + if(walk == 2 || b.override || (walk && feet.squaredist(pos) <= guard*guard) || !makeroute(d, b, pos)) { + // run away and back to keep ourselves busy + if(!b.override && randomnode(d, b, pos, guard, wander)) { b.override = true; return true; } - else if(d->ai->route.empty()) - { - if(!retry) - { + else if(d->ai->route.empty()) { + if(!retry) { b.override = false; return patrol(d, b, pos, guard, wander, walk, true); } @@ -312,14 +231,10 @@ namespace ai b.override = false; return true; } - - bool defend(fpsent *d, aistate &b, const vec &pos, float guard, float wander, int walk) - { + bool defend(fpsent *d, aistate &b, const vec &pos, float guard, float wander, int walk) { bool hasenemy = enemy(d, b, pos, wander, d->gunselect == GUN_FIST ? 1 : 0); - if(!walk) - { - if(d->feetpos().squaredist(pos) <= guard*guard) - { + if(!walk) { + if(d->feetpos().squaredist(pos) <= guard*guard) { b.idle = hasenemy ? 2 : 1; return true; } @@ -327,19 +242,14 @@ namespace ai } return patrol(d, b, pos, guard, wander, walk); } - - bool violence(fpsent *d, aistate &b, fpsent *e, int pursue) - { - if(e && targetable(d, e)) - { - if(pursue) - { + bool violence(fpsent *d, aistate &b, fpsent *e, int pursue) { + if(e && targetable(d, e)) { + if(pursue) { if((b.targtype != AI_T_AFFINITY || !(pursue%2)) && makeroute(d, b, e->lastnode)) d->ai->switchstate(b, AI_S_PURSUE, AI_T_PLAYER, e->clientnum); else if(pursue >= 3) return false; // can't pursue } - if(d->ai->enemy != e->clientnum) - { + if(d->ai->enemy != e->clientnum) { d->ai->enemyseen = d->ai->enemymillis = lastmillis; d->ai->enemy = e->clientnum; } @@ -347,29 +257,23 @@ namespace ai } return false; } - - bool target(fpsent *d, aistate &b, int pursue = 0, bool force = false, float mindist = 0.f) - { + bool target(fpsent *d, aistate &b, int pursue = 0, bool force = false, float mindist = 0.f) { static vector hastried; hastried.setsize(0); vec dp = d->headpos(); - while(true) - { + while(true) { float dist = 1e16f; fpsent *t = NULL; - loopv(players) - { + loopv(players) { fpsent *e = players[i]; if(e == d || hastried.find(e) >= 0 || !targetable(d, e)) continue; vec ep = getaimpos(d, e); float v = ep.squaredist(dp); - if((!t || v < dist) && (mindist <= 0 || v <= mindist) && (force || cansee(d, dp, ep))) - { + if((!t || v < dist) && (mindist <= 0 || v <= mindist) && (force || cansee(d, dp, ep))) { t = e; dist = v; } } - if(t) - { + if(t) { if(violence(d, b, t, pursue)) return true; hastried.add(t); } @@ -377,21 +281,15 @@ namespace ai } return false; } - int isgoodammo(int gun) { return gun >= GUN_SG && gun <= GUN_GL; } - - bool hasgoodammo(fpsent *d) - { + bool hasgoodammo(fpsent *d) { static const int goodguns[] = { GUN_CG, GUN_RL, GUN_SG, GUN_RIFLE }; loopi(sizeof(goodguns)/sizeof(goodguns[0])) if(d->hasammo(goodguns[0])) return true; if(d->ammo[GUN_GL] > 5) return true; return false; } - - void assist(fpsent *d, aistate &b, vector &interests, bool all, bool force) - { - loopv(players) - { + void assist(fpsent *d, aistate &b, vector &interests, bool all, bool force) { + loopv(players) { fpsent *e = players[i]; if(e == d || (!all && e->aitype != AI_NONE) || !isteam(d->team, e->team)) continue; interest &n = interests.add(); @@ -402,28 +300,22 @@ namespace ai n.score = e->o.squaredist(d->o)/(hasgoodammo(d) ? 1e8f : (force ? 1e4f : 1e2f)); } } - - static void tryitem(fpsent *d, extentity &e, int id, aistate &b, vector &interests, bool force = false) - { + static void tryitem(fpsent *d, extentity &e, int id, aistate &b, vector &interests, bool force = false) { float score = 0; - switch(e.type) - { + switch(e.type) { case I_HEALTH: if(d->health < min(d->skill, 75)) score = 1e3f; break; case I_QUAD: score = 1e3f; break; case I_BOOST: score = 1e2f; break; - case I_GREENARMOUR: case I_YELLOWARMOUR: - { + case I_GREENARMOUR: case I_YELLOWARMOUR: { int atype = A_GREEN + e.type - I_GREENARMOUR; if(atype > d->armourtype) score = atype == A_YELLOW ? 1e2f : 1e1f; else if(d->armour < 50) score = 1e1f; break; } - default: - { - if(e.type >= I_SHELLS && e.type <= I_CARTRIDGES && !d->hasmaxammo(e.type)) - { + default: { + if(e.type >= I_SHELLS && e.type <= I_CARTRIDGES && !d->hasmaxammo(e.type)) { int gun = e.type - I_SHELLS + GUN_SG; // go get a weapon upgrade if(gun == d->ai->weappref) score = 1e8f; @@ -432,8 +324,7 @@ namespace ai break; } } - if(score != 0) - { + if(score != 0) { interest &n = interests.add(); n.state = AI_S_INTEREST; n.node = closestwaypoint(e.o, SIGHTMIN, true); @@ -442,61 +333,46 @@ namespace ai n.score = d->feetpos().squaredist(e.o)/(force ? -1 : score); } } - - void items(fpsent *d, aistate &b, vector &interests, bool force = false) - { - loopv(entities::ents) - { + void items(fpsent *d, aistate &b, vector &interests, bool force = false) { + loopv(entities::ents) { extentity &e = *(extentity *)entities::ents[i]; if(!e.spawned() || e.nopickup() || !d->canpickup(e.type)) continue; tryitem(d, e, i, b, interests, force); } } - static vector targets; - - bool parseinterests(fpsent *d, aistate &b, vector &interests, bool override, bool ignore) - { - while(!interests.empty()) - { + bool parseinterests(fpsent *d, aistate &b, vector &interests, bool override, bool ignore) { + while(!interests.empty()) { int q = interests.length()-1; loopi(interests.length()-1) if(interests[i].score < interests[q].score) q = i; interest n = interests.removeunordered(q); bool proceed = true; - if(!ignore) switch(n.state) - { - case AI_S_DEFEND: // don't get into herds - { + if(!ignore) switch(n.state) { + case AI_S_DEFEND: { // don't get into herds { int members = 0; proceed = !checkothers(targets, d, n.state, n.targtype, n.target, true, &members) && members > 1; break; } default: break; } - if(proceed && makeroute(d, b, n.node)) - { + if(proceed && makeroute(d, b, n.node)) { d->ai->switchstate(b, n.state, n.targtype, n.target); return true; } } return false; } - - bool find(fpsent *d, aistate &b, bool override = false) - { + bool find(fpsent *d, aistate &b, bool override = false) { static vector interests; interests.setsize(0); - if(!m_noitems) - { + if(!m_noitems) { if((!m_noammo && !hasgoodammo(d)) || d->health < min(d->skill - 15, 75)) items(d, b, interests); - else - { + else { static vector nearby; nearby.setsize(0); findents(I_SHELLS, I_QUAD, false, d->feetpos(), vec(32, 32, 24), nearby); - loopv(nearby) - { + loopv(nearby) { int id = nearby[i]; extentity &e = *(extentity *)entities::ents[id]; if(d->canpickup(e.type)) tryitem(d, e, id, b, interests); @@ -506,48 +382,37 @@ namespace ai if(m_teammode) assist(d, b, interests); return parseinterests(d, b, interests, override); } - - bool findassist(fpsent *d, aistate &b, bool override = false) - { + bool findassist(fpsent *d, aistate &b, bool override = false) { static vector interests; interests.setsize(0); assist(d, b, interests); - while(!interests.empty()) - { + while(!interests.empty()) { int q = interests.length()-1; loopi(interests.length()-1) if(interests[i].score < interests[q].score) q = i; interest n = interests.removeunordered(q); bool proceed = true; - switch(n.state) - { - case AI_S_DEFEND: // don't get into herds - { + switch(n.state) { + case AI_S_DEFEND: { // don't get into herds { int members = 0; proceed = !checkothers(targets, d, n.state, n.targtype, n.target, true, &members) && members > 1; break; } default: break; } - if(proceed && makeroute(d, b, n.node)) - { + if(proceed && makeroute(d, b, n.node)) { d->ai->switchstate(b, n.state, n.targtype, n.target); return true; } } return false; } - - void damaged(fpsent *d, fpsent *e) - { - if(d->ai && canmove(d) && targetable(d, e)) // see if this ai is interested in a grudge - { + void damaged(fpsent *d, fpsent *e) { + if(d->ai && canmove(d) && targetable(d, e)) { // see if this ai is interested in a grudge { aistate &b = d->ai->getstate(); if(violence(d, b, e, d->gunselect == GUN_FIST ? 1 : 0)) return; } - if(checkothers(targets, d, AI_S_DEFEND, AI_T_PLAYER, d->clientnum, true)) - { - loopv(targets) - { + if(checkothers(targets, d, AI_S_DEFEND, AI_T_PLAYER, d->clientnum, true)) { + loopv(targets) { fpsent *t = getclient(targets[i]); if(!t->ai || !canmove(t) || !targetable(t, e)) continue; aistate &c = t->ai->getstate(); @@ -555,23 +420,18 @@ namespace ai } } } - - void findorientation(vec &o, float yaw, float pitch, vec &pos) - { + void findorientation(vec &o, float yaw, float pitch, vec &pos) { vec dir; vecfromyawpitch(yaw, pitch, 1, 0, dir); if(raycubepos(o, dir, pos, 0, RAY_CLIPMAT|RAY_SKIPFIRST) == -1) pos = dir.mul(2*getworldsize()).add(o); } - - void setup(fpsent *d) - { + void setup(fpsent *d) { d->ai->clearsetup(); d->ai->reset(true); d->ai->lastrun = lastmillis; if(m_insta) d->ai->weappref = GUN_RIFLE; - else - { + else { if(forcegun >= 0 && forcegun < NUMGUNS) d->ai->weappref = forcegun; else if(m_noammo) d->ai->weappref = -1; else d->ai->weappref = rnd(GUN_GL-GUN_SG+1)+GUN_SG; @@ -579,50 +439,34 @@ namespace ai vec dp = d->headpos(); findorientation(dp, d->yaw, d->pitch, d->ai->target); } - - void spawned(fpsent *d) - { + void spawned(fpsent *d) { if(d->ai) setup(d); } - - void killed(fpsent *d, fpsent *e) - { + void killed(fpsent *d, fpsent *e) { if(d->ai) d->ai->reset(); } - - void itemspawned(int ent) - { - if(entities::ents.inrange(ent) && entities::ents[ent]->type >= I_SHELLS && entities::ents[ent]->type <= I_QUAD) - { - loopv(players) if(players[i] && players[i]->ai && players[i]->aitype == AI_BOT && players[i]->canpickup(entities::ents[ent]->type)) - { + void itemspawned(int ent) { + if(entities::ents.inrange(ent) && entities::ents[ent]->type >= I_SHELLS && entities::ents[ent]->type <= I_QUAD) { + loopv(players) if(players[i] && players[i]->ai && players[i]->aitype == AI_BOT && players[i]->canpickup(entities::ents[ent]->type)) { fpsent *d = players[i]; bool wantsitem = false; - switch(entities::ents[ent]->type) - { + switch(entities::ents[ent]->type) { case I_BOOST: - case I_HEALTH: wantsitem = badhealth(d); break; case I_GREENARMOUR: - case I_YELLOWARMOUR: - case I_QUAD: break; - default: - { + default: { itemstat &is = itemstats[entities::ents[ent]->type-I_SHELLS]; wantsitem = isgoodammo(is.info) && d->ammo[is.info] <= (d->ai->weappref == is.info ? is.add : is.add/2); break; } } - if(wantsitem) - { + if(wantsitem) { aistate &b = d->ai->getstate(); if(b.targtype == AI_T_AFFINITY) continue; - if(b.type == AI_S_INTEREST && b.targtype == AI_T_ENTITY) - { - if(entities::ents.inrange(b.target)) - { + if(b.type == AI_S_INTEREST && b.targtype == AI_T_ENTITY) { + if(entities::ents.inrange(b.target)) { if(d->o.squaredist(entities::ents[ent]->o) < d->o.squaredist(entities::ents[b.target]->o)) d->ai->switchstate(b, AI_S_INTEREST, AI_T_ENTITY, ent); } @@ -633,35 +477,27 @@ namespace ai } } } - - int dowait(fpsent *d, aistate &b) - { + int dowait(fpsent *d, aistate &b) { d->ai->clear(true); // ensure they're clean if(find(d, b)) return 1; if(target(d, b, 4, false)) return 1; if(target(d, b, 4, true)) return 1; - if(randomnode(d, b, SIGHTMIN, 1e16f)) - { + if(randomnode(d, b, SIGHTMIN, 1e16f)) { d->ai->switchstate(b, AI_S_INTEREST, AI_T_NODE, d->ai->route[0]); return 1; } return 0; // but don't pop the state } - - int dodefend(fpsent *d, aistate &b) - { - if(d->state == CS_ALIVE) - { - switch(b.targtype) - { + int dodefend(fpsent *d, aistate &b) { + if(d->state == CS_ALIVE) { + switch(b.targtype) { case AI_T_NODE: if(iswaypoint(b.target)) return defend(d, b, waypoints[b.target].o) ? 1 : 0; break; case AI_T_ENTITY: if(entities::ents.inrange(b.target)) return defend(d, b, entities::ents[b.target]->o) ? 1 : 0; break; - case AI_T_PLAYER: - { + case AI_T_PLAYER: { fpsent *e = getclient(b.target); if(e && e->state == CS_ALIVE) return defend(d, b, e->feetpos()) ? 1 : 0; break; @@ -671,12 +507,9 @@ namespace ai } return 0; } - - int dointerest(fpsent *d, aistate &b) - { + int dointerest(fpsent *d, aistate &b) { if(d->state != CS_ALIVE) return 0; - switch(b.targtype) - { + switch(b.targtype) { case AI_T_NODE: // this is like a wait state without sitting still.. if(find(d, b)) return 1; if(target(d, b, 4, true)) return 1; @@ -684,8 +517,7 @@ namespace ai return makeroute(d, b, waypoints[b.target].o) ? 1 : 0; break; case AI_T_ENTITY: - if(entities::ents.inrange(b.target)) - { + if(entities::ents.inrange(b.target)) { extentity &e = *(extentity *)entities::ents[b.target]; if(!e.spawned() || e.nopickup() || e.type < I_SHELLS || e.type > I_CARTRIDGES || d->hasmaxammo(e.type)) return 0; //if(d->feetpos().squaredist(e.o) <= CLOSEDIST*CLOSEDIST) @@ -699,25 +531,17 @@ namespace ai } return 0; } - - int dopursue(fpsent *d, aistate &b) - { - if(d->state == CS_ALIVE) - { - switch(b.targtype) - { - case AI_T_NODE: - { + int dopursue(fpsent *d, aistate &b) { + if(d->state == CS_ALIVE) { + switch(b.targtype) { + case AI_T_NODE: { if(iswaypoint(b.target)) return defend(d, b, waypoints[b.target].o) ? 1 : 0; break; } - - case AI_T_PLAYER: - { + case AI_T_PLAYER: { fpsent *e = getclient(b.target); - if(e && e->state == CS_ALIVE) - { + if(e && e->state == CS_ALIVE) { float guard = SIGHTMIN, wander = guns[d->gunselect].range; if(d->gunselect == GUN_FIST) guard = 0.f; return patrol(d, b, e->feetpos(), guard, wander) ? 1 : 0; @@ -729,20 +553,16 @@ namespace ai } return 0; } - - int closenode(fpsent *d) - { + int closenode(fpsent *d) { vec pos = d->feetpos(); int node1 = -1, node2 = -1; float mindist1 = CLOSEDIST*CLOSEDIST, mindist2 = CLOSEDIST*CLOSEDIST; - loopv(d->ai->route) if(iswaypoint(d->ai->route[i])) - { + loopv(d->ai->route) if(iswaypoint(d->ai->route[i])) { vec epos = waypoints[d->ai->route[i]].o; float dist = epos.squaredist(pos); if(dist > FARDIST*FARDIST) continue; int entid = obstacles.remap(d, d->ai->route[i], epos); - if(entid >= 0) - { + if(entid >= 0) { if(entid != i) dist = epos.squaredist(pos); if(dist < mindist1) { node1 = i; mindist1 = dist; } } @@ -750,15 +570,11 @@ namespace ai } return node1 >= 0 ? node1 : node2; } - - int wpspot(fpsent *d, int n, bool check = false) - { - if(iswaypoint(n)) loopk(2) - { + int wpspot(fpsent *d, int n, bool check = false) { + if(iswaypoint(n)) loopk(2) { vec epos = waypoints[n].o; int entid = obstacles.remap(d, n, epos, k!=0); - if(iswaypoint(entid)) - { + if(iswaypoint(entid)) { d->ai->spot = epos; d->ai->targnode = entid; return !check || d->feetpos().squaredist(epos) > MINWPDIST*MINWPDIST ? 1 : 2; @@ -766,15 +582,11 @@ namespace ai } return 0; } - - int randomlink(fpsent *d, int n) - { - if(iswaypoint(n) && waypoints[n].haslinks()) - { + int randomlink(fpsent *d, int n) { + if(iswaypoint(n) && waypoints[n].haslinks()) { waypoint &w = waypoints[n]; static vector linkmap; linkmap.setsize(0); - loopi(MAXWAYPOINTLINKS) - { + loopi(MAXWAYPOINTLINKS) { if(!w.links[i]) break; if(iswaypoint(w.links[i]) && !d->ai->hasprevnode(w.links[i]) && d->ai->route.find(w.links[i]) < 0) linkmap.add(w.links[i]); @@ -783,19 +595,14 @@ namespace ai } return -1; } - - bool anynode(fpsent *d, aistate &b, int len = NUMPREVNODES) - { - if(iswaypoint(d->lastnode)) loopk(2) - { + bool anynode(fpsent *d, aistate &b, int len = NUMPREVNODES) { + if(iswaypoint(d->lastnode)) loopk(2) { d->ai->clear(k ? true : false); int n = randomlink(d, d->lastnode); - if(wpspot(d, n)) - { + if(wpspot(d, n)) { d->ai->route.add(n); d->ai->route.add(d->lastnode); - loopi(len) - { + loopi(len) { n = randomlink(d, n); if(iswaypoint(n)) d->ai->route.insert(0, n); else break; @@ -805,29 +612,23 @@ namespace ai } return false; } - - bool checkroute(fpsent *d, int n) - { + bool checkroute(fpsent *d, int n) { if(d->ai->route.empty() || !d->ai->route.inrange(n)) return false; int last = d->ai->lastcheck ? lastmillis-d->ai->lastcheck : 0; if(last < 500 || n < 3) return false; // route length is too short d->ai->lastcheck = lastmillis; int w = iswaypoint(d->lastnode) ? d->lastnode : d->ai->route[n], c = min(n-1, NUMPREVNODES); - loopj(c) // check ahead to see if we need to go around something - { + loopj(c) { // check ahead to see if we need to go around something { int p = n-j-1, v = d->ai->route[p]; - if(d->ai->hasprevnode(v) || obstacles.find(v, d)) // something is in the way, try to remap around it - { + if(d->ai->hasprevnode(v) || obstacles.find(v, d)) { // something is in the way, try to remap around it { int m = p-1; if(m < 3) return false; // route length is too short from this point - loopirev(m) - { + loopirev(m) { int t = d->ai->route[i]; - if(!d->ai->hasprevnode(t) && !obstacles.find(t, d)) - { + if(!d->ai->hasprevnode(t) && !obstacles.find(t, d)) { static vector remap; remap.setsize(0); - if(route(d, w, t, remap, obstacles)) - { // kill what we don't want and put the remap in + if(route(d, w, t, remap, obstacles)) { + // kill what we don't want and put the remap in while(d->ai->route.length() > i) d->ai->route.pop(); loopvk(remap) d->ai->route.add(remap[k]); return true; @@ -840,28 +641,20 @@ namespace ai } return false; } - - bool hunt(fpsent *d, aistate &b) - { - if(!d->ai->route.empty()) - { + bool hunt(fpsent *d, aistate &b) { + if(!d->ai->route.empty()) { int n = closenode(d); if(d->ai->route.inrange(n) && checkroute(d, n)) n = closenode(d); - if(d->ai->route.inrange(n)) - { - if(!n) - { - switch(wpspot(d, d->ai->route[n], true)) - { + if(d->ai->route.inrange(n)) { + if(!n) { + switch(wpspot(d, d->ai->route[n], true)) { case 2: d->ai->clear(false); [[fallthrough]]; - case 1: return true; // not close enough to pop it yet default: break; } } - else - { + else { while(d->ai->route.length() > n+1) d->ai->route.pop(); // waka-waka-waka-waka int m = n-1; // next, please! if(d->ai->route.inrange(m) && wpspot(d, d->ai->route[m])) return true; @@ -871,30 +664,24 @@ namespace ai b.override = false; return anynode(d, b); } - - void jumpto(fpsent *d, aistate &b, const vec &pos) - { + void jumpto(fpsent *d, aistate &b, const vec &pos) { vec off = vec(pos).sub(d->feetpos()), dir(off.x, off.y, 0); bool sequenced = d->ai->blockseq || d->ai->targseq, offground = d->timeinair && !d->inwater, jump = !offground && lastmillis >= d->ai->jumpseed && (sequenced || off.z >= JUMPMIN || lastmillis >= d->ai->jumprand); - if(jump) - { + if(jump) { vec old = d->o; d->o = vec(pos).add(vec(0, 0, d->eyeheight)); if(collide(d, vec(0, 0, 1))) jump = false; d->o = old; - if(jump) - { + if(jump) { float radius = 18*18; - loopv(entities::ents) if(entities::ents[i]->type == JUMPPAD) - { + loopv(entities::ents) if(entities::ents[i]->type == JUMPPAD) { extentity &e = *(extentity *)entities::ents[i]; if(e.o.squaredist(pos) <= radius) { jump = false; break; } } } } - if(jump) - { + if(jump) { d->jumping = true; int seed = (111-d->skill)*(d->inwater ? 3 : 5); d->ai->jumpseed = lastmillis+seed+rnd(seed); @@ -902,18 +689,14 @@ namespace ai d->ai->jumprand = lastmillis+seed+rnd(seed); } } - - void fixfullrange(float &yaw, float &pitch, float &roll, bool full) - { - if(full) - { + void fixfullrange(float &yaw, float &pitch, float &roll, bool full) { + if(full) { while(pitch < -180.0f) pitch += 360.0f; while(pitch >= 180.0f) pitch -= 360.0f; while(roll < -180.0f) roll += 360.0f; while(roll >= 180.0f) roll -= 360.0f; } - else - { + else { if(pitch > 89.9f) pitch = 89.9f; if(pitch < -89.9f) pitch = -89.9f; if(roll > 89.9f) roll = 89.9f; @@ -922,95 +705,71 @@ namespace ai while(yaw < 0.0f) yaw += 360.0f; while(yaw >= 360.0f) yaw -= 360.0f; } - - void fixrange(float &yaw, float &pitch) - { + void fixrange(float &yaw, float &pitch) { float r = 0.f; fixfullrange(yaw, pitch, r, false); } - - void getyawpitch(const vec &from, const vec &pos, float &yaw, float &pitch) - { + void getyawpitch(const vec &from, const vec &pos, float &yaw, float &pitch) { float dist = from.dist(pos); yaw = -atan2(pos.x-from.x, pos.y-from.y)/RAD; pitch = asin((pos.z-from.z)/dist)/RAD; } - - void scaleyawpitch(float &yaw, float &pitch, float targyaw, float targpitch, float frame, float scale) - { + void scaleyawpitch(float &yaw, float &pitch, float targyaw, float targpitch, float frame, float scale) { if(yaw < targyaw-180.0f) yaw += 360.0f; if(yaw > targyaw+180.0f) yaw -= 360.0f; float offyaw = fabs(targyaw-yaw)*frame, offpitch = fabs(targpitch-pitch)*frame*scale; - if(targyaw > yaw) - { + if(targyaw > yaw) { yaw += offyaw; if(targyaw < yaw) yaw = targyaw; } - else if(targyaw < yaw) - { + else if(targyaw < yaw) { yaw -= offyaw; if(targyaw > yaw) yaw = targyaw; } - if(targpitch > pitch) - { + if(targpitch > pitch) { pitch += offpitch; if(targpitch < pitch) pitch = targpitch; } - else if(targpitch < pitch) - { + else if(targpitch < pitch) { pitch -= offpitch; if(targpitch > pitch) pitch = targpitch; } fixrange(yaw, pitch); } - - bool lockon(fpsent *d, fpsent *e, float maxdist) - { - if(d->gunselect == GUN_FIST && !d->blocked && !d->timeinair) - { + bool lockon(fpsent *d, fpsent *e, float maxdist) { + if(d->gunselect == GUN_FIST && !d->blocked && !d->timeinair) { vec dir = vec(e->o).sub(d->o); float xydist = dir.x*dir.x+dir.y*dir.y, zdist = dir.z*dir.z, mdist = maxdist*maxdist, ddist = d->radius*d->radius+e->radius*e->radius; if(zdist <= ddist && xydist >= ddist+4 && xydist <= mdist+ddist) return true; } return false; } - - int process(fpsent *d, aistate &b) - { + int process(fpsent *d, aistate &b) { int result = 0, stupify = d->skill <= 10+rnd(15) ? rnd(d->skill*1000) : 0, skmod = 101-d->skill; float frame = d->skill <= 100 ? float(lastmillis-d->ai->lastrun)/float(max(skmod,1)*10) : 1; vec dp = d->headpos(); - bool idle = b.idle == 1 || (stupify && stupify <= skmod); d->ai->dontmove = false; - if(idle) - { + if(idle) { d->ai->lastaction = d->ai->lasthunt = lastmillis; d->ai->dontmove = true; d->ai->spot = vec(0, 0, 0); } - else if(hunt(d, b)) - { + else if(hunt(d, b)) { getyawpitch(dp, vec(d->ai->spot).add(vec(0, 0, d->eyeheight)), d->ai->targyaw, d->ai->targpitch); d->ai->lasthunt = lastmillis; } - else - { + else { idle = d->ai->dontmove = true; d->ai->spot = vec(0, 0, 0); } - if(!d->ai->dontmove) jumpto(d, b, d->ai->spot); - fpsent *e = getclient(d->ai->enemy); bool enemyok = e && targetable(d, e); - if(!enemyok || d->skill >= 50) - { + if(!enemyok || d->skill >= 50) { fpsent *f = (fpsent *)intersectclosest(dp, d->ai->target, d); - if(f) - { - if(targetable(d, f)) - { + if(f) { + if(targetable(d, f)) { if(!enemyok) violence(d, b, f, d->gunselect == GUN_FIST ? 1 : 0); enemyok = true; e = f; @@ -1020,8 +779,7 @@ namespace ai else if(!enemyok && target(d, b, d->gunselect == GUN_FIST ? 1 : 0, false, SIGHTMIN)) enemyok = (e = getclient(d->ai->enemy)) != NULL; } - if(enemyok) - { + if(enemyok) { vec ep = getaimpos(d, e); float yaw, pitch; getyawpitch(dp, ep, yaw, pitch); @@ -1029,21 +787,17 @@ namespace ai bool insight = cansee(d, dp, ep), hasseen = d->ai->enemyseen && lastmillis-d->ai->enemyseen <= (d->skill*10)+3000, quick = d->ai->enemyseen && lastmillis-d->ai->enemyseen <= (d->gunselect == GUN_CG ? 300 : skmod)+30; if(insight) d->ai->enemyseen = lastmillis; - if(idle || insight || hasseen || quick) - { + if(idle || insight || hasseen || quick) { float sskew = insight || d->skill > 100 ? 1.5f : (hasseen ? 1.f : 0.5f); - if(insight && lockon(d, e, 16)) - { + if(insight && lockon(d, e, 16)) { d->ai->targyaw = yaw; d->ai->targpitch = pitch; if(!idle) frame *= 2; d->ai->becareful = false; } scaleyawpitch(d->yaw, d->pitch, yaw, pitch, frame, sskew); - if(insight || quick) - { - if(canshoot(d, e) && hastarget(d, b, e, yaw, pitch, dp.squaredist(ep))) - { + if(insight || quick) { + if(canshoot(d, e) && hastarget(d, b, e, yaw, pitch, dp.squaredist(ep))) { d->attacking = true; d->ai->lastaction = lastmillis; result = 3; @@ -1052,10 +806,8 @@ namespace ai } else result = 1; } - else - { - if(!d->ai->enemyseen || lastmillis-d->ai->enemyseen > (d->skill*50)+3000) - { + else { + if(!d->ai->enemyseen || lastmillis-d->ai->enemyseen > (d->skill*50)+3000) { d->ai->enemy = -1; d->ai->enemyseen = d->ai->enemymillis = 0; } @@ -1063,22 +815,17 @@ namespace ai result = 0; } } - else - { - if(!enemyok) - { + else { + if(!enemyok) { d->ai->enemy = -1; d->ai->enemyseen = d->ai->enemymillis = 0; } enemyok = false; result = 0; } - fixrange(d->ai->targyaw, d->ai->targpitch); if(!result) scaleyawpitch(d->yaw, d->pitch, d->ai->targyaw, d->ai->targpitch, frame*0.25f, 1.f); - - if(d->ai->becareful && d->physstate == PHYS_FALL) - { + if(d->ai->becareful && d->physstate == PHYS_FALL) { float offyaw, offpitch; vectoyawpitch(d->vel, offyaw, offpitch); offyaw -= d->yaw; offpitch -= d->pitch; @@ -1086,20 +833,18 @@ namespace ai else if(d->ai->becareful) d->ai->dontmove = true; } else d->ai->becareful = false; - if(d->ai->dontmove) d->move = d->strafe = 0; - else - { // our guys move one way.. but turn another?! :) - const struct aimdir { int move, strafe, offset; } aimdirs[8] = - { + else { + // our guys move one way.. but turn another?! :) + const struct aimdir { int move, strafe, offset; } aimdirs[8] = { { 1, 0, 0 }, - { 1, -1, 45 }, - { 0, -1, 90 }, - { -1, -1, 135 }, + { 1, -1, 45 }, + { 0, -1, 90 }, + { -1, -1, 135 }, { -1, 0, 180 }, - { -1, 1, 225 }, - { 0, 1, 270 }, - { 1, 1, 315 } + { -1, 1, 225 }, + { 0, 1, 270 }, + { 1, 1, 315 } }; float yaw = d->ai->targyaw-d->yaw; while(yaw < 0.0f) yaw += 360.0f; @@ -1112,31 +857,23 @@ namespace ai findorientation(dp, d->yaw, d->pitch, d->ai->target); return result; } - - bool hasrange(fpsent *d, fpsent *e, int weap) - { + bool hasrange(fpsent *d, fpsent *e, int weap) { if(!e) return true; - if(targetable(d, e)) - { + if(targetable(d, e)) { vec ep = getaimpos(d, e); float dist = ep.squaredist(d->headpos()); if(weaprange(d, weap, dist)) return true; } return false; } - - bool request(fpsent *d, aistate &b) - { + bool request(fpsent *d, aistate &b) { fpsent *e = getclient(d->ai->enemy); - if(!d->hasammo(d->gunselect) || !hasrange(d, e, d->gunselect) || (d->gunselect != d->ai->weappref && (!isgoodammo(d->gunselect) || d->hasammo(d->ai->weappref)))) - { + if(!d->hasammo(d->gunselect) || !hasrange(d, e, d->gunselect) || (d->gunselect != d->ai->weappref && (!isgoodammo(d->gunselect) || d->hasammo(d->ai->weappref)))) { static const int gunprefs[] = { GUN_CG, GUN_RL, GUN_SG, GUN_RIFLE, GUN_GL, GUN_PISTOL, GUN_FIST }; int gun = -1; if(d->hasammo(d->ai->weappref) && hasrange(d, e, d->ai->weappref)) gun = d->ai->weappref; - else - { - loopi(sizeof(gunprefs)/sizeof(gunprefs[0])) if(d->hasammo(gunprefs[i]) && hasrange(d, e, gunprefs[i])) - { + else { + loopi(sizeof(gunprefs)/sizeof(gunprefs[0])) if(d->hasammo(gunprefs[i]) && hasrange(d, e, gunprefs[i])) { gun = gunprefs[i]; break; } @@ -1145,17 +882,12 @@ namespace ai } return process(d, b) >= 2; } - - void timeouts(fpsent *d, aistate &b) - { - if(d->blocked) - { + void timeouts(fpsent *d, aistate &b) { + if(d->blocked) { d->ai->blocktime += lastmillis-d->ai->lastrun; - if(d->ai->blocktime > (d->ai->blockseq+1)*1000) - { + if(d->ai->blocktime > (d->ai->blockseq+1)*1000) { d->ai->blockseq++; - switch(d->ai->blockseq) - { + switch(d->ai->blockseq) { case 1: case 2: case 3: if(entities::ents.inrange(d->ai->targnode)) d->ai->addprevnode(d->ai->targnode); d->ai->clear(false); @@ -1167,15 +899,11 @@ namespace ai } } else d->ai->blocktime = d->ai->blockseq = 0; - - if(d->ai->targnode == d->ai->targlast) - { + if(d->ai->targnode == d->ai->targlast) { d->ai->targtime += lastmillis-d->ai->lastrun; - if(d->ai->targtime > (d->ai->targseq+1)*1000) - { + if(d->ai->targtime > (d->ai->targseq+1)*1000) { d->ai->targseq++; - switch(d->ai->targseq) - { + switch(d->ai->targseq) { case 1: case 2: case 3: if(entities::ents.inrange(d->ai->targnode)) d->ai->addprevnode(d->ai->targnode); d->ai->clear(false); @@ -1186,21 +914,16 @@ namespace ai } } } - else - { + else { d->ai->targtime = d->ai->targseq = 0; d->ai->targlast = d->ai->targnode; } - - if(d->ai->lasthunt) - { + if(d->ai->lasthunt) { int millis = lastmillis-d->ai->lasthunt; if(millis <= 1000) { d->ai->tryreset = false; d->ai->huntseq = 0; } - else if(millis > (d->ai->huntseq+1)*1000) - { + else if(millis > (d->ai->huntseq+1)*1000) { d->ai->huntseq++; - switch(d->ai->huntseq) - { + switch(d->ai->huntseq) { case 1: d->ai->reset(true); break; case 2: d->ai->reset(false); break; case 3: default: suicide(d); return; break; // this is our last resort.. @@ -1208,20 +931,15 @@ namespace ai } } } - - void logic(fpsent *d, aistate &b, bool run) - { + void logic(fpsent *d, aistate &b, bool run) { bool allowmove = canmove(d) && b.type != AI_S_WAIT; if(d->state != CS_ALIVE || !allowmove) d->stopmoving(); - if(d->state == CS_ALIVE) - { - if(allowmove) - { + if(d->state == CS_ALIVE) { + if(allowmove) { if(!request(d, b)) target(d, b, d->gunselect == GUN_FIST ? 1 : 0, b.idle ? true : false); shoot(d, d->ai->target); } - if(!intermission) - { + if(!intermission) { if(d->ragdoll) cleanragdoll(d); moveplayer(d, 10, true); if(allowmove && !b.idle) timeouts(d, b); @@ -1229,25 +947,20 @@ namespace ai entities::checkitems(d); } } - else if(d->state == CS_DEAD) - { + else if(d->state == CS_DEAD) { if(d->ragdoll) moveragdoll(d); - else if(lastmillis-d->lastpain<2000) - { + else if(lastmillis-d->lastpain<2000) { d->move = d->strafe = 0; moveplayer(d, 10, false); } } d->attacking = d->jumping = false; } - - void avoid() - { + void avoid() { // guess as to the radius of ai and other critters relying on the avoid set for now float guessradius = player1->radius; obstacles.clear(); - loopv(players) - { + loopv(players) { dynent *d = players[i]; if(d->state != CS_ALIVE) continue; obstacles.avoidnear(d, d->o.z + d->aboveeye + 1, d->feetpos(), guessradius + d->radius); @@ -1256,46 +969,36 @@ namespace ai obstacles.add(wpavoid); avoidweapons(obstacles, guessradius); } - - void think(fpsent *d, bool run) - { + void think(fpsent *d, bool run) { // the state stack works like a chain of commands, certain commands simply replace each other // others spawn new commands to the stack the ai reads the top command from the stack and executes // it or pops the stack and goes back along the history until it finds a suitable command to execute bool cleannext = false; if(d->ai->state.empty()) d->ai->addstate(AI_S_WAIT); - loopvrev(d->ai->state) - { + loopvrev(d->ai->state) { aistate &c = d->ai->state[i]; - if(cleannext) - { + if(cleannext) { c.millis = lastmillis; c.override = false; cleannext = false; } - if(d->state == CS_DEAD && d->respawned!=d->lifesequence && lastmillis - d->lastpain >= 500) - { + if(d->state == CS_DEAD && d->respawned!=d->lifesequence && lastmillis - d->lastpain >= 500) { addmsg(N_TRYSPAWN, "rc", d); d->respawned = d->lifesequence; } - else if(d->state == CS_ALIVE && run) - { + else if(d->state == CS_ALIVE && run) { int result = 0; c.idle = 0; - switch(c.type) - { + switch(c.type) { case AI_S_WAIT: result = dowait(d, c); break; case AI_S_DEFEND: result = dodefend(d, c); break; case AI_S_PURSUE: result = dopursue(d, c); break; case AI_S_INTEREST: result = dointerest(d, c); break; default: result = 0; break; } - if(result <= 0) - { - if(c.type != AI_S_WAIT) - { - switch(result) - { + if(result <= 0) { + if(c.type != AI_S_WAIT) { + switch(result) { case 0: default: d->ai->removestate(i); cleannext = true; break; case -1: i = d->ai->state.length()-1; break; } @@ -1309,17 +1012,12 @@ namespace ai if(d->ai->trywipe) d->ai->wipe(); d->ai->lastrun = lastmillis; } - - void drawroute(fpsent *d, float amt = 1.f) - { + void drawroute(fpsent *d, float amt = 1.f) { int last = -1; - loopvrev(d->ai->route) - { - if(d->ai->route.inrange(last)) - { + loopvrev(d->ai->route) { + if(d->ai->route.inrange(last)) { int index = d->ai->route[i], prev = d->ai->route[last]; - if(iswaypoint(index) && iswaypoint(prev)) - { + if(iswaypoint(index) && iswaypoint(prev)) { waypoint &e = waypoints[index], &f = waypoints[prev]; vec fr = f.o, dr = e.o; fr.z += amt; dr.z += amt; @@ -1328,45 +1026,22 @@ namespace ai } last = i; } - if(aidebug >= 5) - { - vec pos = d->feetpos(); - if(d->ai->spot != vec(0, 0, 0)) particle_flare(pos, d->ai->spot, 1, PART_LIGHTNING, 0x00FFFF); - if(iswaypoint(d->ai->targnode)) - particle_flare(pos, waypoints[d->ai->targnode].o, 1, PART_LIGHTNING, 0xFF00FF); - if(iswaypoint(d->lastnode)) - particle_flare(pos, waypoints[d->lastnode].o, 1, PART_LIGHTNING, 0xFFFF00); - loopi(NUMPREVNODES) if(iswaypoint(d->ai->prevnodes[i])) - { - particle_flare(pos, waypoints[d->ai->prevnodes[i]].o, 1, PART_LIGHTNING, 0x884400); - pos = waypoints[d->ai->prevnodes[i]].o; - } - } } - VAR(showwaypoints, 0, 0, 1); VAR(showwaypointsradius, 0, 200, 10000); - - const char *stnames[AI_S_MAX] = { - "wait", "defend", "pursue", "interest" - }, *sttypes[AI_T_MAX+1] = { - "none", "node", "player", "affinity", "entity" - }; - void render() - { - if(aidebug > 1) - { + const char *stnames[AI_S_MAX] = { "wait", "defend", "pursue", "interest" }, + *sttypes[AI_T_MAX+1] = { "none", "node", "player", "affinity", "entity" }; + void render() { + if(aidebug > 1) { int total = 0, alive = 0; loopv(players) if(players[i]->ai) total++; - loopv(players) if(players[i]->state == CS_ALIVE && players[i]->ai) - { + loopv(players) if(players[i]->state == CS_ALIVE && players[i]->ai) { fpsent *d = players[i]; vec pos = d->abovehead(); pos.z += 3; alive++; if(aidebug >= 4) drawroute(d, 4.f*(float(alive)/float(total))); - if(aidebug >= 3) - { + if(aidebug >= 3) { defformatstring(q, "node: %d route: %d (%d)", d->lastnode, !d->ai->route.empty() ? d->ai->route[0] : -1, @@ -1376,8 +1051,7 @@ namespace ai pos.z += 2; } bool top = true; - loopvrev(d->ai->state) - { + loopvrev(d->ai->state) { aistate &b = d->ai->state[i]; defformatstring(s, "%s%s (%d ms) %s:%d", top ? "\fg" : "\fy", @@ -1387,36 +1061,29 @@ namespace ai ); particle_textcopy(pos, s, PART_TEXT, 1); pos.z += 2; - if(top) - { + if(top) { if(aidebug >= 3) top = false; else break; } } - if(aidebug >= 3) - { - if(d->ai->weappref >= 0 && d->ai->weappref < NUMGUNS) - { + if(aidebug >= 3) { + if(d->ai->weappref >= 0 && d->ai->weappref < NUMGUNS) { particle_textcopy(pos, guns[d->ai->weappref].name, PART_TEXT, 1); pos.z += 2; } fpsent *e = getclient(d->ai->enemy); - if(e) - { + if(e) { particle_textcopy(pos, colorname(e), PART_TEXT, 1); pos.z += 2; } } } - if(aidebug >= 4) - { + if(aidebug >= 4) { int cur = 0; - loopv(obstacles.obstacles) - { + loopv(obstacles.obstacles) { const avoidset::obstacle &ob = obstacles.obstacles[i]; int next = cur + ob.numwaypoints; - for(; cur < next; cur++) - { + for(; cur < next; cur++) { int ent = obstacles.waypoints[cur]; if(iswaypoint(ent)) regular_particle_splash(PART_EDIT, 2, 40, waypoints[ent].o, 0xFF6600, 1.5f); @@ -1425,26 +1092,21 @@ namespace ai } } } - if(showwaypoints || aidebug >= 6) - { + if(showwaypoints || aidebug >= 6) { vector close; int len = waypoints.length(); - if(showwaypointsradius) - { + if(showwaypointsradius) { findwaypointswithin(camera1->o, 0, showwaypointsradius, close); len = close.length(); } - loopi(len) - { + loopi(len) { waypoint &w = waypoints[showwaypointsradius ? close[i] : i]; - loopj(MAXWAYPOINTLINKS) - { + loopj(MAXWAYPOINTLINKS) { int link = w.links[j]; if(!link) break; particle_flare(w.o, waypoints[link].o, 1, PART_STREAK, 0x0000FF); } } - } } } diff --git a/src/fpsgame/ai.h b/src/fpsgame/ai.h index 9ea7e41..b6db1fc 100644 --- a/src/fpsgame/ai.h +++ b/src/fpsgame/ai.h @@ -5,12 +5,10 @@ struct fpsent; enum { AI_NONE = 0, AI_BOT, AI_MAX }; #define isaitype(a) (a >= 0 && a <= AI_MAX-1) -namespace ai -{ +namespace ai { const int MAXWAYPOINTS = USHRT_MAX - 2; const int MAXWAYPOINTLINKS = 6; const int WAYPOINTRADIUS = 16; - const float MINWPDIST = 4.f; // is on top of const float CLOSEDIST = 32.f; // is close const float FARDIST = 128.f; // too far to remap close @@ -20,97 +18,71 @@ namespace ai const float SIGHTMAX = 1024.f; // maximum line of sight const float VIEWMIN = 90.f; // minimum field of view const float VIEWMAX = 180.f; // maximum field of view - - struct waypoint - { + struct waypoint { vec o; float curscore, estscore; int weight; ushort route, prev; ushort links[MAXWAYPOINTLINKS]; - waypoint() {} waypoint(const vec &o, int weight = 0) : o(o), weight(weight), route(0) { memset(links, 0, sizeof(links)); } - int score() const { return int(curscore) + int(estscore); } - - int find(int wp) - { + int find(int wp) { loopi(MAXWAYPOINTLINKS) if(links[i] == wp) return i; return -1; } - bool haslinks() { return links[0]!=0; } }; extern vector waypoints; - - static inline bool iswaypoint(int n) - { + static inline bool iswaypoint(int n) { return n > 0 && n < waypoints.length(); } - extern int showwaypoints, dropwaypoints; - extern int closestwaypoint(const vec &pos, float mindist, bool links, fpsent *d = NULL); + extern int closestwaypoint(const vec &pos, float mindist, bool links); extern void findwaypointswithin(const vec &pos, float mindist, float maxdist, vector &results); extern void inferwaypoints(fpsent *d, const vec &o, const vec &v, float mindist = ai::CLOSEDIST); - - struct avoidset - { - struct obstacle - { + struct avoidset { + struct obstacle { void *owner; int numwaypoints; float above; - obstacle(void *owner, float above = -1) : owner(owner), numwaypoints(0), above(above) {} }; - vector obstacles; vector waypoints; - - void clear() - { + void clear() { obstacles.setsize(0); waypoints.setsize(0); } - - void add(void *owner, float above) - { + void add(void *owner, float above) { obstacles.add(obstacle(owner, above)); } - - void add(void *owner, float above, int wp) - { + void add(void *owner, float above, int wp) { if(obstacles.empty() || owner != obstacles.last().owner) add(owner, above); obstacles.last().numwaypoints++; waypoints.add(wp); } - - void add(avoidset &avoid) - { + void add(avoidset &avoid) { waypoints.put(avoid.waypoints.getbuf(), avoid.waypoints.length()); - loopv(avoid.obstacles) - { + loopv(avoid.obstacles) { obstacle &o = avoid.obstacles[i]; if(obstacles.empty() || o.owner != obstacles.last().owner) add(o.owner, o.above); obstacles.last().numwaypoints += o.numwaypoints; } } - void avoidnear(void *owner, float above, const vec &pos, float limit); - #define loopavoid(v, d, body) \ - if(!(v).obstacles.empty()) \ - { \ + if(!(v).obstacles.empty()) { \ + \ int cur = 0; \ - loopv((v).obstacles) \ - { \ + loopv((v).obstacles) { \ + \ const ai::avoidset::obstacle &ob = (v).obstacles[i]; \ int next = cur + ob.numwaypoints; \ - if(ob.owner != d) \ - { \ - for(; cur < next; cur++) \ - { \ + if(ob.owner != d) { \ + \ + for(; cur < next; cur++) { \ + \ int wp = (v).waypoints[cur]; \ body; \ } \ @@ -118,72 +90,53 @@ namespace ai cur = next; \ } \ } - - bool find(int n, fpsent *d) const - { + bool find(int n, fpsent *d) const { loopavoid(*this, d, { if(wp == n) return true; }); return false; } - int remap(fpsent *d, int n, vec &pos, bool retry = false); }; - extern bool route(fpsent *d, int node, int goal, vector &route, const avoidset &obstacles, int retries = 0); extern void navigate(); extern void clearwaypoints(bool full = false); extern void seedwaypoints(); extern void loadwaypoints(bool force = false, const char *mname = NULL); extern void savewaypoints(bool force = false, const char *mname = NULL); - // ai state information for the owner client - enum - { + enum { AI_S_WAIT = 0, // waiting for next command AI_S_DEFEND, // defend goal target AI_S_PURSUE, // pursue goal target AI_S_INTEREST, // interest in goal entity AI_S_MAX }; - - enum - { + enum { AI_T_NODE, AI_T_PLAYER, AI_T_AFFINITY, AI_T_ENTITY, AI_T_MAX }; - - struct interest - { + struct interest { int state, node, target, targtype; float score; interest() : state(-1), node(-1), target(-1), targtype(-1), score(0.f) {} ~interest() {} }; - - struct aistate - { + struct aistate { int type, millis, targtype, target, idle; bool override; - - aistate(int m, int t, int r = -1, int v = -1) : type(t), millis(m), targtype(r), target(v) - { + aistate(int m, int t, int r = -1, int v = -1) : type(t), millis(m), targtype(r), target(v) { reset(); } ~aistate() {} - - void reset() - { + void reset() { idle = 0; override = false; } }; - const int NUMPREVNODES = 6; - - struct aiinfo - { + struct aiinfo { vector state; vector route; vec target, spot; @@ -191,17 +144,13 @@ namespace ai lastrun, lasthunt, lastaction, lastcheck, jumpseed, jumprand, blocktime, huntseq, blockseq, lastaimrnd; float targyaw, targpitch, views[3], aimrnd[3]; bool dontmove, becareful, tryreset, trywipe; - - aiinfo() - { + aiinfo() { clearsetup(); reset(); loopk(3) views[k] = 0.f; } ~aiinfo() {} - - void clearsetup() - { + void clearsetup() { weappref = GUN_PISTOL; spot = target = vec(0, 0, 0); lastaction = lasthunt = lastcheck = enemyseen = enemymillis = blocktime = huntseq = blockseq = targtime = targseq = lastaimrnd = 0; @@ -209,68 +158,47 @@ namespace ai jumprand = lastmillis+5000; targnode = targlast = enemy = -1; } - - void clear(bool prev = false) - { + void clear(bool prev = false) { if(prev) memset(prevnodes, -1, sizeof(prevnodes)); route.setsize(0); } - - void wipe(bool prev = false) - { + void wipe(bool prev = false) { clear(prev); state.setsize(0); addstate(AI_S_WAIT); trywipe = false; } - - void clean(bool tryit = false) - { + void clean(bool tryit = false) { if(!tryit) becareful = dontmove = false; targyaw = rnd(360); targpitch = 0.f; tryreset = tryit; } - void reset(bool tryit = false) { wipe(); clean(tryit); } - - bool hasprevnode(int n) const - { + bool hasprevnode(int n) const { loopi(NUMPREVNODES) if(prevnodes[i] == n) return true; return false; } - - void addprevnode(int n) - { - if(prevnodes[0] != n) - { + void addprevnode(int n) { + if(prevnodes[0] != n) { memmove(&prevnodes[1], prevnodes, sizeof(prevnodes) - sizeof(prevnodes[0])); prevnodes[0] = n; } } - - aistate &addstate(int t, int r = -1, int v = -1) - { + aistate &addstate(int t, int r = -1, int v = -1) { return state.add(aistate(lastmillis, t, r, v)); } - - void removestate(int index = -1) - { + void removestate(int index = -1) { if(index < 0) state.pop(); else if(state.inrange(index)) state.remove(index); if(!state.length()) addstate(AI_S_WAIT); } - - aistate &getstate(int idx = -1) - { + aistate &getstate(int idx = -1) { if(state.inrange(idx)) return state[idx]; return state.last(); } - - aistate &switchstate(aistate &b, int t, int r = -1, int v = -1) - { - if((b.type == t && b.targtype == r) || (b.type == AI_S_INTEREST && b.targtype == AI_T_NODE)) - { + aistate &switchstate(aistate &b, int t, int r = -1, int v = -1) { + if((b.type == t && b.targtype == r) || (b.type == AI_S_INTEREST && b.targtype == AI_T_NODE)) { b.millis = lastmillis; b.target = v; b.reset(); @@ -279,21 +207,17 @@ namespace ai return addstate(t, r, v); } }; - extern avoidset obstacles; extern vec aitarget; - extern float viewdist(int x = 101); extern float viewfieldx(int x = 101); extern float viewfieldy(int x = 101); extern bool targetable(fpsent *d, fpsent *e); extern bool cansee(fpsent *d, vec &x, vec &y, vec &targ = aitarget); - extern void init(fpsent *d, int at, int on, int sk, int bn, int pm, const char *name, const char *team); extern void update(); extern void avoid(); extern void think(fpsent *d, bool run); - extern bool badhealth(fpsent *d); extern bool checkothers(vector &targets, fpsent *d = NULL, int state = -1, int targtype = -1, int target = -1, bool teams = false, int *members = NULL); extern bool makeroute(fpsent *d, aistate &b, int node, bool changed = true, int retries = 0); @@ -305,12 +229,10 @@ namespace ai extern bool defend(fpsent *d, aistate &b, const vec &pos, float guard = SIGHTMIN, float wander = SIGHTMAX, int walk = 1); extern void assist(fpsent *d, aistate &b, vector &interests, bool all = false, bool force = false); extern bool parseinterests(fpsent *d, aistate &b, vector &interests, bool override = false, bool ignore = false); - extern void spawned(fpsent *d); extern void damaged(fpsent *d, fpsent *e); extern void killed(fpsent *d, fpsent *e); extern void itemspawned(int ent); - extern void render(); } diff --git a/src/fpsgame/aiman.h b/src/fpsgame/aiman.h index 940f13e..f926d44 100644 --- a/src/fpsgame/aiman.h +++ b/src/fpsgame/aiman.h @@ -1,15 +1,11 @@ // server-side ai manager -namespace aiman -{ +namespace aiman { bool dorefresh = false, botbalance = true; VARN(serverbotlimit, botlimit, 0, 8, MAXBOTS); VAR(serverbotbalance, 0, 1, 1); - - void calcteams(vector &teams) - { + void calcteams(vector &teams) { static const char * const defaults[2] = { "good", "evil" }; - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->state.state==CS_SPECTATOR || !ci->team[0]) continue; teamscore *t = NULL; @@ -18,83 +14,64 @@ namespace aiman else teams.add(teamscore(ci->team, 1)); } teams.sort(teamscore::compare); - if(teams.length() < int(sizeof(defaults)/sizeof(defaults[0]))) - { + if(teams.length() < int(sizeof(defaults)/sizeof(defaults[0]))) { loopi(sizeof(defaults)/sizeof(defaults[0])) if(teams.htfind(defaults[i]) < 0) teams.add(teamscore(defaults[i], 0)); } } - - void balanceteams() - { + void balanceteams() { vector teams; calcteams(teams); vector reassign; loopv(bots) if(bots[i]) reassign.add(bots[i]); - while(reassign.length() && teams.length() && teams[0].score > teams.last().score + 1) - { + while(reassign.length() && teams.length() && teams[0].score > teams.last().score + 1) { teamscore &t = teams.last(); clientinfo *bot = NULL; - loopv(reassign) if(reassign[i] && !strcmp(reassign[i]->team, teams[0].team)) - { + loopv(reassign) if(reassign[i] && !strcmp(reassign[i]->team, teams[0].team)) { bot = reassign.removeunordered(i); teams[0].score--; t.score++; - for(int j = teams.length() - 2; j >= 0; j--) - { + for(int j = teams.length() - 2; j >= 0; j--) { if(teams[j].score >= teams[j+1].score) break; swap(teams[j], teams[j+1]); } break; } - if(bot) - { + if(bot) { copystring(bot->team, t.team, MAXTEAMLEN+1); sendf(-1, 1, "riisi", N_SETTEAM, bot->clientnum, bot->team, 0); } else teams.remove(0, 1); } } - - const char *chooseteam() - { + const char *chooseteam() { vector teams; calcteams(teams); return teams.length() ? teams.last().team : ""; } - - static inline bool validaiclient(clientinfo *ci) - { + static inline bool validaiclient(clientinfo *ci) { return ci->clientnum >= 0 && ci->state.aitype == AI_NONE && (ci->state.state!=CS_SPECTATOR || ci->local || (ci->privilege && !ci->warned)); } - - clientinfo *findaiclient(clientinfo *exclude = NULL) - { + clientinfo *findaiclient(clientinfo *exclude = NULL) { clientinfo *least = NULL; - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(!validaiclient(ci) || ci==exclude) continue; if(!least || ci->bots.length() < least->bots.length()) least = ci; } return least; } - - bool addai(int skill, int limit) - { + bool addai(int skill, int limit) { int numai = 0, cn = -1, maxai = limit >= 0 ? min(limit, MAXBOTS) : MAXBOTS; - loopv(bots) - { + loopv(bots) { clientinfo *ci = bots[i]; if(!ci || ci->ownernum < 0) { if(cn < 0) cn = i; continue; } numai++; } if(numai >= maxai) return false; - if(bots.inrange(cn)) - { + if(bots.inrange(cn)) { clientinfo *ci = bots[cn]; - if(ci) - { // reuse a slot that was going to removed - + if(ci) { + // reuse a slot that was going to removed clientinfo *owner = findaiclient(); ci->ownernum = owner ? owner->clientnum : -1; if(owner) owner->bots.add(ci); @@ -124,9 +101,7 @@ namespace aiman dorefresh = true; return true; } - - void deleteai(clientinfo *ci) - { + void deleteai(clientinfo *ci) { int cn = ci->clientnum - MAXCLIENTS; if(!bots.inrange(cn)) return; sendf(-1, 1, "ri2", N_CDIS, ci->clientnum); @@ -136,25 +111,18 @@ namespace aiman DELETEP(bots[cn]); dorefresh = true; } - - bool deleteai() - { - loopvrev(bots) if(bots[i] && bots[i]->ownernum >= 0) - { + bool deleteai() { + loopvrev(bots) if(bots[i] && bots[i]->ownernum >= 0) { deleteai(bots[i]); return true; } return false; } - - void reinitai(clientinfo *ci) - { + void reinitai(clientinfo *ci) { if(ci->ownernum < 0) deleteai(ci); - else if(ci->aireinit >= 1) - { + else if(ci->aireinit >= 1) { sendf(-1, 1, "ri6ss", N_INITAI, ci->clientnum, ci->ownernum, ci->state.aitype, ci->state.skill, ci->playermodel, ci->name, ci->team); - if(ci->aireinit == 2) - { + if(ci->aireinit == 2) { ci->reassign(); if(ci->state.state==CS_ALIVE) sendspawn(ci); else sendresume(ci); @@ -162,36 +130,27 @@ namespace aiman ci->aireinit = 0; } } - - void shiftai(clientinfo *ci, clientinfo *owner = NULL) - { + void shiftai(clientinfo *ci, clientinfo *owner = NULL) { clientinfo *prevowner = (clientinfo *)getclientinfo(ci->ownernum); if(prevowner) prevowner->bots.removeobj(ci); if(!owner) { ci->aireinit = 0; ci->ownernum = -1; } else if(ci->ownernum != owner->clientnum) { ci->aireinit = 2; ci->ownernum = owner->clientnum; owner->bots.add(ci); } dorefresh = true; } - - void removeai(clientinfo *ci) - { // either schedules a removal, or someone else to assign to - + void removeai(clientinfo *ci) { + // either schedules a removal, or someone else to assign to loopvrev(ci->bots) shiftai(ci->bots[i], findaiclient(ci)); } - - bool reassignai() - { + bool reassignai() { clientinfo *hi = NULL, *lo = NULL; - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(!validaiclient(ci)) continue; if(!lo || ci->bots.length() < lo->bots.length()) lo = ci; if(!hi || ci->bots.length() > hi->bots.length()) hi = ci; } - if(hi && lo && hi->bots.length() - lo->bots.length() > 1) - { - loopvrev(hi->bots) - { + if(hi && lo && hi->bots.length() - lo->bots.length() > 1) { + loopvrev(hi->bots) { shiftai(hi->bots[i], lo); return true; } @@ -199,53 +158,39 @@ namespace aiman return false; } - - void checksetup() - { + void checksetup() { if(m_teammode && botbalance) balanceteams(); loopvrev(bots) if(bots[i]) reinitai(bots[i]); } - - void clearai() - { // clear and remove all ai immediately + void clearai() { + // clear and remove all ai immediately loopvrev(bots) if(bots[i]) deleteai(bots[i]); } - - void checkai() - { + void checkai() { if(!dorefresh) return; dorefresh = false; - if(m_botmode && numclients(-1, false, true)) - { + if(m_botmode && numclients(-1, false, true)) { checksetup(); while(reassignai()); } else clearai(); } - - void reqadd(clientinfo *ci, int skill) - { + void reqadd(clientinfo *ci, int skill) { if(!ci->local && !ci->privilege) return; if(!addai(skill, !ci->local && ci->privilege < PRIV_ADMIN ? botlimit : -1)) sendf(ci->clientnum, 1, "ris", N_SERVMSG, "failed to create or assign bot"); } - - void reqdel(clientinfo *ci) - { + void reqdel(clientinfo *ci) { if(!ci->local && !ci->privilege) return; if(!deleteai()) sendf(ci->clientnum, 1, "ris", N_SERVMSG, "failed to remove any bots"); } - - void setbotlimit(clientinfo *ci, int limit) - { + void setbotlimit(clientinfo *ci, int limit) { if(ci && !ci->local && ci->privilege < PRIV_ADMIN) return; botlimit = clamp(limit, 0, MAXBOTS); dorefresh = true; defformatstring(msg, "bot limit is now %d", botlimit); sendservmsg(msg); } - - void setbotbalance(clientinfo *ci, bool balance) - { + void setbotbalance(clientinfo *ci, bool balance) { if(ci && !ci->local && !ci->privilege) return; botbalance = balance ? 1 : 0; dorefresh = true; @@ -253,21 +198,15 @@ namespace aiman sendservmsg(msg); } - - void changemap() - { + void changemap() { dorefresh = true; loopv(clients) if(clients[i]->local || clients[i]->privilege) return; if(botbalance != (serverbotbalance != 0)) setbotbalance(NULL, serverbotbalance != 0); } - - void addclient(clientinfo *ci) - { + void addclient(clientinfo *ci) { if(ci->state.aitype == AI_NONE) dorefresh = true; } - - void changeteam(clientinfo *ci) - { + void changeteam(clientinfo *ci) { if(ci->state.aitype == AI_NONE) dorefresh = true; } } diff --git a/src/fpsgame/client.cpp b/src/fpsgame/client.cpp index 7155c00..2ad6a6f 100644 --- a/src/fpsgame/client.cpp +++ b/src/fpsgame/client.cpp @@ -1,98 +1,71 @@ #include "game.h" -namespace game -{ +namespace game { bool senditemstoserver = false, sendcrc = false; // after a map change, since server doesn't have map data int lastping = 0; - bool connected = false, remote = false, demoplayback = false, gamepaused = false; int sessionid = 0, mastermode = MM_OPEN, gamespeed = 100; string servinfo = "", servauth = "", connectpass = ""; - VARP(deadpush, 1, 2, 20); - - void switchname(const char *name) - { + void switchname(const char *name) { filtertext(player1->name, name, false, false, MAXNAMELEN); if(!player1->name[0]) copystring(player1->name, "Anonymous"); addmsg(N_SWITCHNAME, "rs", player1->name); } - void printname() - { + void printname() { conoutf("your name is: %s", colorname(player1)); } - ICOMMAND(name, "sN", (char *s, int *numargs), - { + ICOMMAND(name, "sN", (char *s, int *numargs), { if(*numargs > 0) switchname(s); else if(!*numargs) printname(); else result(colorname(player1)); }); ICOMMAND(getname, "", (), result(player1->name)); - - void switchteam(const char *team) - { + void switchteam(const char *team) { if(player1->clientnum < 0) filtertext(player1->team, team, false, false, MAXTEAMLEN); else addmsg(N_SWITCHTEAM, "rs", team); } - void printteam() - { + void printteam() { conoutf("your team is: %s", player1->team); } - ICOMMAND(team, "sN", (char *s, int *numargs), - { + ICOMMAND(team, "sN", (char *s, int *numargs), { if(*numargs > 0) switchteam(s); else if(!*numargs) printteam(); else result(player1->team); }); ICOMMAND(getteam, "", (), result(player1->team)); - - struct authkey - { + struct authkey { char *name, *key, *desc; int lastauth; - authkey(const char *name, const char *key, const char *desc) : name(newstring(name)), key(newstring(key)), desc(newstring(desc)), - lastauth(0) - { + lastauth(0) { } - - ~authkey() - { + ~authkey() { DELETEA(name); DELETEA(key); DELETEA(desc); } }; vector authkeys; - - authkey *findauthkey(const char *desc = "") - { + authkey *findauthkey(const char *desc = "") { loopv(authkeys) if(!strcmp(authkeys[i]->desc, desc) && !strcasecmp(authkeys[i]->name, player1->name)) return authkeys[i]; loopv(authkeys) if(!strcmp(authkeys[i]->desc, desc)) return authkeys[i]; return NULL; } - VARP(autoauth, 0, 1, 1); - - void addauthkey(const char *name, const char *key, const char *desc) - { + void addauthkey(const char *name, const char *key, const char *desc) { loopvrev(authkeys) if(!strcmp(authkeys[i]->desc, desc) && !strcmp(authkeys[i]->name, name)) delete authkeys.remove(i); if(name[0] && key[0]) authkeys.add(new authkey(name, key, desc)); } ICOMMAND(authkey, "sss", (char *name, char *key, char *desc), addauthkey(name, key, desc)); - - bool hasauthkey(const char *name, const char *desc) - { + bool hasauthkey(const char *name, const char *desc) { if(!name[0] && !desc[0]) return authkeys.length() > 0; loopvrev(authkeys) if(!strcmp(authkeys[i]->desc, desc) && !strcmp(authkeys[i]->name, name)) return true; return false; } - ICOMMAND(hasauthkey, "ss", (char *name, char *desc), intret(hasauthkey(name, desc) ? 1 : 0)); - - void genauthkey(const char *secret) - { + void genauthkey(const char *secret) { if(!secret[0]) { conoutf(CON_ERROR, "you must specify a secret password"); return; } vector privkey, pubkey; genprivkey(secret, privkey, pubkey); @@ -101,9 +74,7 @@ namespace game result(privkey.getbuf()); } COMMAND(genauthkey, "s"); - - void getpubkey(const char *desc) - { + void getpubkey(const char *desc) { authkey *k = findauthkey(desc); if(!k) { if(desc[0]) conoutf(CON_ERROR, "no authkey found: %s", desc); else conoutf(CON_ERROR, "no global authkey found"); return; } vector pubkey; @@ -111,13 +82,10 @@ namespace game result(pubkey.getbuf()); } COMMAND(getpubkey, "s"); - - void saveauthkeys() - { + void saveauthkeys() { stream *f = openfile("auth.cfg", "w"); if(!f) { conoutf(CON_ERROR, "failed to open auth.cfg for writing"); return; } - loopv(authkeys) - { + loopv(authkeys) { authkey *a = authkeys[i]; f->printf("authkey %s %s %s\n", escapestring(a->name), escapestring(a->key), escapestring(a->desc)); } @@ -125,139 +93,104 @@ namespace game delete f; } COMMAND(saveauthkeys, ""); - - void sendmapinfo() - { + void sendmapinfo() { if(!connected) return; sendcrc = true; if(player1->state!=CS_SPECTATOR || player1->privilege || !remote) senditemstoserver = true; } - - void writeclientinfo(stream *f) - { + void writeclientinfo(stream *f) { f->printf("name %s\n", escapestring(player1->name)); } - - bool allowedittoggle() - { + bool allowedittoggle() { if(editmode) return true; - if(isconnected() && multiplayer(false) && !m_edit) - { + if(isconnected() && multiplayer(false) && !m_edit) { conoutf(CON_ERROR, "editing in multiplayer requires coop edit mode (1)"); return false; } return execidentbool("allowedittoggle", true); } - - void edittoggled(bool on) - { + void edittoggled(bool on) { addmsg(N_EDITMODE, "ri", on ? 1 : 0); if(player1->state==CS_DEAD) deathstate(player1, true); else if(player1->state==CS_EDITING && player1->editstate==CS_DEAD) showscores(false); disablezoom(); player1->suicided = player1->respawned = -2; } - - const char *getclientname(int cn) - { + const char *getclientname(int cn) { fpsent *d = getclient(cn); return d ? d->name : ""; } ICOMMAND(getclientname, "i", (int *cn), result(getclientname(*cn))); - - const char *getclientteam(int cn) - { + const char *getclientteam(int cn) { fpsent *d = getclient(cn); return d ? d->team : ""; } ICOMMAND(getclientteam, "i", (int *cn), result(getclientteam(*cn))); - - const char *getclienticon(int cn) - { + const char *getclienticon(int cn) { fpsent *d = getclient(cn); if(!d || d->state==CS_SPECTATOR) return "spectator"; const playermodelinfo &mdl = getplayermodelinfo(d); return m_teammode ? (isteam(player1->team, d->team) ? mdl.blueicon : mdl.redicon) : mdl.ffaicon; } ICOMMAND(getclienticon, "i", (int *cn), result(getclienticon(*cn))); - - bool ismaster(int cn) - { + bool ismaster(int cn) { fpsent *d = getclient(cn); return d && d->privilege >= PRIV_MASTER; } ICOMMAND(ismaster, "i", (int *cn), intret(ismaster(*cn) ? 1 : 0)); - - bool isauth(int cn) - { + bool isauth(int cn) { fpsent *d = getclient(cn); return d && d->privilege >= PRIV_AUTH; } ICOMMAND(isauth, "i", (int *cn), intret(isauth(*cn) ? 1 : 0)); - - bool isadmin(int cn) - { + bool isadmin(int cn) { fpsent *d = getclient(cn); return d && d->privilege >= PRIV_ADMIN; } ICOMMAND(isadmin, "i", (int *cn), intret(isadmin(*cn) ? 1 : 0)); - ICOMMAND(getmastermode, "", (), intret(mastermode)); ICOMMAND(mastermodename, "i", (int *mm), result(server::mastermodename(*mm, ""))); - - bool isspectator(int cn) - { + bool isspectator(int cn) { fpsent *d = getclient(cn); return d && d->state==CS_SPECTATOR; } ICOMMAND(isspectator, "i", (int *cn), intret(isspectator(*cn) ? 1 : 0)); - - bool isai(int cn, int type) - { + bool isai(int cn, int type) { fpsent *d = getclient(cn); int aitype = type > 0 && type < AI_MAX ? type : AI_BOT; return d && d->aitype==aitype; } ICOMMAND(isai, "ii", (int *cn, int *type), intret(isai(*cn, *type) ? 1 : 0)); - - int parseplayer(const char *arg) - { + int parseplayer(const char *arg) { char *end; int n = strtol(arg, &end, 10); - if(*arg && !*end) - { + if(*arg && !*end) { if(n!=player1->clientnum && !clients.inrange(n)) return -1; return n; } // try case sensitive first - loopv(players) - { + loopv(players) { fpsent *o = players[i]; if(!strcmp(arg, o->name)) return o->clientnum; } // nothing found, try case insensitive - loopv(players) - { + loopv(players) { fpsent *o = players[i]; if(!strcasecmp(arg, o->name)) return o->clientnum; } return -1; } ICOMMAND(getclientnum, "s", (char *name), intret(name[0] ? parseplayer(name) : player1->clientnum)); - - void listclients(bool local, bool bots) - { + void listclients(bool local, bool bots) { vector buf; string cn; int numclients = 0; - if(local && connected) - { + if(local && connected) { formatstring(cn, "%d", player1->clientnum); buf.put(cn, strlen(cn)); numclients++; } - loopv(clients) if(clients[i] && (bots || clients[i]->aitype == AI_NONE)) - { + loopv(clients) if(clients[i] && (bots || clients[i]->aitype == AI_NONE)) { formatstring(cn, "%d", clients[i]->clientnum); if(numclients++) buf.add(' '); buf.put(cn, strlen(cn)); @@ -266,26 +199,19 @@ namespace game result(buf.getbuf()); } ICOMMAND(listclients, "bb", (int *local, int *bots), listclients(*local>0, *bots!=0)); - - void clearbans() - { + void clearbans() { addmsg(N_CLEARBANS, "r"); } COMMAND(clearbans, ""); - - void kick(const char *victim, const char *reason) - { + void kick(const char *victim, const char *reason) { int vn = parseplayer(victim); if(vn>=0 && vn!=player1->clientnum) addmsg(N_KICK, "ris", vn, reason); } COMMAND(kick, "ss"); - - void authkick(const char *desc, const char *victim, const char *reason) - { + void authkick(const char *desc, const char *victim, const char *reason) { authkey *a = findauthkey(desc); int vn = parseplayer(victim); - if(a && vn>=0 && vn!=player1->clientnum) - { + if(a && vn>=0 && vn!=player1->clientnum) { a->lastauth = lastmillis; addmsg(N_AUTHKICK, "rssis", a->desc, a->name, vn, reason); } @@ -293,60 +219,45 @@ namespace game ICOMMAND(authkick, "ss", (const char *victim, const char *reason), authkick("", victim, reason)); ICOMMAND(sauthkick, "ss", (const char *victim, const char *reason), if(servauth[0]) authkick(servauth, victim, reason)); ICOMMAND(dauthkick, "sss", (const char *desc, const char *victim, const char *reason), if(desc[0]) authkick(desc, victim, reason)); - vector ignores; - - void ignore(int cn) - { + void ignore(int cn) { fpsent *d = getclient(cn); if(!d || d == player1) return; conoutf("ignoring %s", d->name); if(ignores.find(cn) < 0) ignores.add(cn); } - - void unignore(int cn) - { + void unignore(int cn) { if(ignores.find(cn) < 0) return; fpsent *d = getclient(cn); if(d) conoutf("stopped ignoring %s", d->name); ignores.removeobj(cn); } - bool isignored(int cn) { return ignores.find(cn) >= 0; } - ICOMMAND(ignore, "s", (char *arg), ignore(parseplayer(arg))); ICOMMAND(unignore, "s", (char *arg), unignore(parseplayer(arg))); ICOMMAND(isignored, "s", (char *arg), intret(isignored(parseplayer(arg)) ? 1 : 0)); - - void setteam(const char *arg1, const char *arg2) - { + void setteam(const char *arg1, const char *arg2) { int i = parseplayer(arg1); if(i>=0) addmsg(N_SETTEAM, "ris", i, arg2); } COMMAND(setteam, "ss"); - - void hashpwd(const char *pwd) - { + void hashpwd(const char *pwd) { if(player1->clientnum<0) return; string hash; server::hashpassword(player1->clientnum, sessionid, pwd, hash); result(hash); } COMMAND(hashpwd, "s"); - - void setmaster(const char *arg, const char *who) - { + void setmaster(const char *arg, const char *who) { if(!arg[0]) return; int val = 1, cn = player1->clientnum; - if(who[0]) - { + if(who[0]) { cn = parseplayer(who); if(cn < 0) return; } string hash = ""; if(!arg[1] && isdigit(arg[0])) val = parseint(arg); - else - { + else { if(cn != player1->clientnum) return; server::hashpassword(player1->clientnum, sessionid, arg, hash); } @@ -354,9 +265,7 @@ namespace game } COMMAND(setmaster, "ss"); ICOMMAND(mastermode, "i", (int *val), addmsg(N_MASTERMODE, "ri", *val)); - - bool tryauth(const char *desc) - { + bool tryauth(const char *desc) { authkey *a = findauthkey(desc); if(!a) return false; a->lastauth = lastmillis; @@ -366,45 +275,32 @@ namespace game ICOMMAND(auth, "s", (char *desc), tryauth(desc)); ICOMMAND(sauth, "", (), if(servauth[0]) tryauth(servauth)); ICOMMAND(dauth, "s", (char *desc), if(desc[0]) tryauth(desc)); - ICOMMAND(getservauth, "", (), result(servauth)); - - void togglespectator(int val, const char *who) - { + void togglespectator(int val, const char *who) { int i = who[0] ? parseplayer(who) : player1->clientnum; if(i>=0) addmsg(N_SPECTATOR, "rii", i, val); } ICOMMAND(spectator, "is", (int *val, char *who), togglespectator(*val, who)); - ICOMMAND(checkmaps, "", (), addmsg(N_CHECKMAPS, "r")); - int gamemode = INT_MAX, nextmode = INT_MAX; string clientmap = ""; - - void changemapserv(const char *name, int mode) // forced map change from the server - { - if(multiplayer(false) && !m_mp(mode)) - { + void changemapserv(const char *name, int mode) { // forced map change from the server { + if(multiplayer(false) && !m_mp(mode)) { conoutf(CON_ERROR, "mode %s (%d) not supported in multiplayer", server::modename(gamemode), gamemode); loopi(NUMGAMEMODES) if(m_mp(STARTGAMEMODE + i)) { mode = STARTGAMEMODE + i; break; } } - gamemode = mode; nextmode = mode; if(editmode) toggleedit(); if(m_demo) { entities::resetspawns(); return; } - if((m_edit && !name[0]) || !load_world(name)) - { + if((m_edit && !name[0]) || !load_world(name)) { emptymap(0, true, name); senditemstoserver = false; } startgame(); } - - void setmode(int mode) - { - if(multiplayer(false) && !m_mp(mode)) - { + void setmode(int mode) { + if(multiplayer(false) && !m_mp(mode)) { conoutf(CON_ERROR, "mode %s (%d) not supported in multiplayer", server::modename(mode), mode); intret(0); return; @@ -414,11 +310,9 @@ namespace game } ICOMMAND(mode, "i", (int *val), setmode(*val)); ICOMMAND(getmode, "", (), intret(gamemode)); - ICOMMAND(timeremaining, "i", (int *formatted), - { + ICOMMAND(timeremaining, "i", (int *formatted), { int val = max(maplimit - lastmillis + 999, 0)/1000; - if(*formatted) - { + if(*formatted) { defformatstring(str, "%d:%02d", val/60, val%60); result(str); } @@ -432,46 +326,32 @@ namespace game ICOMMANDS("m_demo", "i", (int *mode), { int gamemode = *mode; intret(m_demo); }); ICOMMANDS("m_edit", "i", (int *mode), { int gamemode = *mode; intret(m_edit); }); ICOMMANDS("m_lobby", "i", (int *mode), { int gamemode = *mode; intret(m_lobby); }); - - void changemap(const char *name, int mode) // request map change, server may ignore - { - if(!remote) - { + void changemap(const char *name, int mode) { // request map change, server may ignore { + if(!remote) { server::forcemap(name, mode); if(!isconnected()) localconnect(); } else if(player1->state!=CS_SPECTATOR || player1->privilege) addmsg(N_MAPVOTE, "rsi", name, mode); } - void changemap(const char *name) - { + void changemap(const char *name) { changemap(name, m_valid(nextmode) ? nextmode : (remote ? 0 : 1)); } ICOMMAND(map, "s", (char *name), changemap(name)); - - void forceintermission() - { + void forceintermission() { if(!remote && !hasnonlocalclients()) server::startintermission(); else addmsg(N_FORCEINTERMISSION, "r"); } - - void forceedit(const char *name) - { + void forceedit(const char *name) { changemap(name, 1); } - - void newmap(int size) - { + void newmap(int size) { addmsg(N_NEWMAP, "ri", size); } - int needclipboard = -1; - - void sendclipboard() - { + void sendclipboard() { uchar *outbuf = NULL; int inlen = 0, outlen = 0; - if(!packeditinfo(localedit, inlen, outbuf, outlen)) - { + if(!packeditinfo(localedit, inlen, outbuf, outlen)) { outbuf = NULL; inlen = outlen = 0; } @@ -483,22 +363,16 @@ namespace game sendclientpacket(p.finalize(), 1); needclipboard = -1; } - - void edittrigger(const selinfo &sel, int op, int arg1, int arg2, int arg3, const VSlot *vs) - { - if(m_edit) switch(op) - { + void edittrigger(const selinfo &sel, int op, int arg1, int arg2, int arg3, const VSlot *vs) { + if(m_edit) switch(op) { case EDIT_FLIP: case EDIT_COPY: case EDIT_PASTE: - case EDIT_DELCUBE: - { - switch(op) - { + case EDIT_DELCUBE: { + switch(op) { case EDIT_COPY: needclipboard = 0; break; case EDIT_PASTE: - if(needclipboard > 0) - { + if(needclipboard > 0) { c2sinfo(true); sendclipboard(); } @@ -509,8 +383,7 @@ namespace game sel.cx, sel.cxs, sel.cy, sel.cys, sel.corner); break; } - case EDIT_ROTATE: - { + case EDIT_ROTATE: { addmsg(N_EDITF + op, "ri9i5", sel.o.x, sel.o.y, sel.o.z, sel.s.x, sel.s.y, sel.s.z, sel.grid, sel.orient, sel.cx, sel.cxs, sel.cy, sel.cys, sel.corner, @@ -518,22 +391,19 @@ namespace game break; } case EDIT_MAT: - case EDIT_FACE: - { + case EDIT_FACE: { addmsg(N_EDITF + op, "ri9i6", sel.o.x, sel.o.y, sel.o.z, sel.s.x, sel.s.y, sel.s.z, sel.grid, sel.orient, sel.cx, sel.cxs, sel.cy, sel.cys, sel.corner, arg1, arg2); break; } - case EDIT_TEX: - { + case EDIT_TEX: { int tex1 = shouldpacktex(arg1); if(addmsg(N_EDITF + op, "ri9i6", sel.o.x, sel.o.y, sel.o.z, sel.s.x, sel.s.y, sel.s.z, sel.grid, sel.orient, sel.cx, sel.cxs, sel.cy, sel.cys, sel.corner, - tex1 ? tex1 : arg1, arg2)) - { + tex1 ? tex1 : arg1, arg2)) { messages.pad(2); int offset = messages.length(); if(tex1) packvslot(messages, arg1); @@ -541,14 +411,12 @@ namespace game } break; } - case EDIT_REPLACE: - { + case EDIT_REPLACE: { int tex1 = shouldpacktex(arg1), tex2 = shouldpacktex(arg2); if(addmsg(N_EDITF + op, "ri9i7", sel.o.x, sel.o.y, sel.o.z, sel.s.x, sel.s.y, sel.s.z, sel.grid, sel.orient, sel.cx, sel.cxs, sel.cy, sel.cys, sel.corner, - tex1 ? tex1 : arg1, tex2 ? tex2 : arg2, arg3)) - { + tex1 ? tex1 : arg1, tex2 ? tex2 : arg2, arg3)) { messages.pad(2); int offset = messages.length(); if(tex1) packvslot(messages, arg1); @@ -557,18 +425,15 @@ namespace game } break; } - case EDIT_REMIP: - { + case EDIT_REMIP: { addmsg(N_EDITF + op, "r"); break; } - case EDIT_VSLOT: - { + case EDIT_VSLOT: { if(addmsg(N_EDITF + op, "ri9i6", sel.o.x, sel.o.y, sel.o.z, sel.s.x, sel.s.y, sel.s.z, sel.grid, sel.orient, sel.cx, sel.cxs, sel.cy, sel.cys, sel.corner, - arg1, arg2)) - { + arg1, arg2)) { messages.pad(2); int offset = messages.length(); packvslot(messages, vs); @@ -577,12 +442,10 @@ namespace game break; } case EDIT_UNDO: - case EDIT_REDO: - { + case EDIT_REDO: { uchar *outbuf = NULL; int inlen = 0, outlen = 0; - if(packundo(op, inlen, outbuf, outlen)) - { + if(packundo(op, inlen, outbuf, outlen)) { if(addmsg(N_EDITF + op, "ri2", inlen, outlen)) messages.put(outbuf, outlen); delete[] outbuf; } @@ -590,13 +453,9 @@ namespace game } } } - - void printvar(fpsent *d, ident *id) - { - if(id) switch(id->type) - { - case ID_VAR: - { + void printvar(fpsent *d, ident *id) { + if(id) switch(id->type) { + case ID_VAR: { int val = *id->storage.i; string str; if(val < 0) @@ -616,20 +475,15 @@ namespace game break; } } - - void vartrigger(ident *id) - { + void vartrigger(ident *id) { if(!m_edit) return; - switch(id->type) - { + switch(id->type) { case ID_VAR: addmsg(N_EDITVAR, "risi", ID_VAR, id->name, *id->storage.i); break; - case ID_FVAR: addmsg(N_EDITVAR, "risf", ID_FVAR, id->name, *id->storage.f); break; - case ID_SVAR: addmsg(N_EDITVAR, "riss", ID_SVAR, id->name, *id->storage.s); break; @@ -637,83 +491,64 @@ namespace game } printvar(player1, id); } - - void pausegame(bool val) - { + void pausegame(bool val) { if(!connected) return; if(!remote) server::forcepaused(val); else addmsg(N_PAUSEGAME, "ri", val ? 1 : 0); } ICOMMAND(pausegame, "i", (int *val), pausegame(*val > 0)); - ICOMMAND(paused, "iN$", (int *val, int *numargs, ident *id), - { + ICOMMAND(paused, "iN$", (int *val, int *numargs, ident *id), { if(*numargs > 0) pausegame(clampvar(id, *val, 0, 1) > 0); else if(*numargs < 0) intret(gamepaused ? 1 : 0); else printvar(id, gamepaused ? 1 : 0); }); - bool ispaused() { return gamepaused; } - bool allowmouselook() { return !gamepaused || !remote || m_edit; } - - void changegamespeed(int val) - { + void changegamespeed(int val) { if(!connected) return; if(!remote) server::forcegamespeed(val); else addmsg(N_GAMESPEED, "ri", val); } - ICOMMAND(gamespeed, "iN$", (int *val, int *numargs, ident *id), - { + ICOMMAND(gamespeed, "iN$", (int *val, int *numargs, ident *id), { if(*numargs > 0) changegamespeed(clampvar(id, *val, 10, 1000)); else if(*numargs < 0) intret(gamespeed); else printvar(id, gamespeed); }); - int scaletime(int t) { return t*gamespeed; } - // collect c2s messages conveniently vector messages; int messagecn = -1, messagereliable = false; - - bool addmsg(int type, const char *fmt, ...) - { + bool addmsg(int type, const char *fmt, ...) { if(!connected) return false; static uchar buf[MAXTRANS]; ucharbuf p(buf, sizeof(buf)); putint(p, type); int numi = 1, numf = 0, nums = 0, mcn = -1; bool reliable = false; - if(fmt) - { + if(fmt) { va_list args; va_start(args, fmt); - while(*fmt) switch(*fmt++) - { + while(*fmt) switch(*fmt++) { case 'r': reliable = true; break; - case 'c': - { + case 'c': { fpsent *d = va_arg(args, fpsent *); mcn = !d || d == player1 ? -1 : d->clientnum; break; } - case 'v': - { + case 'v': { int n = va_arg(args, int); int *v = va_arg(args, int *); loopi(n) putint(p, v[i]); numi += n; break; } - - case 'i': - { + case 'i': { int n = isdigit(*fmt) ? *fmt++-'0' : 1; loopi(n) putint(p, va_arg(args, int)); numi += n; break; } - case 'f': - { + case 'f': { int n = isdigit(*fmt) ? *fmt++-'0' : 1; loopi(n) putfloat(p, (float)va_arg(args, double)); numf += n; @@ -726,8 +561,7 @@ namespace game int num = nums || numf ? 0 : numi, msgsize = server::msgsizelookup(type); if(msgsize && num!=msgsize) { fatal("inconsistent msg size for %d (%d != %d)", type, num, msgsize); } if(reliable) messagereliable = true; - if(mcn != messagecn) - { + if(mcn != messagecn) { static uchar mbuf[16]; ucharbuf m(mbuf, sizeof(mbuf)); putint(m, N_FROMAI); @@ -738,25 +572,17 @@ namespace game messages.put(buf, p.length()); return true; } - - void connectattempt(const char *name, const char *password, const ENetAddress &address) - { + void connectattempt(const char *name, const char *password, const ENetAddress &address) { copystring(connectpass, password); } - - void connectfail() - { + void connectfail() { memset(connectpass, 0, sizeof(connectpass)); } - - void gameconnect(bool _remote) - { + void gameconnect(bool _remote) { remote = _remote; if(editmode) toggleedit(); } - - void gamedisconnect(bool cleanup) - { + void gamedisconnect(bool cleanup) { if(remote) stopfollowing(); ignores.setsize(0); connected = remote = false; @@ -775,26 +601,19 @@ namespace game gamepaused = false; gamespeed = 100; clearclients(false); - if(cleanup) - { + if(cleanup) { nextmode = gamemode = INT_MAX; clientmap[0] = '\0'; } } - VARP(teamcolorchat, 0, 1, 1); const char *chatcolorname(fpsent *d) { return teamcolorchat ? teamcolorname(d, NULL) : colorname(d); } - void toserver(char *text) { conoutf(CON_CHAT, "%s:\f0 %s", chatcolorname(player1), text); addmsg(N_TEXT, "rcs", player1, text); } COMMANDN(say, toserver, "C"); - void sayteam(char *text) { conoutf(CON_TEAMCHAT, "\fs\f8[team]\fr %s: \f8%s", chatcolorname(player1), text); addmsg(N_SAYTEAM, "rcs", player1, text); } COMMAND(sayteam, "C"); - ICOMMAND(servcmd, "C", (char *cmd), addmsg(N_SERVCMD, "rs", cmd)); - - static void sendposition(fpsent *d, packetbuf &q) - { + static void sendposition(fpsent *d, packetbuf &q) { putint(q, N_POS); putuint(q, d->clientnum); // 3 bits phys state, 1 bit life sequence, 2 bits move, 2 bits strafe @@ -808,16 +627,14 @@ namespace game if(o.y < 0 || o.y > 0xFFFF) flags |= 1<<1; if(o.z < 0 || o.z > 0xFFFF) flags |= 1<<2; if(vel > 0xFF) flags |= 1<<3; - if(fall > 0) - { + if(fall > 0) { flags |= 1<<4; if(fall > 0xFF) flags |= 1<<5; if(d->falling.x || d->falling.y || d->falling.z > 0) flags |= 1<<6; } if((lookupmaterial(d->feetpos())&MATF_CLIP) == MAT_GAMECLIP) flags |= 1<<7; putuint(q, flags); - loopk(3) - { + loopk(3) { q.put(o[k]&0xFF); q.put((o[k]>>8)&0xFF); if(o[k] < 0 || o[k] > 0xFFFF) q.put((o[k]>>16)&0xFF); @@ -833,12 +650,10 @@ namespace game uint veldir = (velyaw < 0 ? 360 + int(velyaw)%360 : int(velyaw)%360) + clamp(int(velpitch+90), 0, 180)*360; q.put(veldir&0xFF); q.put((veldir>>8)&0xFF); - if(fall > 0) - { + if(fall > 0) { q.put(fall&0xFF); if(fall > 0xFF) q.put((fall>>8)&0xFF); - if(d->falling.x || d->falling.y || d->falling.z > 0) - { + if(d->falling.x || d->falling.y || d->falling.z > 0) { float fallyaw, fallpitch; vectoyawpitch(d->falling, fallyaw, fallpitch); uint falldir = (fallyaw < 0 ? 360 + int(fallyaw)%360 : int(fallyaw)%360) + clamp(int(fallpitch+90), 0, 180)*360; @@ -847,26 +662,19 @@ namespace game } } } - - void sendposition(fpsent *d, bool reliable) - { + void sendposition(fpsent *d, bool reliable) { if(d->state != CS_ALIVE && d->state != CS_EDITING) return; packetbuf q(100, reliable ? ENET_PACKET_FLAG_RELIABLE : 0); sendposition(d, q); sendclientpacket(q.finalize(), 0); } - - void sendpositions() - { - loopv(players) - { + void sendpositions() { + loopv(players) { fpsent *d = players[i]; - if((d == player1 || d->ai) && (d->state == CS_ALIVE || d->state == CS_EDITING)) - { + if((d == player1 || d->ai) && (d->state == CS_ALIVE || d->state == CS_EDITING)) { packetbuf q(100); sendposition(d, q); - for(int j = i+1; j < players.length(); j++) - { + for(int j = i+1; j < players.length(); j++) { fpsent *d = players[j]; if((d == player1 || d->ai) && (d->state == CS_ALIVE || d->state == CS_EDITING)) sendposition(d, q); @@ -876,12 +684,9 @@ namespace game } } } - - void sendmessages() - { + void sendmessages() { packetbuf p(MAXTRANS); - if(sendcrc) - { + if(sendcrc) { p.reliable(); sendcrc = false; const char *mname = getclientmap(); @@ -889,31 +694,26 @@ namespace game sendstring(mname, p); putint(p, mname[0] ? getmapcrc() : 0); } - if(senditemstoserver) - { + if(senditemstoserver) { if(!m_noitems) p.reliable(); if(!m_noitems) entities::putitems(p); senditemstoserver = false; } - if(messages.length()) - { + if(messages.length()) { p.put(messages.getbuf(), messages.length()); messages.setsize(0); if(messagereliable) p.reliable(); messagereliable = false; messagecn = -1; } - if(totalmillis-lastping>250) - { + if(totalmillis-lastping>250) { putint(p, N_PING); putint(p, totalmillis); lastping = totalmillis; } sendclientpacket(p.finalize(), 1); } - - void c2sinfo(bool force) // send update to the server - { + void c2sinfo(bool force) { // send update to the server { static int lastupdate = -1000; if(totalmillis - lastupdate < 33 && !force) return; // don't update faster than 30fps lastupdate = totalmillis; @@ -921,73 +721,58 @@ namespace game sendmessages(); flushclient(); } - - void sendintro() - { + void sendintro() { packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE); putint(p, N_CONNECT); sendstring(player1->name, p); putint(p, player1->playermodel); string hash = ""; - if(connectpass[0]) - { + if(connectpass[0]) { server::hashpassword(player1->clientnum, sessionid, connectpass, hash); memset(connectpass, 0, sizeof(connectpass)); } sendstring(hash, p); authkey *a = servauth[0] && autoauth ? findauthkey(servauth) : NULL; - if(a) - { + if(a) { a->lastauth = lastmillis; sendstring(a->desc, p); sendstring(a->name, p); } - else - { + else { sendstring("", p); sendstring("", p); } sendclientpacket(p.finalize(), 1); } - - void updatepos(fpsent *d) - { + void updatepos(fpsent *d) { // update the position of other clients in the game in our world // don't care if he's in the scenery or other players, // just don't overlap with our client - const float r = player1->radius+d->radius; const float dx = player1->o.x-d->o.x; const float dy = player1->o.y-d->o.y; const float dz = player1->o.z-d->o.z; const float rz = player1->aboveeye+d->eyeheight; const float fx = (float)fabs(dx), fy = (float)fabs(dy), fz = (float)fabs(dz); - if(fxstate!=CS_SPECTATOR && d->state!=CS_DEAD) - { + if(fxstate!=CS_SPECTATOR && d->state!=CS_DEAD) { if(fxo.y += dy<0 ? r-fy : -(r-fy); // push aside else d->o.x += dx<0 ? r-fx : -(r-fx); } int lagtime = totalmillis-d->lastupdate; - if(lagtime) - { + if(lagtime) { if(d->state!=CS_SPAWNING && d->lastupdate) d->plag = (d->plag*5+lagtime)/6; d->lastupdate = totalmillis; } } - - void parsepositions(ucharbuf &p) - { + void parsepositions(ucharbuf &p) { int type; - while(p.remaining()) switch(type = getint(p)) - { + while(p.remaining()) switch(type = getint(p)) { case N_DEMOPACKET: break; - case N_POS: // position of another client - { + case N_POS: { // position of another client { int cn = getuint(p), physstate = p.get(), flags = getuint(p); vec o, vel, falling; float yaw, pitch, roll; - loopk(3) - { + loopk(3) { int n = p.get(); n |= p.get()<<8; if(flags&(1<physstate = physstate&7; updatephysstate(d); updatepos(d); - if(smoothmove && d->smoothmillis>=0 && oldpos.dist(d->o) < smoothdist) - { + if(smoothmove && d->smoothmillis>=0 && oldpos.dist(d->o) < smoothdist) { d->newpos = d->o; d->newyaw = d->yaw; d->newpitch = d->pitch; @@ -1050,36 +832,28 @@ namespace game if(d->state==CS_LAGGED || d->state==CS_SPAWNING) d->state = CS_ALIVE; break; } - - case N_TELEPORT: - { + case N_TELEPORT: { int cn = getint(p), tp = getint(p), td = getint(p); fpsent *d = getclient(cn); if(!d || d->lifesequence < 0 || d->state==CS_DEAD) continue; entities::teleporteffects(d, tp, td, false); break; } - - case N_JUMPPAD: - { + case N_JUMPPAD: { int cn = getint(p), jp = getint(p); fpsent *d = getclient(cn); if(!d || d->lifesequence < 0 || d->state==CS_DEAD) continue; entities::jumppadeffects(d, jp, false); break; } - default: neterr("type"); return; } } - - void parsestate(fpsent *d, ucharbuf &p, bool resume = false) - { + void parsestate(fpsent *d, ucharbuf &p, bool resume = false) { if(!d) { static fpsent dummy; d = &dummy; } - if(resume) - { + if(resume) { if(d==player1) getint(p); else d->state = getint(p); d->frags = getint(p); @@ -1094,36 +868,26 @@ namespace game d->armour = getint(p); d->maxarmour = getint(p); d->armourtype = getint(p); - if(resume && d==player1) - { + if(resume && d==player1) { getint(p); loopi(GUN_PISTOL-GUN_SG+1) getint(p); } - else - { + else { int gun = getint(p); d->gunselect = clamp(gun, int(GUN_FIST), int(GUN_PISTOL)); loopi(GUN_PISTOL-GUN_SG+1) d->ammo[GUN_SG+i] = getint(p); } } - extern int deathscore; - - void parsemessages(int cn, fpsent *d, ucharbuf &p) - { + void parsemessages(int cn, fpsent *d, ucharbuf &p) { static char text[MAXTRANS]; int type; bool mapchanged = false, demopacket = false; - - while(p.remaining()) switch(type = getint(p)) - { + while(p.remaining()) switch(type = getint(p)) { case N_DEMOPACKET: demopacket = true; break; - - case N_SERVINFO: // welcome messsage from the server - { + case N_SERVINFO: { // welcome messsage from the server { int mycn = getint(p), prot = getint(p); - if(prot!=PROTOCOL_VERSION) - { + if(prot!=PROTOCOL_VERSION) { conoutf(CON_ERROR, "you are using a different game protocol (you: %d, server: %d)", PROTOCOL_VERSION, prot); disconnect(); return; @@ -1136,21 +900,16 @@ namespace game sendintro(); break; } - - case N_WELCOME: - { + case N_WELCOME: { connected = true; notifywelcome(); break; } - - case N_PAUSEGAME: - { + case N_PAUSEGAME: { bool val = getint(p) > 0; int cn = getint(p); fpsent *a = cn >= 0 ? getclient(cn) : NULL; - if(!demopacket) - { + if(!demopacket) { gamepaused = val; player1->attacking = false; } @@ -1158,9 +917,7 @@ namespace game else conoutf("game is %s", val ? "paused" : "resumed"); break; } - - case N_GAMESPEED: - { + case N_GAMESPEED: { int val = clamp(getint(p), 10, 1000), cn = getint(p); fpsent *a = cn >= 0 ? getclient(cn) : NULL; if(!demopacket) gamespeed = val; @@ -1168,22 +925,17 @@ namespace game else conoutf("gamespeed is %d", val); break; } - - case N_CLIENT: - { + case N_CLIENT: { int cn = getint(p), len = getuint(p); ucharbuf q = p.subbuf(len); parsemessages(cn, getclient(cn), q); break; } - case N_SOUND: if(!d) return; playsound(getint(p), &d->o); break; - - case N_TEXT: - { + case N_TEXT: { if(!d) return; getstring(text, p); filtertext(text, text, true, true); @@ -1193,9 +945,7 @@ namespace game conoutf(CON_CHAT, "%s:\f0 %s", chatcolorname(d), text); break; } - - case N_SAYTEAM: - { + case N_SAYTEAM: { int tcn = getint(p); fpsent *t = getclient(tcn); getstring(text, p); @@ -1206,7 +956,6 @@ namespace game conoutf(CON_TEAMCHAT, "\fs\f8[team]\fr %s: \f8%s", chatcolorname(t), text); break; } - case N_MAPCHANGE: getstring(text, p); filtertext(text, text, false); @@ -1216,14 +965,11 @@ namespace game if(getint(p)) entities::spawnitems(); else senditemstoserver = false; break; - - case N_FORCEDEATH: - { + case N_FORCEDEATH: { int cn = getint(p); fpsent *d = cn==player1->clientnum ? player1 : newclient(cn); if(!d) break; - if(d==player1) - { + if(d==player1) { if(editmode) toggleedit(); stopfollowing(); if(deathscore) showscores(true); @@ -1232,24 +978,18 @@ namespace game d->state = CS_DEAD; break; } - - case N_ITEMLIST: - { + case N_ITEMLIST: { int n; - while((n = getint(p))>=0 && !p.overread()) - { + while((n = getint(p))>=0 && !p.overread()) { if(mapchanged) entities::setspawn(n, true); getint(p); // type } break; } - - case N_INITCLIENT: // another client either connected or changed name/team - { + case N_INITCLIENT: { // another client either connected or changed name/team { int cn = getint(p); fpsent *d = newclient(cn); - if(!d) - { + if(!d) { getstring(text, p); getstring(text, p); getint(p); @@ -1258,13 +998,11 @@ namespace game getstring(text, p); filtertext(text, text, false, false, MAXNAMELEN); if(!text[0]) copystring(text, "Anonymous"); - if(d->name[0]) // already connected - { + if(d->name[0]) { // already connected { if(strcmp(d->name, text) && !isignored(d->clientnum)) conoutf("%s is now known as %s", colorname(d), colorname(d, text)); } - else // new client - { + else { // new client { conoutf("\f0join:\f7 %s", colorname(d, text)); if(needclipboard >= 0) needclipboard++; } @@ -1275,32 +1013,24 @@ namespace game d->playermodel = 0; break; } - case N_SWITCHNAME: getstring(text, p); - if(d) - { + if(d) { filtertext(text, text, false, false, MAXNAMELEN); if(!text[0]) copystring(text, "Anonymous"); - if(strcmp(text, d->name)) - { + if(strcmp(text, d->name)) { if(!isignored(d->clientnum)) conoutf("%s is now known as %s", colorname(d), colorname(d, text)); copystring(d->name, text, MAXNAMELEN+1); } } break; - case N_SWITCHMODEL: break; - case N_CDIS: clientdisconnected(getint(p)); break; - - case N_SPAWN: - { - if(d) - { + case N_SPAWN: { + if(d) { if(d->state==CS_DEAD && d->lastpain) saveragdoll(d); d->respawn(); } @@ -1311,15 +1041,12 @@ namespace game lasthit = 0; break; } - - case N_SPAWNSTATE: - { + case N_SPAWNSTATE: { int scn = getint(p); fpsent *s = getclient(scn); if(!s) { parsestate(NULL, p); break; } if(s->state==CS_DEAD && s->lastpain) saveragdoll(s); - if(s==player1) - { + if(s==player1) { if(editmode) toggleedit(); stopfollowing(); } @@ -1327,8 +1054,7 @@ namespace game parsestate(s, p); s->state = CS_ALIVE; pickgamespawn(s); - if(s == player1) - { + if(s == player1) { showscores(false); lasthit = 0; } @@ -1336,9 +1062,7 @@ namespace game addmsg(N_SPAWN, "rcii", s, s->lifesequence, s->gunselect); break; } - - case N_SHOTFX: - { + case N_SHOTFX: { int scn = getint(p), gun = getint(p), id = getint(p); vec from, to; loopk(3) from[k] = getint(p)/DMF; @@ -1354,17 +1078,14 @@ namespace game shoteffects(s->gunselect, from, to, s, false, id, prevaction); break; } - - case N_EXPLODEFX: - { + case N_EXPLODEFX: { int ecn = getint(p), gun = getint(p), id = getint(p); fpsent *e = getclient(ecn); if(!e) break; explodeeffects(gun, e, false, id); break; } - case N_DAMAGE: - { + case N_DAMAGE: { int tcn = getint(p), acn = getint(p), damage = getint(p), @@ -1379,9 +1100,7 @@ namespace game damaged(damage, target, actor, false); break; } - - case N_HITPUSH: - { + case N_HITPUSH: { int tcn = getint(p), gun = getint(p), damage = getint(p); fpsent *target = getclient(tcn); vec dir; @@ -1389,9 +1108,7 @@ namespace game if(target) target->hitpush(damage * (target->health<=0 ? deadpush : 1), dir, NULL, gun); break; } - - case N_DIED: - { + case N_DIED: { int vcn = getint(p), acn = getint(p), frags = getint(p), tfrags = getint(p); fpsent *victim = getclient(vcn), *actor = getclient(acn); @@ -1399,8 +1116,7 @@ namespace game actor->frags = frags; if(m_teammode) setteaminfo(actor->team, tfrags); extern int hidefrags; - if(actor!=player1 && (!hidefrags)) - { + if(actor!=player1 && (!hidefrags)) { defformatstring(ds, "%d", actor->frags); particle_textcopy(actor->abovehead(), ds, PART_TEXT, 2000, 0x32FF64, 4.0f, -8); } @@ -1408,10 +1124,8 @@ namespace game killed(victim, actor); break; } - case N_TEAMINFO: - for(;;) - { + for(;;) { getstring(text, p); if(p.overread() || !text[0]) break; int frags = getint(p); @@ -1419,27 +1133,20 @@ namespace game if(m_teammode) setteaminfo(text, frags); } break; - - case N_GUNSELECT: - { + case N_GUNSELECT: { if(!d) return; int gun = getint(p); d->gunselect = clamp(gun, int(GUN_FIST), int(GUN_PISTOL)); playsound(S_WEAPLOAD, &d->o); break; } - - case N_TAUNT: - { + case N_TAUNT: { if(!d) return; d->lasttaunt = lastmillis; break; } - - case N_RESUME: - { - for(;;) - { + case N_RESUME: { + for(;;) { int cn = getint(p); if(p.overread() || cn<0) break; fpsent *d = (cn == player1->clientnum ? player1 : newclient(cn)); @@ -1447,9 +1154,7 @@ namespace game } break; } - - case N_ITEMSPAWN: - { + case N_ITEMSPAWN: { int i = getint(p); if(!entities::ents.inrange(i)) break; entities::setspawn(i, true); @@ -1463,21 +1168,16 @@ namespace game if(icon >= 0) particle_icon(vec(0.0f, 0.0f, 4.0f).add(entities::ents[i]->o), icon%4, icon/4, PART_HUD_ICON, 2000, 0xFFFFFF, 2.0f, -8); break; } - - case N_ITEMACC: // server acknowledges that I picked up this item - { + case N_ITEMACC: { // server acknowledges that I picked up this item { int i = getint(p), cn = getint(p); - if(cn >= 0) - { + if(cn >= 0) { fpsent *d = getclient(cn); entities::pickupeffects(i, d); } else entities::setspawn(i, true); break; } - - case N_CLIPBOARD: - { + case N_CLIPBOARD: { int cn = getint(p), unpacklen = getint(p), packlen = getint(p); fpsent *d = getclient(cn); ucharbuf q = p.subbuf(max(packlen, 0)); @@ -1485,15 +1185,13 @@ namespace game break; } case N_UNDO: - case N_REDO: - { + case N_REDO: { int cn = getint(p), unpacklen = getint(p), packlen = getint(p); fpsent *d = getclient(cn); ucharbuf q = p.subbuf(max(packlen, 0)); if(d) unpackundo(q.buf, q.maxlen, unpacklen); break; } - case N_EDITF: // coop editing messages case N_EDITT: case N_EDITM: @@ -1503,8 +1201,7 @@ namespace game case N_ROTATE: case N_REPLACE: case N_DELCUBE: - case N_EDITVSLOT: - { + case N_EDITVSLOT: { if(!d) return; selinfo sel; sel.o.x = getint(p); sel.o.y = getint(p); sel.o.z = getint(p); @@ -1512,11 +1209,9 @@ namespace game sel.grid = getint(p); sel.orient = getint(p); sel.cx = getint(p); sel.cxs = getint(p); sel.cy = getint(p), sel.cys = getint(p); sel.corner = getint(p); - switch(type) - { + switch(type) { case N_EDITF: { int dir = getint(p), mode = getint(p); if(sel.validate()) mpeditface(dir, mode, sel, false); break; } - case N_EDITT: - { + case N_EDITT: { int tex = getint(p), allfaces = getint(p); if(p.remaining() < 2) return; @@ -1531,8 +1226,7 @@ namespace game case N_COPY: if(d && sel.validate()) mpcopy(d->edit, sel, false); break; case N_PASTE: if(d && sel.validate()) mppaste(d->edit, sel, false); break; case N_ROTATE: { int dir = getint(p); if(sel.validate()) mprotate(dir, sel, false); break; } - case N_REPLACE: - { + case N_REPLACE: { int oldtex = getint(p), newtex = getint(p), insel = getint(p); @@ -1544,8 +1238,7 @@ namespace game break; } case N_DELCUBE: if(sel.validate()) mpdelcube(sel, false); break; - case N_EDITVSLOT: - { + case N_EDITVSLOT: { int delta = getint(p), allfaces = getint(p); if(p.remaining() < 2) return; @@ -1558,48 +1251,40 @@ namespace game } break; } - case N_REMIP: - { + case N_REMIP: { if(!d) return; conoutf("%s remipped", colorname(d)); mpremip(false); break; } - case N_EDITENT: // coop edit of ent - { + case N_EDITENT: { // coop edit of ent { if(!d) return; int i = getint(p); float x = getint(p)/DMF, y = getint(p)/DMF, z = getint(p)/DMF; int type = getint(p); int attr1 = getint(p), attr2 = getint(p), attr3 = getint(p), attr4 = getint(p), attr5 = getint(p); - mpeditent(i, vec(x, y, z), type, attr1, attr2, attr3, attr4, attr5, false); break; } - case N_EDITVAR: - { + case N_EDITVAR: { if(!d) return; int type = getint(p); getstring(text, p); string name; filtertext(name, text, false); ident *id = getident(name); - switch(type) - { - case ID_VAR: - { + switch(type) { + case ID_VAR: { int val = getint(p); if(id && id->flags&IDF_OVERRIDE && !(id->flags&IDF_READONLY)) setvar(name, val); break; } - case ID_FVAR: - { + case ID_FVAR: { float val = getfloat(p); if(id && id->flags&IDF_OVERRIDE && !(id->flags&IDF_READONLY)) setfvar(name, val); break; } - case ID_SVAR: - { + case ID_SVAR: { getstring(text, p); if(id && id->flags&IDF_OVERRIDE && !(id->flags&IDF_READONLY)) setsvar(name, text); break; @@ -1608,40 +1293,31 @@ namespace game printvar(d, id); break; } - case N_PONG: addmsg(N_CLIENTPING, "i", player1->ping = (player1->ping*5+totalmillis-getint(p))/6); break; - case N_CLIENTPING: if(!d) return; d->ping = getint(p); break; - case N_TIMEUP: timeupdate(getint(p)); break; - case N_SERVMSG: getstring(text, p); conoutf("%s", text); break; - - case N_SENDDEMOLIST: - { + case N_SENDDEMOLIST: { int demos = getint(p); if(demos <= 0) conoutf("no demos available"); - else loopi(demos) - { + else loopi(demos) { getstring(text, p); if(p.overread()) break; conoutf("%d. %s", i+1, text); } break; } - - case N_DEMOPLAYBACK: - { + case N_DEMOPLAYBACK: { int on = getint(p); if(on) player1->state = CS_SPECTATOR; else clearclients(); @@ -1651,80 +1327,62 @@ namespace game execident(on ? "demostart" : "demoend"); break; } - - case N_CURRENTMASTER: - { + case N_CURRENTMASTER: { int mm = getint(p), mn; loopv(players) players[i]->privilege = PRIV_NONE; - while((mn = getint(p))>=0 && !p.overread()) - { + while((mn = getint(p))>=0 && !p.overread()) { fpsent *m = mn==player1->clientnum ? player1 : newclient(mn); int priv = getint(p); if(m) m->privilege = priv; } - if(mm != mastermode) - { + if(mm != mastermode) { mastermode = mm; conoutf("mastermode is %s (%d)", server::mastermodename(mastermode), mastermode); } break; } - - case N_MASTERMODE: - { + case N_MASTERMODE: { mastermode = getint(p); conoutf("mastermode is %s (%d)", server::mastermodename(mastermode), mastermode); break; } - - case N_EDITMODE: - { + case N_EDITMODE: { int val = getint(p); if(!d) break; - if(val) - { + if(val) { d->editstate = d->state; d->state = CS_EDITING; } - else - { + else { d->state = d->editstate; if(d->state==CS_DEAD) deathstate(d, true); } break; } - - case N_SPECTATOR: - { + case N_SPECTATOR: { int sn = getint(p), val = getint(p); fpsent *s; - if(sn==player1->clientnum) - { + if(sn==player1->clientnum) { s = player1; if(val && remote && !player1->privilege) senditemstoserver = false; } else s = newclient(sn); if(!s) return; - if(val) - { - if(s==player1) - { + if(val) { + if(s==player1) { if(editmode) toggleedit(); if(s->state==CS_DEAD) showscores(false); disablezoom(); } s->state = CS_SPECTATOR; } - else if(s->state==CS_SPECTATOR) - { + else if(s->state==CS_SPECTATOR) { if(s==player1) stopfollowing(); deathstate(s, true); } break; } - - case N_SETTEAM: - { + case N_SETTEAM: { int wn = getint(p); getstring(text, p); int reason = getint(p); @@ -1736,44 +1394,34 @@ namespace game conoutf(fmt[reason], colorname(w), w->team); break; } - - case N_ANNOUNCE: - { + case N_ANNOUNCE: { int t = getint(p); - if (t==I_QUAD) { playsound(S_V_QUAD10, NULL, NULL, 0, 0, 0, -1, 0, 3000); conoutf(CON_GAMEINFO, "\f2quad damage will spawn in 10 seconds!"); } + if (t==I_QUAD) { playsound(S_V_QUAD10, NULL, NULL, 0, 0, 0, -1, 0, 3000); conoutf(CON_GAMEINFO, "\f2quad damage will spawn in 10 seconds!"); } else if(t==I_BOOST) { playsound(S_V_BOOST10, NULL, NULL, 0, 0, 0, -1, 0, 3000); conoutf(CON_GAMEINFO, "\f2health boost will spawn in 10 seconds!"); } break; } - - case N_NEWMAP: - { + case N_NEWMAP: { int size = getint(p); if(size>=0) emptymap(size, true, NULL); else enlargemap(true); - if(d && d!=player1) - { + if(d && d!=player1) { int newsize = 0; while(1<=0 ? "%s started a new map of size %d" : "%s enlarged the map to size %d", colorname(d), newsize); } break; } - - case N_REQAUTH: - { + case N_REQAUTH: { getstring(text, p); if(autoauth && text[0] && tryauth(text)) conoutf("server requested authkey \"%s\"", text); break; } - - case N_AUTHCHAL: - { + case N_AUTHCHAL: { getstring(text, p); authkey *a = findauthkey(text); uint id = (uint)getint(p); getstring(text, p); - if(a && a->lastauth && lastmillis - a->lastauth < 60*1000) - { + if(a && a->lastauth && lastmillis - a->lastauth < 60*1000) { vector buf; answerchallenge(a->key, text, buf); //conoutf(CON_DEBUG, "answering %u, challenge %s with %s", id, text, buf.getbuf()); @@ -1786,9 +1434,7 @@ namespace game } break; } - - case N_INITAI: - { + case N_INITAI: { int bn = getint(p), on = getint(p), at = getint(p), sk = clamp(getint(p), 1, 101), pm = getint(p); string name, team; getstring(text, p); @@ -1800,45 +1446,35 @@ namespace game ai::init(b, at, on, sk, bn, pm, name, team); break; } - case N_SERVCMD: getstring(text, p); break; - default: neterr("type", cn < 0); return; } } - - struct demoreq - { + struct demoreq { int tag; string name; }; vector demoreqs; enum { MAXDEMOREQS = 7 }; static int lastdemoreq = 0; - - void receivefile(packetbuf &p) - { + void receivefile(packetbuf &p) { int type; - while(p.remaining()) switch(type = getint(p)) - { + while(p.remaining()) switch(type = getint(p)) { case N_DEMOPACKET: return; - case N_SENDDEMO: - { + case N_SENDDEMO: { string fname; fname[0] = '\0'; int tag = getint(p); - loopv(demoreqs) if(demoreqs[i].tag == tag) - { + loopv(demoreqs) if(demoreqs[i].tag == tag) { copystring(fname, demoreqs[i].name); demoreqs.remove(i); break; } - if(!fname[0]) - { + if(!fname[0]) { time_t t = time(NULL); size_t len = strftime(fname, sizeof(fname), "%Y-%m-%d_%H.%M.%S", localtime(&t)); fname[min(len, sizeof(fname)-1)] = '\0'; @@ -1855,9 +1491,7 @@ namespace game delete demo; break; } - - case N_SENDMAP: - { + case N_SENDMAP: { if(!m_edit) return; string oldname; copystring(oldname, getclientmap()); @@ -1876,69 +1510,52 @@ namespace game } } } - - void parsepacketclient(int chan, packetbuf &p) // processes any updates from the server - { + void parsepacketclient(int chan, packetbuf &p) { // processes any updates from the server { if(p.packet->flags&ENET_PACKET_FLAG_UNSEQUENCED) return; - switch(chan) - { + switch(chan) { case 0: parsepositions(p); break; - case 1: parsemessages(-1, NULL, p); break; - case 2: receivefile(p); break; } } - - void getmap() - { + void getmap() { if(!m_edit) { conoutf(CON_ERROR, "\"getmap\" only works in coop edit mode"); return; } conoutf("getting map..."); addmsg(N_GETMAP, "r"); } COMMAND(getmap, ""); - - void stopdemo() - { - if(remote) - { + void stopdemo() { + if(remote) { if(player1->privilegeprivilegeprivilege= MAXDEMOREQS) demoreqs.remove(0); demoreq &r = demoreqs.add(); r.tag = lastdemoreq; @@ -1947,29 +1564,23 @@ namespace game addmsg(N_GETDEMO, "rii", i, lastdemoreq); } ICOMMAND(getdemo, "ss", (char *val, char *name), getdemo(val, name)); - - void listdemos() - { + void listdemos() { conoutf("listing demos..."); addmsg(N_LISTDEMOS, "r"); } COMMAND(listdemos, ""); - - void sendmap() - { + void sendmap() { if(!m_edit || (player1->state==CS_SPECTATOR && remote && !player1->privilege)) { conoutf(CON_ERROR, "\"sendmap\" only works in coop edit mode"); return; } conoutf("sending map..."); defformatstring(mname, "sendmap_%d", lastmillis); save_world(mname, true); defformatstring(fname, "packages/maps/%s.ogz", mname); stream *map = openrawfile(path(fname), "rb"); - if(map) - { + if(map) { stream::offset len = map->size(); if(len > 4*1024*1024) conoutf(CON_ERROR, "map is too large"); else if(len <= 0) conoutf(CON_ERROR, "could not read map"); - else - { + else { sendfile(-1, 2, map); if(needclipboard >= 0) needclipboard++; } @@ -1979,13 +1590,10 @@ namespace game remove(findfile(fname, "rb")); } COMMAND(sendmap, ""); - - void gotoplayer(const char *arg) - { + void gotoplayer(const char *arg) { if(player1->state!=CS_SPECTATOR && player1->state!=CS_EDITING) return; int i = parseplayer(arg); - if(i>=0) - { + if(i>=0) { fpsent *d = getclient(i); if(!d || d==player1) return; player1->o = d->o; @@ -1996,9 +1604,7 @@ namespace game } } COMMANDN(goto, gotoplayer, "s"); - - void gotosel() - { + void gotosel() { if(player1->state!=CS_EDITING) return; player1->o = getselpos(); vec dir; diff --git a/src/fpsgame/entities.cpp b/src/fpsgame/entities.cpp index 93e3dc9..9336c4e 100644 --- a/src/fpsgame/entities.cpp +++ b/src/fpsgame/entities.cpp @@ -2,38 +2,27 @@ int pwitemspicked[7] = { 0 }; -namespace entities -{ +namespace entities { using namespace game; - int extraentinfosize() { return 0; } // size in bytes of what the 2 methods below read/write... so it can be skipped by other games #ifndef STANDALONE vector ents; - vector &getents() { return ents; } - bool mayattach(extentity &e) { return false; } bool attachent(extentity &e, extentity &a) { return false; } - - const char *itemname(int i) - { + const char *itemname(int i) { int t = ents[i]->type; if(tI_QUAD) return NULL; return itemstats[t-I_SHELLS].name; } - - int itemicon(int i) - { + int itemicon(int i) { int t = ents[i]->type; if(tI_QUAD) return -1; return itemstats[t-I_SHELLS].icon; } - - const char *entmdlname(int type) - { - static const char * const entmdlnames[] = - { + const char *entmdlname(int type) { + static const char * const entmdlnames[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "ammo/shells", "ammo/bullets", "ammo/rockets", "ammo/rrounds", "ammo/grenades", "ammo/cartridges", "health", "boost", "tinyhealth", "tinyarmour", "armor/green", "armor/yellow", "quad", "teleporter", @@ -47,23 +36,16 @@ namespace entities }; return entmdlnames[type]; } - - const char *entmodel(const entity &e) - { - if(e.type == TELEPORT) - { + const char *entmodel(const entity &e) { + if(e.type == TELEPORT) { if(e.attr2 > 0) return mapmodelname(e.attr2); if(e.attr2 < 0) return NULL; } return e.type < MAXENTTYPES ? entmdlname(e.type) : NULL; } - - void preloadentities() - { - loopi(MAXENTTYPES) - { - switch(i) - { + void preloadentities() { + loopi(MAXENTTYPES) { + switch(i) { case I_SHELLS: [[fallthrough]]; case I_BULLETS: @@ -97,30 +79,23 @@ namespace entities if(!mdl) continue; preloadmodel(mdl); } - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; - switch(e.type) - { + switch(e.type) { case TELEPORT: if(e.attr2 > 0) preloadmodel(mapmodelname(e.attr2)); [[fallthrough]]; - case JUMPPAD: if(e.attr4 > 0) preloadmapsound(e.attr4); break; } } } - - void renderentities() - { - loopv(ents) - { + void renderentities() { + loopv(ents) { extentity &e = *ents[i]; int revs = 10; - switch(e.type) - { + switch(e.type) { case TELEPORT: if(e.attr2 < 0) continue; break; @@ -128,33 +103,25 @@ namespace entities if(!e.spawned() || e.type < I_SHELLS || e.type > I_QUAD) continue; } const char *mdlname = entmodel(e); - if(mdlname) - { + if(mdlname) { vec p = e.o; p.z += 1+sinf(lastmillis/100.0+e.o.x+e.o.y)/20; rendermodel(&e.light, mdlname, ANIM_MAPMODEL|ANIM_LOOP, p, lastmillis/(float)revs, 0, MDL_SHADOW | MDL_CULL_VFC | MDL_CULL_DIST | MDL_CULL_OCCLUDED); } } } - - void addammo(int type, int &v, bool local) - { + void addammo(int type, int &v, bool local) { itemstat &is = itemstats[type-I_SHELLS]; v += is.add; if(v>is.max) v = is.max; if(local) msgsound(is.sound); } - - void repammo(fpsent *d, int type, bool local) - { + void repammo(fpsent *d, int type, bool local) { addammo(type, d->ammo[type-I_SHELLS+GUN_SG], local); } - // these two functions are called when the server acknowledges that you really // picked up the item (in multiplayer someone may grab it before you). - - void pickupeffects(int n, fpsent *d) - { + void pickupeffects(int n, fpsent *d) { if(!ents.inrange(n)) return; extentity *e = ents[n]; int type = e->type; @@ -164,8 +131,7 @@ namespace entities if(!d) return; itemstat &is = itemstats[type-I_SHELLS]; fpsent *h = followingplayer(player1); - if(d!=h || isthirdperson()) - { + if(d!=h || isthirdperson()) { //particle_text(d->abovehead(), is.name, PART_TEXT, 2000, 0xFFC864, 4.0f, -8); particle_icon(d->abovehead(), is.icon%4, is.icon/4, PART_HUD_ICON_GREY, 2000, 0xFFFFFF, 2.0f, -8); } @@ -180,29 +146,22 @@ namespace entities case I_BOOST: pwitemspicked[5]++; break; case I_QUAD: pwitemspicked[6]++; break; } - if(d==h) switch(type) - { + if(d==h) switch(type) { case I_BOOST: conoutf(CON_GAMEINFO, "\f2you got the health boost!"); playsound(S_V_BOOST, NULL, NULL, 0, 0, 0, -1, 0, 3000); break; - case I_QUAD: conoutf(CON_GAMEINFO, "\f2you got the quad!"); playsound(S_V_QUAD, NULL, NULL, 0, 0, 0, -1, 0, 3000); break; } } - // these functions are called when the client touches the item - - void teleporteffects(fpsent *d, int tp, int td, bool local) - { - if(ents.inrange(tp) && ents[tp]->type == TELEPORT) - { + void teleporteffects(fpsent *d, int tp, int td, bool local) { + if(ents.inrange(tp) && ents[tp]->type == TELEPORT) { extentity &e = *ents[tp]; - if(e.attr4 >= 0) - { + if(e.attr4 >= 0) { int snd = S_TELEPORT, flags = 0; if(e.attr4 > 0) { snd = e.attr4; flags = SND_MAP; } fpsent *h = followingplayer(player1); @@ -210,8 +169,7 @@ namespace entities if(d!=h && ents.inrange(td) && ents[td]->type == TELEDEST) playsound(snd, &ents[td]->o, NULL, flags); } } - if(local && d->clientnum >= 0) - { + if(local && d->clientnum >= 0) { sendposition(d); packetbuf p(32, ENET_PACKET_FLAG_RELIABLE); putint(p, N_TELEPORT); @@ -222,21 +180,16 @@ namespace entities flushclient(); } } - - void jumppadeffects(fpsent *d, int jp, bool local) - { - if(ents.inrange(jp) && ents[jp]->type == JUMPPAD) - { + void jumppadeffects(fpsent *d, int jp, bool local) { + if(ents.inrange(jp) && ents[jp]->type == JUMPPAD) { extentity &e = *ents[jp]; - if(e.attr4 >= 0) - { + if(e.attr4 >= 0) { int snd = S_JUMPPAD, flags = 0; if(e.attr4 > 0) { snd = e.attr4; flags = SND_MAP; } playsound(snd, d == followingplayer(player1) ? NULL : &e.o, NULL, flags); } } - if(local && d->clientnum >= 0) - { + if(local && d->clientnum >= 0) { sendposition(d); packetbuf p(16, ENET_PACKET_FLAG_RELIABLE); putint(p, N_JUMPPAD); @@ -246,22 +199,17 @@ namespace entities flushclient(); } } - - void teleport(int n, fpsent *d) // also used by monsters - { + void teleport(int n, fpsent *d) { // also used by monsters { int e = -1, tag = ents[n]->attr1, beenhere = -1; - for(;;) - { + for(;;) { e = findentity(TELEDEST, e+1); if(e==beenhere || e<0) { conoutf(CON_WARN, "no teleport destination for tag %d", tag); return; } if(beenhere<0) beenhere = e; - if(ents[e]->attr2==tag) - { + if(ents[e]->attr2==tag) { teleporteffects(d, n, e, true); d->o = ents[e]->o; d->yaw = ents[e]->attr1; - if(ents[e]->attr3 > 0) - { + if(ents[e]->attr3 > 0) { vec dir; vecfromyawpitch(d->yaw, 0, 1, 0, dir); float speed = d->vel.magnitude2(); @@ -276,25 +224,18 @@ namespace entities } } } - - void trypickup(int n, fpsent *d) - { + void trypickup(int n, fpsent *d) { extentity *e = ents[n]; - switch(e->type) - { + switch(e->type) { default: - if(d->canpickup(e->type)) - { + if(d->canpickup(e->type)) { addmsg(N_ITEMPICKUP, "rci", d, n); e->setnopickup(); // even if someone else gets it first } break; - - case TELEPORT: - { + case TELEPORT: { if(d->lastpickup==e->type && lastmillis-d->lastpickupmillis<500) break; - if(e->attr3 > 0) - { + if(e->attr3 > 0) { defformatstring(hookname, "can_teleport_%d", e->attr3); if(!execidentbool(hookname, true)) break; } @@ -303,9 +244,7 @@ namespace entities teleport(n, d); break; } - - case JUMPPAD: - { + case JUMPPAD: { if(d->lastpickup==e->type && lastmillis-d->lastpickupmillis<300) break; d->lastpickup = e->type; d->lastpickupmillis = lastmillis; @@ -320,13 +259,10 @@ namespace entities } } } - - void checkitems(fpsent *d) - { + void checkitems(fpsent *d) { if(d->state!=CS_ALIVE) return; vec o = d->feetpos(); - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; if(e.type==NOTUSED) continue; if((!e.spawned() || e.nopickup()) && e.type!=TELEPORT && e.type!=JUMPPAD) continue; @@ -334,97 +270,68 @@ namespace entities if(dist<(e.type==TELEPORT ? 16 : 12)) trypickup(i, d); } } - - void checkquad(int time, fpsent *d) - { - if(d->quadmillis && (d->quadmillis -= time)<=0) - { + void checkquad(int time, fpsent *d) { + if(d->quadmillis && (d->quadmillis -= time)<=0) { d->quadmillis = 0; fpsent *h = followingplayer(player1); playsound(S_PUPOUT, d==h ? NULL : &d->o); if(d==h) conoutf(CON_GAMEINFO, "\f2quad damage is over"); } } - - void putitems(packetbuf &p) // puts items in network stream and also spawns them locally - { + void putitems(packetbuf &p) { // puts items in network stream and also spawns them locally { putint(p, N_ITEMLIST); - loopv(ents) if(ents[i]->type>=I_SHELLS && ents[i]->type<=I_QUAD && (!m_noammo || ents[i]->typetype>I_CARTRIDGES)) - { + loopv(ents) if(ents[i]->type>=I_SHELLS && ents[i]->type<=I_QUAD && (!m_noammo || ents[i]->typetype>I_CARTRIDGES)) { putint(p, i); putint(p, ents[i]->type); } putint(p, -1); } - void resetspawns() { loopv(ents) { extentity *e = ents[i]; e->clearspawned(); e->clearnopickup(); } } - - void spawnitems(bool force) - { + void spawnitems(bool force) { if(m_noitems) return; - loopv(ents) - { + loopv(ents) { extentity *e = ents[i]; - if(e->type>=I_SHELLS && e->type<=I_QUAD && (!m_noammo || e->typetype>I_CARTRIDGES)) - { + if(e->type>=I_SHELLS && e->type<=I_QUAD && (!m_noammo || e->typetype>I_CARTRIDGES)) { e->setspawned(force || !server::delayspawn(e->type)); e->clearnopickup(); } } } - void setspawn(int i, bool on) { if(ents.inrange(i)) { extentity *e = ents[i]; e->setspawned(on); e->clearnopickup(); } } - extentity *newentity() { return new extentity(); } void deleteentity(extentity *e) { delete e; } - - void clearents() - { + void clearents() { while(ents.length()) deleteentity(ents.pop()); } - - void fixentity(extentity &e) - { + void fixentity(extentity &e) { if(e.type == TELEDEST) e.attr3 = e.attr2; } - - void entradius(extentity &e, bool color) - { - switch(e.type) - { - case TELEDEST: - { + void entradius(extentity &e, bool color) { + switch(e.type) { + case TELEDEST: { vec dir; vecfromyawpitch(e.attr1, 0, 1, 0, dir); renderentarrow(e, dir, 4); break; } case TELEPORT: - loopv(ents) if(ents[i]->type == TELEDEST && e.attr1==ents[i]->attr2) - { + loopv(ents) if(ents[i]->type == TELEDEST && e.attr1==ents[i]->attr2) { renderentarrow(e, vec(ents[i]->o).sub(e.o).normalize(), e.o.dist(ents[i]->o)); break; } break; - case JUMPPAD: renderentarrow(e, vec((int)(char)e.attr3*10.0f, (int)(char)e.attr2*10.0f, e.attr1*12.5f).normalize(), 4); break; - default: break; } } - - bool printent(extentity &e, char *buf, int len) - { + bool printent(extentity &e, char *buf, int len) { return false; } - const char *entnameinfo(entity &e) { return ""; } - const char *entname(int i) - { - static const char * const entnames[] = - { + const char *entname(int i) { + static const char * const entnames[] = { "none?", "light", "mapmodel", "playerstart", "none?", "particles", "sound", "spotlight", "shells", "bullets", "rockets", "riflerounds", "grenades", "cartridges", "health", "healthboost", "tinyhealth", "tinyarmour", "greenarmour", "yellowarmour", "quaddamage", @@ -434,9 +341,7 @@ namespace entities }; return i>=0 && size_t(i)clientnum); //add player id @@ -53,91 +48,65 @@ q.put((uchar*)&ip, 3); sendserverinforeply(q); } - - static inline void extinfoteamscore(ucharbuf &p, const char *team, int score) - { + static inline void extinfoteamscore(ucharbuf &p, const char *team, int score) { sendstring(team, p); putint(p, score); putint(p,-1); //no bases follow } - - void extinfoteams(ucharbuf &p) - { + void extinfoteams(ucharbuf &p) { putint(p, m_teammode ? 0 : 1); putint(p, gamemode); putint(p, max((gamelimit - gamemillis)/1000, 0)); if(!m_teammode) return; - vector scores; - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; - if(ci->state.state!=CS_SPECTATOR && ci->team[0] && scores.htfind(ci->team) < 0) - { + if(ci->state.state!=CS_SPECTATOR && ci->team[0] && scores.htfind(ci->team) < 0) { teaminfo *ti = teaminfos.access(ci->team); scores.add(teamscore(ci->team, ti ? ti->frags : 0)); } } loopv(scores) extinfoteamscore(p, scores[i].team, scores[i].score); } - - void extserverinforeply(ucharbuf &req, ucharbuf &p) - { + void extserverinforeply(ucharbuf &req, ucharbuf &p) { int extcmd = getint(req); // extended commands - //Build a new packet putint(p, EXT_ACK); //send ack putint(p, EXT_VERSION); //send version of extended info - - switch(extcmd) - { - case EXT_UPTIME: - { + switch(extcmd) { + case EXT_UPTIME: { putint(p, totalsecs); //in seconds break; } - - case EXT_PLAYERSTATS: - { + case EXT_PLAYERSTATS: { int cn = getint(req); //a special player, -1 for all - clientinfo *ci = NULL; - if(cn >= 0) - { + if(cn >= 0) { loopv(clients) if(clients[i]->clientnum == cn) { ci = clients[i]; break; } - if(!ci) - { + if(!ci) { putint(p, EXT_ERROR); //client requested by id was not found sendserverinforeply(p); return; } } - putint(p, EXT_NO_ERROR); //so far no error can happen anymore - ucharbuf q = p; //remember buffer position putint(q, EXT_PLAYERSTATS_RESP_IDS); //send player ids following if(ci) putint(q, ci->clientnum); else loopv(clients) putint(q, clients[i]->clientnum); sendserverinforeply(q); - if(ci) extinfoplayer(p, ci); else loopv(clients) extinfoplayer(p, clients[i]); return; } - - case EXT_TEAMSCORE: - { + case EXT_TEAMSCORE: { extinfoteams(p); break; } - - default: - { + default: { putint(p, EXT_ERROR); break; } } sendserverinforeply(p); } - diff --git a/src/fpsgame/fps.cpp b/src/fpsgame/fps.cpp index da678f6..c74f5f4 100644 --- a/src/fpsgame/fps.cpp +++ b/src/fpsgame/fps.cpp @@ -1,39 +1,28 @@ #include "game.h" -namespace game -{ +namespace game { bool intermission = false; int maptime = 0, maprealtime = 0, maplimit = -1; int respawnent = -1; int lasthit = 0, lastspawnattempt = 0; - int following = -1, followdir = 0; - fpsent *player1 = NULL; // our client vector players; // other clients int savedammo[NUMGUNS]; - bool clientoption(const char *arg) { return false; } - - void taunt() - { + void taunt() { if(player1->state!=CS_ALIVE || player1->physstatelasttaunt<1000) return; player1->lasttaunt = lastmillis; addmsg(N_TAUNT, "rc", player1); } COMMAND(taunt, ""); - - ICOMMAND(getfollow, "", (), - { + ICOMMAND(getfollow, "", (), { fpsent *f = followingplayer(); intret(f ? f->clientnum : -1); }); - - void follow(char *arg) - { - if(arg[0] ? player1->state==CS_SPECTATOR : following>=0) - { + void follow(char *arg) { + if(arg[0] ? player1->state==CS_SPECTATOR : following>=0) { following = arg[0] ? parseplayer(arg) : -1; if(following==player1->clientnum) following = -1; followdir = 0; @@ -41,20 +30,15 @@ namespace game } } COMMAND(follow, "s"); - - void nextfollow(int dir) - { - if(player1->state!=CS_SPECTATOR || clients.empty()) - { + void nextfollow(int dir) { + if(player1->state!=CS_SPECTATOR || clients.empty()) { stopfollowing(); return; } int cur = following >= 0 ? following : (dir < 0 ? clients.length() - 1 : 0); - loopv(clients) - { + loopv(clients) { cur = (cur + dir + clients.length()) % clients.length(); - if(clients[cur] && clients[cur]->state!=CS_SPECTATOR) - { + if(clients[cur] && clients[cur]->state!=CS_SPECTATOR) { if(following<0) conoutf("follow on"); following = cur; followdir = dir; @@ -65,117 +49,85 @@ namespace game } ICOMMAND(nextfollow, "i", (int *dir), nextfollow(*dir < 0 ? -1 : 1)); - const char *getclientmap() { return clientmap; } - - void resetgamestate() - { + void resetgamestate() { clearprojectiles(); clearbouncers(); } - - fpsent *spawnstate(fpsent *d) // reset player state not persistent accross spawns - { + fpsent *spawnstate(fpsent *d) { // reset player state not persistent accross spawns { d->respawn(); d->spawnstate(gamemode); return d; } - - void respawnself() - { + void respawnself() { if(ispaused()) return; - if(m_mp(gamemode)) - { + if(m_mp(gamemode)) { int seq = (player1->lifesequence<<16)|((lastmillis/1000)&0xFFFF); if(player1->respawned!=seq) { addmsg(N_TRYSPAWN, "rc", player1); player1->respawned = seq; } } - else - { + else { spawnplayer(player1); showscores(false); lasthit = 0; } } - - fpsent *pointatplayer() - { + fpsent *pointatplayer() { loopv(players) if(players[i] != player1 && intersect(players[i], player1->o, worldpos)) return players[i]; return NULL; } - - void stopfollowing() - { + void stopfollowing() { if(following<0) return; following = -1; followdir = 0; conoutf("follow off"); } - - fpsent *followingplayer(fpsent *fallback) - { + fpsent *followingplayer(fpsent *fallback) { if(player1->state!=CS_SPECTATOR || following<0) return fallback; fpsent *target = getclient(following); if(target && target->state!=CS_SPECTATOR) return target; return fallback; } - - fpsent *hudplayer() - { + fpsent *hudplayer() { if(thirdperson && allowthirdperson()) return player1; return followingplayer(player1); } - - void setupcamera() - { + void setupcamera() { fpsent *target = followingplayer(); - if(target) - { + if(target) { player1->yaw = target->yaw; player1->pitch = target->state==CS_DEAD ? 0 : target->pitch; player1->o = target->o; player1->resetinterp(); } } - - bool allowthirdperson(bool msg) - { + bool allowthirdperson(bool msg) { return player1->state==CS_SPECTATOR || player1->state==CS_EDITING || m_edit || !multiplayer(msg); } ICOMMAND(allowthirdperson, "b", (int *msg), intret(allowthirdperson(*msg!=0) ? 1 : 0)); - - bool detachcamera() - { + bool detachcamera() { fpsent *d = hudplayer(); return d->state==CS_DEAD; } - - bool collidecamera() - { - switch(player1->state) - { + bool collidecamera() { + switch(player1->state) { case CS_EDITING: return false; case CS_SPECTATOR: return followingplayer()!=NULL; } return true; } - VARP(smoothmove, 0, 75, 100); VARP(smoothdist, 0, 32, 64); - - void predictplayer(fpsent *d, bool move) - { + void predictplayer(fpsent *d, bool move) { d->o = d->newpos; d->yaw = d->newyaw; d->pitch = d->newpitch; d->roll = d->newroll; - if(move) - { + if(move) { moveplayer(d, 1, false); d->newpos = d->o; } float k = 1.0f - float(lastmillis - d->smoothmillis)/smoothmove; - if(k>0) - { + if(k>0) { d->o.add(vec(d->deltapos).mul(k)); d->yaw += d->deltayaw*k; if(d->yaw<0) d->yaw += 360; @@ -184,57 +136,42 @@ namespace game d->roll += d->deltaroll*k; } } - - void otherplayers(int curtime) - { - loopv(players) - { + void otherplayers(int curtime) { + loopv(players) { fpsent *d = players[i]; if(d == player1 || d->ai) continue; - if(d->state==CS_DEAD && d->ragdoll) moveragdoll(d); - else if(!intermission) - { + else if(!intermission) { if(lastmillis - d->lastaction >= d->gunwait) d->gunwait = 0; if(d->quadmillis) entities::checkquad(curtime, d); } - const int lagtime = totalmillis-d->lastupdate; if(!lagtime || intermission) continue; - else if(lagtime>1000 && d->state==CS_ALIVE) - { + else if(lagtime>1000 && d->state==CS_ALIVE) { d->state = CS_LAGGED; continue; } - if(d->state==CS_ALIVE || d->state==CS_EDITING) - { + if(d->state==CS_ALIVE || d->state==CS_EDITING) { if(smoothmove && d->smoothmillis>0) predictplayer(d, true); else moveplayer(d, 1, false); } else if(d->state==CS_DEAD && !d->ragdoll && lastmillis-d->lastpain<2000) moveplayer(d, 1, true); } } - - void checkslowmo() - { + void checkslowmo() { static int lastslowmohealth = 0; server::forcegamespeed(intermission ? 100 : clamp(player1->health, 25, 200)); - if(player1->healthmaxhealth && lastmillis-max(maptime, lastslowmohealth)>player1->health*player1->health/2) - { + if(player1->healthmaxhealth && lastmillis-max(maptime, lastslowmohealth)>player1->health*player1->health/2) { lastslowmohealth = lastmillis; player1->health++; } } - - void updateworld() // main game update loop - { + void updateworld() { // main game update loop { if(!maptime) { maptime = lastmillis; maprealtime = totalmillis; return; } if(!curtime) { gets2c(); if(player1->clientnum>=0) c2sinfo(); return; } - physicsframe(); ai::navigate(); - if(player1->state != CS_DEAD && !intermission) - { + if(player1->state != CS_DEAD && !intermission) { if(player1->quadmillis) entities::checkquad(curtime, player1); } updateweapons(curtime); @@ -242,19 +179,15 @@ namespace game ai::update(); moveragdolls(); gets2c(); - if(connected) - { - if(player1->state == CS_DEAD) - { + if(connected) { + if(player1->state == CS_DEAD) { if(player1->ragdoll) moveragdoll(player1); - else if(lastmillis-player1->lastpain<2000) - { + else if(lastmillis-player1->lastpain<2000) { player1->move = player1->strafe = 0; moveplayer(player1, 10, true); } } - else if(!intermission) - { + else if(!intermission) { if(player1->ragdoll) cleanragdoll(player1); moveplayer(player1, 10, true); swayhudgun(curtime); @@ -263,139 +196,98 @@ namespace game } if(player1->clientnum>=0) c2sinfo(); // do this last, to reduce the effective frame lag } - - float proximityscore(float x, float lower, float upper) - { + float proximityscore(float x, float lower, float upper) { if(x <= lower) return 1.0f; if(x >= upper) return 0.0f; float a = x - lower, b = x - upper; return (b * b) / (a * a + b * b); } - static inline float harmonicmean(float a, float b) { return a + b > 0 ? 2 * a * b / (a + b) : 0.0f; } - // avoid spawning near other players - float ratespawn(dynent *d, const extentity &e) - { + float ratespawn(dynent *d, const extentity &e) { fpsent *p = (fpsent *)d; vec loc = vec(e.o).addz(p->eyeheight); float maxrange = !m_noitems ? 400.0f : 110.0f; float minplayerdist = maxrange; - loopv(players) - { + loopv(players) { const fpsent *o = players[i]; - if(o == p) - { + if(o == p) { if(m_noitems || (o->state != CS_ALIVE && lastmillis - o->lastpain > 3000)) continue; } else if(o->state != CS_ALIVE || isteam(o->team, p->team)) continue; - vec dir = vec(o->o).sub(loc); float dist = dir.squaredlen(); if(dist >= minplayerdist*minplayerdist) continue; dist = sqrtf(dist); dir.mul(1/dist); - // scale actual distance if not in line of sight if(raycube(loc, dir, dist) < dist) dist *= 1.5f; minplayerdist = min(minplayerdist, dist); } return 1.0f - proximityscore(minplayerdist, 80.0f, maxrange); } - - void pickgamespawn(fpsent *d) - { + void pickgamespawn(fpsent *d) { int ent = d == player1 && respawnent >= 0 ? respawnent : -1; findplayerspawn(d, ent, 0); } - - void spawnplayer(fpsent *d) // place at random spawn - { + void spawnplayer(fpsent *d) { // place at random spawn { pickgamespawn(d); spawnstate(d); - if(d==player1) - { + if(d==player1) { if(editmode) d->state = CS_EDITING; else if(d->state != CS_SPECTATOR) d->state = CS_ALIVE; } else d->state = CS_ALIVE; } - VARP(spawnwait, 0, 0, 1000); - - void respawn() - { - if(player1->state==CS_DEAD) - { + void respawn() { + if(player1->state==CS_DEAD) { player1->attacking = false; respawnself(); } } COMMAND(respawn, ""); - // inputs - VARP(attackspawn, 0, 1, 1); - - void doattack(bool on) - { + void doattack(bool on) { if(!connected || intermission) return; if((player1->attacking = on) && attackspawn) respawn(); } - VARP(jumpspawn, 0, 1, 1); - - bool canjump() - { + bool canjump() { if(!connected || intermission) return false; if(jumpspawn) respawn(); return player1->state!=CS_DEAD; } - - bool allowmove(physent *d) - { + bool allowmove(physent *d) { if(d->type!=ENT_PLAYER) return true; return !((fpsent *)d)->lasttaunt || lastmillis-((fpsent *)d)->lasttaunt>=1000; } - VARP(hitsound, 0, 0, 1); - - void damaged(int damage, fpsent *d, fpsent *actor, bool local) - { + void damaged(int damage, fpsent *d, fpsent *actor, bool local) { if((d->state!=CS_ALIVE && d->state != CS_LAGGED && d->state != CS_SPAWNING) || intermission) return; - if(local) damage = d->dodamage(damage); else if(actor==player1) return; - fpsent *h = hudplayer(); - if(h!=player1 && actor==h && d!=actor) - { + if(h!=player1 && actor==h && d!=actor) { if(hitsound && lasthit != lastmillis) playsound(S_HIT); lasthit = lastmillis; } - if(d==h) - { + if(d==h) { damagecompass(damage, actor->o); } damageeffect(damage, d, d!=h); - ai::damaged(d, actor); - if(d->health<=0) { if(local) killed(d, actor); } else if(d==h) playsound(S_PAIN6); else playsound(S_PAIN1+rnd(5), &d->o); } - VARP(deathscore, 0, 1, 1); - - void deathstate(fpsent *d, bool restore) - { + void deathstate(fpsent *d, bool restore) { d->state = CS_DEAD; d->lastpain = lastmillis; if(!restore) d->deaths++; - - if(d==player1) - { + if(d==player1) { if(deathscore) showscores(true); disablezoom(); if(!restore) loopi(NUMGUNS) savedammo[i] = player1->ammo[i]; @@ -403,53 +295,41 @@ namespace game d->roll = 0; playsound(S_DIE1+rnd(2)); } - else - { + else { d->move = d->strafe = 0; d->resetinterp(); d->smoothmillis = 0; playsound(S_DIE1+rnd(2), &d->o); } } - VARP(teamcolorfrags, 0, 1, 1); - /// xolatile: HUD frag messages #define fragmessageduration (2000) - string hudfragger, hudfragged; int hudfraggun, hudfragmillis; - - void sethudfragdata(char *fragger, char *fragged, int gunid) - { + void sethudfragdata(char *fragger, char *fragged, int gunid) { copystring(hudfragger, fragger ? fragger : ""); copystring(hudfragged, fragged); hudfraggun = gunid; hudfragmillis = lastmillis; } - - void killed(fpsent *d, fpsent *actor) - { - if(d->state==CS_EDITING) - { + void killed(fpsent *d, fpsent *actor) { + if(d->state==CS_EDITING) { d->editstate = CS_DEAD; d->deaths++; if(d!=player1) d->resetinterp(); return; } else if((d->state!=CS_ALIVE && d->state != CS_LAGGED && d->state != CS_SPAWNING) || intermission) return; - fpsent *h = followingplayer(player1); int contype = d==h || actor==h ? CON_FRAG_SELF : CON_FRAG_OTHER; const char *dname = "", *aname = ""; - if(m_teammode && teamcolorfrags) - { + if(m_teammode && teamcolorfrags) { dname = teamcolorname(d, "you"); aname = teamcolorname(actor, "you"); } - else - { + else { dname = colorname(d, NULL, "", "", "you"); aname = colorname(actor, NULL, "", "", "you"); } @@ -457,22 +337,18 @@ namespace game conoutf(contype, "\f2%s got killed by %s!", dname, aname); else if(d==actor || actor->type==ENT_INANIMATE) conoutf(contype, "\f2%s suicided%s", dname, d==player1 ? "!" : ""); - else if(isteam(d->team, actor->team)) - { + else if(isteam(d->team, actor->team)) { contype |= CON_TEAMKILL; if(actor==player1) conoutf(contype, "\f6%s fragged a teammate (%s)", aname, dname); else if(d==player1) conoutf(contype, "\f6%s got fragged by a teammate (%s)", dname, aname); else conoutf(contype, "\f2%s fragged a teammate (%s)", aname, dname); } - else - { - if(d==player1) - { + else { + if(d==player1) { conoutf(contype, "\f2%s got fragged by %s", dname, aname); sethudfragdata(actor->name, d->name, actor->gunselect); } - else - { + else { conoutf(contype, "\f2%s fragged %s", aname, dname); sethudfragdata(actor->name, d->name, actor->gunselect); } @@ -480,16 +356,12 @@ namespace game deathstate(d); ai::killed(d, actor); } - - void timeupdate(int secs) - { + void timeupdate(int secs) { server::timeupdate(secs); - if(secs > 0) - { + if(secs > 0) { maplimit = lastmillis + secs*1000; } - else - { + else { intermission = true; player1->attacking = false; conoutf(CON_GAMEINFO, "\f2intermission:"); @@ -497,36 +369,26 @@ namespace game conoutf(CON_GAMEINFO, "\f2player frags: %d, deaths: %d", player1->frags, player1->deaths); int accuracy = (player1->totaldamage*100)/max(player1->totalshots, 1); conoutf(CON_GAMEINFO, "\f2player total damage dealt: %d, damage wasted: %d, accuracy(%%): %d", player1->totaldamage, player1->totalshots-player1->totaldamage, accuracy); - showscores(true); disablezoom(); - execident("intermission"); } } - ICOMMAND(getfrags, "", (), intret(player1->frags)); ICOMMAND(getflags, "", (), intret(player1->flags)); ICOMMAND(getdeaths, "", (), intret(player1->deaths)); ICOMMAND(getaccuracy, "", (), intret((player1->totaldamage*100)/max(player1->totalshots, 1))); ICOMMAND(gettotaldamage, "", (), intret(player1->totaldamage)); ICOMMAND(gettotalshots, "", (), intret(player1->totalshots)); - vector clients; - - fpsent *newclient(int cn) // ensure valid entity - { - if(cn < 0 || cn > max(0xFF, MAXCLIENTS + MAXBOTS)) - { + fpsent *newclient(int cn) { // ensure valid entity { + if(cn < 0 || cn > max(0xFF, MAXCLIENTS + MAXBOTS)) { neterr("clientnum", false); return NULL; } - if(cn == player1->clientnum) return player1; - while(cn >= clients.length()) clients.add(NULL); - if(!clients[cn]) - { + if(!clients[cn]) { fpsent *d = new fpsent; d->clientnum = cn; clients[cn] = d; @@ -534,18 +396,13 @@ namespace game } return clients[cn]; } - - fpsent *getclient(int cn) // ensure valid entity - { + fpsent *getclient(int cn) { // ensure valid entity { if(cn == player1->clientnum) return player1; return clients.inrange(cn) ? clients[cn] : NULL; } - - void clientdisconnected(int cn, bool notify) - { + void clientdisconnected(int cn, bool notify) { if(!clients.inrange(cn)) return; - if(following==cn) - { + if(following==cn) { if(followdir) nextfollow(followdir); else stopfollowing(); } @@ -560,32 +417,22 @@ namespace game DELETEP(clients[cn]); cleardynentcache(); } - - void clearclients(bool notify) - { + void clearclients(bool notify) { loopv(clients) if(clients[i]) clientdisconnected(i, notify); } - - void initclient() - { + void initclient() { player1 = spawnstate(new fpsent); filtertext(player1->name, "Anonymous", false, false, MAXNAMELEN); players.add(player1); } - VARP(showmodeinfo, 0, 1, 1); - - void startgame() - { + void startgame() { clearprojectiles(); clearbouncers(); clearragdolls(); - clearteaminfo(); - // reset perma-state - loopv(players) - { + loopv(players) { fpsent *d = players[i]; d->frags = d->flags = 0; d->deaths = 0; @@ -596,106 +443,74 @@ namespace game d->lifesequence = -1; d->respawned = d->suicided = -2; } - intermission = false; maptime = maprealtime = 0; maplimit = -1; - conoutf(CON_GAMEINFO, "\f2game mode is %s", server::modename(gamemode)); - const char *info = m_valid(gamemode) ? gamemodes[gamemode - STARTGAMEMODE].info : NULL; if(showmodeinfo && info) conoutf(CON_GAMEINFO, "\f0%s", info); - showscores(false); disablezoom(); lasthit = 0; - execident("mapstart"); } - - void loadingmap(const char *name) - { + void loadingmap(const char *name) { execident("playsong"); } - - void startmap(const char *name) // called just after a map load - { + void startmap(const char *name) { // called just after a map load { pwreset(); ai::savewaypoints(); ai::clearwaypoints(true); - respawnent = -1; // so we don't respawn at an old spot if(!m_mp(gamemode)) spawnplayer(player1); else findplayerspawn(player1, -1); entities::resetspawns(); copystring(clientmap, name ? name : ""); - sendmapinfo(); } - - const char *getmapinfo() - { + const char *getmapinfo() { return showmodeinfo && m_valid(gamemode) ? gamemodes[gamemode - STARTGAMEMODE].info : NULL; } - - const char *getscreenshotinfo() - { + const char *getscreenshotinfo() { return server::modename(gamemode, NULL); } - - void physicstrigger(physent *d, bool local, int floorlevel, int material) - { + void physicstrigger(physent *d, bool local, int floorlevel, int material) { if(d->type==ENT_INANIMATE) return; if (floorlevel>0) { if(d==player1 || d->type!=ENT_PLAYER || ((fpsent *)d)->ai) msgsound(S_JUMP, d); } else if(floorlevel<0) { if(d==player1 || d->type!=ENT_PLAYER || ((fpsent *)d)->ai) msgsound(S_LAND, d); } } - - void dynentcollide(physent *d, physent *o, const vec &dir) - { + void dynentcollide(physent *d, physent *o, const vec &dir) { return; } - - void msgsound(int n, physent *d) - { - if(!d || d==player1) - { + void msgsound(int n, physent *d) { + if(!d || d==player1) { addmsg(N_SOUND, "ci", d, n); playsound(n); } - else - { + else { if(d->type==ENT_PLAYER && ((fpsent *)d)->ai) addmsg(N_SOUND, "ci", d, n); playsound(n, &d->o); } } - int numdynents() { return players.length(); } - - dynent *iterdynents(int i) - { + dynent *iterdynents(int i) { if(iname; if(alt && d != player1 && !strcmp(name, alt)) return true; loopv(players) if(d!=players[i] && !strcmp(name, players[i]->name)) return true; return false; } - static string cname[3]; static int cidx = 0; - - const char *colorname(fpsent *d, const char *name, const char *prefix, const char *suffix, const char *alt) - { + const char *colorname(fpsent *d, const char *name, const char *prefix, const char *suffix, const char *alt) { if(!name) name = alt && d == player1 ? alt : d->name; bool dup = !name[0] || duplicatename(d, name, alt) || d->aitype != AI_NONE; - if(dup || prefix[0] || suffix[0]) - { + if(dup || prefix[0] || suffix[0]) { cidx = (cidx+1)%3; if(dup) formatstring(cname[cidx], d->aitype == AI_NONE ? "%s%s \fs\f5(%d)\fr%s" : "%s%s \fs\f5[%d]\fr%s", prefix, name, d->clientnum, suffix); else formatstring(cname[cidx], "%s%s%s", prefix, name, suffix); @@ -703,58 +518,40 @@ namespace game } return name; } - VARP(teamcolortext, 0, 1, 1); - - const char *teamcolorname(fpsent *d, const char *alt) - { + const char *teamcolorname(fpsent *d, const char *alt) { if(!teamcolortext || !m_teammode || d->state==CS_SPECTATOR) return colorname(d, NULL, "", "", alt); return colorname(d, NULL, isteam(d->team, player1->team) ? "\fs\f1" : "\fs\f3", "\fr", alt); } - - const char *teamcolor(const char *name, bool sameteam, const char *alt) - { + const char *teamcolor(const char *name, bool sameteam, const char *alt) { if(!teamcolortext || !m_teammode) return sameteam || !alt ? name : alt; cidx = (cidx+1)%3; formatstring(cname[cidx], sameteam ? "\fs\f1%s\fr" : "\fs\f3%s\fr", sameteam || !alt ? name : alt); return cname[cidx]; } - - const char *teamcolor(const char *name, const char *team, const char *alt) - { + const char *teamcolor(const char *name, const char *team, const char *alt) { return teamcolor(name, team && isteam(team, player1->team), alt); } - VARP(teamsounds, 0, 1, 1); - - void teamsound(bool sameteam, int n, const vec *loc) - { + void teamsound(bool sameteam, int n, const vec *loc) { playsound(n, loc, NULL, teamsounds ? (m_teammode && sameteam ? SND_USE_ALT : SND_NO_ALT) : 0); } - - void teamsound(fpsent *d, int n, const vec *loc) - { + void teamsound(fpsent *d, int n, const vec *loc) { teamsound(isteam(d->team, player1->team), n, loc); } - - void suicide(physent *d) - { - if(d==player1 || (d->type==ENT_PLAYER && ((fpsent *)d)->ai)) - { + void suicide(physent *d) { + if(d==player1 || (d->type==ENT_PLAYER && ((fpsent *)d)->ai)) { if(d->state!=CS_ALIVE) return; fpsent *pl = (fpsent *)d; if(!m_mp(gamemode)) killed(pl, pl); - else - { + else { int seq = (pl->lifesequence<<16)|((lastmillis/1000)&0xFFFF); if(pl->suicided!=seq) { addmsg(N_SUICIDE, "rc", pl); pl->suicided = seq; } } } } ICOMMAND(suicide, "", (), suicide(player1)); - - void drawicon(int icon, float x, float y, float sz) - { + void drawicon(int icon, float x, float y, float sz) { settexture("packages/hud/items.png"); float tsz = 0.25f, tx = tsz*(icon%4), ty = tsz*(icon/4); gle::defvertex(2); @@ -766,11 +563,8 @@ namespace game gle::attribf(x+sz, y+sz); gle::attribf(tx+tsz, ty+tsz); gle::end(); } - - float abovegameplayhud(int w, int h) - { - switch(hudplayer()->state) - { + float abovegameplayhud(int w, int h) { + switch(hudplayer()->state) { case CS_EDITING: case CS_SPECTATOR: return 1; @@ -778,61 +572,47 @@ namespace game return 1650.0f/1800.0f; } } - int ammohudup[3] = { GUN_CG, GUN_RL, GUN_GL }, ammohuddown[3] = { GUN_RIFLE, GUN_SG, GUN_PISTOL }, ammohudcycle[7] = { -1, -1, -1, -1, -1, -1, -1 }; - - ICOMMAND(ammohudup, "V", (tagval *args, int numargs), - { + ICOMMAND(ammohudup, "V", (tagval *args, int numargs), { loopi(3) ammohudup[i] = i < numargs ? getweapon(args[i].getstr()) : -1; }); - - ICOMMAND(ammohuddown, "V", (tagval *args, int numargs), - { + ICOMMAND(ammohuddown, "V", (tagval *args, int numargs), { loopi(3) ammohuddown[i] = i < numargs ? getweapon(args[i].getstr()) : -1; }); - - ICOMMAND(ammohudcycle, "V", (tagval *args, int numargs), - { + ICOMMAND(ammohudcycle, "V", (tagval *args, int numargs), { loopi(7) ammohudcycle[i] = i < numargs ? getweapon(args[i].getstr()) : -1; }); - VARP(ammohud, 0, 1, 1); - - void drawammohud(fpsent *d) - { + void drawammohud(fpsent *d) { float x = HICON_X + 2*HICON_STEP, y = HICON_Y, sz = HICON_SIZE; pushhudmatrix(); hudmatrix.scale(1/3.2f, 1/3.2f, 1); flushhudmatrix(); float xup = (x+sz)*3.2f, yup = y*3.2f + 0.1f*sz; - loopi(3) - { + loopi(3) { int gun = ammohudup[i]; if(gun < GUN_FIST || gun > GUN_PISTOL || gun == d->gunselect || !d->ammo[gun]) continue; drawicon(HICON_FIST+gun, xup, yup, sz); yup += sz; } float xdown = x*3.2f - sz, ydown = (y+sz)*3.2f - 0.1f*sz; - loopi(3) - { + loopi(3) { int gun = ammohuddown[3-i-1]; if(gun < GUN_FIST || gun > GUN_PISTOL || gun == d->gunselect || !d->ammo[gun]) continue; ydown -= sz; drawicon(HICON_FIST+gun, xdown, ydown, sz); } int offset = 0, num = 0; - loopi(7) - { + loopi(7) { int gun = ammohudcycle[i]; if(gun < GUN_FIST || gun > GUN_PISTOL) continue; if(gun == d->gunselect) offset = i + 1; else if(d->ammo[gun]) num++; } float xcycle = (x+sz/2)*3.2f + 0.5f*num*sz, ycycle = y*3.2f-sz; - loopi(7) - { + loopi(7) { int gun = ammohudcycle[(i + offset)%7]; if(gun < GUN_FIST || gun > GUN_PISTOL || gun == d->gunselect || !d->ammo[gun]) continue; xcycle -= sz; @@ -840,9 +620,7 @@ namespace game } pophudmatrix(); } - - void hudquad(float x, float y, float w, float h, float r = 1, float g = 1, float b = 1, float tx = 0, float ty = 0, float tw = 1, float th = 1) - { + void hudquad(float x, float y, float w, float h, float r = 1, float g = 1, float b = 1, float tx = 0, float ty = 0, float tw = 1, float th = 1) { gle::defvertex(2); gle::deftexcoord0(); gle::colorf(r, g, b); @@ -853,20 +631,15 @@ namespace game gle::attribf(x+w, y+h); gle::attribf(tx + tw, ty + th); gle::end(); } - VARP(healthcolors, 0, 1, 1); - VARP(hudhealth, 0, 1, 1); FVARP(hudhealthx, 0, 0, 1); FVARP(hudhealthy, 0, 1, 1); FVARP(hudhealthscale, 0.1, 1.0, 1.0); - - void drawhudhealth(fpsent *d, int w, int h) - { + void drawhudhealth(fpsent *d, int w, int h) { pushhudmatrix(); hudmatrix.scale(hudhealthscale, hudhealthscale, 1); flushhudmatrix(); - bvec healthcolor = bvec::hexcolor(healthcolors && !m_insta ? (d->state==CS_DEAD ? 0x808080 : (d->health<=25 ? 0xc02020 : @@ -889,21 +662,16 @@ namespace game defformatstring(health, "%d", d->state==CS_DEAD ? 0 : d->health); float tw=0, th=0; text_boundsf(health, tw, th); draw_text(health, offset.x+(125*proportion-tw)/2, offset.y+(healthbarh-th)/2, healthcolor.r, healthcolor.g, healthcolor.b); - pophudmatrix(); } - VARP(hudmaxhealth, 0, 1, 1); FVARP(hudmaxhealthx, 0, 0.207, 1); FVARP(hudmaxhealthy, 0, 0.97, 1); FVARP(hudmaxhealthscale, 0.1, 1.0, 1.0); - - void drawhudmaxhealth(fpsent *d, int w, int h) - { + void drawhudmaxhealth(fpsent *d, int w, int h) { pushhudmatrix(); hudmatrix.scale(hudmaxhealthscale, hudmaxhealthscale, 1); flushhudmatrix(); - const float proportion = (w/15.0f)/160.0f; const float healthboostw = 160*proportion; const float healthboosth = 78*proportion; @@ -917,23 +685,17 @@ namespace game settexture("packages/hud/health_boost_quad.png"); hudquad(offset.x, offset.y, healthboostw, healthboosth); } - pophudmatrix(); } - VARP(armourcolors, 0, 1, 1); - VARP(hudarmour, 0, 1, 1); FVARP(hudarmourx, 0, 1, 1); FVARP(hudarmoury, 0, 1, 1); FVARP(hudarmourscale, 0.1, 1.0, 1.0); - - void drawhudarmour(fpsent *d, int w, int h) - { + void drawhudarmour(fpsent *d, int w, int h) { pushhudmatrix(); hudmatrix.scale(hudarmourscale, hudarmourscale, 1); flushhudmatrix(); - bvec armourcolor = bvec::hexcolor(d->armourtype == A_BLUE ? 0x83ade5 : (d->armourtype == A_GREEN ? 0x77f29e : (d->armourtype == A_YELLOW ? 0xf5f19b : 0xffffff))); const float proportion = (w/4.0f)/600.0f; const float armourbarw = 600*proportion; @@ -951,25 +713,19 @@ namespace game defformatstring(armour, "%d", d->state==CS_DEAD ? 0 : d->armour); float tw=0, th=0; text_boundsf(armour, tw, th); draw_text(armour, offset.x+(2*(600-63)*proportion-tw)/2, offset.y+(armourbarh-th)/2, armourcolor.r, armourcolor.g, armourcolor.b); - pophudmatrix(); } - - void drawhudicons(fpsent *d, int w, int h) - { + void drawhudicons(fpsent *d, int w, int h) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - if(hudhealth) drawhudhealth(d, w, h); if(hudmaxhealth) drawhudmaxhealth(d, w, h); if(hudarmour) drawhudarmour(d, w, h); - if(d->state!=CS_DEAD) { drawicon(HICON_FIST+d->gunselect, HICON_X + 2*HICON_STEP, HICON_Y); if(ammohud) drawammohud(d); } } - VARP(gameclock, 0, 0, 1); FVARP(gameclockscale, 1e-3f, 0.75f, 1e3f); HVARP(gameclockcolour, 0, 0xFFFFFF, 0xFFFFFF); @@ -978,34 +734,25 @@ namespace game VARP(gameclockalign, -1, 0, 1); FVARP(gameclockx, 0, 0.50f, 1); FVARP(gameclocky, 0, 0.03f, 1); - - void drawgameclock(int w, int h) - { + void drawgameclock(int w, int h) { int secs = max(maplimit-lastmillis + 999, 0)/1000, mins = secs/60; secs %= 60; - defformatstring(buf, "%d:%02d", mins, secs); int tw = 0, th = 0; text_bounds(buf, tw, th); - vec2 offset = vec2(gameclockx, gameclocky).mul(vec2(w, h).div(gameclockscale)); if(gameclockalign == 1) offset.x -= tw; else if(gameclockalign == 0) offset.x -= tw/2.0f; offset.y -= th/2.0f; - pushhudmatrix(); hudmatrix.scale(gameclockscale, gameclockscale, 1); flushhudmatrix(); - int color = mins < 1 ? gameclocklowcolour : gameclockcolour; draw_text(buf, int(offset.x), int(offset.y), (color>>16)&0xFF, (color>>8)&0xFF, color&0xFF, gameclockalpha); - pophudmatrix(); } - extern int hudscore; extern void drawhudscore(int w, int h); - VARP(ammobar, 0, 0, 1); VARP(ammobaralign, -1, 0, 1); VARP(ammobarhorizontal, 0, 0, 1); @@ -1017,77 +764,58 @@ namespace game FVARP(ammobarx, 0, 0.025f, 1.0f); FVARP(ammobary, 0, 0.5f, 1.0f); FVARP(ammobarscale, 0.1f, 0.5f, 1.0f); - - void drawammobarcounter(const vec2 ¢er, const fpsent *p, int gun) - { + void drawammobarcounter(const vec2 ¢er, const fpsent *p, int gun) { vec2 icondrawpos = vec2(center).sub(HICON_SIZE / 2); int alpha = p->ammo[gun] ? 0xFF : 0x7F; gle::color(bvec(0xFF, 0xFF, 0xFF), alpha); drawicon(HICON_FIST + gun, icondrawpos.x, icondrawpos.y); - int fw, fh; text_bounds("000", fw, fh); float labeloffset = HICON_SIZE / 2.0f + ammobarcountsep + ammobarcountscale * (ammobarhorizontal ? fh : fw) / 2.0f; vec2 offsetdir = (ammobarhorizontal ? vec2(0, 1) : vec2(1, 0)).mul(ammobarflip ? -1 : 1); vec2 labelorigin = vec2(offsetdir).mul(labeloffset).add(center); - pushhudmatrix(); hudmatrix.translate(labelorigin.x, labelorigin.y, 0); hudmatrix.scale(ammobarcountscale, ammobarcountscale, 1); flushhudmatrix(); - defformatstring(label, "%d", p->ammo[gun]); int tw, th; text_bounds(label, tw, th); vec2 textdrawpos = vec2(-tw, -th).div(2); float ammoratio = (float)p->ammo[gun] / itemstats[gun-GUN_SG].add; bvec color = bvec::hexcolor(p->ammo[gun] == 0 || ammoratio >= 1.0f ? 0xFFFFFF : (ammoratio >= 0.5f ? 0xFFC040 : 0xFF0000)); draw_text(label, textdrawpos.x, textdrawpos.y, color.r, color.g, color.b, alpha); - pophudmatrix(); } - - static inline bool ammobargunvisible(const fpsent *d, int gun) - { + static inline bool ammobargunvisible(const fpsent *d, int gun) { return d->ammo[gun] > 0 || d->gunselect == gun; } - - void drawammobar(int w, int h, fpsent *p) - { + void drawammobar(int w, int h, fpsent *p) { if(m_insta) return; - int NUMPLAYERGUNS = GUN_PISTOL - GUN_SG + 1; int numvisibleguns = NUMPLAYERGUNS; if(ammobarhideempty) loopi(NUMPLAYERGUNS) if(!ammobargunvisible(p, GUN_SG + i)) numvisibleguns--; - vec2 origin = vec2(ammobarx, ammobary).mul(vec2(w, h).div(ammobarscale)); vec2 offsetdir = ammobarhorizontal ? vec2(1, 0) : vec2(0, 1); float stepsize = HICON_SIZE + ammobarsep; float initialoffset = (ammobaralign - 1) * (numvisibleguns - 1) * stepsize / 2; - pushhudmatrix(); hudmatrix.scale(ammobarscale, ammobarscale, 1); flushhudmatrix(); - int numskippedguns = 0; - loopi(NUMPLAYERGUNS) if(ammobargunvisible(p, GUN_SG + i) || !ammobarhideempty) - { + loopi(NUMPLAYERGUNS) if(ammobargunvisible(p, GUN_SG + i) || !ammobarhideempty) { float offset = initialoffset + (i - numskippedguns) * stepsize; vec2 drawpos = vec2(offsetdir).mul(offset).add(origin); drawammobarcounter(drawpos, p, GUN_SG + i); } else numskippedguns++; - pophudmatrix(); } - VARP(speedometer, 0, 1, 1); FVARP(speedometerx, 0.0, 0.5, 1.0); FVARP(speedometery, 0.0, 0.6, 1.0); FVARP(speedometerscale, 0.1, 0.5, 1.0); VARP(speedometercolor, 0, 1, 1); FVARP(speedometeralpha, 0.0, 0.5, 1.0); - - void drawspeedometer(fpsent *d, int w, int h) - { + void drawspeedometer(fpsent *d, int w, int h) { int speedforreal = (int) (sqrtf(d->vel.squaredlen()) + 1.0f); speedforreal = (speedforreal == 1) ? 0 : speedforreal; vec colour = vec(255, 255, 255); @@ -1101,35 +829,26 @@ namespace game else if (speedforreal>180 && speedforreal<=240) colour = vec(90, 180, 60); else colour = vec(30, 240, 30); } - defformatstring(speedstring, "%d", speedforreal); text_boundsf(speedstring, realw, realh); vec2 offset = vec2(speedometerx, speedometery).mul(vec2(w, h).div(speedometerscale)); offset.x -= realw/2.0f; offset.y -= realh/2.0f; - pushhudmatrix(); hudmatrix.scale(speedometerscale, speedometerscale, 1); flushhudmatrix(); - const int speedow = 220; const int speedoh = 101; settexture("packages/hud/speedometer.png"); hudquad(offset.x+realw/2.0f-speedow/2, offset.y+realh/2.0f-speedoh/2, speedow, speedoh); - draw_text(speedstring, int(offset.x), int(offset.y), colour.x, colour.y, colour.z, (int)(speedometeralpha*255.0f)); - pophudmatrix(); } - - void gameplayhud(int w, int h) - { + void gameplayhud(int w, int h) { pushhudmatrix(); hudmatrix.scale(h/1800.0f, h/1800.0f, 1); flushhudmatrix(); - - if(player1->state==CS_SPECTATOR) - { + if(player1->state==CS_SPECTATOR) { int pw, ph, tw, th, fw, fh; text_bounds(" ", pw, ph); text_bounds("SPECTATOR", tw, th); @@ -1138,36 +857,25 @@ namespace game text_bounds(f ? colorname(f) : " ", fw, fh); fh = max(fh, ph); draw_text("SPECTATOR", w*1800/h - tw - pw, 1650 - th - fh); - if(f) - { + if(f) { int color = statuscolor(f, 0xFFFFFF); draw_text(colorname(f), w*1800/h - fw - pw, 1650 - fh, (color>>16)&0xFF, (color>>8)&0xFF, color&0xFF); } } - fpsent *d = hudplayer(); - pophudmatrix(); - if(d->state!=CS_EDITING && d->state!=CS_SPECTATOR) drawhudicons(d, w, h); - - if(d->state!=CS_EDITING && d->state!=CS_SPECTATOR && d->state!=CS_DEAD) - { + if(d->state!=CS_EDITING && d->state!=CS_SPECTATOR && d->state!=CS_DEAD) { if(ammobar) drawammobar(w, h, d); if(speedometer) drawspeedometer(d, w, h); } - - if(!m_edit) - { + if(!m_edit) { if(gameclock) drawgameclock(w, h); if(hudscore) drawhudscore(w, h); } - /// Frag message. - - if((hudfragmillis+fragmessageduration > lastmillis) && (lastmillis>fragmessageduration)) - { + if((hudfragmillis+fragmessageduration > lastmillis) && (lastmillis>fragmessageduration)) { vec2 center = vec2(0.5*w, 0.2*h); float width = 0, height = 0; pushhudmatrix(); @@ -1180,69 +888,49 @@ namespace game pophudmatrix(); } } - - int clipconsole(int w, int h) - { + int clipconsole(int w, int h) { return 0; } - VARP(teamcrosshair, 0, 1, 1); VARP(hitcrosshair, 0, 425, 1000); - - const char *defaultcrosshair(int index) - { - switch(index) - { + const char *defaultcrosshair(int index) { + switch(index) { case 2: return "data/hit.png"; case 1: return "data/teammate.png"; default: return "data/crosshair.png"; } } - - int selectcrosshair(vec &color) - { + int selectcrosshair(vec &color) { fpsent *d = hudplayer(); if(d->state==CS_SPECTATOR || d->state==CS_DEAD) return -1; - if(d->state!=CS_ALIVE) return 0; - int crosshair = 0; if(lasthit && lastmillis - lasthit < hitcrosshair) crosshair = 2; - else if(teamcrosshair) - { + else if(teamcrosshair) { dynent *o = intersectclosest(d->o, worldpos, d); - if(o && o->type==ENT_PLAYER && isteam(((fpsent *)o)->team, d->team)) - { + if(o && o->type==ENT_PLAYER && isteam(((fpsent *)o)->team, d->team)) { crosshair = 1; color = vec(0, 0, 1); } } - - if(crosshair!=1 && !editmode && !m_insta) - { + if(crosshair!=1 && !editmode && !m_insta) { if(d->health<=25) color = vec(1, 0, 0); else if(d->health<=50) color = vec(1, 0.5f, 0); } if(d->gunwait) color.mul(0.5f); return crosshair; } - - void lighteffects(dynent *e, vec &color, vec &dir) - { + void lighteffects(dynent *e, vec &color, vec &dir) { #if 0 fpsent *d = (fpsent *)e; - if(d->state!=CS_DEAD && d->quadmillis) - { + if(d->state!=CS_DEAD && d->quadmillis) { float t = 0.5f + 0.5f*sinf(2*M_PI*lastmillis/1000.0f); color.y = color.y*(1-t) + t; } #endif } - - int maxsoundradius(int n) - { - switch(n) - { + int maxsoundradius(int n) { + switch(n) { case S_JUMP: case S_LAND: case S_WEAPLOAD: @@ -1258,11 +946,9 @@ namespace game return 500; } } - - bool serverinfostartcolumn(g3d_gui *g, int i) - { + bool serverinfostartcolumn(g3d_gui *g, int i) { static const char * const names[] = { "ping ", "players ", "mode ", "map ", "time ", "master ", "host ", "port ", "description " }; - static const float struts[] = { 7, 7, 12.5f, 14, 7, 8, 14, 7, 24.5f }; + static const float struts[] = { 7, 7, 12.5f, 14, 7, 8, 14, 7, 24.5f }; if(size_t(i) >= sizeof(names)/sizeof(names[0])) return false; g->pushlist(); g->text(names[i], 0xFFFF80, !i ? " " : NULL); @@ -1270,34 +956,23 @@ namespace game g->mergehits(true); return true; } - - void serverinfoendcolumn(g3d_gui *g, int i) - { + void serverinfoendcolumn(g3d_gui *g, int i) { g->mergehits(false); g->column(i); g->poplist(); } - - const char *mastermodecolor(int n, const char *unknown) - { + const char *mastermodecolor(int n, const char *unknown) { return (n>=MM_START && size_t(n-MM_START)=MM_START && size_t(n-MM_START) &attr, int np) - { - if(ping < 0 || attr.empty() || attr[0]!=PROTOCOL_VERSION) - { - switch(i) - { + bool serverinfoentry(g3d_gui *g, int i, const char *name, int port, const char *sdesc, const char *map, int ping, const vector &attr, int np) { + if(ping < 0 || attr.empty() || attr[0]!=PROTOCOL_VERSION) { + switch(i) { case 0: if(g->button(" ", 0xFFFFDD, "serverunk")&G3D_UP) return true; break; - case 1: case 2: case 3: @@ -1305,18 +980,14 @@ namespace game case 5: if(g->button(" ", 0xFFFFDD)&G3D_UP) return true; break; - case 6: if(g->buttonf("%s ", 0xFFFFDD, NULL, name)&G3D_UP) return true; break; - case 7: if(g->buttonf("%d ", 0xFFFFDD, NULL, port)&G3D_UP) return true; break; - case 8: - if(ping < 0) - { + if(ping < 0) { if(g->button(sdesc, 0xFFFFDD)&G3D_UP) return true; } else if(g->buttonf("[%s protocol] ", 0xFFFFDD, NULL, attr.empty() ? "unknown" : (attr[0] < PROTOCOL_VERSION ? "older" : "newer"))&G3D_UP) return true; @@ -1324,35 +995,26 @@ namespace game } return false; } - - switch(i) - { - case 0: - { + switch(i) { + case 0: { const char *icon = attr.inrange(3) && np >= attr[3] ? "serverfull" : (attr.inrange(4) ? mastermodeicon(attr[4], "serverunk") : "serverunk"); if(g->buttonf("%d ", 0xFFFFDD, icon, ping)&G3D_UP) return true; break; } - case 1: - if(attr.length()>=4) - { + if(attr.length()>=4) { if(g->buttonf(np >= attr[3] ? "\f3%d/%d " : "%d/%d ", 0xFFFFDD, NULL, np, attr[3])&G3D_UP) return true; } else if(g->buttonf("%d ", 0xFFFFDD, NULL, np)&G3D_UP) return true; break; - case 2: if(g->buttonf("%s ", 0xFFFFDD, NULL, attr.length()>=2 ? server::modename(attr[1], "") : "")&G3D_UP) return true; break; - case 3: if(g->buttonf("%.25s ", 0xFFFFDD, NULL, map)&G3D_UP) return true; break; - case 4: - if(attr.length()>=3 && attr[2] > 0) - { + if(attr.length()>=3 && attr[2] > 0) { int secs = clamp(attr[2], 0, 59*60+59), mins = secs/60; secs %= 60; @@ -1363,36 +1025,28 @@ namespace game case 5: if(g->buttonf("%s%s ", 0xFFFFDD, NULL, attr.length()>=5 ? mastermodecolor(attr[4], "") : "", attr.length()>=5 ? server::mastermodename(attr[4], "") : "")&G3D_UP) return true; break; - case 6: if(g->buttonf("%s ", 0xFFFFDD, NULL, name)&G3D_UP) return true; break; - case 7: if(g->buttonf("%d ", 0xFFFFDD, NULL, port)&G3D_UP) return true; break; - case 8: if(g->buttonf("%.25s", 0xFFFFDD, NULL, sdesc)&G3D_UP) return true; break; } return false; } - // any data written into this vector will get saved with the map data. Must take care to do own versioning, and endianess if applicable. Will not get called when loading maps from other games, so provide defaults. void writegamedata(vector &extras) {} void readgamedata(vector &extras) {} - const char *savedconfig() { return "config.cfg"; } const char *restoreconfig() { return "restore.cfg"; } const char *defaultconfig() { return "data/defaults.cfg"; } const char *autoexec() { return "autoexec.cfg"; } const char *savedservers() { return "servers.cfg"; } - - void loadconfigs() - { + void loadconfigs() { execident("playsong"); - execfile("auth.cfg", false); } } diff --git a/src/fpsgame/game.h b/src/fpsgame/game.h index 3cdbba3..974f1f3 100644 --- a/src/fpsgame/game.h +++ b/src/fpsgame/game.h @@ -5,8 +5,7 @@ // console message types -enum -{ +enum { CON_CHAT = 1<<8, CON_TEAMCHAT = 1<<9, CON_GAMEINFO = 1<<10, @@ -20,8 +19,7 @@ enum #define DNF 100.0f // for normalized vectors #define DVELF 1.0f // for playerspeed based velocity vectors -enum // static entity types -{ +enum { // static entity types { NOTUSED = ET_EMPTY, // entity slot not in use in map LIGHT = ET_LIGHT, // lightsource, attr1 = radius, attr2 = intensity MAPMODEL = ET_MAPMODEL, // attr1 = angle, attr2 = idx @@ -41,10 +39,9 @@ enum // static entity types }; enum { GUN_FIST = 0, GUN_SG, GUN_CG, GUN_RL, GUN_RIFLE, GUN_GL, GUN_PISTOL, NUMGUNS }; -enum { A_BLUE, A_GREEN, A_YELLOW }; // armour types... take 20/40/60 % off +enum { A_BLUE, A_GREEN, A_YELLOW }; // armour types... take 20/40/60 % off INCORRECT! -enum -{ +enum { M_TEAM = 1<<0, M_NOITEMS = 1<<1, M_NOAMMO = 1<<2, @@ -56,21 +53,20 @@ enum M_LOBBY = 1<<15 }; -static struct gamemodeinfo -{ +static struct gamemodeinfo { const char *name; int flags; const char *info; -} gamemodes[] = -{ - { "demo", M_DEMO | M_LOCAL, NULL}, - { "ffa", M_LOBBY, "Free For All: Collect items for ammo. Frag everyone to score points." }, - { "coop edit", M_EDIT, "Cooperative Editing: Edit maps with multiple players simultaneously." }, - { "teamplay", M_TEAM, "Teamplay: Collect items for ammo. Frag \fs\f3the enemy team\fr to score points for \fs\f1your team\fr." }, - { "instagib", M_NOITEMS | M_INSTA, "Instagib: You spawn with full rifle ammo and die instantly from one shot. There are no items. Frag everyone to score points." }, - { "insta team", M_NOITEMS | M_INSTA | M_TEAM, "Instagib Team: You spawn with full rifle ammo and die instantly from one shot. There are no items. Frag \fs\f3the enemy team\fr to score points for \fs\f1your team\fr." }, - { "efficiency", M_NOITEMS | M_EFFICIENCY, "Efficiency: You spawn with all weapons and armour. There are no items. Frag everyone to score points." }, - { "effic team", M_NOITEMS | M_EFFICIENCY | M_TEAM, "Efficiency Team: You spawn with all weapons and armour. There are no items. Frag \fs\f3the enemy team\fr to score points for \fs\f1your team\fr." }, +} gamemodes[] = { + { + "demo", M_DEMO | M_LOCAL, NULL}, { + "ffa", M_LOBBY, "Free For All: Collect items for ammo. Frag everyone to score points." }, { + "coop edit", M_EDIT, "Cooperative Editing: Edit maps with multiple players simultaneously." }, { + "teamplay", M_TEAM, "Teamplay: Collect items for ammo. Frag \fs\f3the enemy team\fr to score points for \fs\f1your team\fr." }, { + "instagib", M_NOITEMS | M_INSTA, "Instagib: You spawn with full rifle ammo and die instantly from one shot. There are no items. Frag everyone to score points." }, { + "insta team", M_NOITEMS | M_INSTA | M_TEAM, "Instagib Team: You spawn with full rifle ammo and die instantly from one shot. There are no items. Frag \fs\f3the enemy team\fr to score points for \fs\f1your team\fr." }, { + "efficiency", M_NOITEMS | M_EFFICIENCY, "Efficiency: You spawn with all weapons and armour. There are no items. Frag everyone to score points." }, { + "effic team", M_NOITEMS | M_EFFICIENCY | M_TEAM, "Efficiency Team: You spawn with all weapons and armour. There are no items. Frag \fs\f3the enemy team\fr to score points for \fs\f1your team\fr." }, }; #define STARTGAMEMODE (-1) @@ -98,13 +94,12 @@ static struct gamemodeinfo enum { MM_AUTH = -1, MM_OPEN = 0, MM_VETO, MM_LOCKED, MM_PRIVATE, MM_PASSWORD, MM_START = MM_AUTH }; -static const char * const mastermodenames[] = { "auth", "open", "veto", "locked", "private", "password" }; +static const char * const mastermodenames[] = { "auth", "open", "veto", "locked", "private", "password" }; static const char * const mastermodecolors[] = { "", "\f0", "\f2", "\f2", "\f3", "\f3" }; -static const char * const mastermodeicons[] = { "server", "server", "serverlock", "serverlock", "serverpriv", "serverpriv" }; +static const char * const mastermodeicons[] = { "server", "server", "serverlock", "serverlock", "serverpriv", "serverpriv" }; // hardcoded sounds, defined in sounds.cfg -enum -{ +enum { S_JUMP = 0, S_LAND, S_RIFLE, S_PUNCH1, S_SG, S_CG, S_RLFIRE, S_RLHIT, S_WEAPLOAD, S_ITEMAMMO, S_ITEMHEALTH, S_ITEMARMOUR, S_ITEMPUP, S_ITEMSPAWN, S_TELEPORT, S_NOAMMO, S_PUPOUT, @@ -113,15 +108,12 @@ enum S_FLAUNCH, S_FEXPLODE, S_SPLASH1, S_SPLASH2, S_JUMPPAD, S_PISTOL, - S_V_FIGHT, S_V_BOOST, S_V_BOOST10, S_V_QUAD, S_V_QUAD10, - S_BURN, S_CHAINSAW_ATTACK, S_CHAINSAW_IDLE, - S_HIT }; @@ -129,8 +121,7 @@ enum enum { PRIV_NONE = 0, PRIV_MASTER, PRIV_AUTH, PRIV_ADMIN }; -enum -{ +enum { N_CONNECT = 0, N_SERVINFO, N_WELCOME, N_INITCLIENT, N_POS, N_TEXT, N_SOUND, N_CDIS, N_SHOOT, N_EXPLODE, N_SUICIDE, N_DIED, N_DAMAGE, N_HITPUSH, N_SHOTFX, N_EXPLODEFX, @@ -157,8 +148,7 @@ enum NUMMSG }; -static const int msgsizes[] = // size inclusive message token, 0 for variable or not-checked sizes -{ +static const int msgsizes[] = { // size inclusive message token, 0 for variable or not-checked sizes { N_CONNECT, 0, N_SERVINFO, 0, N_WELCOME, 1, N_INITCLIENT, 0, N_POS, 0, N_TEXT, 0, N_SOUND, 2, N_CDIS, 2, N_SHOOT, 0, N_EXPLODE, 0, N_SUICIDE, 1, N_DIED, 5, N_DAMAGE, 6, N_HITPUSH, 7, N_SHOTFX, 10, N_EXPLODEFX, 4, @@ -193,8 +183,7 @@ static const int msgsizes[] = // size inclusive message token, 0 for variab #define DEMO_VERSION 1 // bump when demo format changes #define DEMO_MAGIC "SAUERBRATEN_DEMO" -struct demoheader -{ +struct demoheader { char magic[16]; int version, protocol; }; @@ -202,14 +191,11 @@ struct demoheader #define MAXNAMELEN 15 #define MAXTEAMLEN 4 -enum -{ +enum { HICON_BLUE_ARMOUR = 0, HICON_GREEN_ARMOUR, HICON_YELLOW_ARMOUR, - HICON_HEALTH, - HICON_FIST, HICON_SG, HICON_CG, @@ -217,11 +203,8 @@ enum HICON_RIFLE, HICON_GL, HICON_PISTOL, - HICON_QUAD, - HICON_TOKEN, - HICON_X = 20, HICON_Y = 1650, HICON_TEXTY = 1644, @@ -234,20 +217,20 @@ static struct itemstat { int add, max, sound; const char *name; int icon, info; -} itemstats[] = { - {10, 30, S_ITEMAMMO, "SG", HICON_SG, GUN_SG}, - {20, 60, S_ITEMAMMO, "CG", HICON_CG, GUN_CG}, - {5, 15, S_ITEMAMMO, "RL", HICON_RL, GUN_RL}, - {5, 15, S_ITEMAMMO, "RI", HICON_RIFLE, GUN_RIFLE}, - {10, 30, S_ITEMAMMO, "GL", HICON_GL, GUN_GL}, - {30, 120, S_ITEMAMMO, "PI", HICON_PISTOL, GUN_PISTOL}, - {25, 100, S_ITEMHEALTH, "H", HICON_HEALTH, -1}, - {100, 200, S_ITEMHEALTH, "MH", HICON_HEALTH, 50}, - {5, 100, S_ITEMHEALTH, "TH", HICON_HEALTH, -1}, - {5, 50, S_ITEMARMOUR, "TA", HICON_BLUE_ARMOUR, A_BLUE}, - {50, 100, S_ITEMARMOUR, "GA", HICON_GREEN_ARMOUR, A_GREEN}, - {100, 200, S_ITEMARMOUR, "YA", HICON_YELLOW_ARMOUR, A_YELLOW}, - {20000, 30000, S_ITEMPUP, "Q", HICON_QUAD, -1}, +} itemstats[] = { { + 10, 30, S_ITEMAMMO, "SG", HICON_SG, GUN_SG}, { + 20, 60, S_ITEMAMMO, "CG", HICON_CG, GUN_CG}, { + 5, 15, S_ITEMAMMO, "RL", HICON_RL, GUN_RL}, { + 5, 15, S_ITEMAMMO, "RI", HICON_RIFLE, GUN_RIFLE}, { + 10, 30, S_ITEMAMMO, "GL", HICON_GL, GUN_GL}, { + 30, 120, S_ITEMAMMO, "PI", HICON_PISTOL, GUN_PISTOL}, { + 25, 100, S_ITEMHEALTH, "H", HICON_HEALTH, -1}, { + 100, 200, S_ITEMHEALTH, "MH", HICON_HEALTH, 50}, { + 5, 100, S_ITEMHEALTH, "TH", HICON_HEALTH, -1}, { + 5, 50, S_ITEMARMOUR, "TA", HICON_BLUE_ARMOUR, A_BLUE}, { + 50, 100, S_ITEMARMOUR, "GA", HICON_GREEN_ARMOUR, A_GREEN}, { + 100, 200, S_ITEMARMOUR, "YA", HICON_YELLOW_ARMOUR, A_YELLOW}, { + 20000, 30000, S_ITEMPUP, "Q", HICON_QUAD, -1}, }; #define MAXRAYS 12 @@ -260,7 +243,7 @@ static const struct guninfo { const char *name, *file; short part; } guns[NUMGUNS] = { - // delay| dmg| spr| spd| kck| rng| ray| pus| exp| + // delay| dmg| spr| spd| kck| rng| ray| pus| exp| { { S_PUNCH1, 100, 30, 0, 0, 0, 30, 1, 80, 0, 0, "fist", "fist", 0 }, { S_SG, 1000, 20, 280, 0, 20, 1024, MAXRAYS, 100, 0, 0, "shotgun", "shotg", 0 }, { S_CG, 100, 20, 70, 0, 10, 1024, 1, 80, 0, 0, "chaingun", "chaing", 0 }, @@ -287,61 +270,45 @@ extern void pwreset(void); #include "ai.h" // inherited by fpsent and server clients -struct fpsstate -{ +struct fpsstate { int health, maxhealth; int armour, maxarmour, armourtype; int quadmillis; int gunselect, gunwait; int ammo[NUMGUNS]; int aitype, skill; - fpsstate() : maxhealth(100), maxarmour(50), aitype(AI_NONE), skill(0) {} - - void baseammo(int gun, int k = 2, int scale = 1) - { + void baseammo(int gun, int k = 2, int scale = 1) { ammo[gun] = (itemstats[gun-GUN_SG].add*k)/scale; } - - void addammo(int gun, int k = 1, int scale = 1) - { + void addammo(int gun, int k = 1, int scale = 1) { itemstat &is = itemstats[gun-GUN_SG]; ammo[gun] = min(ammo[gun] + (is.add*k)/scale, is.max); } - - bool hasmaxammo(int type) - { + bool hasmaxammo(int type) { const itemstat &is = itemstats[type-I_SHELLS]; return ammo[type-I_SHELLS+GUN_SG]>=is.max; } - - bool canpickup(int type) - { + bool canpickup(int type) { if(typeI_QUAD) return false; itemstat &is = itemstats[type-I_SHELLS]; - switch(type) - { + switch(type) { case I_BOOST: return maxhealthI_QUAD) return; itemstat &is = itemstats[type-I_SHELLS]; - switch(type) - { + switch(type) { case I_TINYHEALTH: health = min(health+is.add, maxhealth); break; @@ -368,9 +335,7 @@ struct fpsstate break; } } - - void respawn() - { + void respawn() { maxhealth = 100; health = maxhealth; maxarmour = 50; @@ -382,39 +347,31 @@ struct fpsstate loopi(NUMGUNS) ammo[i] = 0; ammo[GUN_FIST] = 1; } - - void spawnstate(int gamemode) - { - if(m_demo) - { + void spawnstate(int gamemode) { + if(m_demo) { gunselect = GUN_FIST; } - else if(m_insta) - { + else if(m_insta) { armour = 0; health = 1; gunselect = GUN_RIFLE; ammo[GUN_RIFLE] = 100; } - else if(m_efficiency) - { + else if(m_efficiency) { armourtype = A_GREEN; armour = 100; loopi(NUMGUNS-1) baseammo(i+1); gunselect = GUN_CG; ammo[GUN_CG] /= 2; } - else - { + else { armourtype = A_BLUE; armour = 25; ammo[GUN_PISTOL] = 40; } } - // just subtract damage here, can set death, etc. later in code calling this - int dodamage(int damage) - { + int dodamage(int damage) { int ad = (damage*(armourtype+1)*30)/100; // let armour absorb when possible if(ad>armour) ad = armour; armour -= ad; @@ -422,17 +379,14 @@ struct fpsstate health -= damage; return damage; } - - int hasammo(int gun, int exclude = -1) - { + int hasammo(int gun, int exclude = -1) { return gun >= 0 && gun <= NUMGUNS && gun != exclude && ammo[gun] > 0; } }; extern int screenw, screenh; -struct fpsent : dynent, fpsstate -{ +struct fpsent : dynent, fpsstate { int weight; // affects the effectiveness of hitpush int clientnum, privilege, lastupdate, plag, ping; int lifesequence; // sequence id for each respawn, used in damage test @@ -448,48 +402,35 @@ struct fpsent : dynent, fpsstate editinfo *edit; float deltayaw, deltapitch, deltaroll, newyaw, newpitch, newroll; int smoothmillis; - string name, team, info; int playermodel; ai::aiinfo *ai; int ownernum, lastnode; - vec muzzle; - - fpsent() : weight(100), clientnum(-1), privilege(PRIV_NONE), lastupdate(0), plag(0), ping(0), lifesequence(0), respawned(-1), suicided(-1), lastpain(0), attacksound(-1), attackchan(-1), idlesound(-1), idlechan(-1), frags(0), flags(0), deaths(0), totaldamage(0), totalshots(0), edit(NULL), smoothmillis(-1), playermodel(-1), ai(NULL), ownernum(-1), muzzle(-1, -1, -1) - { + fpsent() : weight(100), clientnum(-1), privilege(PRIV_NONE), lastupdate(0), plag(0), ping(0), lifesequence(0), respawned(-1), suicided(-1), lastpain(0), attacksound(-1), attackchan(-1), idlesound(-1), idlechan(-1), frags(0), flags(0), deaths(0), totaldamage(0), totalshots(0), edit(NULL), smoothmillis(-1), playermodel(-1), ai(NULL), ownernum(-1), muzzle(-1, -1, -1) { name[0] = team[0] = info[0] = 0; respawn(); } - ~fpsent() - { + ~fpsent() { freeeditinfo(edit); if(attackchan >= 0) stopsound(attacksound, attackchan); if(idlechan >= 0) stopsound(idlesound, idlechan); if(ai) delete ai; } - - void hitpush(int damage, const vec &dir, fpsent *actor, int gun) - { + void hitpush(int damage, const vec &dir, fpsent *actor, int gun) { vec push(dir); push.mul((actor==this && guns[gun].exprad ? EXP_SELFPUSH : 1.0f)*guns[gun].hitpush*damage/weight); vel.add(push); } - - void stopattacksound() - { + void stopattacksound() { if(attackchan >= 0) stopsound(attacksound, attackchan, 250); attacksound = attackchan = -1; } - - void stopidlesound() - { + void stopidlesound() { if(idlechan >= 0) stopsound(idlesound, idlechan, 100); idlesound = idlechan = -1; } - - void respawn() - { + void respawn() { dynent::reset(); fpsstate::respawn(); respawned = suicided = -1; @@ -506,22 +447,17 @@ struct fpsent : dynent, fpsstate stopattacksound(); lastnode = -1; } - - int respawnwait(int secs, int delay = 0) - { + int respawnwait(int secs, int delay = 0) { return max(0, secs - (::lastmillis - lastpain - delay)/1000); } }; -struct teamscore -{ +struct teamscore { const char *team; int score; teamscore() {} teamscore(const char *s, int n) : team(s), score(n) {} - - static bool compare(const teamscore &x, const teamscore &y) - { + static bool compare(const teamscore &x, const teamscore &y) { if(x.score > y.score) return true; if(x.score < y.score) return false; return strcmp(x.team, y.team) < 0; @@ -533,8 +469,7 @@ static inline bool htcmp(const char *key, const teamscore &t) { return htcmp(key #define MAXTEAMS 128 -struct teaminfo -{ +struct teaminfo { char team[MAXTEAMLEN+1]; int frags; }; @@ -542,14 +477,11 @@ struct teaminfo static inline uint hthash(const teaminfo &t) { return hthash(t.team); } static inline bool htcmp(const char *team, const teaminfo &t) { return !strcmp(team, t.team); } -namespace entities -{ +namespace entities { extern vector ents; - extern const char *entmdlname(int type); extern const char *itemname(int i); extern int itemicon(int i); - extern void preloadentities(); extern void renderentities(); extern void checkitems(fpsent *d); @@ -562,12 +494,10 @@ namespace entities extern void pickupeffects(int n, fpsent *d); extern void teleporteffects(fpsent *d, int tp, int td, bool local = true); extern void jumppadeffects(fpsent *d, int jp, bool local = true); - extern void repammo(fpsent *d, int type, bool local = true); } -namespace game -{ +namespace game { // fps extern int gamemode, nextmode; extern string clientmap; @@ -580,7 +510,6 @@ namespace game extern int respawnent; extern int following; extern int smoothmove, smoothdist; - extern bool clientoption(const char *arg); extern fpsent *getclient(int cn); extern fpsent *newclient(int cn); @@ -608,12 +537,10 @@ namespace game extern void drawicon(int icon, float x, float y, float sz = 120); const char *mastermodecolor(int n, const char *unknown); const char *mastermodeicon(int n, const char *unknown); - // client extern bool connected, remote, demoplayback; extern string servinfo; extern vector messages; - extern int parseplayer(const char *arg); extern void ignore(int cn); extern void unignore(int cn); @@ -627,7 +554,6 @@ namespace game extern void forceintermission(); extern void c2sinfo(bool force = false); extern void sendposition(fpsent *d, bool reliable = false); - // weapon extern int getweapon(const char *name); extern void shoot(fpsent *d, const vec &targ); @@ -652,7 +578,6 @@ namespace game extern void gunselect(int gun, fpsent *d); extern void weaponswitch(fpsent *d); extern void avoidweapons(ai::avoidset &obstacles, float radius); - // scoreboard extern void showscores(bool on); extern void getbestplayers(vector &best); @@ -660,18 +585,14 @@ namespace game extern void clearteaminfo(); extern void setteaminfo(const char *team, int frags); extern int statuscolor(fpsent *d, int color); - // render - struct playermodelinfo - { + struct playermodelinfo { const char *ffa, *blueteam, *redteam, *hudguns, *vwep, *quad, *armour[3], *ffaicon, *blueicon, *redicon; bool ragdoll; }; - extern int playermodel, teamskins, testteam; - extern void saveragdoll(fpsent *d); extern void clearragdolls(); extern void moveragdolls(); @@ -680,8 +601,7 @@ namespace game extern vec hudgunorigin(int gun, const vec &from, const vec &to, fpsent *d); } -namespace server -{ +namespace server { extern const char *modename(int n, const char *unknown = "unknown"); extern const char *mastermodename(int n, const char *unknown = "unknown"); extern void startintermission(); diff --git a/src/fpsgame/render.cpp b/src/fpsgame/render.cpp index f35daec..dacdcd9 100644 --- a/src/fpsgame/render.cpp +++ b/src/fpsgame/render.cpp @@ -3,21 +3,16 @@ struct spawninfo { const extentity *e; float weight; }; extern float gatherspawninfos(dynent *d, int tag, vector &spawninfos); -namespace game -{ +namespace game { vector bestplayers; vector bestteams; - VARP(ragdoll, 0, 1, 1); VARP(ragdollmillis, 0, 10000, 300000); VARP(ragdollfade, 0, 1000, 300000); VARP(playermodel, 0, 0, 0); VARP(hidedead, 0, 0, 2); - vector ragdolls; - - void saveragdoll(fpsent *d) - { + void saveragdoll(fpsent *d) { if(!d->ragdoll || !ragdollmillis || (!ragdollfade && lastmillis > d->lastpain + ragdollmillis)) return; fpsent *r = new fpsent(*d); r->lastupdate = ragdollfade && lastmillis > d->lastpain + max(ragdollmillis - ragdollfade, 0) ? lastmillis - max(ragdollmillis - ragdollfade, 0) : d->lastpain; @@ -28,49 +23,38 @@ namespace game ragdolls.add(r); d->ragdoll = NULL; } - - void clearragdolls() - { + void clearragdolls() { ragdolls.deletecontents(); } - - void moveragdolls() - { - loopv(ragdolls) - { + void moveragdolls() { + loopv(ragdolls) { fpsent *d = ragdolls[i]; - if(lastmillis > d->lastupdate + ragdollmillis) - { + if(lastmillis > d->lastupdate + ragdollmillis) { delete ragdolls.remove(i--); continue; } moveragdoll(d); } } - - static const playermodelinfo playermodels[1] = - { - { "mrfixit", "mrfixit/blue", "mrfixit/red", "mrfixit/hudguns", NULL, "mrfixit/horns", { "mrfixit/armor/blue", "mrfixit/armor/green", "mrfixit/armor/yellow" }, "mrfixit", "mrfixit_blue", "mrfixit_red", true }, + static const playermodelinfo playermodels[1] = { + { + "mrfixit", "mrfixit/blue", "mrfixit/red", "mrfixit/hudguns", NULL, "mrfixit/horns", { + "mrfixit/armor/blue", "mrfixit/armor/green", "mrfixit/armor/yellow" }, + "mrfixit", "mrfixit_blue", "mrfixit_red", true }, }; - - const playermodelinfo *getplayermodelinfo(int n) - { + const playermodelinfo *getplayermodelinfo(int n) { (void) n; return &playermodels[0]; } - - const playermodelinfo &getplayermodelinfo(fpsent *d) - { + const playermodelinfo &getplayermodelinfo(fpsent *d) { + (void) d; const playermodelinfo *mdl = getplayermodelinfo(0); if(!mdl) mdl = getplayermodelinfo(playermodel); return *mdl; } - - void preloadplayermodel() - { + void preloadplayermodel() { const playermodelinfo *mdl = getplayermodelinfo(0); - if(m_teammode) - { + if(m_teammode) { preloadmodel(mdl->blueteam); preloadmodel(mdl->redteam); } @@ -79,23 +63,18 @@ namespace game if(mdl->quad) preloadmodel(mdl->quad); loopj(3) if(mdl->armour[j]) preloadmodel(mdl->armour[j]); } - VAR(testquad, 0, 0, 1); VAR(testarmour, 0, 0, 1); VAR(testteam, 0, 0, 3); - - void renderplayer(fpsent *d, const playermodelinfo &mdl, int team, float fade, bool mainpass) - { + void renderplayer(fpsent *d, const playermodelinfo &mdl, int team, float fade, bool mainpass) { int lastaction = d->lastaction, hold = mdl.vwep || d->gunselect==GUN_PISTOL ? 0 : (ANIM_HOLD1+d->gunselect)|ANIM_LOOP, attack = ANIM_ATTACK1+d->gunselect, delay = mdl.vwep ? 300 : guns[d->gunselect].attackdelay+50; - if(intermission && d->state!=CS_DEAD) - { + if(intermission && d->state!=CS_DEAD) { lastaction = 0; hold = attack = ANIM_LOSE|ANIM_LOOP; delay = 0; if(m_teammode ? bestteams.htfind(d->team)>=0 : bestplayers.find(d)>=0) hold = attack = ANIM_WIN|ANIM_LOOP; } - else if(d->state==CS_ALIVE && d->lasttaunt && lastmillis-d->lasttaunt<1000 && lastmillis-d->lastaction>delay) - { + else if(d->state==CS_ALIVE && d->lasttaunt && lastmillis-d->lasttaunt<1000 && lastmillis-d->lastaction>delay) { lastaction = d->lasttaunt; hold = attack = ANIM_TAUNT; delay = 1000; @@ -103,94 +82,75 @@ namespace game modelattach a[5]; static const char * const vweps[] = {"vwep/fist", "vwep/shotg", "vwep/chaing", "vwep/rocket", "vwep/rifle", "vwep/gl", "vwep/pistol"}; int ai = 0; - if((!mdl.vwep || d->gunselect!=GUN_FIST) && d->gunselect<=GUN_PISTOL) - { + if((!mdl.vwep || d->gunselect!=GUN_FIST) && d->gunselect<=GUN_PISTOL) { int vanim = ANIM_VWEP_IDLE|ANIM_LOOP, vtime = 0; - if(lastaction && d->lastattackgun==d->gunselect && lastmillis < lastaction + delay) - { + if(lastaction && d->lastattackgun==d->gunselect && lastmillis < lastaction + delay) { vanim = ANIM_VWEP_SHOOT; vtime = lastaction; } a[ai++] = modelattach("tag_weapon", mdl.vwep ? mdl.vwep : vweps[d->gunselect], vanim, vtime); } - if(d->state==CS_ALIVE) - { + if(d->state==CS_ALIVE) { if((testquad || d->quadmillis) && mdl.quad) a[ai++] = modelattach("tag_powerup", mdl.quad, ANIM_POWERUP|ANIM_LOOP, 0); - if(testarmour || d->armour) - { + if(testarmour || d->armour) { int type = clamp(d->armourtype, (int)A_BLUE, (int)A_YELLOW); if(mdl.armour[type]) a[ai++] = modelattach("tag_shield", mdl.armour[type], ANIM_SHIELD|ANIM_LOOP, 0); } } - if(mainpass) - { + if(mainpass) { d->muzzle = vec(-1, -1, -1); a[ai++] = modelattach("tag_muzzle", &d->muzzle); } const char *mdlname = mdl.ffa; - switch(testteam ? testteam-1 : team) - { + switch(testteam ? testteam-1 : team) { case 1: mdlname = mdl.blueteam; break; case 2: mdlname = mdl.redteam; break; } renderclient(d, mdlname, a[0].tag ? a : NULL, hold, attack, delay, lastaction, intermission && d->state!=CS_DEAD ? 0 : d->lastpain, fade, ragdoll && mdl.ragdoll); } - VARP(teamskins, 0, 0, 1); - VARP(statusicons, 0, 1, 1); - - void renderstatusicons(fpsent *d, int team, float yoffset)///TODO - { + void renderstatusicons(fpsent *d, int team, float yoffset) {///TODO { vec p = d->abovehead().madd(camup, yoffset); int icons = 0; const itemstat &boost = itemstats[I_BOOST-I_SHELLS]; - if(statusicons && (d->state==CS_ALIVE || d->state==CS_LAGGED)) - { + if(statusicons && (d->state==CS_ALIVE || d->state==CS_LAGGED)) { if(d->quadmillis) icons++; if(d->maxhealth>100) icons += (min(d->maxhealth, boost.max) - 100 + boost.info-1) / boost.info; if(d->armour>0 && d->armourtype>=A_GREEN && !m_noitems) icons++; } if(icons) concatstring(d->info, " "); particle_text(p, d->info, PART_TEXT, 1, team ? (team==1 ? 0x6496FF : 0xFF4B19) : 0x1EC850, 2.0f, 0, icons); - if(icons) - { + if(icons) { float tw, th; text_boundsf(d->info, tw, th); float offset = (tw - icons*th)/2; - if(d->armour>0 && d->armourtype>=A_GREEN && !m_noitems) - { + if(d->armour>0 && d->armourtype>=A_GREEN && !m_noitems) { int icon = itemstats[(d->armourtype==A_YELLOW ? I_YELLOWARMOUR : I_GREENARMOUR)-I_SHELLS].icon; particle_texticon(p, icon%4, icon/4, offset, PART_TEXT_ICON, 1, 0xFFFFFF, 2.0f); offset += th; } - for(int i = 100; i < min(d->maxhealth, boost.max); i += boost.info) - { + for(int i = 100; i < min(d->maxhealth, boost.max); i += boost.info) { particle_texticon(p, boost.icon%4, boost.icon/4, offset, PART_TEXT_ICON, 1, 0xFFFFFF, 2.0f); offset += th; } - if(d->quadmillis) - { + if(d->quadmillis) { int icon = itemstats[I_QUAD-I_SHELLS].icon; particle_texticon(p, icon%4, icon/4, offset, PART_TEXT_ICON, 1, 0xFFFFFF, 2.0f); offset += th; } } } - VARP(statusbars, 0, 1, 2); FVARP(statusbarscale, 0, 1, 2); - - float renderstatusbars(fpsent *d, int team)///TODO - { + float renderstatusbars(fpsent *d, int team) {///TODO { if(!statusbars || m_insta || (player1->state==CS_SPECTATOR ? statusbars <= 1 : team != 1) || (d->state!=CS_ALIVE && d->state!=CS_LAGGED)) return 0; vec p = d->abovehead().msub(camdir, 50/80.0f).msub(camup, 2.0f); float offset = 0; float scale = statusbarscale; - if(d->armour > 0) - { + if(d->armour > 0) { int limit = d->armourtype==A_YELLOW ? 200 : (d->armourtype==A_GREEN ? 100 : 50); int color = d->armourtype==A_YELLOW ? 0xFFC040 : (d->armourtype==A_GREEN ? 0x008C00 : 0x0B5899); float size = scale*sqrtf(max(d->armour, limit)/100.0f); @@ -205,48 +165,36 @@ namespace game particle_meter(vec(p).madd(camup, offset), fill, PART_METER, 1, color, 0, size); return offset; } - - void rendergame(bool mainpass) - { + void rendergame(bool mainpass) { if(mainpass) ai::render(); - - if(intermission) - { + if(intermission) { bestteams.shrink(0); bestplayers.shrink(0); if(m_teammode) getbestteams(bestteams); else getbestplayers(bestplayers); } - startmodelbatches(); - fpsent *exclude = isthirdperson() ? NULL : followingplayer(); - loopv(players) - { + loopv(players) { fpsent *d = players[i]; if(d == player1 || d->state==CS_SPECTATOR || d->state==CS_SPAWNING || d->lifesequence < 0 || d == exclude || (d->state==CS_DEAD && hidedead)) continue; int team = 0; if(teamskins || m_teammode) team = isteam(player1->team, d->team) ? 1 : 2; renderplayer(d, getplayermodelinfo(d), team, 1, mainpass); - vec dir = vec(d->o).sub(camera1->o); float dist = dir.magnitude(); dir.div(dist); - if(d->state!=CS_EDITING && raycube(camera1->o, dir, dist, 0) < dist) - { + if(d->state!=CS_EDITING && raycube(camera1->o, dir, dist, 0) < dist) { d->info[0] = '\0'; continue; } - copystring(d->info, colorname(d)); - if(d->state!=CS_DEAD) - { + if(d->state!=CS_DEAD) { float offset = renderstatusbars(d, team); renderstatusicons(d, team, offset); } } - loopv(ragdolls) - { + loopv(ragdolls) { fpsent *d = ragdolls[i]; int team = 0; if(teamskins || m_teammode) team = isteam(player1->team, d->team) ? 1 : 2; @@ -259,42 +207,32 @@ namespace game entities::renderentities(); renderbouncers(); renderprojectiles(); - endmodelbatches(); } - VARP(hudgun, 0, 1, 1); VARP(hudgunsway, 0, 1, 1); VARP(teamhudguns, 0, 1, 1); VARP(chainsawhudgun, 0, 1, 1); VAR(testhudgun, 0, 0, 1); - FVAR(swaystep, 1, 35.0f, 100); FVAR(swayside, 0, 0.04f, 1); FVAR(swayup, -1, 0.05f, 1); - float swayfade = 0, swayspeed = 0, swaydist = 0; vec swaydir(0, 0, 0); - - void swayhudgun(int curtime) - { + void swayhudgun(int curtime) { fpsent *d = hudplayer(); - if(d->state != CS_SPECTATOR) - { - if(d->physstate >= PHYS_SLOPE) - { + if(d->state != CS_SPECTATOR) { + if(d->physstate >= PHYS_SLOPE) { swayspeed = min(sqrtf(d->vel.x*d->vel.x + d->vel.y*d->vel.y), d->maxspeed); swaydist += swayspeed*curtime/1000.0f; swaydist = fmod(swaydist, 2*swaystep); swayfade = 1; } - else if(swayfade > 0) - { + else if(swayfade > 0) { swaydist += swayspeed*swayfade*curtime/1000.0f; swaydist = fmod(swaydist, 2*swaystep); swayfade -= 0.5f*(curtime*d->maxspeed)/(swaystep*1000.0f); } - float k = pow(0.7f, curtime/10.0f); swaydir.mul(k); vec vel(d->vel); @@ -302,18 +240,12 @@ namespace game swaydir.add(vec(vel).mul((1-k)/(15*max(vel.magnitude(), d->maxspeed)))); } } - - struct hudent : dynent - { + struct hudent : dynent { hudent() { type = ENT_CAMERA; } } guninterp; - SVARP(hudgunsdir, ""); - - void drawhudmodel(fpsent *d, int anim, float speed = 0, int base = 0) - { + void drawhudmodel(fpsent *d, int anim, float speed = 0, int base = 0) { if(d->gunselect>GUN_PISTOL) return; - vec sway; vecfromyawpitch(d->yaw, 0, 0, 1, sway); float steps = swaydist/swaystep*M_PI; @@ -323,8 +255,7 @@ namespace game if(!hudgunsway) sway = d->o; #if 0 - if(player1->state!=CS_DEAD && player1->quadmillis) - { + if(player1->state!=CS_DEAD && player1->quadmillis) { float t = 0.5f + 0.5f*sinf(2*M_PI*lastmillis/1000.0f); color.y = color.y*(1-t) + t; } @@ -339,8 +270,7 @@ namespace game d->muzzle = vec(-1, -1, -1); a[0] = modelattach("tag_muzzle", &d->muzzle); dynent *interp = NULL; - if(d->gunselect==GUN_FIST && chainsawhudgun) - { + if(d->gunselect==GUN_FIST && chainsawhudgun) { anim |= ANIM_LOOP; base = 0; interp = &guninterp; @@ -348,37 +278,26 @@ namespace game rendermodel(NULL, gunname, anim, sway, testhudgun ? 0 : d->yaw+90, testhudgun ? 0 : d->pitch, MDL_LIGHT|MDL_HUD, interp, a, base, (int)ceil(speed)); if(d->muzzle.x >= 0) d->muzzle = calcavatarpos(d->muzzle, 12); } - - void drawhudgun() - { + void drawhudgun() { fpsent *d = hudplayer(); - if(d->state==CS_SPECTATOR || d->state==CS_EDITING || !hudgun || editmode) - { + if(d->state==CS_SPECTATOR || d->state==CS_EDITING || !hudgun || editmode) { d->muzzle = player1->muzzle = vec(-1, -1, -1); return; } - int rtime = guns[d->gunselect].attackdelay; - if(d->lastaction && d->lastattackgun==d->gunselect && lastmillis-d->lastactionlastaction && d->lastattackgun==d->gunselect && lastmillis-d->lastactionlastaction); } - else - { + else { drawhudmodel(d, ANIM_GUN_IDLE|ANIM_LOOP); } } - - void renderavatar() - { + void renderavatar() { drawhudgun(); } - - void renderplayerpreview(int model, int team, int weap) - { + void renderplayerpreview(int model, int team, int weap) { static fpsent *previewent = NULL; - if(!previewent) - { + if(!previewent) { previewent = new fpsent; previewent->light.color = vec(1, 1, 1); previewent->light.dir = vec(0, -1, 2).normalize(); @@ -394,18 +313,15 @@ namespace game if(!mdlinfo) return; renderplayer(previewent, *mdlinfo, team >= 0 && team <= 2 ? team : 0, 1, false); } - - vec hudgunorigin(int gun, const vec &from, const vec &to, fpsent *d) - { + vec hudgunorigin(int gun, const vec &from, const vec &to, fpsent *d) { + (void) gun; if(d->muzzle.x >= 0) return d->muzzle; vec offset(from); - if(d!=hudplayer() || isthirdperson()) - { + if(d!=hudplayer() || isthirdperson()) { vec front, right; vecfromyawpitch(d->yaw, d->pitch, 1, 0, front); offset.add(front.mul(d->radius)); - if(d->type!=ENT_AI) - { + if(d->type!=ENT_AI) { offset.z += (d->aboveeye + d->eyeheight)*0.75f - d->eyeheight; vecfromyawpitch(d->yaw, 0, 0, -1, right); offset.add(right.mul(0.5f*d->radius)); @@ -414,30 +330,24 @@ namespace game return offset; } offset.add(vec(to).sub(from).normalize().mul(2)); - if(hudgun) - { + if(hudgun) { offset.sub(vec(camup).mul(1.0f)); offset.add(vec(camright).mul(0.8f)); } else offset.sub(vec(camup).mul(0.8f)); return offset; } - - void preloadweapons() - { + void preloadweapons() { const playermodelinfo &mdl = getplayermodelinfo(player1); - loopi(NUMGUNS) - { + loopi(NUMGUNS) { const char *file = guns[i].file; if(!file) continue; string fname; - if((m_teammode || teamskins) && teamhudguns) - { + if((m_teammode || teamskins) && teamhudguns) { formatstring(fname, "%s/%s/blue", hudgunsdir[0] ? hudgunsdir : mdl.hudguns, file); preloadmodel(fname); } - else - { + else { formatstring(fname, "%s/%s", hudgunsdir[0] ? hudgunsdir : mdl.hudguns, file); preloadmodel(fname); } @@ -445,14 +355,10 @@ namespace game preloadmodel(fname); } } - - void preloadsounds() - { + void preloadsounds() { for(int i = S_JUMP; i <= S_HIT; i++) preloadsound(i); } - - void preload() - { + void preload() { if(hudgun) preloadweapons(); preloadbouncers(); preloadplayermodel(); diff --git a/src/fpsgame/scoreboard.cpp b/src/fpsgame/scoreboard.cpp index 96f8868..81f93a1 100644 --- a/src/fpsgame/scoreboard.cpp +++ b/src/fpsgame/scoreboard.cpp @@ -1,8 +1,7 @@ // creation of scoreboard #include "game.h" -namespace game -{ +namespace game { VARP(scoreboard2d, 0, 1, 1); VARP(showservinfo, 0, 1, 1); VARP(showclientnum, 0, 1, 1); @@ -15,25 +14,17 @@ namespace game VARP(hidefrags, 0, 0, 1); VARP(showdeaths, 0, 1, 1); VARP(showdamagedealt, 0, 1, 1); - static hashset teaminfos; - - void clearteaminfo() - { + void clearteaminfo() { teaminfos.clear(); } - - void setteaminfo(const char *team, int frags) - { + void setteaminfo(const char *team, int frags) { teaminfo *t = teaminfos.access(team); if(!t) { t = &teaminfos[team]; copystring(t->team, team, sizeof(t->team)); } t->frags = frags; } - - static inline bool playersort(const fpsent *a, const fpsent *b) - { - if(a->state==CS_SPECTATOR) - { + static inline bool playersort(const fpsent *a, const fpsent *b) { + if(a->state==CS_SPECTATOR) { if(b->state==CS_SPECTATOR) return strcmp(a->name, b->name) < 0; else return false; } @@ -42,51 +33,38 @@ namespace game if(a->frags < b->frags) return false; return strcmp(a->name, b->name) < 0; } - - void getbestplayers(vector &best) - { - loopv(players) - { + void getbestplayers(vector &best) { + loopv(players) { fpsent *o = players[i]; if(o->state!=CS_SPECTATOR) best.add(o); } best.sort(playersort); while(best.length() > 1 && best.last()->frags < best[0]->frags) best.drop(); } - - void getbestteams(vector &best) - { - if(!hidefrags) - { + void getbestteams(vector &best) { + if(!hidefrags) { vector teamscores; teamscores.sort(teamscore::compare); while(teamscores.length() > 1 && teamscores.last().score < teamscores[0].score) teamscores.drop(); loopv(teamscores) best.add(teamscores[i].team); } - else - { + else { int bestfrags = INT_MIN; enumerate(teaminfos, teaminfo, t, bestfrags = max(bestfrags, t.frags)); - if(bestfrags <= 0) loopv(players) - { + if(bestfrags <= 0) loopv(players) { fpsent *o = players[i]; if(o->state!=CS_SPECTATOR && !teaminfos.access(o->team) && best.htfind(o->team) < 0) { bestfrags = 0; best.add(o->team); } } enumerate(teaminfos, teaminfo, t, if(t.frags >= bestfrags) best.add(t.team)); } } - - struct scoregroup : teamscore - { + struct scoregroup : teamscore { vector players; }; static vector groups; static vector spectators; - - static inline bool scoregroupcmp(const scoregroup *x, const scoregroup *y) - { - if(!x->team) - { + static inline bool scoregroupcmp(const scoregroup *x, const scoregroup *y) { + if(!x->team) { if(y->team) return false; } else if(!y->team) return true; @@ -96,20 +74,16 @@ namespace game if(x->players.length() < y->players.length()) return false; return x->team && y->team && strcmp(x->team, y->team) < 0; } - - static int groupplayers() - { + static int groupplayers() { int numgroups = 0; spectators.setsize(0); - loopv(players) - { + loopv(players) { fpsent *o = players[i]; if(!showconnecting && !o->name[0]) continue; if(o->state==CS_SPECTATOR) { spectators.add(o); continue; } const char *team = m_teammode && o->team[0] ? o->team : NULL; bool found = false; - loopj(numgroups) - { + loopj(numgroups) { scoregroup &g = *groups[j]; if(team!=g.team && (!team || !g.team || strcmp(team, g.team))) continue; g.players.add(o); @@ -129,31 +103,23 @@ namespace game groups.sort(scoregroupcmp, 0, numgroups); return numgroups; } - - int statuscolor(fpsent *d, int color) - { - if(d->privilege) - { + int statuscolor(fpsent *d, int color) { + if(d->privilege) { color = d->privilege>=PRIV_ADMIN ? 0xFF8000 : (d->privilege>=PRIV_AUTH ? 0xC040C0 : 0x40FF80); if(d->state==CS_DEAD) color = (color>>1)&0x7F7F7F; } else if(d->state==CS_DEAD) color = 0x606060; return color; } - - void renderscoreboard(g3d_gui &g, bool firstpass) - { + void renderscoreboard(g3d_gui &g, bool firstpass) { const ENetAddress *address = connectedpeer(); - if(showservinfo && address) - { + if(showservinfo && address) { string hostname; - if(enet_address_get_host_ip(address, hostname, sizeof(hostname)) >= 0) - { + if(enet_address_get_host_ip(address, hostname, sizeof(hostname)) >= 0) { if(servinfo[0]) g.titlef("%.25s", 0xFFFF80, NULL, servinfo); else g.titlef("%s:%d", 0xFFFF80, NULL, hostname, address->port); } } - g.pushlist(); g.spring(); g.text(server::modename(gamemode), 0xFFFF80); @@ -162,12 +128,10 @@ namespace game g.text(mname[0] ? mname : "[new map]", 0xFFFF80); extern int gamespeed; if(gamespeed != 100) { g.separator(); g.textf("%d.%02dx", 0xFFFF80, NULL, gamespeed/100, gamespeed%100); } - if(m_timed && mname[0] && (maplimit >= 0 || intermission)) - { + if(m_timed && mname[0] && (maplimit >= 0 || intermission)) { g.separator(); if(intermission) g.text("intermission", 0xFFFF80); - else - { + else { int secs = max(maplimit-lastmillis+999, 0)/1000, mins = secs/60; secs %= 60; g.pushlist(); @@ -179,41 +143,31 @@ namespace game if(ispaused()) { g.separator(); g.text("paused", 0xFFFF80); } g.spring(); g.poplist(); - g.separator(); - int numgroups = groupplayers(); - loopk(numgroups) - { + loopk(numgroups) { if((k%2)==0) g.pushlist(); // horizontal - scoregroup &sg = *groups[k]; int bgcolor = sg.team && m_teammode ? (isteam(player1->team, sg.team) ? 0x3030C0 : 0xC03030) : 0, fgcolor = 0xFFFF80; - g.pushlist(); // vertical g.pushlist(); // horizontal - #define loopscoregroup(o, b) \ - loopv(sg.players) \ - { \ + loopv(sg.players) { \ + \ fpsent *o = sg.players[i]; \ b; \ } - g.pushlist(); - if(sg.team && m_teammode) - { + if(sg.team && m_teammode) { g.pushlist(); g.background(bgcolor, numgroups>1 ? 3 : 5); g.strut(1); g.poplist(); } g.text("", 0, " "); - loopscoregroup(o, - { - if(o==player1 && highlightscore && (multiplayer(false) || demoplayback || players.length() > 1)) - { + loopscoregroup(o, { + if(o==player1 && highlightscore && (multiplayer(false) || demoplayback || players.length() > 1)) { g.pushlist(); g.background(0x808080, numgroups>1 ? 3 : 5); } @@ -223,104 +177,79 @@ namespace game if(o==player1 && highlightscore && (multiplayer(false) || demoplayback || players.length() > 1)) g.poplist(); }); g.poplist(); - - if(sg.team && m_teammode) - { + if(sg.team && m_teammode) { g.pushlist(); // vertical - if(sg.score>=10000) g.textf("%s: WIN", fgcolor, NULL, sg.team); else g.textf("%s: %d", fgcolor, NULL, sg.team, sg.score); - g.pushlist(); // horizontal } - - if(!hidefrags) - { + if(!hidefrags) { g.pushlist(); g.strut(6); g.text("frags", fgcolor); loopscoregroup(o, g.textf("%d", 0xFFFFDD, NULL, o->frags)); g.poplist(); } - - if(showdeaths) - { + if(showdeaths) { g.pushlist(); g.strut(6); g.text("deaths", fgcolor); loopscoregroup(o, g.textf("%d", 0xFFFFDD, NULL, o->deaths)); g.poplist(); } - - if(showdamagedealt) - { + if(showdamagedealt) { g.pushlist(); g.strut(7); g.text("damage", fgcolor); loopscoregroup(o, g.textf("%d", 0xFFFFDD, NULL, o->totaldamage)); g.poplist(); } - g.pushlist(); g.text("name", fgcolor); g.strut(12); loopscoregroup(o, { g.textf("%s ", statuscolor(o, 0xFFFFDD), NULL, colorname(o)); }); g.poplist(); - - if(multiplayer(false) || demoplayback) - { + if(multiplayer(false) || demoplayback) { if(showpj || showping) g.space(1); - - if(showpj && showping <= 1) - { + if(showpj && showping <= 1) { g.pushlist(); g.strut(6); g.text("pj", fgcolor); - loopscoregroup(o, - { + loopscoregroup(o, { if(o->state==CS_LAGGED) g.text("LAG", 0xFFFFDD); else g.textf("%d", 0xFFFFDD, NULL, o->plag); }); g.poplist(); } - - if(showping > 1) - { + if(showping > 1) { g.pushlist(); g.strut(6); - g.pushlist(); g.text("ping", fgcolor); g.space(1); g.spring(); g.text("pj", fgcolor); g.poplist(); - - loopscoregroup(o, - { + loopscoregroup(o, { fpsent *p = o->ownernum >= 0 ? getclient(o->ownernum) : o; if(!p) p = o; g.pushlist(); if(p->state==CS_LAGGED) g.text("LAG", 0xFFFFDD); - else - { + else { g.textf("%d", 0xFFFFDD, NULL, p->ping); g.space(1); g.spring(); g.textf("%d", 0xFFFFDD, NULL, o->plag); } g.poplist(); - }); g.poplist(); } - else if(showping) - { + else if(showping) { g.pushlist(); g.text("ping", fgcolor); g.strut(6); - loopscoregroup(o, - { + loopscoregroup(o, { fpsent *p = o->ownernum >= 0 ? getclient(o->ownernum) : o; if(!p) p = o; if(!showpj && p->state==CS_LAGGED) g.text("LAG", 0xFFFFDD); @@ -329,43 +258,31 @@ namespace game g.poplist(); } } - - if(showclientnum || player1->privilege>=PRIV_MASTER) - { + if(showclientnum || player1->privilege>=PRIV_MASTER) { g.space(1); g.pushlist(); g.text("cn", fgcolor); loopscoregroup(o, g.textf("%d", 0xFFFFDD, NULL, o->clientnum)); g.poplist(); } - - if(sg.team && m_teammode) - { + if(sg.team && m_teammode) { g.poplist(); // horizontal g.poplist(); // vertical } - g.poplist(); // horizontal g.poplist(); // vertical - if(k+1privilege>=PRIV_MASTER) - { + if(showspectators && spectators.length()) { + if(showclientnum || player1->privilege>=PRIV_MASTER) { g.pushlist(); - g.pushlist(); g.text("spectator", 0xFFFF80, " "); g.strut(12); - loopv(spectators) - { + loopv(spectators) { fpsent *o = spectators[i]; - if(o==player1 && highlightscore) - { + if(o==player1 && highlightscore) { g.pushlist(); g.background(0x808080, 3); } @@ -373,15 +290,12 @@ namespace game if(o==player1 && highlightscore) g.poplist(); } g.poplist(); - - if((multiplayer(false) || demoplayback) && showspectatorping) - { + if((multiplayer(false) || demoplayback) && showspectatorping) { g.space(1); g.pushlist(); g.text("ping", 0xFFFF80); g.strut(6); - loopv(spectators) - { + loopv(spectators) { fpsent *o = spectators[i]; fpsent *p = o->ownernum >= 0 ? getclient(o->ownernum) : o; if(!p) p = o; @@ -390,28 +304,22 @@ namespace game } g.poplist(); } - g.space(1); g.pushlist(); g.text("cn", 0xFFFF80); loopv(spectators) g.textf("%d", 0xFFFFDD, NULL, spectators[i]->clientnum); g.poplist(); - g.poplist(); } - else - { + else { g.textf("%d spectator%s", 0xFFFF80, " ", spectators.length(), spectators.length()!=1 ? "s" : ""); - loopv(spectators) - { - if((i%3)==0) - { + loopv(spectators) { + if((i%3)==0) { g.pushlist(); g.text("", 0xFFFFDD, "spectator"); } fpsent *o = spectators[i]; - if(o==player1 && highlightscore) - { + if(o==player1 && highlightscore) { g.pushlist(); g.background(0x808080); } @@ -422,7 +330,6 @@ namespace game } } } - /// PW g.separator(); g.pushlist(); @@ -445,53 +352,36 @@ namespace game g.textf(" x %d ", 0xffffff, "quad_damage.png", pwitemspicked[6]); g.poplist(); } - - struct scoreboardgui : g3d_callback - { + struct scoreboardgui : g3d_callback { bool showing; vec menupos; int menustart; - scoreboardgui() : showing(false) {} - - void show(bool on) - { - if(!showing && on) - { + void show(bool on) { + if(!showing && on) { menupos = menuinfrontofplayer(); menustart = starttime(); } showing = on; } - - void gui(g3d_gui &g, bool firstpass) - { + void gui(g3d_gui &g, bool firstpass) { g.start(menustart, 0.03f, NULL, false); renderscoreboard(g, firstpass); g.end(); } - - void render() - { + void render() { if(showing) g3d_addgui(this, menupos, (scoreboard2d ? GUI_FORCE_2D : GUI_2D | GUI_FOLLOW) | GUI_BOTTOM); } - } scoreboard; - - void g3d_gamemenus() - { + void g3d_gamemenus() { scoreboard.render(); } - VARFN(scoreboard, showscoreboard, 0, 0, 1, scoreboard.show(showscoreboard!=0)); - - void showscores(bool on) - { + void showscores(bool on) { showscoreboard = on ? 1 : 0; scoreboard.show(on); } ICOMMAND(showscores, "D", (int *down), showscores(*down!=0)); - VARP(hudscore, 0, 0, 1); FVARP(hudscorescale, 1e-3f, 1.0f, 1e3f); VARP(hudscorealign, -1, 0, 1); @@ -501,61 +391,48 @@ namespace game HVARP(hudscoreenemycolour, 0, 0xFF4040, 0xFFFFFF); VARP(hudscorealpha, 0, 255, 255); VARP(hudscoresep, 0, 200, 1000); - - void drawhudscore(int w, int h) - { + void drawhudscore(int w, int h) { int numgroups = groupplayers(); if(!numgroups) return; - scoregroup *g = groups[0]; int score = INT_MIN, score2 = INT_MIN; bool best = false; - if(m_teammode) - { + if(m_teammode) { score = g->score; best = isteam(player1->team, g->team); - if(numgroups > 1) - { + if(numgroups > 1) { if(best) score2 = groups[1]->score; else for(int i = 1; i < groups.length(); ++i) if(isteam(player1->team, groups[i]->team)) { score2 = groups[i]->score; break; } - if(score2 == INT_MIN) - { + if(score2 == INT_MIN) { fpsent *p = followingplayer(player1); if(p->state==CS_SPECTATOR) score2 = groups[1]->score; } } } - else - { + else { fpsent *p = followingplayer(player1); score = g->players[0]->frags; best = p == g->players[0]; - if(g->players.length() > 1) - { + if(g->players.length() > 1) { if(best || p->state==CS_SPECTATOR) score2 = g->players[1]->frags; else score2 = p->frags; } } if(score == score2 && !best) best = true; - score = clamp(score, -999, 9999); defformatstring(buf, "%d", score); int tw = 0, th = 0; text_bounds(buf, tw, th); - string buf2; int tw2 = 0, th2 = 0; - if(score2 > INT_MIN) - { + if(score2 > INT_MIN) { score2 = clamp(score2, -999, 9999); formatstring(buf2, "%d", score2); text_bounds(buf2, tw2, th2); } - int fw = 0, fh = 0; text_bounds("00", fw, fh); fw = max(fw, max(tw, tw2)); - vec2 offset = vec2(hudscorex, hudscorey).mul(vec2(w, h).div(hudscorescale)); if(hudscorealign == 1) offset.x -= 2*fw + hudscoresep; else if(hudscorealign == 0) offset.x -= (2*fw + hudscoresep) / 2.0f; @@ -564,17 +441,13 @@ namespace game offset.y -= th/2.0f; offset2.x += fw + hudscoresep + (fw-tw2)/2.0f; offset2.y -= th2/2.0f; - pushhudmatrix(); hudmatrix.scale(hudscorescale, hudscorescale, 1); flushhudmatrix(); - int color = hudscoreplayercolour, color2 = hudscoreenemycolour; if(!best) swap(color, color2); - draw_text(buf, int(offset.x), int(offset.y), (color>>16)&0xFF, (color>>8)&0xFF, color&0xFF, hudscorealpha); if(score2 > INT_MIN) draw_text(buf2, int(offset2.x), int(offset2.y), (color2>>16)&0xFF, (color2>>8)&0xFF, color2&0xFF, hudscorealpha); - pophudmatrix(); } } diff --git a/src/fpsgame/server.cpp b/src/fpsgame/server.cpp index ec781c6..2095dd1 100644 --- a/src/fpsgame/server.cpp +++ b/src/fpsgame/server.cpp @@ -1,9 +1,7 @@ #include "game.h" -namespace game -{ - void parseoptions(vector &args) - { +namespace game { + void parseoptions(vector &args) { loopv(args) #ifndef STANDALONE if(!game::clientoption(args[i])) @@ -11,7 +9,6 @@ namespace game if(!server::serveroption(args[i])) conoutf(CON_ERROR, "unknown command-line option: %s", args[i]); } - const char *gameident() { return "fps"; } } @@ -19,105 +16,69 @@ VAR(regenbluearmour, 0, 1, 1); extern ENetAddress masteraddress; -namespace server -{ - struct server_entity // server side version of "entity" type - { +namespace server { + struct server_entity { // server side version of "entity" type { int type; int spawntime; bool spawned; }; - static const int DEATHMILLIS = 300; - struct clientinfo; - - struct gameevent - { + struct gameevent { virtual ~gameevent() {} - virtual bool flush(clientinfo *ci, int fmillis); - virtual void process(clientinfo *ci) {} - + virtual void process(clientinfo *) {} virtual bool keepable() const { return false; } }; - - struct timedevent : gameevent - { + struct timedevent : gameevent { int millis; - bool flush(clientinfo *ci, int fmillis); }; - - struct hitinfo - { + struct hitinfo { int target; int lifesequence; int rays; float dist; vec dir; }; - - struct shotevent : timedevent - { + struct shotevent : timedevent { int id, gun; vec from, to; vector hits; - void process(clientinfo *ci); }; - - struct explodeevent : timedevent - { + struct explodeevent : timedevent { int id, gun; vector hits; - bool keepable() const { return true; } - void process(clientinfo *ci); }; - - struct suicideevent : gameevent - { + struct suicideevent : gameevent { void process(clientinfo *ci); }; - - struct pickupevent : gameevent - { + struct pickupevent : gameevent { int ent; - void process(clientinfo *ci); }; - template - struct projectilestate - { + struct projectilestate { int projs[N]; int numprojs; - projectilestate() : numprojs(0) {} - void reset() { numprojs = 0; } - - void add(int val) - { + void add(int val) { if(numprojs>=N) numprojs = 0; projs[numprojs++] = val; } - - bool remove(int val) - { - loopi(numprojs) if(projs[i]==val) - { + bool remove(int val) { + loopi(numprojs) if(projs[i]==val) { projs[i] = projs[--numprojs]; return true; } return false; } }; - - struct gamestate : fpsstate - { + struct gamestate : fpsstate { vec o; int state, editstate; int lastdeath, deadflush, lastspawn, lifesequence; @@ -126,38 +87,26 @@ namespace server int frags, flags, deaths, teamkills, shotdamage, damage, tokens; int lasttimeplayed, timeplayed; float effectiveness; - gamestate() : state(CS_DEAD), editstate(CS_DEAD), lifesequence(0) {} - - bool isalive(int gamemillis) - { + bool isalive(int gamemillis) { return state==CS_ALIVE || (state==CS_DEAD && gamemillis - lastdeath <= DEATHMILLIS); } - - bool waitexpired(int gamemillis) - { + bool waitexpired(int gamemillis) { return gamemillis - lastshot >= gunwait; } - - void reset() - { + void reset() { if(state!=CS_SPECTATOR) state = editstate = CS_DEAD; maxhealth = 100; maxarmour = 50; rockets.reset(); grenades.reset(); - timeplayed = 0; effectiveness = 0; frags = flags = deaths = teamkills = shotdamage = damage = tokens = 0; - lastdeath = 0; - respawn(); } - - void respawn() - { + void respawn() { fpsstate::respawn(); o = vec(-1e10f, -1e10f, -1e10f); deadflush = 0; @@ -165,25 +114,19 @@ namespace server lastshot = 0; tokens = 0; } - - void reassign() - { + void reassign() { respawn(); rockets.reset(); grenades.reset(); } }; - - struct savedscore - { + struct savedscore { uint ip; string name; int frags, flags, deaths, teamkills, shotdamage, damage; int timeplayed; float effectiveness; - - void save(gamestate &gs) - { + void save(gamestate &gs) { frags = gs.frags; flags = gs.flags; deaths = gs.deaths; @@ -193,9 +136,7 @@ namespace server timeplayed = gs.timeplayed; effectiveness = gs.effectiveness; } - - void restore(gamestate &gs) - { + void restore(gamestate &gs) { gs.frags = frags; gs.flags = flags; gs.deaths = deaths; @@ -206,11 +147,8 @@ namespace server gs.effectiveness = effectiveness; } }; - extern int gamemillis, nextexceeded; - - struct clientinfo - { + struct clientinfo { int clientnum, ownernum, connectmillis, sessionid, overflow; string name, team, mapvote; int playermodel; @@ -236,58 +174,39 @@ namespace server void *authchallenge; int authkickvictim; char *authkickreason; - clientinfo() : getdemo(NULL), getmap(NULL), clipboard(NULL), authchallenge(NULL), authkickreason(NULL) { reset(); } ~clientinfo() { events.deletecontents(); cleanclipboard(); cleanauth(); } - - void addevent(gameevent *e) - { + void addevent(gameevent *e) { if(state.state==CS_SPECTATOR || events.length()>100) delete e; else events.add(e); } - - enum - { + enum { PUSHMILLIS = 3000 }; - - int calcpushrange() - { + int calcpushrange() { ENetPeer *peer = getclientpeer(ownernum); return PUSHMILLIS + ((peer) ? (int) (peer->roundTripTime + peer->roundTripTimeVariance) : (int) ENET_PEER_DEFAULT_ROUND_TRIP_TIME); } - - bool checkpushed(int millis, int range) - { + bool checkpushed(int millis, int range) { return millis >= pushed - range && millis <= pushed + range; } - - void scheduleexceeded() - { + void scheduleexceeded() { if(state.state!=CS_ALIVE || !exceeded) return; int range = calcpushrange(); if(!nextexceeded || exceeded + range < nextexceeded) nextexceeded = exceeded + range; } - - void setexceeded() - { + void setexceeded() { if(state.state==CS_ALIVE && !exceeded && !checkpushed(gamemillis, calcpushrange())) exceeded = gamemillis; scheduleexceeded(); } - - void setpushed() - { + void setpushed() { pushed = max(pushed, gamemillis); if(exceeded && checkpushed(exceeded, calcpushrange())) exceeded = 0; } - - bool checkexceeded() - { + bool checkexceeded() { return state.state==CS_ALIVE && exceeded && gamemillis > exceeded + calcpushrange(); } - - void mapchange() - { + void mapchange() { mapvote[0] = 0; modevote = INT_MAX; state.reset(); @@ -302,36 +221,26 @@ namespace server warned = false; gameclip = false; } - - void reassign() - { + void reassign() { state.reassign(); events.deletecontents(); timesync = false; lastevent = 0; } - - void cleanclipboard(bool fullclean = true) - { + void cleanclipboard(bool fullclean = true) { if(clipboard) { if(--clipboard->referenceCount <= 0) enet_packet_destroy(clipboard); clipboard = NULL; } if(fullclean) lastclipboard = 0; } - - void cleanauthkick() - { + void cleanauthkick() { authkickvictim = -1; DELETEA(authkickreason); } - - void cleanauth(bool full = true) - { + void cleanauth(bool full = true) { authreq = 0; if(authchallenge) { freechallenge(authchallenge); authchallenge = NULL; } if(full) cleanauthkick(); } - - void reset() - { + void reset() { name[0] = team[0] = 0; playermodel = -1; privilege = PRIV_NONE; @@ -346,11 +255,8 @@ namespace server cleanauth(); mapchange(); } - - int geteventmillis(int servmillis, int clientmillis) - { - if(!timesync || (events.empty() && state.waitexpired(servmillis))) - { + int geteventmillis(int servmillis, int clientmillis) { + if(!timesync || (events.empty() && state.waitexpired(servmillis))) { timesync = true; gameoffset = servmillis - clientmillis; return servmillis; @@ -358,15 +264,11 @@ namespace server else return gameoffset + clientmillis; } }; - - struct ban - { + struct ban { int time, expire; uint ip; }; - - namespace aiman - { + namespace aiman { extern void removeai(clientinfo *ci); extern void clearai(); extern void checkai(); @@ -378,29 +280,23 @@ namespace server extern void addclient(clientinfo *ci); extern void changeteam(clientinfo *ci); } - #define MM_MODE 0xF #define MM_AUTOAPPROVE 0x1000 #define MM_PRIVSERV (MM_MODE | MM_AUTOAPPROVE) #define MM_PUBSERV ((1< allowedips; vector bannedips; - - void addban(uint ip, int expire) - { + void addban(uint ip, int expire) { allowedips.removeobj(ip); ban b; b.time = totalmillis; @@ -409,71 +305,49 @@ namespace server loopv(bannedips) if(bannedips[i].expire - b.expire > 0) { bannedips.insert(i, b); return; } bannedips.add(b); } - vector connects, clients, bots; - - void kickclients(uint ip, clientinfo *actor = NULL, int priv = PRIV_NONE) - { - loopvrev(clients) - { + void kickclients(clientinfo *actor = NULL, int priv = PRIV_NONE) { + loopvrev(clients) { clientinfo &c = *clients[i]; if(c.state.aitype != AI_NONE || c.privilege >= PRIV_ADMIN || c.local) continue; if(actor && ((c.privilege > priv && !actor->local) || c.clientnum == actor->clientnum)) continue; - //~if(getclientip(c.clientnum) == ip) disconnect_client(c.clientnum, DISC_KICK); } } - - struct maprotation - { + struct maprotation { static int exclude; int modes; string map; - int calcmodemask() const { return modes&(1< maprotations; int curmaprotation = 0; - VAR(lockmaprotation, 0, 0, 2); - - void maprotationreset() - { + void maprotationreset() { maprotations.setsize(0); curmaprotation = 0; maprotation::exclude = 0; } - - void nextmaprotation() - { + void nextmaprotation() { curmaprotation++; if(maprotations.inrange(curmaprotation) && maprotations[curmaprotation].modes) return; do curmaprotation--; while(maprotations.inrange(curmaprotation) && maprotations[curmaprotation].modes); curmaprotation++; } - - int findmaprotation(int mode, const char *map) - { - for(int i = max(curmaprotation, 0); i < maprotations.length(); i++) - { + int findmaprotation(int mode, const char *map) { + for(int i = max(curmaprotation, 0); i < maprotations.length(); i++) { maprotation &rot = maprotations[i]; if(!rot.modes) break; if(rot.match(mode, map)) return i; @@ -481,35 +355,28 @@ namespace server int start; for(start = max(curmaprotation, 0) - 1; start >= 0; start--) if(!maprotations[start].modes) break; start++; - for(int i = start; i < curmaprotation; i++) - { + for(int i = start; i < curmaprotation; i++) { maprotation &rot = maprotations[i]; if(!rot.modes) break; if(rot.match(mode, map)) return i; } int best = -1; - loopv(maprotations) - { + loopv(maprotations) { maprotation &rot = maprotations[i]; if(rot.match(mode, map) && (best < 0 || maprotations[best].includes(rot))) best = i; } return best; } - - bool searchmodename(const char *haystack, const char *needle) - { + bool searchmodename(const char *haystack, const char *needle) { if(!needle[0]) return true; - do - { - if(needle[0] != '.') - { + do { + if(needle[0] != '.') { haystack = strchr(haystack, needle[0]); if(!haystack) break; haystack++; } const char *h = haystack, *n = needle+1; - for(; *h && *n; h++) - { + for(; *h && *n; h++) { if(*h == *n) n++; else if(*h != ' ') break; } @@ -518,16 +385,12 @@ namespace server } while(needle[0] != '.'); return false; } - - int genmodemask(vector &modes) - { + int genmodemask(vector &modes) { int modemask = 0; - loopv(modes) - { + loopv(modes) { const char *mode = modes[i]; int op = mode[0]; - switch(mode[0]) - { + switch(mode[0]) { case '*': modemask |= 1< modes, maps; - for(int i = 0; i + 1 < numargs; i += 2) - { + for(int i = 0; i + 1 < numargs; i += 2) { explodelist(args[i].getstr(), modes); explodelist(args[i+1].getstr(), maps); int modemask = genmodemask(modes); @@ -582,74 +438,54 @@ namespace server modes.deletearrays(); maps.deletearrays(); } - if(maprotations.length() && maprotations.last().modes) - { + if(maprotations.length() && maprotations.last().modes) { maprotation &rot = maprotations.add(); rot.modes = 0; rot.map[0] = '\0'; } } - COMMAND(maprotationreset, ""); COMMANDN(maprotation, addmaprotations, "ss2V"); - - struct demofile - { + struct demofile { string info; uchar *data; int len; }; - vector demos; - bool demonextmatch = false; stream *demotmp = NULL, *demorecord = NULL, *demoplayback = NULL; int nextplayback = 0; - VAR(maxdemos, 0, 5, 25); VAR(maxdemosize, 0, 16, 31); VAR(restrictdemos, 0, 1, 1); VARF(autorecorddemo, 0, 0, 1, demonextmatch = autorecorddemo!=0); - VAR(restrictpausegame, 0, 1, 1); VAR(restrictgamespeed, 0, 1, 1); - SVAR(serverdesc, ""); SVAR(serverpass, ""); SVAR(adminpass, ""); VARF(publicserver, 0, 0, 2, { - switch(publicserver) - { + switch(publicserver) { case 0: default: mastermask = MM_PRIVSERV; break; case 1: mastermask = MM_PUBSERV; break; case 2: mastermask = MM_COOPSERV; break; } }); SVAR(servermotd, ""); - - struct teamkillkick - { + struct teamkillkick { int modes, limit, ban; - - bool match(int mode) const - { + bool match(int mode) const { return (modes&(1<<(mode-STARTGAMEMODE)))!=0; } - - bool includes(const teamkillkick &tk) const - { + bool includes(const teamkillkick &tk) const { return tk.modes != modes && (tk.modes & modes) == tk.modes; } }; vector teamkillkicks; - - void teamkillkickreset() - { + void teamkillkickreset() { teamkillkicks.setsize(0); } - - void addteamkillkick(char *modestr, int *limit, int *ban) - { + void addteamkillkick(char *modestr, int *limit, int *ban) { vector modes; explodelist(modestr, modes); teamkillkick &kick = teamkillkicks.add(); @@ -658,25 +494,19 @@ namespace server kick.ban = *ban > 0 ? *ban*60000 : (*ban < 0 ? 0 : 30*60000); modes.deletearrays(); } - COMMAND(teamkillkickreset, ""); COMMANDN(teamkillkick, addteamkillkick, "sii"); - - struct teamkillinfo - { + struct teamkillinfo { uint ip; int teamkills; }; vector teamkills; bool shouldcheckteamkills = false; - - void addteamkill(clientinfo *actor, clientinfo *victim, int n) - { + void addteamkill(clientinfo *actor, clientinfo *victim, int n) { if(!m_timed || actor->state.aitype != AI_NONE || actor->local || actor->privilege || (victim && victim->state.aitype != AI_NONE)) return; shouldcheckteamkills = true; uint ip = getclientip(actor->clientnum); - loopv(teamkills) if(teamkills[i].ip == ip) - { + loopv(teamkills) if(teamkills[i].ip == ip) { teamkills[i].teamkills += n; return; } @@ -684,92 +514,67 @@ namespace server tk.ip = ip; tk.teamkills = n; } - - void checkteamkills() - { + void checkteamkills() { teamkillkick *kick = NULL; if(m_timed) loopv(teamkillkicks) if(teamkillkicks[i].match(gamemode) && (!kick || kick->includes(teamkillkicks[i]))) kick = &teamkillkicks[i]; - if(kick) loopvrev(teamkills) - { + if(kick) loopvrev(teamkills) { teamkillinfo &tk = teamkills[i]; - if(tk.teamkills >= kick->limit) - { + if(tk.teamkills >= kick->limit) { if(kick->ban > 0) addban(tk.ip, kick->ban); - kickclients(tk.ip); + kickclients(); teamkills.removeunordered(i); } } shouldcheckteamkills = false; } - void *newclientinfo() { return new clientinfo; } void deleteclientinfo(void *ci) { delete (clientinfo *)ci; } - - clientinfo *getinfo(int n) - { + clientinfo *getinfo(int n) { if(n < MAXCLIENTS) return (clientinfo *)getclientinfo(n); n -= MAXCLIENTS; return bots.inrange(n) ? bots[n] : NULL; } - uint mcrc = 0; vector ments; vector sents; vector scores; - - int msgsizelookup(int msg) - { + int msgsizelookup(int msg) { static int sizetable[NUMMSG] = { -1 }; - if(sizetable[0] < 0) - { + if(sizetable[0] < 0) { memset(sizetable, -1, sizeof(sizetable)); for(const int *p = msgsizes; *p >= 0; p += 2) sizetable[p[0]] = p[1]; } return msg >= 0 && msg < NUMMSG ? sizetable[msg] : -1; } - - const char *modename(int n, const char *unknown) - { + const char *modename(int n, const char *unknown) { if(m_valid(n)) return gamemodes[n - STARTGAMEMODE].name; return unknown; } - - const char *mastermodename(int n, const char *unknown) - { + const char *mastermodename(int n, const char *unknown) { return (n>=MM_START && size_t(n-MM_START)clientnum!=exclude && (!nospec || ci->state.state!=CS_SPECTATOR || (priv && (ci->privilege || ci->local))) && (!noai || ci->state.aitype == AI_NONE)) n++; } return n; } - - bool duplicatename(clientinfo *ci, const char *name) - { + bool duplicatename(clientinfo *ci, const char *name) { if(!name) name = ci->name; loopv(clients) if(clients[i]!=ci && !strcmp(name, clients[i]->name)) return true; return false; } - - const char *colorname(clientinfo *ci, const char *name = NULL) - { + const char *colorname(clientinfo *ci, const char *name = NULL) { if(!name) name = ci->name; if(name[0] && !duplicatename(ci, name) && ci->state.aitype == AI_NONE) return name; static string cname[3]; @@ -812,16 +608,12 @@ namespace server formatstring(cname[cidx], ci->state.aitype == AI_NONE ? "%s \fs\f5(%d)\fr" : "%s \fs\f5[%d]\fr", name, ci->clientnum); return cname[cidx]; } - bool canspawnitem(int type) { return !m_noitems && (type>=I_SHELLS && type<=I_QUAD && (!m_noammo || typeI_CARTRIDGES)); } - - int spawntime(int type) - { + int spawntime(int type) { int np = numclients(-1, true, false); np = np<3 ? 4 : (np>4 ? 2 : 3); // spawn times are dependent on number of players int sec = 0; - switch(type) - { + switch(type) { case I_SHELLS: case I_BULLETS: case I_ROCKETS: @@ -838,11 +630,8 @@ namespace server } return sec*1000; } - - bool delayspawn(int type) - { - switch(type) - { + bool delayspawn(int type) { + switch(type) { case I_GREENARMOUR: case I_YELLOWARMOUR: case I_BOOST: @@ -852,14 +641,11 @@ namespace server return false; } } - - bool pickup(int i, int sender) // server side item pickup, acknowledge first client that gets it - { + bool pickup(int i, int sender) { // server side item pickup, acknowledge first client that gets it { if((m_timed && gamemillis>=gamelimit) || !sents.inrange(i) || !sents[i].spawned) return false; clientinfo *ci = getinfo(sender); if(!ci) return false; - if(!ci->local && !ci->state.canpickup(sents[i].type)) - { + if(!ci->local && !ci->state.canpickup(sents[i].type)) { sendf(sender, 1, "ri3", N_ITEMACC, i, -1); return false; } @@ -869,30 +655,21 @@ namespace server ci->state.pickup(sents[i].type); return true; } - static hashset teaminfos; - - void clearteaminfo() - { + void clearteaminfo() { teaminfos.clear(); } - bool teamhasplayers(const char *team) { loopv(clients) if(!strcmp(clients[i]->team, team)) return true; return false; } - - bool pruneteaminfo() - { + bool pruneteaminfo() { int oldteams = teaminfos.numelems; enumerate(teaminfos, teaminfo, old, if(!old.frags && !teamhasplayers(old.team)) teaminfos.remove(old.team); ); return teaminfos.numelems < oldteams; } - - teaminfo *addteaminfo(const char *team) - { + teaminfo *addteaminfo(const char *team) { teaminfo *t = teaminfos.access(team); - if(!t) - { + if(!t) { if(teaminfos.numelems >= MAXTEAMS && !pruneteaminfo()) return NULL; t = &teaminfos[team]; copystring(t->team, team, sizeof(t->team)); @@ -900,13 +677,10 @@ namespace server } return t; } - - clientinfo *choosebestclient(float &bestrank) - { + clientinfo *choosebestclient(float &bestrank) { clientinfo *best = NULL; bestrank = -1; - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->state.timeplayed<0) continue; float rank = ci->state.state!=CS_SPECTATOR ? ci->state.effectiveness/max(ci->state.timeplayed, 1) : -1; @@ -914,19 +688,14 @@ namespace server } return best; } - VAR(persistteams, 0, 0, 1); - - void autoteam() - { + void autoteam() { static const char * const teamnames[2] = {"good", "evil"}; vector team[2]; float teamrank[2] = {0, 0}; - for(int round = 0, remaining = clients.length(); remaining>=0; round++) - { + for(int round = 0, remaining = clients.length(); remaining>=0; round++) { int first = round&1, second = (round+1)&1, selected = 0; - while(teamrank[first] <= teamrank[second]) - { + while(teamrank[first] <= teamrank[second]) { float rank; clientinfo *ci = choosebestclient(rank); if(!ci) break; @@ -940,15 +709,12 @@ namespace server if(!selected) break; remaining -= selected; } - loopi(sizeof(team)/sizeof(team[0])) - { + loopi(sizeof(team)/sizeof(team[0])) { addteaminfo(teamnames[i]); - loopvj(team[i]) - { + loopvj(team[i]) { clientinfo *ci = team[i][j]; if(!strcmp(ci->team, teamnames[i])) continue; - if(persistteams && ci->team[0]) - { + if(persistteams && ci->team[0]) { addteaminfo(ci->team); continue; } @@ -957,29 +723,21 @@ namespace server } } } - - struct teamrank - { + struct teamrank { const char *name; float rank; int clients; - teamrank(const char *name) : name(name), rank(0), clients(0) {} }; - - const char *chooseworstteam(const char *suggest = NULL, clientinfo *exclude = NULL) - { + const char *chooseworstteam(clientinfo *exclude = NULL) { teamrank teamranks[2] = { teamrank("good"), teamrank("evil") }; const int numteams = sizeof(teamranks)/sizeof(teamranks[0]); - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(ci==exclude || ci->state.aitype!=AI_NONE || ci->state.state==CS_SPECTATOR || !ci->team[0]) continue; ci->state.timeplayed += lastmillis - ci->state.lasttimeplayed; ci->state.lasttimeplayed = lastmillis; - - loopj(numteams) if(!strcmp(ci->team, teamranks[j].name)) - { + loopj(numteams) if(!strcmp(ci->team, teamranks[j].name)) { teamrank &ts = teamranks[j]; ts.rank += ci->state.effectiveness/max(ci->state.timeplayed, 1); ts.clients++; @@ -987,24 +745,19 @@ namespace server } } teamrank *worst = &teamranks[numteams-1]; - loopi(numteams-1) - { + loopi(numteams-1) { teamrank &ts = teamranks[i]; if(ts.rank < worst->rank || (ts.rank == worst->rank && ts.clients < worst->clients)) worst = &ts; } return worst->name; } - - void prunedemos(int extra = 0) - { + void prunedemos(int extra = 0) { int n = clamp(demos.length() + extra - maxdemos, 0, demos.length()); if(n <= 0) return; loopi(n) delete[] demos[i].data; demos.remove(0, n); } - - void adddemo() - { + void adddemo() { if(!demotmp) return; int len = (int)min(demotmp->size(), stream::offset((maxdemosize<<20) + 0x10000)); demofile &d = demos.add(); @@ -1019,22 +772,15 @@ namespace server demotmp->read(d.data, len); DELETEP(demotmp); } - - void enddemorecord() - { + void enddemorecord() { if(!demorecord) return; - DELETEP(demorecord); - if(!demotmp) return; if(!maxdemos || !maxdemosize) { DELETEP(demotmp); return; } - prunedemos(1); adddemo(); } - - void writedemo(int chan, void *data, int len) - { + void writedemo(int chan, void *data, int len) { if(!demorecord) return; int stamp[3] = { gamemillis, chan, len }; lilswap(stamp, 3); @@ -1042,86 +788,61 @@ namespace server demorecord->write(data, len); if(demorecord->rawtell() >= (maxdemosize<<20)) enddemorecord(); } - - void recordpacket(int chan, void *data, int len) - { + void recordpacket(int chan, void *data, int len) { writedemo(chan, data, len); } - int welcomepacket(packetbuf &p, clientinfo *ci); void sendwelcome(clientinfo *ci); - - void setupdemorecord() - { + void setupdemorecord() { if(!m_mp(gamemode) || m_edit) return; - demotmp = opentempfile("demorecord", "w+b"); if(!demotmp) return; - stream *f = opengzfile(NULL, "wb", demotmp); if(!f) { DELETEP(demotmp); return; } - sendservmsg("recording demo"); - demorecord = f; - demoheader hdr; memcpy(hdr.magic, DEMO_MAGIC, sizeof(hdr.magic)); hdr.version = DEMO_VERSION; hdr.protocol = PROTOCOL_VERSION; lilswap(&hdr.version, 2); demorecord->write(&hdr, sizeof(demoheader)); - packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE); welcomepacket(p, NULL); writedemo(1, p.buf, p.len); } - - void listdemos(int cn) - { + void listdemos(int cn) { packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE); putint(p, N_SENDDEMOLIST); putint(p, demos.length()); loopv(demos) sendstring(demos[i].info, p); sendpacket(cn, 1, p.finalize()); } - - void cleardemos(int n) - { - if(!n) - { + void cleardemos(int n) { + if(!n) { loopv(demos) delete[] demos[i].data; demos.shrink(0); sendservmsg("cleared all demos"); } - else if(demos.inrange(n-1)) - { + else if(demos.inrange(n-1)) { delete[] demos[n-1].data; demos.remove(n-1); sendservmsgf("cleared demo %d", n); } } - - static void freegetmap(ENetPacket *packet) - { - loopv(clients) - { + static void freegetmap(ENetPacket *packet) { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->getmap == packet) ci->getmap = NULL; } } - - static void freegetdemo(ENetPacket *packet) - { - loopv(clients) - { + static void freegetdemo(ENetPacket *packet) { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->getdemo == packet) ci->getdemo = NULL; } } - - void senddemo(clientinfo *ci, int num, int tag) - { + void senddemo(clientinfo *ci, int num, int tag) { if(ci->getdemo) return; if(!num) num = demos.length(); if(!demos.inrange(num-1)) return; @@ -1129,39 +850,28 @@ namespace server if((ci->getdemo = sendf(ci->clientnum, 2, "riim", N_SENDDEMO, tag, d.len, d.data))) ci->getdemo->freeCallback = freegetdemo; } - - void enddemoplayback() - { + void enddemoplayback() { if(!demoplayback) return; DELETEP(demoplayback); - loopv(clients) sendf(clients[i]->clientnum, 1, "ri3", N_DEMOPLAYBACK, 0, clients[i]->clientnum); - sendservmsg("demo playback finished"); - loopv(clients) sendwelcome(clients[i]); } - SVARP(demodir, "demo"); - - const char *getdemofile(const char *file, bool init) - { + const char *getdemofile(const char *file, bool init) { if(!demodir[0]) return NULL; static string buf; copystring(buf, demodir); int dirlen = strlen(buf); if(buf[dirlen] != '/' && buf[dirlen] != '\\' && dirlen+1 < (int)sizeof(buf)) { buf[dirlen++] = '/'; buf[dirlen] = '\0'; } - if(init) - { + if(init) { const char *dir = findfile(buf, "w"); if(!fileexists(dir, "w")) createdir(dir); } concatstring(buf, file); return buf; } - - void setupdemoplayback() - { + void setupdemoplayback() { if(demoplayback) return; demoheader hdr; string msg; @@ -1175,48 +885,37 @@ namespace server if(!demoplayback) formatstring(msg, "could not read demo \"%s\"", file); else if(demoplayback->read(&hdr, sizeof(demoheader))!=sizeof(demoheader) || memcmp(hdr.magic, DEMO_MAGIC, sizeof(hdr.magic))) formatstring(msg, "\"%s\" is not a demo file", file); - else - { + else { lilswap(&hdr.version, 2); if(hdr.version!=DEMO_VERSION) formatstring(msg, "demo \"%s\" requires an %s version of Cube 2: Sauerbraten", file, hdr.versionread(&nextplayback, sizeof(nextplayback))!=sizeof(nextplayback)) - { + if(demoplayback->read(&nextplayback, sizeof(nextplayback))!=sizeof(nextplayback)) { enddemoplayback(); return; } lilswap(&nextplayback, 1); } - - void readdemo() - { + void readdemo() { if(!demoplayback) return; - while(gamemillis>=nextplayback) - { + while(gamemillis>=nextplayback) { int chan, len; if(demoplayback->read(&chan, sizeof(chan))!=sizeof(chan) || - demoplayback->read(&len, sizeof(len))!=sizeof(len)) - { + demoplayback->read(&len, sizeof(len))!=sizeof(len)) { enddemoplayback(); return; } lilswap(&chan, 1); lilswap(&len, 1); ENetPacket *packet = enet_packet_create(NULL, len+1, 0); - if(!packet || demoplayback->read(packet->data+1, len)!=size_t(len)) - { + if(!packet || demoplayback->read(packet->data+1, len)!=size_t(len)) { if(packet) enet_packet_destroy(packet); enddemoplayback(); return; @@ -1225,24 +924,19 @@ namespace server sendpacket(-1, chan, packet); if(!packet->referenceCount) enet_packet_destroy(packet); if(!demoplayback) break; - if(demoplayback->read(&nextplayback, sizeof(nextplayback))!=sizeof(nextplayback)) - { + if(demoplayback->read(&nextplayback, sizeof(nextplayback))!=sizeof(nextplayback)) { enddemoplayback(); return; } lilswap(&nextplayback, 1); } } - - void timeupdate(int secs) - { + void timeupdate(int secs) { if(!demoplayback) return; if(secs <= 0) interm = -1; else gamelimit = max(gamelimit, nextplayback + secs*1000); } - - void seekdemo(char *t) - { + void seekdemo(char *t) { if(!demoplayback) return; bool rev = *t == '-'; if(rev) t++; @@ -1251,170 +945,123 @@ namespace server else { secs = mins; mins = 0; } if(*t == '.') millis = strtoul(t+1, &t, 10); int offset = max(millis + (mins*60 + secs)*1000, 0), prevmillis = gamemillis; - if(rev) while(gamelimit - offset > gamemillis) - { + if(rev) while(gamelimit - offset > gamemillis) { gamemillis = gamelimit - offset; readdemo(); } - else if(offset > gamemillis) - { + else if(offset > gamemillis) { gamemillis = offset; readdemo(); } - if(gamemillis > prevmillis) - { + if(gamemillis > prevmillis) { if(!interm) sendf(-1, 1, "ri2", N_TIMEUP, max((gamelimit - gamemillis)/1000, 1)); } } - - ICOMMAND(seekdemo, "sN$", (char *t, int *numargs, ident *id), - { + ICOMMAND(seekdemo, "sN$", (char *t, int *numargs, ident *id), { if(*numargs > 0) seekdemo(t); - else - { + else { int secs = gamemillis/1000; defformatstring(str, "%d:%02d.%03d", secs/60, secs%60, gamemillis%1000); if(*numargs < 0) result(str); else printsvar(id, str); } }); - - void stopdemo() - { + void stopdemo() { if(m_demo) enddemoplayback(); else enddemorecord(); } - - void pausegame(bool val, clientinfo *ci = NULL) - { + void pausegame(bool val, clientinfo *ci = NULL) { if(gamepaused==val) return; gamepaused = val; sendf(-1, 1, "riii", N_PAUSEGAME, gamepaused ? 1 : 0, ci ? ci->clientnum : -1); } - - void checkpausegame() - { + void checkpausegame() { if(!gamepaused) return; int admins = 0; loopv(clients) if(clients[i]->privilege >= (restrictpausegame ? PRIV_ADMIN : PRIV_MASTER) || clients[i]->local) admins++; if(!admins) pausegame(false); } - - void forcepaused(bool paused) - { + void forcepaused(bool paused) { pausegame(paused); } - bool ispaused() { return gamepaused; } - - void changegamespeed(int val, clientinfo *ci = NULL) - { + void changegamespeed(int val, clientinfo *ci = NULL) { val = clamp(val, 10, 1000); if(gamespeed==val) return; gamespeed = val; sendf(-1, 1, "riii", N_GAMESPEED, gamespeed, ci ? ci->clientnum : -1); } - - void forcegamespeed(int speed) - { + void forcegamespeed(int speed) { changegamespeed(speed); } - int scaletime(int t) { return t*gamespeed; } - SVAR(serverauth, ""); - - struct userkey - { + struct userkey { char *name; char *desc; - userkey() : name(NULL), desc(NULL) {} userkey(char *name, char *desc) : name(name), desc(desc) {} }; - static inline uint hthash(const userkey &k) { return ::hthash(k.name); } static inline bool htcmp(const userkey &x, const userkey &y) { return !strcmp(x.name, y.name) && !strcmp(x.desc, y.desc); } - - struct userinfo : userkey - { + struct userinfo : userkey { void *pubkey; int privilege; - userinfo() : pubkey(NULL), privilege(PRIV_NONE) {} ~userinfo() { delete[] name; delete[] desc; if(pubkey) freepubkey(pubkey); } }; hashset users; - - void adduser(char *name, char *desc, char *pubkey, char *priv) - { + void adduser(char *name, char *desc, char *pubkey, char *priv) { userkey key(name, desc); userinfo &u = users[key]; if(u.pubkey) { freepubkey(u.pubkey); u.pubkey = NULL; } if(!u.name) u.name = newstring(name); if(!u.desc) u.desc = newstring(desc); u.pubkey = parsepubkey(pubkey); - switch(priv[0]) - { + switch(priv[0]) { case 'a': case 'A': u.privilege = PRIV_ADMIN; break; case 'm': case 'M': default: u.privilege = PRIV_AUTH; break; case 'n': case 'N': u.privilege = PRIV_NONE; break; } } COMMAND(adduser, "ssss"); - - void clearusers() - { + void clearusers() { users.clear(); } COMMAND(clearusers, ""); - - void hashpassword(int cn, int sessionid, const char *pwd, char *result, int maxlen) - { + void hashpassword(int cn, int sessionid, const char *pwd, char *result, int maxlen) { char buf[2*sizeof(string)]; formatstring(buf, "%d %d ", cn, sessionid); concatstring(buf, pwd, sizeof(buf)); if(!hashstring(buf, result, maxlen)) *result = '\0'; } - - bool checkpassword(clientinfo *ci, const char *wanted, const char *given) - { + bool checkpassword(clientinfo *ci, const char *wanted, const char *given) { string hash; hashpassword(ci->clientnum, ci->sessionid, wanted, hash, sizeof(hash)); return !strcmp(hash, given); } - - void revokemaster(clientinfo *ci) - { + void revokemaster(clientinfo *ci) { ci->privilege = PRIV_NONE; if(ci->state.state==CS_SPECTATOR && !ci->local) aiman::removeai(ci); } - extern void connected(clientinfo *ci); - - bool setmaster(clientinfo *ci, bool val, const char *pass = "", const char *authname = NULL, const char *authdesc = NULL, int authpriv = PRIV_MASTER, bool force = false, bool trial = false) - { + bool setmaster(clientinfo *ci, bool val, const char *pass = "", const char *authname = NULL, const char *authdesc = NULL, int authpriv = PRIV_MASTER, bool force = false, bool trial = false) { if(authname && !val) return false; const char *name = ""; - if(val) - { + if(val) { bool haspass = adminpass[0] && checkpassword(ci, adminpass, pass); int wantpriv = ci->local || haspass ? PRIV_ADMIN : authpriv; if(wantpriv <= ci->privilege) return true; - else if(wantpriv <= PRIV_MASTER && !force) - { - if(ci->state.state==CS_SPECTATOR) - { + else if(wantpriv <= PRIV_MASTER && !force) { + if(ci->state.state==CS_SPECTATOR) { sendf(ci->clientnum, 1, "ris", N_SERVMSG, "Spectators may not claim master."); return false; } - loopv(clients) if(ci!=clients[i] && clients[i]->privilege) - { + loopv(clients) if(ci!=clients[i] && clients[i]->privilege) { sendf(ci->clientnum, 1, "ris", N_SERVMSG, "Master is already claimed."); return false; } - if(!authname && !(mastermask&MM_AUTOAPPROVE) && !ci->privilege && !ci->local) - { + if(!authname && !(mastermask&MM_AUTOAPPROVE) && !ci->privilege && !ci->local) { sendf(ci->clientnum, 1, "ris", N_SERVMSG, "This server requires you to use the \"/auth\" command to claim master."); return false; } @@ -1423,8 +1070,7 @@ namespace server ci->privilege = wantpriv; name = privname(ci->privilege); } - else - { + else { if(!ci->privilege) return false; if(trial) return true; name = privname(ci->privilege); @@ -1432,14 +1078,12 @@ namespace server } bool hasmaster = false; loopv(clients) if(clients[i]->local || clients[i]->privilege >= PRIV_MASTER) hasmaster = true; - if(!hasmaster) - { + if(!hasmaster) { mastermode = MM_OPEN; allowedips.shrink(0); } string msg; - if(val && authname) - { + if(val && authname) { if(authdesc && authdesc[0]) formatstring(msg, "%s claimed %s as '\fs\f5%s\fr' [\fs\f0%s\fr]", colorname(ci), name, authname, authdesc); else formatstring(msg, "%s claimed %s as '\fs\f5%s\fr'", colorname(ci), name, authname); } @@ -1449,8 +1093,7 @@ namespace server sendstring(msg, p); putint(p, N_CURRENTMASTER); putint(p, mastermode); - loopv(clients) if(clients[i]->privilege >= PRIV_MASTER) - { + loopv(clients) if(clients[i]->privilege >= PRIV_MASTER) { putint(p, clients[i]->clientnum); putint(p, clients[i]->privilege); } @@ -1459,24 +1102,18 @@ namespace server checkpausegame(); return true; } - - bool trykick(clientinfo *ci, int victim, const char *reason = NULL, const char *authname = NULL, const char *authdesc = NULL, int authpriv = PRIV_NONE, bool trial = false) - { + bool trykick(clientinfo *ci, int victim, const char *reason = NULL, const char *authname = NULL, const char *authdesc = NULL, int authpriv = PRIV_NONE, bool trial = false) { int priv = ci->privilege; - if(authname) - { + if(authname) { if(priv >= authpriv || ci->local) authname = authdesc = NULL; else priv = authpriv; } - if((priv || ci->local) && ci->clientnum!=victim) - { + if((priv || ci->local) && ci->clientnum!=victim) { clientinfo *vinfo = (clientinfo *)getclientinfo(victim); - if(vinfo && vinfo->connected && (priv >= vinfo->privilege || ci->local) && vinfo->privilege < PRIV_ADMIN && !vinfo->local) - { + if(vinfo && vinfo->connected && (priv >= vinfo->privilege || ci->local) && vinfo->privilege < PRIV_ADMIN && !vinfo->local) { if(trial) return true; string kicker; - if(authname) - { + if(authname) { if(authdesc && authdesc[0]) formatstring(kicker, "%s as '\fs\f5%s\fr' [\fs\f0%s\fr]", colorname(ci), authname, authdesc); else formatstring(kicker, "%s as '\fs\f5%s\fr'", colorname(ci), authname); } @@ -1485,23 +1122,18 @@ namespace server else sendservmsgf("%s kicked %s", kicker, colorname(vinfo)); uint ip = getclientip(victim); addban(ip, 4*60*60000); - kickclients(ip, ci, priv); + kickclients(ci, priv); } } return false; } - - savedscore *findscore(clientinfo *ci, bool insert) - { + savedscore *findscore(clientinfo *ci, bool insert) { uint ip = getclientip(ci->clientnum); if(!ip && !ci->local) return 0; - if(!insert) - { - loopv(clients) - { + if(!insert) { + loopv(clients) { clientinfo *oi = clients[i]; - if(oi->clientnum != ci->clientnum && getclientip(oi->clientnum) == ip && !strcmp(oi->name, ci->name)) - { + if(oi->clientnum != ci->clientnum && getclientip(oi->clientnum) == ip && !strcmp(oi->name, ci->name)) { oi->state.timeplayed += lastmillis - oi->state.lasttimeplayed; oi->state.lasttimeplayed = lastmillis; static savedscore curscore; @@ -1510,8 +1142,7 @@ namespace server } } } - loopv(scores) - { + loopv(scores) { savedscore &sc = scores[i]; if(sc.ip == ip && !strcmp(sc.name, ci->name)) return ≻ } @@ -1521,30 +1152,22 @@ namespace server copystring(sc.name, ci->name); return ≻ } - - void savescore(clientinfo *ci) - { + void savescore(clientinfo *ci) { savedscore *sc = findscore(ci, true); if(sc) sc->save(ci->state); } - - static struct msgfilter - { + static struct msgfilter { uchar msgmask[NUMMSG]; - - msgfilter(int msg, ...) - { + msgfilter(int msg, ...) { memset(msgmask, 0, sizeof(msgmask)); va_list msgs; va_start(msgs, msg); - for(uchar val = 1; msg < NUMMSG; msg = va_arg(msgs, int)) - { + for(uchar val = 1; msg < NUMMSG; msg = va_arg(msgs, int)) { if(msg < 0) val = uchar(-msg); else msgmask[msg] = val; } va_end(msgs); } - uchar operator[](int msg) const { return msg >= 0 && msg < NUMMSG ? msgmask[msg] : 0; } } msgfilter(-1, N_CONNECT, N_SERVINFO, N_INITCLIENT, N_WELCOME, N_MAPCHANGE, N_SERVMSG, N_DAMAGE, N_HITPUSH, N_SHOTFX, N_EXPLODEFX, N_DIED, N_SPAWNSTATE, N_FORCEDEATH, N_TEAMINFO, N_ITEMACC, N_ITEMSPAWN, N_TIMEUP, N_CDIS, N_CURRENTMASTER, N_PONG, N_RESUME, @@ -1553,13 +1176,9 @@ namespace server N_NEWMAP, N_GETMAP, N_SENDMAP, N_CLIPBOARD, -3, N_EDITENT, N_EDITF, N_EDITT, N_EDITM, N_FLIP, N_COPY, N_PASTE, N_ROTATE, N_REPLACE, N_DELCUBE, N_EDITVAR, N_EDITVSLOT, N_UNDO, N_REDO, -4, N_POS, NUMMSG), connectfilter(-1, N_CONNECT, -2, N_AUTHANS, -3, N_PING, NUMMSG); - - int checktype(int type, clientinfo *ci) - { - if(ci) - { - if(!ci->connected) switch(connectfilter[type]) - { + int checktype(int type, clientinfo *ci) { + if(ci) { + if(!ci->connected) switch(connectfilter[type]) { // allow only before authconnect case 1: return !ci->connectauth ? type : -1; // allow only during authconnect @@ -1571,8 +1190,7 @@ namespace server } if(ci->local) return type; } - switch(msgfilter[type]) - { + switch(msgfilter[type]) { // server-only messages case 1: return ci ? -1 : type; // only allowed in coop-edit @@ -1585,54 +1203,41 @@ namespace server if(ci && ++ci->overflow >= 200) return -2; return type; } - - struct worldstate - { + struct worldstate { int uses, len; uchar *data; - worldstate() : uses(0), len(0), data(NULL) {} - void setup(int n) { len = n; data = new uchar[n]; } void cleanup() { DELETEA(data); len = 0; } bool contains(const uchar *p) const { return p >= data && p < &data[len]; } }; vector worldstates; bool reliablemessages = false; - - void cleanworldstate(ENetPacket *packet) - { - loopv(worldstates) - { + void cleanworldstate(ENetPacket *packet) { + loopv(worldstates) { worldstate &ws = worldstates[i]; if(!ws.contains(packet->data)) continue; ws.uses--; - if(ws.uses <= 0) - { + if(ws.uses <= 0) { ws.cleanup(); worldstates.removeunordered(i); } break; } } - - void flushclientposition(clientinfo &ci) - { + void flushclientposition(clientinfo &ci) { if(ci.position.empty() || (!hasnonlocalclients() && !demorecord)) return; packetbuf p(ci.position.length(), 0); p.put(ci.position.getbuf(), ci.position.length()); ci.position.setsize(0); sendpacket(-1, 0, p.finalize(), ci.ownernum); } - - static void sendpositions(worldstate &ws, ucharbuf &wsbuf) - { + static void sendpositions(worldstate &ws, ucharbuf &wsbuf) { if(wsbuf.empty()) return; int wslen = wsbuf.length(); recordpacket(0, wsbuf.buf, wslen); wsbuf.put(wsbuf.buf, wslen); - loopv(clients) - { + loopv(clients) { clientinfo &ci = *clients[i]; if(ci.state.aitype != AI_NONE) continue; uchar *data = wsbuf.buf; @@ -1646,9 +1251,7 @@ namespace server } wsbuf.offset(wsbuf.length()); } - - static inline void addposition(worldstate &ws, ucharbuf &wsbuf, int mtu, clientinfo &bi, clientinfo &ci) - { + static inline void addposition(worldstate &ws, ucharbuf &wsbuf, int mtu, clientinfo &bi, clientinfo &ci) { if(bi.position.empty()) return; if(wsbuf.length() + bi.position.length() > mtu) sendpositions(ws, wsbuf); int offset = wsbuf.length(); @@ -1658,15 +1261,12 @@ namespace server if(ci.wsdata < wsbuf.buf) { ci.wsdata = &wsbuf.buf[offset]; ci.wslen = len; } else ci.wslen += len; } - - static void sendmessages(worldstate &ws, ucharbuf &wsbuf) - { + static void sendmessages(worldstate &ws, ucharbuf &wsbuf) { if(wsbuf.empty()) return; int wslen = wsbuf.length(); recordpacket(1, wsbuf.buf, wslen); wsbuf.put(wsbuf.buf, wslen); - loopv(clients) - { + loopv(clients) { clientinfo &ci = *clients[i]; if(ci.state.aitype != AI_NONE) continue; uchar *data = wsbuf.buf; @@ -1680,9 +1280,7 @@ namespace server } wsbuf.offset(wsbuf.length()); } - - static inline void addmessages(worldstate &ws, ucharbuf &wsbuf, int mtu, clientinfo &bi, clientinfo &ci) - { + static inline void addmessages(worldstate &ws, ucharbuf &wsbuf, int mtu, clientinfo &bi, clientinfo &ci) { if(bi.messages.empty()) return; if(wsbuf.length() + 10 + bi.messages.length() > mtu) sendmessages(ws, wsbuf); int offset = wsbuf.length(); @@ -1695,20 +1293,16 @@ namespace server if(ci.wsdata < wsbuf.buf) { ci.wsdata = &wsbuf.buf[offset]; ci.wslen = len; } else ci.wslen += len; } - - bool buildworldstate() - { + bool buildworldstate() { int wsmax = 0; - loopv(clients) - { + loopv(clients) { clientinfo &ci = *clients[i]; ci.overflow = 0; ci.wsdata = NULL; wsmax += ci.position.length(); if(ci.messages.length()) wsmax += 10 + ci.messages.length(); } - if(wsmax <= 0) - { + if(wsmax <= 0) { reliablemessages = false; return false; } @@ -1717,16 +1311,14 @@ namespace server int mtu = getservermtu() - 100; if(mtu <= 0) mtu = ws.len; ucharbuf wsbuf(ws.data, ws.len); - loopv(clients) - { + loopv(clients) { clientinfo &ci = *clients[i]; if(ci.state.aitype != AI_NONE) continue; addposition(ws, wsbuf, mtu, ci, ci); loopvj(ci.bots) addposition(ws, wsbuf, mtu, *ci.bots[j], ci); } sendpositions(ws, wsbuf); - loopv(clients) - { + loopv(clients) { clientinfo &ci = *clients[i]; if(ci.state.aitype != AI_NONE) continue; addmessages(ws, wsbuf, mtu, ci, ci); @@ -1739,9 +1331,7 @@ namespace server worldstates.drop(); return false; } - - bool sendpackets(bool force) - { + bool sendpackets(bool force) { if(clients.empty() || (!hasnonlocalclients() && !demorecord)) return false; enet_uint32 curtime = enet_time_get()-lastsend; if(curtime<33 && !force) return false; @@ -1749,10 +1339,8 @@ namespace server lastsend += curtime - (curtime%33); return flush; } - template - void sendstate(gamestate &gs, T &p) - { + void sendstate(gamestate &gs, T &p) { putint(p, gs.lifesequence); putint(p, gs.health); putint(p, gs.maxhealth); @@ -1762,16 +1350,12 @@ namespace server putint(p, gs.gunselect); loopi(GUN_PISTOL-GUN_SG+1) putint(p, gs.ammo[GUN_SG+i]); } - - void spawnstate(clientinfo *ci) - { + void spawnstate(clientinfo *ci) { gamestate &gs = ci->state; gs.spawnstate(gamemode); gs.lifesequence = (gs.lifesequence + 1)&0x7F; } - - void sendspawn(clientinfo *ci) - { + void sendspawn(clientinfo *ci) { gamestate &gs = ci->state; spawnstate(ci); sendf(ci->ownernum, 1, "rii8v", N_SPAWNSTATE, ci->clientnum, gs.lifesequence, @@ -1780,18 +1364,13 @@ namespace server gs.gunselect, GUN_PISTOL-GUN_SG+1, &gs.ammo[GUN_SG]); gs.lastspawn = gamemillis; } - - void sendwelcome(clientinfo *ci) - { + void sendwelcome(clientinfo *ci) { packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE); int chan = welcomepacket(p, ci); sendpacket(ci->clientnum, chan, p.finalize()); } - - void putinitclient(clientinfo *ci, packetbuf &p) - { - if(ci->state.aitype != AI_NONE) - { + void putinitclient(clientinfo *ci, packetbuf &p) { + if(ci->state.aitype != AI_NONE) { putint(p, N_INITAI); putint(p, ci->clientnum); putint(p, ci->ownernum); @@ -1801,8 +1380,7 @@ namespace server sendstring(ci->name, p); sendstring(ci->team, p); } - else - { + else { putint(p, N_INITCLIENT); putint(p, ci->clientnum); sendstring(ci->name, p); @@ -1810,57 +1388,43 @@ namespace server putint(p, ci->playermodel); } } - - void welcomeinitclient(packetbuf &p, int exclude = -1) - { - loopv(clients) - { + void welcomeinitclient(packetbuf &p, int exclude = -1) { + loopv(clients) { clientinfo *ci = clients[i]; if(!ci->connected || ci->clientnum == exclude) continue; - putinitclient(ci, p); } } - - bool hasmap(clientinfo *ci) - { + bool hasmap(clientinfo *ci) { return (m_edit && (clients.length() > 0 || ci->local)) || (smapname[0] && (!m_timed || gamemillis < gamelimit || (ci->state.state==CS_SPECTATOR && !ci->privilege && !ci->local) || numclients(ci->clientnum, true, true, true))); } - - int welcomepacket(packetbuf &p, clientinfo *ci) - { + int welcomepacket(packetbuf &p, clientinfo *ci) { putint(p, N_WELCOME); putint(p, N_MAPCHANGE); sendstring(smapname, p); putint(p, gamemode); putint(p, notgotitems ? 1 : 0); - if(!ci || (m_timed && smapname[0])) - { + if(!ci || (m_timed && smapname[0])) { putint(p, N_TIMEUP); putint(p, gamemillis < gamelimit && !interm ? max((gamelimit - gamemillis)/1000, 1) : 0); } - if(!notgotitems) - { + if(!notgotitems) { putint(p, N_ITEMLIST); - loopv(sents) if(sents[i].spawned) - { + loopv(sents) if(sents[i].spawned) { putint(p, i); putint(p, sents[i].type); } putint(p, -1); } bool hasmaster = false; - if(mastermode != MM_OPEN) - { + if(mastermode != MM_OPEN) { putint(p, N_CURRENTMASTER); putint(p, mastermode); hasmaster = true; } - loopv(clients) if(clients[i]->privilege >= PRIV_MASTER) - { - if(!hasmaster) - { + loopv(clients) if(clients[i]->privilege >= PRIV_MASTER) { + if(!hasmaster) { putint(p, N_CURRENTMASTER); putint(p, mastermode); hasmaster = true; @@ -1869,35 +1433,30 @@ namespace server putint(p, clients[i]->privilege); } if(hasmaster) putint(p, -1); - if(gamepaused) - { + if(gamepaused) { putint(p, N_PAUSEGAME); putint(p, 1); putint(p, -1); } - if(gamespeed != 100) - { + if(gamespeed != 100) { putint(p, N_GAMESPEED); putint(p, gamespeed); putint(p, -1); } - if(m_teammode) - { + if(m_teammode) { putint(p, N_TEAMINFO); enumerate(teaminfos, teaminfo, t, if(t.frags) { sendstring(t.team, p); putint(p, t.frags); } ); sendstring("", p); } - if(ci) - { + if(ci) { putint(p, N_SETTEAM); putint(p, ci->clientnum); sendstring(ci->team, p); putint(p, -1); } - if(ci && (m_demo || m_mp(gamemode)) && ci->state.state!=CS_SPECTATOR) - { + if(ci && (m_demo || m_mp(gamemode)) && ci->state.state!=CS_SPECTATOR) { gamestate &gs = ci->state; spawnstate(ci); putint(p, N_SPAWNSTATE); @@ -1905,18 +1464,15 @@ namespace server sendstate(gs, p); gs.lastspawn = gamemillis; } - if(ci && ci->state.state==CS_SPECTATOR) - { + if(ci && ci->state.state==CS_SPECTATOR) { putint(p, N_SPECTATOR); putint(p, ci->clientnum); putint(p, 1); sendf(-1, 1, "ri3x", N_SPECTATOR, ci->clientnum, 1, ci->clientnum); } - if(!ci || clients.length()>1) - { + if(!ci || clients.length()>1) { putint(p, N_RESUME); - loopv(clients) - { + loopv(clients) { clientinfo *oi = clients[i]; if(ci && oi->clientnum==ci->clientnum) continue; putint(p, oi->clientnum); @@ -1932,21 +1488,16 @@ namespace server } return 1; } - - bool restorescore(clientinfo *ci) - { + bool restorescore(clientinfo *ci) { //if(ci->local) return false; savedscore *sc = findscore(ci, false); - if(sc) - { + if(sc) { sc->restore(ci->state); return true; } return false; } - - void sendresume(clientinfo *ci) - { + void sendresume(clientinfo *ci) { gamestate &gs = ci->state; sendf(-1, 1, "ri3i5i6vi", N_RESUME, ci->clientnum, gs.state, gs.frags, gs.flags, gs.deaths, gs.quadmillis, @@ -1955,22 +1506,17 @@ namespace server gs.armour, gs.maxarmour, gs.armourtype, gs.gunselect, GUN_PISTOL-GUN_SG+1, &gs.ammo[GUN_SG], -1); } - - void sendinitclient(clientinfo *ci) - { + void sendinitclient(clientinfo *ci) { packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE); putinitclient(ci, p); sendpacket(-1, 1, p.finalize(), ci->clientnum); } - - void loaditems() - { + void loaditems() { resetitems(); notgotitems = true; if(m_edit || !loadents(smapname, ments, &mcrc)) return; - loopv(ments) if(canspawnitem(ments[i].type)) - { + loopv(ments) if(canspawnitem(ments[i].type)) { server_entity se = { NOTUSED, 0, false }; while(sents.length()<=i) sents.add(se); sents[i].type = ments[i].type; @@ -1979,14 +1525,11 @@ namespace server } notgotitems = false; } - - void changemap(const char *s, int mode) - { + void changemap(const char *s, int mode) { stopdemo(); pausegame(false); changegamespeed(100); aiman::clearai(); - gamemode = mode; gamemillis = 0; gamelimit = 10*60000; @@ -1997,50 +1540,36 @@ namespace server scores.shrink(0); shouldcheckteamkills = false; teamkills.shrink(0); - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; ci->state.timeplayed += lastmillis - ci->state.lasttimeplayed; } - if(!m_mp(gamemode)) kicknonlocalclients(DISC_LOCAL); - sendf(-1, 1, "risii", N_MAPCHANGE, smapname, gamemode, 1); - clearteaminfo(); if(m_teammode) autoteam(); - if(m_timed && smapname[0]) sendf(-1, 1, "ri2", N_TIMEUP, gamemillis < gamelimit && !interm ? max((gamelimit - gamemillis)/1000, 1) : 0); - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; ci->mapchange(); ci->state.lasttimeplayed = lastmillis; if(m_mp(gamemode) && ci->state.state!=CS_SPECTATOR) sendspawn(ci); } - aiman::changemap(); - - if(m_demo) - { + if(m_demo) { if(clients.length()) setupdemoplayback(); } - else - { + else { if(demonextmatch) setupdemorecord(); demonextmatch = autorecorddemo!=0; } } - - void rotatemap(bool next) - { - if(!maprotations.inrange(curmaprotation)) - { + void rotatemap(bool next) { + if(!maprotations.inrange(curmaprotation)) { changemap("", 1); return; } - if(next) - { + if(next) { curmaprotation = findmaprotation(gamemode, smapname); if(curmaprotation >= 0) nextmaprotation(); else curmaprotation = smapname[0] ? max(findmaprotation(gamemode, ""), 0) : 0; @@ -2048,29 +1577,23 @@ namespace server maprotation &rot = maprotations[curmaprotation]; changemap(rot.map, rot.findmode(gamemode)); } - - struct votecount - { + struct votecount { char *map; int mode, count; votecount() {} votecount(char *s, int n) : map(s), mode(n), count(0) {} }; - - void checkvotes(bool force = false) - { + void checkvotes(bool force = false) { vector votes; int maxvotes = 0; - loopv(clients) - { + loopv(clients) { clientinfo *oi = clients[i]; if(oi->state.state==CS_SPECTATOR && !oi->privilege && !oi->local) continue; if(oi->state.aitype!=AI_NONE) continue; maxvotes++; if(!m_valid(oi->modevote)) continue; votecount *vc = NULL; - loopvj(votes) if(!strcmp(oi->mapvote, votes[j].map) && oi->modevote==votes[j].mode) - { + loopvj(votes) if(!strcmp(oi->mapvote, votes[j].map) && oi->modevote==votes[j].mode) { vc = &votes[j]; break; } @@ -2079,24 +1602,19 @@ namespace server } votecount *best = NULL; loopv(votes) if(!best || votes[i].count > best->count || (votes[i].count == best->count && rnd(2))) best = &votes[i]; - if(force || (best && best->count > maxvotes/2)) - { + if(force || (best && best->count > maxvotes/2)) { sendpackets(true); if(demorecord) enddemorecord(); - if(best && (best->count > (force ? 1 : maxvotes/2))) - { + if(best && (best->count > (force ? 1 : maxvotes/2))) { sendservmsg(force ? "vote passed by default" : "vote passed by majority"); changemap(best->map, best->mode); } else rotatemap(true); } } - - void forcemap(const char *map, int mode) - { + void forcemap(const char *map, int mode) { stopdemo(); - if(!map[0] && !m_check(mode, M_EDIT)) - { + if(!map[0] && !m_check(mode, M_EDIT)) { int idx = findmaprotation(mode, smapname); if(idx < 0 && smapname[0]) idx = findmaprotation(mode, ""); if(idx < 0) return; @@ -2105,54 +1623,43 @@ namespace server if(hasnonlocalclients()) sendservmsgf("local player forced %s on map %s", modename(mode), map[0] ? map : "[new map]"); changemap(map, mode); } - - void vote(const char *map, int reqmode, int sender) - { + void vote(const char *map, int reqmode, int sender) { clientinfo *ci = getinfo(sender); if(!ci || (ci->state.state==CS_SPECTATOR && !ci->privilege && !ci->local) || (!ci->local && !m_mp(reqmode))) return; if(!m_valid(reqmode)) return; - if(!map[0] && !m_check(reqmode, M_EDIT)) - { + if(!map[0] && !m_check(reqmode, M_EDIT)) { int idx = findmaprotation(reqmode, smapname); if(idx < 0 && smapname[0]) idx = findmaprotation(reqmode, ""); if(idx < 0) return; map = maprotations[idx].map; } - if(lockmaprotation && !ci->local && ci->privilege < (lockmaprotation > 1 ? PRIV_ADMIN : PRIV_MASTER) && findmaprotation(reqmode, map) < 0) - { + if(lockmaprotation && !ci->local && ci->privilege < (lockmaprotation > 1 ? PRIV_ADMIN : PRIV_MASTER) && findmaprotation(reqmode, map) < 0) { sendf(sender, 1, "ris", N_SERVMSG, "This server has locked the map rotation."); return; } copystring(ci->mapvote, map); ci->modevote = reqmode; - if(ci->local || (ci->privilege && mastermode>=MM_VETO)) - { + if(ci->local || (ci->privilege && mastermode>=MM_VETO)) { sendpackets(true); if(demorecord) enddemorecord(); if(!ci->local || hasnonlocalclients()) sendservmsgf("%s forced %s on map %s", colorname(ci), modename(ci->modevote), ci->mapvote[0] ? ci->mapvote : "[new map]"); changemap(ci->mapvote, ci->modevote); } - else - { + else { sendservmsgf("%s suggests %s on map %s (select map to vote)", colorname(ci), modename(reqmode), map[0] ? map : "[new map]"); checkvotes(); } } - VAR(overtime, 0, 0, 1); - - bool checkovertime() - { + bool checkovertime() { if(!m_timed || !overtime) return false; const char* topteam = NULL; int topscore = INT_MIN; bool tied = false; - if(m_teammode) - { + if(m_teammode) { vector scores; - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->state.state==CS_SPECTATOR || !ci->team[0]) continue; int score = 0; @@ -2161,10 +1668,8 @@ namespace server else if(score == topscore && strcmp(ci->team, topteam)) tied = true; } } - else - { - loopv(clients) - { + else { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->state.state==CS_SPECTATOR) continue; int score = ci->state.frags; @@ -2178,39 +1683,30 @@ namespace server sendf(-1, 1, "ri2", N_TIMEUP, max((gamelimit - gamemillis)/1000, 1)); return true; } - - void checkintermission(bool force = false) - { - if(gamemillis >= gamelimit && !interm && (force || !checkovertime())) - { + void checkintermission(bool force = false) { + if(gamemillis >= gamelimit && !interm && (force || !checkovertime())) { sendf(-1, 1, "ri2", N_TIMEUP, 0); changegamespeed(100); interm = gamemillis + 10000; } } - void startintermission() { gamelimit = min(gamelimit, gamemillis); checkintermission(true); } - - void dodamage(clientinfo *target, clientinfo *actor, int damage, int gun, const vec &hitpush = vec(0, 0, 0)) - { + void dodamage(clientinfo *target, clientinfo *actor, int damage, int gun, const vec &hitpush = vec(0, 0, 0)) { gamestate &ts = target->state; ts.dodamage(damage); if(target!=actor && !isteam(target->team, actor->team)) actor->state.damage += damage; sendf(-1, 1, "ri6", N_DAMAGE, target->clientnum, actor->clientnum, damage, ts.armour, ts.health); if(target==actor) target->setpushed(); - else if(!hitpush.iszero()) - { + else if(!hitpush.iszero()) { ivec v(vec(hitpush).rescale(DNF)); sendf(ts.health<=0 ? -1 : target->ownernum, 1, "ri7", N_HITPUSH, target->clientnum, gun, damage, v.x, v.y, v.z); target->setpushed(); } - if(ts.health<=0) - { + if(ts.health<=0) { target->state.deaths++; int fragvalue = (target==actor || isteam(target->team, actor->team) ? -1 : 1); actor->state.frags += fragvalue; - if(fragvalue>0) - { + if(fragvalue>0) { int friends = 0, enemies = 0; // note: friends also includes the fragger if(m_teammode) loopv(clients) if(strcmp(clients[i]->team, actor->team)) enemies++; else friends++; else { friends = 1; enemies = clients.length()-1; } @@ -2222,8 +1718,7 @@ namespace server target->position.setsize(0); ts.state = CS_DEAD; ts.lastdeath = gamemillis; - if(actor!=target && isteam(actor->team, target->team)) - { + if(actor!=target && isteam(actor->team, target->team)) { actor->state.teamkills++; addteamkill(actor, target, 1); } @@ -2232,9 +1727,7 @@ namespace server // ts.respawn(); } } - - void suicide(clientinfo *ci) - { + void suicide(clientinfo *ci) { gamestate &gs = ci->state; if(gs.state!=CS_ALIVE) return; int fragvalue = -1; @@ -2248,39 +1741,29 @@ namespace server gs.lastdeath = gamemillis; gs.respawn(); } - - void suicideevent::process(clientinfo *ci) - { + void suicideevent::process(clientinfo *ci) { suicide(ci); } - - void explodeevent::process(clientinfo *ci) - { + void explodeevent::process(clientinfo *ci) { gamestate &gs = ci->state; - switch(gun) - { + switch(gun) { case GUN_RL: if(!gs.rockets.remove(id)) return; break; - case GUN_GL: if(!gs.grenades.remove(id)) return; break; - default: return; } sendf(-1, 1, "ri4x", N_EXPLODEFX, ci->clientnum, gun, id, ci->ownernum); - loopv(hits) - { + loopv(hits) { hitinfo &h = hits[i]; clientinfo *target = getinfo(h.target); if(!target || target->state.state!=CS_ALIVE || h.lifesequence!=target->state.lifesequence || h.dist<0 || h.dist>guns[gun].exprad) continue; - bool dup = false; loopj(i) if(hits[j].target==h.target) { dup = true; break; } if(dup) continue; - int damage = guns[gun].damage; if(gs.quadmillis) damage *= 4; damage = int(damage*(1-h.dist/EXP_DISTSCALE/guns[gun].exprad)); @@ -2288,9 +1771,7 @@ namespace server dodamage(target, ci, damage, gun, h.dir); } } - - void shotevent::process(clientinfo *ci) - { + void shotevent::process(clientinfo *ci) { gamestate &gs = ci->state; int wait = millis - gs.lastshot; if(!gs.isalive(gamemillis) || @@ -2306,19 +1787,15 @@ namespace server int(to.x*DMF), int(to.y*DMF), int(to.z*DMF), ci->ownernum); gs.shotdamage += guns[gun].damage*(gs.quadmillis ? 4 : 1)*guns[gun].rays; - switch(gun) - { + switch(gun) { case GUN_RL: gs.rockets.add(id); break; case GUN_GL: gs.grenades.add(id); break; - default: - { + default: { int totalrays = 0, maxrays = guns[gun].rays; - loopv(hits) - { + loopv(hits) { hitinfo &h = hits[i]; clientinfo *target = getinfo(h.target); if(!target || target->state.state!=CS_ALIVE || h.lifesequence!=target->state.lifesequence || h.rays<1 || h.dist > guns[gun].range + 1) continue; - totalrays += h.rays; if(totalrays>maxrays) continue; int damage = h.rays*guns[gun].damage; @@ -2329,65 +1806,46 @@ namespace server } } } - - void pickupevent::process(clientinfo *ci) - { + void pickupevent::process(clientinfo *ci) { gamestate &gs = ci->state; if(m_mp(gamemode) && !gs.isalive(gamemillis)) return; pickup(ent, ci->clientnum); } - - bool gameevent::flush(clientinfo *ci, int fmillis) - { + bool gameevent::flush(clientinfo *ci, int fmillis) { + (void) fmillis; process(ci); return true; } - - bool timedevent::flush(clientinfo *ci, int fmillis) - { + bool timedevent::flush(clientinfo *ci, int fmillis) { if(millis > fmillis) return false; - else if(millis >= ci->lastevent) - { + else if(millis >= ci->lastevent) { ci->lastevent = millis; process(ci); } return true; } - - void clearevent(clientinfo *ci) - { + void clearevent(clientinfo *ci) { delete ci->events.remove(0); } - - void flushevents(clientinfo *ci, int millis) - { - while(ci->events.length()) - { + void flushevents(clientinfo *ci, int millis) { + while(ci->events.length()) { gameevent *ev = ci->events[0]; if(ev->flush(ci, millis)) clearevent(ci); else break; } } - - void processevents() - { - loopv(clients) - { + void processevents() { + loopv(clients) { clientinfo *ci = clients[i]; if(curtime>0 && ci->state.quadmillis) ci->state.quadmillis = max(ci->state.quadmillis-curtime, 0); flushevents(ci, gamemillis); } } - - void cleartimedevents(clientinfo *ci) - { + void cleartimedevents(clientinfo *ci) { int keep = 0; - loopv(ci->events) - { - if(ci->events[i]->keepable()) - { - if(keep < i) - { + loopv(ci->events) { + if(ci->events[i]->keepable()) { + if(keep < i) { for(int j = keep; j < i; j++) delete ci->events[j]; ci->events.remove(keep, i - keep); i = keep; @@ -2399,31 +1857,22 @@ namespace server while(ci->events.length() > keep) delete ci->events.pop(); ci->timesync = false; } - - void serverupdate() - { - if(shouldstep && !gamepaused) - { + void serverupdate() { + if(shouldstep && !gamepaused) { gamemillis += curtime; - if(m_demo) readdemo(); - else if(!m_timed || gamemillis < gamelimit) - { + else if(!m_timed || gamemillis < gamelimit) { processevents(); - if(curtime) - { - loopv(sents) if(sents[i].spawntime) // spawn entities when timer reached - { + if(curtime) { + loopv(sents) if(sents[i].spawntime) { // spawn entities when timer reached { int oldtime = sents[i].spawntime; sents[i].spawntime -= curtime; - if(sents[i].spawntime<=0) - { + if(sents[i].spawntime<=0) { sents[i].spawntime = 0; sents[i].spawned = true; sendf(-1, 1, "ri2", N_ITEMSPAWN, i); } - else if(sents[i].spawntime<=10000 && oldtime>10000 && (sents[i].type==I_QUAD || sents[i].type==I_BOOST)) - { + else if(sents[i].spawntime<=10000 && oldtime>10000 && (sents[i].type==I_QUAD || sents[i].type==I_BOOST)) { sendf(-1, 1, "ri2", N_ANNOUNCE, sents[i].type); } } @@ -2431,77 +1880,56 @@ namespace server aiman::checkai(); } } - while(bannedips.length() && bannedips[0].expire-totalmillis <= 0) bannedips.remove(0); //~loopv(connects) if(totalmillis-connects[i]->connectmillis>15000) disconnect_client(connects[i]->clientnum, DISC_TIMEOUT); - - if(nextexceeded && gamemillis > nextexceeded && (!m_timed || gamemillis < gamelimit)) - { + if(nextexceeded && gamemillis > nextexceeded && (!m_timed || gamemillis < gamelimit)) { nextexceeded = 0; - loopvrev(clients) - { + loopvrev(clients) { clientinfo &c = *clients[i]; if(c.state.aitype != AI_NONE) continue; //~if(c.checkexceeded()) disconnect_client(c.clientnum, DISC_MSGERR); else c.scheduleexceeded(); } } - if(shouldcheckteamkills) checkteamkills(); - - if(shouldstep && !gamepaused) - { + if(shouldstep && !gamepaused) { if(m_timed && smapname[0] && gamemillis-curtime>0) checkintermission(); - if(interm > 0 && gamemillis>interm) - { + if(interm > 0 && gamemillis>interm) { if(demorecord) enddemorecord(); interm = -1; checkvotes(true); } } - shouldstep = clients.length() > 0; } - - void forcespectator(clientinfo *ci) - { + void forcespectator(clientinfo *ci) { if(ci->state.state==CS_ALIVE) suicide(ci); ci->state.state = CS_SPECTATOR; ci->state.timeplayed += lastmillis - ci->state.lasttimeplayed; if(!ci->local && (!ci->privilege || ci->warned)) aiman::removeai(ci); sendf(-1, 1, "ri3", N_SPECTATOR, ci->clientnum, 1); } - - struct crcinfo - { + struct crcinfo { int crc, matches; - crcinfo() {} crcinfo(int crc, int matches) : crc(crc), matches(matches) {} - static bool compare(const crcinfo &x, const crcinfo &y) { return x.matches > y.matches; } }; - VAR(modifiedmapspectator, 0, 1, 2); - - void checkmaps(int req = -1) - { + void checkmaps(int req = -1) { if(m_edit || !smapname[0]) return; vector crcs; int total = 0, unsent = 0, invalid = 0; if(mcrc) crcs.add(crcinfo(mcrc, clients.length() + 1)); - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->state.state==CS_SPECTATOR || ci->state.aitype != AI_NONE) continue; total++; - if(!ci->clientmap[0]) - { + if(!ci->clientmap[0]) { if(ci->mapcrc < 0) invalid++; else if(!ci->mapcrc) unsent++; } - else - { + else { crcinfo *match = NULL; loopvj(crcs) if(crcs[j].crc == ci->mapcrc) { match = &crcs[j]; break; } if(!match) crcs.add(crcinfo(ci->mapcrc, 1)); @@ -2511,19 +1939,16 @@ namespace server if(!mcrc && total - unsent < min(total, 4)) return; crcs.sort(crcinfo::compare); string msg; - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->state.state==CS_SPECTATOR || ci->state.aitype != AI_NONE || ci->clientmap[0] || ci->mapcrc >= 0 || (req < 0 && ci->warned)) continue; formatstring(msg, "%s has modified map \"%s\"", colorname(ci), smapname); sendf(req, 1, "ris", N_SERVMSG, msg); if(req < 0) ci->warned = true; } - if(crcs.length() >= 2) loopv(crcs) - { + if(crcs.length() >= 2) loopv(crcs) { crcinfo &info = crcs[i]; - if(i || info.matches <= crcs[i+1].matches) loopvj(clients) - { + if(i || info.matches <= crcs[i+1].matches) loopvj(clients) { clientinfo *ci = clients[j]; if(ci->state.state==CS_SPECTATOR || ci->state.aitype != AI_NONE || !ci->clientmap[0] || ci->mapcrc != info.crc || (req < 0 && ci->warned)) continue; formatstring(msg, "%s has modified map \"%s\"", colorname(ci), smapname); @@ -2531,20 +1956,15 @@ namespace server if(req < 0) ci->warned = true; } } - if(req < 0 && modifiedmapspectator && (mcrc || modifiedmapspectator > 1)) loopv(clients) - { + if(req < 0 && modifiedmapspectator && (mcrc || modifiedmapspectator > 1)) loopv(clients) { clientinfo *ci = clients[i]; if(!ci->local && ci->warned && ci->state.state != CS_SPECTATOR) forcespectator(ci); } } - - bool shouldspectate(clientinfo *ci) - { + bool shouldspectate(clientinfo *ci) { return !ci->local && ci->warned && modifiedmapspectator && (mcrc || modifiedmapspectator > 1); } - - void unspectate(clientinfo *ci) - { + void unspectate(clientinfo *ci) { if(shouldspectate(ci)) return; ci->state.state = CS_DEAD; ci->state.respawn(); @@ -2554,55 +1974,40 @@ namespace server if(ci->clientmap[0] || ci->mapcrc) checkmaps(); if(!hasmap(ci)) rotatemap(true); } - - void sendservinfo(clientinfo *ci) - { + void sendservinfo(clientinfo *ci) { sendf(ci->clientnum, 1, "ri5ss", N_SERVINFO, ci->clientnum, PROTOCOL_VERSION, ci->sessionid, serverpass[0] ? 1 : 0, serverdesc, serverauth); } - - void noclients() - { + void noclients() { bannedips.shrink(0); aiman::clearai(); } - - void localconnect(int n) - { + void localconnect(int n) { clientinfo *ci = getinfo(n); ci->clientnum = ci->ownernum = n; ci->connectmillis = totalmillis; ci->sessionid = (rnd(0x1000000)*((totalmillis%10000)+1))&0xFFFFFF; ci->local = true; - connects.add(ci); sendservinfo(ci); } - - void localdisconnect(int n) - { + void localdisconnect(int n) { if(m_demo) enddemoplayback(); clientdisconnect(n); } - - int clientconnect(int n) - { + int clientconnect(int n) { clientinfo *ci = getinfo(n); ci->clientnum = ci->ownernum = n; ci->connectmillis = totalmillis; ci->sessionid = (rnd(0x1000000)*((totalmillis%10000)+1))&0xFFFFFF; - connects.add(ci); if(!m_mp(gamemode)) return DISC_LOCAL; sendservinfo(ci); return DISC_NONE; } - - void clientdisconnect(int n) - { + void clientdisconnect(int n) { clientinfo *ci = getinfo(n); loopv(clients) if(clients[i]->authkickvictim == ci->clientnum) clients[i]->cleanauth(); - if(ci->connected) - { + if(ci->connected) { if(ci->privilege) setmaster(ci, false); ci->state.timeplayed += lastmillis - ci->state.lasttimeplayed; savescore(ci); @@ -2614,58 +2019,39 @@ namespace server } else connects.removeobj(ci); } - int reserveclients() { return 3; } - extern void verifybans(); - - struct banlist - { + struct banlist { vector bans; - void clear() { bans.shrink(0); } - - bool check(uint ip) - { + bool check(uint ip) { loopv(bans) if(bans[i].check(ip)) return true; return false; } - - void add(const char *ipname) - { + void add(const char *ipname) { ipmask ban; ban.parse(ipname); bans.add(ban); - verifybans(); } } ipbans, gbans; - - bool checkbans(uint ip) - { + bool checkbans(uint ip) { loopv(bannedips) if(bannedips[i].ip==ip) return true; return ipbans.check(ip) || gbans.check(ip); } - - void verifybans() - { - loopvrev(clients) - { + void verifybans() { + loopvrev(clients) { clientinfo *ci = clients[i]; if(ci->state.aitype != AI_NONE || ci->local || ci->privilege >= PRIV_ADMIN) continue; //~if(checkbans(getclientip(ci->clientnum))) disconnect_client(ci->clientnum, DISC_IPBAN); } } - ICOMMAND(clearipbans, "", (), ipbans.clear()); ICOMMAND(ipban, "s", (const char *ipname), ipbans.add(ipname)); - - int allowconnect(clientinfo *ci, const char *pwd = "") - { + int allowconnect(clientinfo *ci, const char *pwd = "") { if(ci->local) return DISC_NONE; if(!m_mp(gamemode)) return DISC_LOCAL; - if(serverpass[0]) - { + if(serverpass[0]) { if(!checkpassword(ci, serverpass, pwd)) return DISC_PASSWORD; return DISC_NONE; } @@ -2676,68 +2062,50 @@ namespace server if(mastermode>=MM_PRIVATE && allowedips.find(ip)<0) return DISC_PRIVATE; return DISC_NONE; } - - bool allowbroadcast(int n) - { + bool allowbroadcast(int n) { clientinfo *ci = getinfo(n); return ci && ci->connected; } - - clientinfo *findauth(uint id) - { + clientinfo *findauth(uint id) { loopv(clients) if(clients[i]->authreq == id) return clients[i]; return NULL; } - - void authfailed(clientinfo *ci) - { + void authfailed(clientinfo *ci) { if(!ci) return; ci->cleanauth(); //~if(ci->connectauth) disconnect_client(ci->clientnum, ci->connectauth); } - - void authfailed(uint id) - { + void authfailed(uint id) { authfailed(findauth(id)); } - - void authsucceeded(uint id) - { + void authsucceeded(uint id) { clientinfo *ci = findauth(id); if(!ci) return; ci->cleanauth(ci->connectauth!=0); if(ci->connectauth) connected(ci); - if(ci->authkickvictim >= 0) - { + if(ci->authkickvictim >= 0) { if(setmaster(ci, true, "", ci->authname, NULL, PRIV_AUTH, false, true)) trykick(ci, ci->authkickvictim, ci->authkickreason, ci->authname, NULL, PRIV_AUTH); ci->cleanauthkick(); } else setmaster(ci, true, "", ci->authname, NULL, PRIV_AUTH); } - - void authchallenged(uint id, const char *val, const char *desc = "") - { + void authchallenged(uint id, const char *val, const char *desc = "") { clientinfo *ci = findauth(id); if(!ci) return; sendf(ci->clientnum, 1, "risis", N_AUTHCHAL, desc, id, val); } - uint nextauthreq = 0; - - bool tryauth(clientinfo *ci, const char *user, const char *desc) - { + bool tryauth(clientinfo *ci, const char *user, const char *desc) { ci->cleanauth(); if(!nextauthreq) nextauthreq = 1; ci->authreq = nextauthreq++; filtertext(ci->authname, user, false, false, 100); copystring(ci->authdesc, desc); - if(ci->authdesc[0]) - { + if(ci->authdesc[0]) { userinfo *u = users.access(userkey(ci->authname, ci->authdesc)); - if(u) - { + if(u) { uint seed[3] = { ::hthash(serverauth) + detrnd(size_t(ci) + size_t(user) + size_t(desc), 0x10000), uint(totalmillis), randomMT() }; vector buf; ci->authchallenge = genchallenge(u->pubkey, seed, sizeof(seed), buf); @@ -2745,8 +2113,7 @@ namespace server } else ci->cleanauth(); } - else if(!requestmasterf("reqauth %u %s\n", ci->authreq, ci->authname)) - { + else if(!requestmasterf("reqauth %u %s\n", ci->authreq, ci->authname)) { ci->cleanauth(); sendf(ci->clientnum, 1, "ris", N_SERVMSG, "not connected to authentication server"); } @@ -2754,28 +2121,20 @@ namespace server //~if(ci->connectauth) disconnect_client(ci->clientnum, ci->connectauth); return false; } - - bool answerchallenge(clientinfo *ci, uint id, char *val, const char *desc) - { - if(ci->authreq != id || strcmp(ci->authdesc, desc)) - { + bool answerchallenge(clientinfo *ci, uint id, char *val, const char *desc) { + if(ci->authreq != id || strcmp(ci->authdesc, desc)) { ci->cleanauth(); return !ci->connectauth; } - for(char *s = val; *s; s++) - { + for(char *s = val; *s; s++) { if(!isxdigit(*s)) { *s = '\0'; break; } } - if(desc[0]) - { - if(ci->authchallenge && checkchallenge(val, ci->authchallenge)) - { + if(desc[0]) { + if(ci->authchallenge && checkchallenge(val, ci->authchallenge)) { userinfo *u = users.access(userkey(ci->authname, ci->authdesc)); - if(u) - { + if(u) { if(ci->connectauth) connected(ci); - if(ci->authkickvictim >= 0) - { + if(ci->authkickvictim >= 0) { if(setmaster(ci, true, "", ci->authname, ci->authdesc, u->privilege, false, true)) trykick(ci, ci->authkickvictim, ci->authkickreason, ci->authname, ci->authdesc, u->privilege); } @@ -2784,29 +2143,21 @@ namespace server } ci->cleanauth(); } - else if(!requestmasterf("confauth %u %s\n", id, val)) - { + else if(!requestmasterf("confauth %u %s\n", id, val)) { ci->cleanauth(); sendf(ci->clientnum, 1, "ris", N_SERVMSG, "not connected to authentication server"); } return ci->authreq || !ci->connectauth; } - - void masterconnected() - { + void masterconnected() { } - - void masterdisconnected() - { - loopvrev(clients) - { + void masterdisconnected() { + loopvrev(clients) { clientinfo *ci = clients[i]; if(ci->authreq) authfailed(ci); } } - - void processmasterinput(const char *cmd, int cmdlen, const char *args) - { + void processmasterinput(const char *cmd, int cmdlen) { uint id; string val; if(sscanf(cmd, "failauth %u", &id) == 1) @@ -2820,9 +2171,7 @@ namespace server else if(sscanf(cmd, "addgban %100s", val) == 1) gbans.add(val); } - - void receivefile(int sender, uchar *data, int len) - { + void receivefile(int sender, uchar *data, int len) { if(!m_edit || len <= 0 || len > 4*1024*1024) return; clientinfo *ci = getinfo(sender); if(ci->state.state==CS_SPECTATOR && !ci->privilege && !ci->local) return; @@ -2832,82 +2181,59 @@ namespace server mapdata->write(data, len); sendservmsgf("[%s sent a map to server, \"/getmap\" to receive it]", colorname(ci)); } - - void sendclipboard(clientinfo *ci) - { + void sendclipboard(clientinfo *ci) { if(!ci->lastclipboard || !ci->clipboard) return; bool flushed = false; - loopv(clients) - { + loopv(clients) { clientinfo &e = *clients[i]; - if(e.clientnum != ci->clientnum && e.needclipboard - ci->lastclipboard >= 0) - { + if(e.clientnum != ci->clientnum && e.needclipboard - ci->lastclipboard >= 0) { if(!flushed) { flushserver(true); flushed = true; } sendpacket(e.clientnum, 1, ci->clipboard); } } } - - void connected(clientinfo *ci) - { + void connected(clientinfo *ci) { if(m_demo) enddemoplayback(); - if(!hasmap(ci)) rotatemap(false); - shouldstep = true; - connects.removeobj(ci); clients.add(ci); - ci->connectauth = 0; ci->connected = true; ci->needclipboard = totalmillis ? totalmillis : 1; if(mastermode>=MM_LOCKED) ci->state.state = CS_SPECTATOR; ci->state.lasttimeplayed = lastmillis; - - const char *worst = m_teammode ? chooseworstteam(NULL, ci) : NULL; + const char *worst = m_teammode ? chooseworstteam(ci) : NULL; copystring(ci->team, worst ? worst : "good", MAXTEAMLEN+1); - sendwelcome(ci); if(restorescore(ci)) sendresume(ci); sendinitclient(ci); - aiman::addclient(ci); - if(m_demo) setupdemoplayback(); - if(servermotd[0]) sendf(ci->clientnum, 1, "ris", N_SERVMSG, servermotd); } - - void parsepacket(int sender, int chan, packetbuf &p) // has to parse exactly each byte of the packet - { + void parsepacket(int sender, int chan, packetbuf &p) { // has to parse exactly each byte of the packet { if(sender<0 || p.packet->flags&ENET_PACKET_FLAG_UNSEQUENCED || chan > 2) return; char text[MAXTRANS]; int type; clientinfo *ci = sender>=0 ? getinfo(sender) : NULL, *cq = ci, *cm = ci; - if(ci && !ci->connected) - { + if(ci && !ci->connected) { if(chan==0) return; //~else if(chan!=1) { disconnect_client(sender, DISC_MSGERR); return; } - else while(p.length() < p.maxlen) switch(checktype(getint(p), ci)) - { - case N_CONNECT: - { + else while(p.length() < p.maxlen) switch(checktype(getint(p), ci)) { + case N_CONNECT: { getstring(text, p); filtertext(text, text, false, false, MAXNAMELEN); if(!text[0]) copystring(text, "Anonymous"); copystring(ci->name, text, MAXNAMELEN+1); ci->playermodel = 0; - string password, authdesc, authname; getstring(password, p, sizeof(password)); getstring(authdesc, p, sizeof(authdesc)); getstring(authname, p, sizeof(authname)); int disc = allowconnect(ci, password); - if(disc) - { - if(disc == DISC_LOCAL || !serverauth[0] || strcmp(serverauth, authdesc) || !tryauth(ci, authname, authdesc)) - { + if(disc) { + if(disc == DISC_LOCAL || !serverauth[0] || strcmp(serverauth, authdesc) || !tryauth(ci, authname, authdesc)) { //~disconnect_client(sender, disc); return; } @@ -2916,63 +2242,53 @@ namespace server else connected(ci); break; } - - case N_AUTHANS: - { + case N_AUTHANS: { string desc, ans; getstring(desc, p, sizeof(desc)); uint id = (uint)getint(p); getstring(ans, p, sizeof(ans)); - if(!answerchallenge(ci, id, ans, desc)) - { + if(!answerchallenge(ci, id, ans, desc)) { //~disconnect_client(sender, ci->connectauth); return; } break; } - case N_PING: getint(p); break; - default: //~disconnect_client(sender, DISC_MSGERR); return; } return; } - else if(chan==2) - { + else if(chan==2) { receivefile(sender, p.buf, p.maxlen); return; } - if(p.packet->flags&ENET_PACKET_FLAG_RELIABLE) reliablemessages = true; #define QUEUE_AI clientinfo *cm = cq; #define QUEUE_MSG { if(cm && (!cm->local || demorecord || hasnonlocalclients())) while(curmsgmessages.add(p.buf[curmsg++]); } #define QUEUE_BUF(body) { \ - if(cm && (!cm->local || demorecord || hasnonlocalclients())) \ - { \ - curmsg = p.length(); \ - { body; } \ + if(cm && (!cm->local || demorecord || hasnonlocalclients())) { \ + \ + curmsg = p.length(); { \ + body; } \ } \ } #define QUEUE_INT(n) QUEUE_BUF(putint(cm->messages, n)) #define QUEUE_UINT(n) QUEUE_BUF(putuint(cm->messages, n)) #define QUEUE_STR(text) QUEUE_BUF(sendstring(text, cm->messages)) int curmsg; - while((curmsg = p.length()) < p.maxlen) switch(type = checktype(getint(p), ci)) - { - case N_POS: - { + while((curmsg = p.length()) < p.maxlen) switch(type = checktype(getint(p), ci)) { + case N_POS: { int pcn = getuint(p); p.get(); uint flags = getuint(p); clientinfo *cp = getinfo(pcn); if(cp && pcn != sender && cp->ownernum != sender) cp = NULL; vec pos; - loopk(3) - { + loopk(3) { int n = p.get(); n |= p.get()<<8; if(flags&(1<local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) - { + if(cp) { + if((!ci->local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) { if(!ci->local && !m_edit && max(vel.magnitude2(), (float)fabs(vel.z)) >= 180) cp->setexceeded(); cp->position.setsize(0); @@ -2999,53 +2312,41 @@ namespace server } break; } - - case N_TELEPORT: - { + case N_TELEPORT: { int pcn = getint(p), teleport = getint(p), teledest = getint(p); clientinfo *cp = getinfo(pcn); if(cp && pcn != sender && cp->ownernum != sender) cp = NULL; - if(cp && (!ci->local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) - { + if(cp && (!ci->local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) { flushclientposition(*cp); sendf(-1, 0, "ri4x", N_TELEPORT, pcn, teleport, teledest, cp->ownernum); } break; } - - case N_JUMPPAD: - { + case N_JUMPPAD: { int pcn = getint(p), jumppad = getint(p); clientinfo *cp = getinfo(pcn); if(cp && pcn != sender && cp->ownernum != sender) cp = NULL; - if(cp && (!ci->local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) - { + if(cp && (!ci->local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) { cp->setpushed(); flushclientposition(*cp); sendf(-1, 0, "ri3x", N_JUMPPAD, pcn, jumppad, cp->ownernum); } break; } - - case N_FROMAI: - { + case N_FROMAI: { int qcn = getint(p); if(qcn < 0) cq = ci; - else - { + else { cq = getinfo(qcn); if(cq && qcn != sender && cq->ownernum != sender) cq = NULL; } break; } - - case N_EDITMODE: - { + case N_EDITMODE: { int val = getint(p); if(!ci->local && !m_edit) break; if(val ? ci->state.state!=CS_ALIVE && ci->state.state!=CS_DEAD : ci->state.state!=CS_EDITING) break; - if(val) - { + if(val) { ci->state.editstate = ci->state.state; ci->state.state = CS_EDITING; ci->events.setsize(0); @@ -3056,16 +2357,12 @@ namespace server QUEUE_MSG; break; } - - case N_MAPCRC: - { + case N_MAPCRC: { getstring(text, p); int crc = getint(p); if(!ci) break; - if(strcmp(text, smapname)) - { - if(ci->clientmap[0]) - { + if(strcmp(text, smapname)) { + if(ci->clientmap[0]) { ci->clientmap[0] = '\0'; ci->mapcrc = 0; } @@ -3078,31 +2375,25 @@ namespace server if(cq && cq != ci && cq->ownernum != ci->clientnum) cq = NULL; break; } - case N_CHECKMAPS: checkmaps(sender); break; - case N_TRYSPAWN: if(!ci || !cq || cq->state.state!=CS_DEAD || cq->state.lastspawn>=0) break; - if(!ci->clientmap[0] && !ci->mapcrc) - { + if(!ci->clientmap[0] && !ci->mapcrc) { ci->mapcrc = -1; checkmaps(); if(ci == cq) { if(ci->state.state != CS_DEAD) break; } else if(cq->ownernum != ci->clientnum) { cq = NULL; break; } } - if(cq->state.deadflush) - { + if(cq->state.deadflush) { flushevents(cq, cq->state.deadflush); cq->state.respawn(); } cleartimedevents(cq); sendspawn(cq); break; - - case N_GUNSELECT: - { + case N_GUNSELECT: { int gunselect = getint(p); if(!cq || cq->state.state!=CS_ALIVE) break; cq->state.gunselect = gunselect >= GUN_FIST && gunselect <= GUN_PISTOL ? gunselect : GUN_FIST; @@ -3110,9 +2401,7 @@ namespace server QUEUE_MSG; break; } - - case N_SPAWN: - { + case N_SPAWN: { int ls = getint(p), gunselect = getint(p); if(!cq || (cq->state.state!=CS_ALIVE && cq->state.state!=CS_DEAD && cq->state.state!=CS_EDITING) || ls!=cq->state.lifesequence || cq->state.lastspawn<0) break; cq->state.lastspawn = -1; @@ -3126,15 +2415,11 @@ namespace server }); break; } - - case N_SUICIDE: - { + case N_SUICIDE: { if(cq) cq->addevent(new suicideevent); break; } - - case N_SHOOT: - { + case N_SHOOT: { shotevent *shot = new shotevent; shot->id = getint(p); shot->millis = cq ? cq->geteventmillis(gamemillis, shot->id) : 0; @@ -3142,8 +2427,7 @@ namespace server loopk(3) shot->from[k] = getint(p)/DMF; loopk(3) shot->to[k] = getint(p)/DMF; int hits = getint(p); - loopk(hits) - { + loopk(hits) { if(p.overread()) break; hitinfo &hit = shot->hits.add(); hit.target = getint(p); @@ -3152,25 +2436,21 @@ namespace server hit.rays = getint(p); loopk(3) hit.dir[k] = getint(p)/DNF; } - if(cq) - { + if(cq) { cq->addevent(shot); cq->setpushed(); } else delete shot; break; } - - case N_EXPLODE: - { + case N_EXPLODE: { explodeevent *exp = new explodeevent; int cmillis = getint(p); exp->millis = cq ? cq->geteventmillis(gamemillis, cmillis) : 0; exp->gun = getint(p); exp->id = getint(p); int hits = getint(p); - loopk(hits) - { + loopk(hits) { if(p.overread()) break; hitinfo &hit = exp->hits.add(); hit.target = getint(p); @@ -3183,9 +2463,7 @@ namespace server else delete exp; break; } - - case N_ITEMPICKUP: - { + case N_ITEMPICKUP: { int n = getint(p); if(!cq) break; pickupevent *pickup = new pickupevent; @@ -3193,9 +2471,7 @@ namespace server cq->addevent(pickup); break; } - - case N_TEXT: - { + case N_TEXT: { QUEUE_AI; QUEUE_MSG; getstring(text, p); @@ -3204,14 +2480,11 @@ namespace server if(isdedicatedserver() && cq) logoutf("%s: %s", colorname(cq), text); break; } - - case N_SAYTEAM: - { + case N_SAYTEAM: { getstring(text, p); if(!ci || !cq || (ci->state.state==CS_SPECTATOR && !ci->local && !ci->privilege) || !m_teammode || !cq->team[0]) break; filtertext(text, text, true, true); - loopv(clients) - { + loopv(clients) { clientinfo *t = clients[i]; if(t==cq || t->state.state==CS_SPECTATOR || t->state.aitype != AI_NONE || strcmp(cq->team, t->team)) continue; sendf(t->clientnum, 1, "riis", N_SAYTEAM, cq->clientnum, text); @@ -3219,9 +2492,7 @@ namespace server if(isdedicatedserver() && cq) logoutf("%s <%s>: %s", colorname(cq), cq->team, text); break; } - - case N_SWITCHNAME: - { + case N_SWITCHNAME: { QUEUE_MSG; getstring(text, p); filtertext(ci->name, text, false, false, MAXNAMELEN); @@ -3229,20 +2500,15 @@ namespace server QUEUE_STR(ci->name); break; } - - case N_SWITCHMODEL: - { + case N_SWITCHMODEL: { ci->playermodel = 0; QUEUE_MSG; break; } - - case N_SWITCHTEAM: - { + case N_SWITCHTEAM: { getstring(text, p); filtertext(text, text, false, false, MAXTEAMLEN); - if(m_teammode && text[0] && strcmp(ci->team, text) && addteaminfo(text)) - { + if(m_teammode && text[0] && strcmp(ci->team, text) && addteaminfo(text)) { if(ci->state.state==CS_ALIVE) suicide(ci); copystring(ci->team, text); aiman::changeteam(ci); @@ -3250,9 +2516,7 @@ namespace server } break; } - - case N_MAPVOTE: - { + case N_MAPVOTE: { getstring(text, p); filtertext(text, text, false); fixmapname(text); @@ -3260,18 +2524,14 @@ namespace server vote(text, reqmode, sender); break; } - - case N_ITEMLIST: - { + case N_ITEMLIST: { if((ci->state.state==CS_SPECTATOR && !ci->privilege && !ci->local) || !notgotitems || strcmp(ci->clientmap, smapname)) { while(getint(p)>=0 && !p.overread()) getint(p); break; } int n; - while((n = getint(p))>=0 && n=0 && nstate.state==CS_SPECTATOR) break; QUEUE_MSG; bool canspawn = canspawnitem(type); - if(istate.state!=CS_SPECTATOR) QUEUE_MSG; break; } - case N_PING: sendf(sender, 1, "i2", N_PONG, getint(p)); break; - - case N_CLIENTPING: - { + case N_CLIENTPING: { int ping = getint(p); - if(ci) - { + if(ci) { ci->ping = ping; loopv(ci->bots) ci->bots[i]->ping = ping; } QUEUE_MSG; break; } - - case N_MASTERMODE: - { + case N_MASTERMODE: { int mm = getint(p); - if((ci->privilege || ci->local) && mm>=MM_OPEN && mm<=MM_PRIVATE) - { - if((ci->privilege>=PRIV_ADMIN || ci->local) || (mastermask&(1<privilege || ci->local) && mm>=MM_OPEN && mm<=MM_PRIVATE) { + if((ci->privilege>=PRIV_ADMIN || ci->local) || (mastermask&(1<=MM_PRIVATE) - { + if(mm>=MM_PRIVATE) { loopv(clients) allowedips.add(getclientip(clients[i]->clientnum)); } sendf(-1, 1, "rii", N_MASTERMODE, mastermode); //sendservmsgf("mastermode is now %s (%d)", mastermodename(mastermode), mastermode); } - else - { + else { defformatstring(s, "mastermode %d is disabled on this server", mm); sendf(sender, 1, "ris", N_SERVMSG, s); } } break; } - - case N_CLEARBANS: - { - if(ci->privilege || ci->local) - { + case N_CLEARBANS: { + if(ci->privilege || ci->local) { bannedips.shrink(0); sendservmsg("cleared all bans"); } break; } - - case N_KICK: - { + case N_KICK: { int victim = getint(p); getstring(text, p); filtertext(text, text); trykick(ci, victim, text); break; } - - case N_SPECTATOR: - { + case N_SPECTATOR: { int spectator = getint(p), val = getint(p); if(!ci->privilege && !ci->local && (spectator!=sender || (ci->state.state==CS_SPECTATOR && mastermode>=MM_LOCKED))) break; clientinfo *spinfo = (clientinfo *)getclientinfo(spectator); // no bots if(!spinfo || !spinfo->connected || (spinfo->state.state==CS_SPECTATOR ? val : !val)) break; - if(spinfo->state.state!=CS_SPECTATOR && val) forcespectator(spinfo); else if(spinfo->state.state==CS_SPECTATOR && !val) unspectate(spinfo); - if(cq && cq != ci && cq->ownernum != ci->clientnum) cq = NULL; break; } - - case N_SETTEAM: - { + case N_SETTEAM: { int who = getint(p); getstring(text, p); filtertext(text, text, false, false, MAXTEAMLEN); if(!ci->privilege && !ci->local) break; clientinfo *wi = getinfo(who); if(!m_teammode || !text[0] || !wi || !wi->connected || !strcmp(wi->team, text)) break; - if(addteaminfo(text)) - { + if(addteaminfo(text)) { if(wi->state.state==CS_ALIVE) suicide(wi); copystring(wi->team, text, MAXTEAMLEN+1); } @@ -3408,17 +2639,13 @@ namespace server sendf(-1, 1, "riisi", N_SETTEAM, who, wi->team, 1); break; } - case N_FORCEINTERMISSION: if(ci->local && !hasnonlocalclients()) startintermission(); break; - - case N_RECORDDEMO: - { + case N_RECORDDEMO: { int val = getint(p); if(ci->privilege < (restrictdemos ? PRIV_ADMIN : PRIV_MASTER) && !ci->local) break; - if(!maxdemos || !maxdemosize) - { + if(!maxdemos || !maxdemosize) { sendf(ci->clientnum, 1, "ris", N_SERVMSG, "the server has disabled demo recording"); break; } @@ -3426,53 +2653,41 @@ namespace server sendservmsgf("demo recording is %s for next match", demonextmatch ? "enabled" : "disabled"); break; } - - case N_STOPDEMO: - { + case N_STOPDEMO: { if(ci->privilege < (restrictdemos ? PRIV_ADMIN : PRIV_MASTER) && !ci->local) break; stopdemo(); break; } - - case N_CLEARDEMOS: - { + case N_CLEARDEMOS: { int demo = getint(p); if(ci->privilege < (restrictdemos ? PRIV_ADMIN : PRIV_MASTER) && !ci->local) break; cleardemos(demo); break; } - case N_LISTDEMOS: if(!ci->privilege && !ci->local && ci->state.state==CS_SPECTATOR) break; listdemos(sender); break; - - case N_GETDEMO: - { + case N_GETDEMO: { int n = getint(p), tag = getint(p); if(!ci->privilege && !ci->local && ci->state.state==CS_SPECTATOR) break; senddemo(ci, n, tag); break; } - case N_GETMAP: if(!mapdata) sendf(sender, 1, "ris", N_SERVMSG, "no map to send"); else if(ci->getmap) sendf(sender, 1, "ris", N_SERVMSG, "already sending map"); - else - { + else { sendservmsgf("[%s is getting the map]", colorname(ci)); if((ci->getmap = sendfile(sender, 2, mapdata, "ri", N_SENDMAP))) ci->getmap->freeCallback = freegetmap; ci->needclipboard = totalmillis ? totalmillis : 1; } break; - - case N_NEWMAP: - { + case N_NEWMAP: { int size = getint(p); if(!ci->privilege && !ci->local && ci->state.state==CS_SPECTATOR) break; - if(size>=0) - { + if(size>=0) { smapname[0] = '\0'; resetitems(); notgotitems = false; @@ -3480,13 +2695,10 @@ namespace server QUEUE_MSG; break; } - - case N_SETMASTER: - { + case N_SETMASTER: { int mn = getint(p), val = getint(p); getstring(text, p); - if(mn != ci->clientnum) - { + if(mn != ci->clientnum) { if(!ci->privilege && !ci->local) break; clientinfo *minfo = (clientinfo *)getclientinfo(mn); if(!minfo || !minfo->connected || (!ci->local && minfo->privilege >= ci->privilege) || (val && minfo->privilege)) break; @@ -3496,44 +2708,32 @@ namespace server // don't broadcast the master password break; } - - case N_ADDBOT: - { + case N_ADDBOT: { aiman::reqadd(ci, getint(p)); break; } - - case N_DELBOT: - { + case N_DELBOT: { aiman::reqdel(ci); break; } - - case N_BOTLIMIT: - { + case N_BOTLIMIT: { int limit = getint(p); if(ci) aiman::setbotlimit(ci, limit); break; } - - case N_BOTBALANCE: - { + case N_BOTBALANCE: { int balance = getint(p); if(ci) aiman::setbotbalance(ci, balance!=0); break; } - - case N_AUTHTRY: - { + case N_AUTHTRY: { string desc, name; getstring(desc, p, sizeof(desc)); getstring(name, p, sizeof(name)); tryauth(ci, name, desc); break; } - - case N_AUTHKICK: - { + case N_AUTHKICK: { string desc, name; getstring(desc, p, sizeof(desc)); getstring(name, p, sizeof(name)); @@ -3541,22 +2741,18 @@ namespace server getstring(text, p); filtertext(text, text); int authpriv = PRIV_AUTH; - if(desc[0]) - { + if(desc[0]) { userinfo *u = users.access(userkey(name, desc)); if(u) authpriv = u->privilege; else break; } if(ci->local || ci->privilege >= authpriv) trykick(ci, victim, text); - else if(trykick(ci, victim, text, name, desc, authpriv, true) && tryauth(ci, name, desc)) - { + else if(trykick(ci, victim, text, name, desc, authpriv, true) && tryauth(ci, name, desc)) { ci->authkickvictim = victim; ci->authkickreason = newstring(text); } break; } - - case N_AUTHANS: - { + case N_AUTHANS: { string desc, ans; getstring(desc, p, sizeof(desc)); uint id = (uint)getint(p); @@ -3564,43 +2760,33 @@ namespace server answerchallenge(ci, id, ans, desc); break; } - - case N_PAUSEGAME: - { + case N_PAUSEGAME: { int val = getint(p); if(ci->privilege < (restrictpausegame ? PRIV_ADMIN : PRIV_MASTER) && !ci->local) break; pausegame(val > 0, ci); break; } - - case N_GAMESPEED: - { + case N_GAMESPEED: { int val = getint(p); if(ci->privilege < (restrictgamespeed ? PRIV_ADMIN : PRIV_MASTER) && !ci->local) break; changegamespeed(val, ci); break; } - case N_COPY: ci->cleanclipboard(); ci->lastclipboard = totalmillis ? totalmillis : 1; goto genericmsg; - case N_PASTE: if(ci->state.state!=CS_SPECTATOR) sendclipboard(ci); goto genericmsg; - - case N_CLIPBOARD: - { + case N_CLIPBOARD: { int unpacklen = getint(p), packlen = getint(p); ci->cleanclipboard(false); - if(ci->state.state==CS_SPECTATOR) - { + if(ci->state.state==CS_SPECTATOR) { if(packlen > 0) p.subbuf(packlen); break; } - if(packlen <= 0 || packlen > (1<<16) || unpacklen <= 0) - { + if(packlen <= 0 || packlen > (1<<16) || unpacklen <= 0) { if(packlen > 0) p.subbuf(packlen); packlen = unpacklen = 0; } @@ -3614,11 +2800,9 @@ namespace server ci->clipboard->referenceCount++; break; } - case N_EDITT: case N_REPLACE: - case N_EDITVSLOT: - { + case N_EDITVSLOT: { int size = server::msgsizelookup(type); //~if(size<=0) { disconnect_client(sender, DISC_MSGERR); return; } loopi(size-1) getint(p); @@ -3629,13 +2813,10 @@ namespace server if(ci && ci->state.state!=CS_SPECTATOR) QUEUE_MSG; break; } - case N_UNDO: - case N_REDO: - { + case N_REDO: { int unpacklen = getint(p), packlen = getint(p); - if(!ci || ci->state.state==CS_SPECTATOR || packlen <= 0 || packlen > (1<<16) || unpacklen <= 0) - { + if(!ci || ci->state.state==CS_SPECTATOR || packlen <= 0 || packlen > (1<<16) || unpacklen <= 0) { if(packlen > 0) p.subbuf(packlen); break; } @@ -3649,27 +2830,21 @@ namespace server sendpacket(-1, 1, q.finalize(), ci->clientnum); break; } - case N_SERVCMD: getstring(text, p); break; - case -1: //~disconnect_client(sender, DISC_MSGERR); return; - case -2: //~disconnect_client(sender, DISC_OVERFLOW); return; - - default: genericmsg: - { + default: genericmsg: { int size = server::msgsizelookup(type); //~if(size<=0) { disconnect_client(sender, DISC_MSGERR); return; } loopi(size-1) getint(p); - if(ci) switch(msgfilter[type]) - { + if(ci) switch(msgfilter[type]) { case 2: case 3: if(ci->state.state != CS_SPECTATOR) QUEUE_MSG; break; default: if(cq && (ci != cq || ci->state.state!=CS_SPECTATOR)) { QUEUE_AI; QUEUE_MSG; } break; } @@ -3677,24 +2852,18 @@ namespace server } } } - int laninfoport() { return SAUERBRATEN_LANINFO_PORT; } int serverinfoport(int servport) { return servport < 0 ? SAUERBRATEN_SERVINFO_PORT : servport+1; } int serverport(int infoport) { return infoport < 0 ? SAUERBRATEN_SERVER_PORT : infoport-1; } const char *defaultmaster() { return "master.sauerbraten.org"; } int masterport() { return SAUERBRATEN_MASTER_PORT; } int numchannels() { return 3; } - #include "extinfo.h" - - void serverinforeply(ucharbuf &req, ucharbuf &p) - { - if(req.remaining() && !getint(req)) - { + void serverinforeply(ucharbuf &req, ucharbuf &p) { + if(req.remaining() && !getint(req)) { extserverinforeply(req, p); return; } - putint(p, numclients(-1, false, true)); putint(p, gamepaused || gamespeed != 100 ? 7 : 5); // number of attrs following putint(p, PROTOCOL_VERSION); // generic attributes, passed back below @@ -3702,8 +2871,7 @@ namespace server putint(p, m_timed ? max((gamelimit - gamemillis)/1000, 0) : 0); putint(p, maxclients); putint(p, serverpass[0] ? MM_PASSWORD : (!m_mp(gamemode) ? MM_PRIVATE : (mastermode || mastermask&MM_AUTOAPPROVE ? mastermode : MM_AUTH))); - if(gamepaused || gamespeed != 100) - { + if(gamepaused || gamespeed != 100) { putint(p, gamepaused ? 1 : 0); putint(p, gamespeed); } @@ -3711,7 +2879,6 @@ namespace server sendstring(serverdesc, p); sendserverinforeply(p); } - #include "aiman.h" } diff --git a/src/fpsgame/waypoint.cpp b/src/fpsgame/waypoint.cpp index 30a1403..05afb6c 100644 --- a/src/fpsgame/waypoint.cpp +++ b/src/fpsgame/waypoint.cpp @@ -2,26 +2,19 @@ extern selinfo sel; -namespace ai -{ +namespace ai { using namespace game; - vector waypoints; - - bool clipped(const vec &o) - { + bool clipped(const vec &o) { int material = lookupmaterial(o), clipmat = material&MATF_CLIP; return clipmat == MAT_CLIP || material&MAT_DEATH; } - - int getweight(const vec &o) - { + int getweight(const vec &o) { vec pos = o; pos.z += ai::JUMPMIN; if(!insideworld(vec(pos.x, pos.y, min(pos.z, getworldsize() - 1e-3f)))) return -2; float dist = raycube(pos, vec(0, 0, -1), 0, RAY_CLIPMAT); int weight = 1; - if(dist >= 0) - { + if(dist >= 0) { weight = int(dist/ai::JUMPMIN); pos.z -= clamp(dist-8.0f, 0.0f, pos.z); int trgmat = lookupmaterial(pos); @@ -29,46 +22,33 @@ namespace ai } return weight; } - - enum - { + enum { WPCACHE_STATIC = 0, WPCACHE_DYNAMIC, NUMWPCACHES }; - - struct wpcache - { - struct node - { + struct wpcache { + struct node { float split[2]; uint child[2]; - int axis() const { return child[0]>>30; } int childindex(int which) const { return child[which]&0x3FFFFFFF; } bool isleaf(int which) const { return (child[1]&(1<<(30+which)))!=0; } }; - vector nodes; int firstwp, lastwp; vec bbmin, bbmax; - wpcache() { clear(); } - - void clear() - { + void clear() { nodes.setsize(0); firstwp = lastwp = -1; bbmin = vec(1e16f, 1e16f, 1e16f); bbmax = vec(-1e16f, -1e16f, -1e16f); } - - void build(int first = 0, int last = -1) - { + void build(int first = 0, int last = -1) { if(last < 0) last = waypoints.length(); vector indices; - for(int i = first; i < last; i++) - { + for(int i = first; i < last; i++) { waypoint &w = waypoints[i]; indices.add(i); if(firstwp < 0) firstwp = i; @@ -77,34 +57,27 @@ namespace ai bbmax.max(vec(w.o).add(radius)); } if(first < last) lastwp = max(lastwp, last-1); - if(indices.length()) - { + if(indices.length()) { nodes.reserve(indices.length()); build(indices.getbuf(), indices.length(), bbmin, bbmax); } } - - void build(int *indices, int numindices, const vec &vmin, const vec &vmax) - { + void build(int *indices, int numindices, const vec &vmin, const vec &vmax) { int axis = 2; loopk(2) if(vmax[k] - vmin[k] > vmax[axis] - vmin[axis]) axis = k; - vec leftmin(1e16f, 1e16f, 1e16f), leftmax(-1e16f, -1e16f, -1e16f), rightmin(1e16f, 1e16f, 1e16f), rightmax(-1e16f, -1e16f, -1e16f); float split = 0.5f*(vmax[axis] + vmin[axis]), splitleft = -1e16f, splitright = 1e16f; int left, right; - for(left = 0, right = numindices; left < right;) - { + for(left = 0, right = numindices; left < right;) { waypoint &w = waypoints[indices[left]]; float radius = WAYPOINTRADIUS; - if(max(split - (w.o[axis]-radius), 0.0f) > max((w.o[axis]+radius) - split, 0.0f)) - { + if(max(split - (w.o[axis]-radius), 0.0f) > max((w.o[axis]+radius) - split, 0.0f)) { ++left; splitleft = max(splitleft, w.o[axis]+radius); leftmin.min(vec(w.o).sub(radius)); leftmax.max(vec(w.o).add(radius)); } - else - { + else { --right; swap(indices[left], indices[right]); splitright = min(splitright, w.o[axis]-radius); @@ -112,111 +85,84 @@ namespace ai rightmax.max(vec(w.o).add(radius)); } } - - if(!left || right==numindices) - { + if(!left || right==numindices) { leftmin = rightmin = vec(1e16f, 1e16f, 1e16f); leftmax = rightmax = vec(-1e16f, -1e16f, -1e16f); left = right = numindices/2; splitleft = -1e16f; splitright = 1e16f; - loopi(numindices) - { + loopi(numindices) { waypoint &w = waypoints[indices[i]]; float radius = WAYPOINTRADIUS; - if(i < left) - { + if(i < left) { splitleft = max(splitleft, w.o[axis]+radius); leftmin.min(vec(w.o).sub(radius)); leftmax.max(vec(w.o).add(radius)); } - else - { + else { splitright = min(splitright, w.o[axis]-radius); rightmin.min(vec(w.o).sub(radius)); rightmax.max(vec(w.o).add(radius)); } } } - int offset = nodes.length(); node &curnode = nodes.add(); curnode.split[0] = splitleft; curnode.split[1] = splitright; - if(left<=1) curnode.child[0] = (axis<<30) | (left>0 ? indices[0] : 0x3FFFFFFF); - else - { + else { curnode.child[0] = (axis<<30) | (nodes.length()-offset); if(left) build(indices, left, leftmin, leftmax); } - if(numindices-right<=1) curnode.child[1] = (1<<31) | (left<=1 ? 1<<30 : 0) | (numindices-right>0 ? indices[right] : 0x3FFFFFFF); - else - { + else { curnode.child[1] = (left<=1 ? 1<<30 : 0) | (nodes.length()-offset); if(numindices-right) build(&indices[right], numindices-right, rightmin, rightmax); } } } wpcaches[NUMWPCACHES]; - static int invalidatedwpcaches = 0, clearedwpcaches = (1<= 1000) { numinvalidatewpcaches = 0; invalidatedwpcaches = (1<= wpcaches[i].firstwp && wp <= wpcaches[i].lastwp) { invalidatedwpcaches |= 1< 0 ? wpcaches[i-1].lastwp+1 : 1, i+1 >= NUMWPCACHES || wpcaches[i+1].firstwp < 0 ? -1 : wpcaches[i+1].firstwp); clearedwpcaches = 0; lastwpcache = waypoints.length(); - wpavoid.clear(); loopv(waypoints) if(waypoints[i].weight < 0) wpavoid.avoidnear(NULL, waypoints[i].o.z + WAYPOINTRADIUS, waypoints[i].o, WAYPOINTRADIUS); } - - struct wpcachestack - { + struct wpcachestack { wpcache::node *node; float tmin, tmax; }; - vector wpcachestack; - - int closestwaypoint(const vec &pos, float mindist, bool links, fpsent *d) - { + int closestwaypoint(const vec &pos, float mindist, bool links) { if(waypoints.empty()) return -1; if(clearedwpcaches) buildwpcache(); - #define CHECKCLOSEST(index) do { \ int n = (index); \ - if(n < waypoints.length()) \ - { \ + if(n < waypoints.length()) { \ + \ const waypoint &w = waypoints[n]; \ - if(!links || w.links[0]) \ - { \ + if(!links || w.links[0]) { \ + \ float dist = w.o.squaredist(pos); \ if(dist < mindist*mindist) { closest = n; mindist = sqrtf(dist); } \ } \ @@ -224,31 +170,24 @@ namespace ai } while(0) int closest = -1; wpcache::node *curnode; - loop(which, NUMWPCACHES) if(wpcaches[which].firstwp >= 0) for(curnode = &wpcaches[which].nodes[0], wpcachestack.setsize(0);;) - { + loop(which, NUMWPCACHES) if(wpcaches[which].firstwp >= 0) for(curnode = &wpcaches[which].nodes[0], wpcachestack.setsize(0);;) { int axis = curnode->axis(); float dist1 = pos[axis] - curnode->split[0], dist2 = curnode->split[1] - pos[axis]; - if(dist1 >= mindist) - { - if(dist2 < mindist) - { + if(dist1 >= mindist) { + if(dist2 < mindist) { if(!curnode->isleaf(1)) { curnode += curnode->childindex(1); continue; } CHECKCLOSEST(curnode->childindex(1)); } } - else if(curnode->isleaf(0)) - { + else if(curnode->isleaf(0)) { CHECKCLOSEST(curnode->childindex(0)); - if(dist2 < mindist) - { + if(dist2 < mindist) { if(!curnode->isleaf(1)) { curnode += curnode->childindex(1); continue; } CHECKCLOSEST(curnode->childindex(1)); } } - else - { - if(dist2 < mindist) - { + else { + if(dist2 < mindist) { if(!curnode->isleaf(1)) wpcachestack.add(curnode + curnode->childindex(1)); else CHECKCLOSEST(curnode->childindex(1)); } @@ -261,48 +200,38 @@ namespace ai for(int i = lastwpcache; i < waypoints.length(); i++) { CHECKCLOSEST(i); } return closest; } - - void findwaypointswithin(const vec &pos, float mindist, float maxdist, vector &results) - { + void findwaypointswithin(const vec &pos, float mindist, float maxdist, vector &results) { if(waypoints.empty()) return; if(clearedwpcaches) buildwpcache(); - float mindist2 = mindist*mindist, maxdist2 = maxdist*maxdist; #define CHECKWITHIN(index) do { \ int n = (index); \ - if(n < waypoints.length()) \ - { \ + if(n < waypoints.length()) { \ + \ const waypoint &w = waypoints[n]; \ float dist = w.o.squaredist(pos); \ if(dist > mindist2 && dist < maxdist2) results.add(n); \ } \ } while(0) wpcache::node *curnode; - loop(which, NUMWPCACHES) if(wpcaches[which].firstwp >= 0) for(curnode = &wpcaches[which].nodes[0], wpcachestack.setsize(0);;) - { + loop(which, NUMWPCACHES) if(wpcaches[which].firstwp >= 0) for(curnode = &wpcaches[which].nodes[0], wpcachestack.setsize(0);;) { int axis = curnode->axis(); float dist1 = pos[axis] - curnode->split[0], dist2 = curnode->split[1] - pos[axis]; - if(dist1 >= maxdist) - { - if(dist2 < maxdist) - { + if(dist1 >= maxdist) { + if(dist2 < maxdist) { if(!curnode->isleaf(1)) { curnode += curnode->childindex(1); continue; } CHECKWITHIN(curnode->childindex(1)); } } - else if(curnode->isleaf(0)) - { + else if(curnode->isleaf(0)) { CHECKWITHIN(curnode->childindex(0)); - if(dist2 < maxdist) - { + if(dist2 < maxdist) { if(!curnode->isleaf(1)) { curnode += curnode->childindex(1); continue; } CHECKWITHIN(curnode->childindex(1)); } } - else - { - if(dist2 < maxdist) - { + else { + if(dist2 < maxdist) { if(!curnode->isleaf(1)) wpcachestack.add(curnode + curnode->childindex(1)); else CHECKWITHIN(curnode->childindex(1)); } @@ -314,47 +243,37 @@ namespace ai } for(int i = lastwpcache; i < waypoints.length(); i++) { CHECKWITHIN(i); } } - - void avoidset::avoidnear(void *owner, float above, const vec &pos, float limit) - { + void avoidset::avoidnear(void *owner, float above, const vec &pos, float limit) { if(ai::waypoints.empty()) return; if(clearedwpcaches) buildwpcache(); - float limit2 = limit*limit; #define CHECKNEAR(index) do { \ int n = (index); \ - if(n < ai::waypoints.length()) \ - { \ + if(n < ai::waypoints.length()) { \ + \ const waypoint &w = ai::waypoints[n]; \ if(w.o.squaredist(pos) < limit2) add(owner, above, n); \ } \ } while(0) wpcache::node *curnode; - loop(which, NUMWPCACHES) if(wpcaches[which].firstwp >= 0) for(curnode = &wpcaches[which].nodes[0], wpcachestack.setsize(0);;) - { + loop(which, NUMWPCACHES) if(wpcaches[which].firstwp >= 0) for(curnode = &wpcaches[which].nodes[0], wpcachestack.setsize(0);;) { int axis = curnode->axis(); float dist1 = pos[axis] - curnode->split[0], dist2 = curnode->split[1] - pos[axis]; - if(dist1 >= limit) - { - if(dist2 < limit) - { + if(dist1 >= limit) { + if(dist2 < limit) { if(!curnode->isleaf(1)) { curnode += curnode->childindex(1); continue; } CHECKNEAR(curnode->childindex(1)); } } - else if(curnode->isleaf(0)) - { + else if(curnode->isleaf(0)) { CHECKNEAR(curnode->childindex(0)); - if(dist2 < limit) - { + if(dist2 < limit) { if(!curnode->isleaf(1)) { curnode += curnode->childindex(1); continue; } CHECKNEAR(curnode->childindex(1)); } } - else - { - if(dist2 < limit) - { + else { + if(dist2 < limit) { if(!curnode->isleaf(1)) wpcachestack.add(curnode + curnode->childindex(1)); else CHECKNEAR(curnode->childindex(1)); } @@ -366,27 +285,21 @@ namespace ai } for(int i = lastwpcache; i < waypoints.length(); i++) { CHECKNEAR(i); } } - - int avoidset::remap(fpsent *d, int n, vec &pos, bool retry) - { - if(!obstacles.empty()) - { + int avoidset::remap(fpsent *d, int n, vec &pos, bool retry) { + if(!obstacles.empty()) { int cur = 0; - loopv(obstacles) - { + loopv(obstacles) { obstacle &ob = obstacles[i]; int next = cur + ob.numwaypoints; - if(ob.owner != d) - { - for(; cur < next; cur++) if(waypoints[cur] == n) - { + if(ob.owner != d) { + for(; cur < next; cur++) if(waypoints[cur] == n) { if(ob.above < 0) return retry ? n : -1; vec above(pos.x, pos.y, ob.above); if(above.z-d->o.z >= ai::JUMPMAX) return retry ? n : -1; // too much scotty - int node = closestwaypoint(above, ai::SIGHTMIN, true, d); - if(ai::iswaypoint(node) && node != n) - { // try to reroute above their head? + int node = closestwaypoint(above, ai::SIGHTMIN, true); + if(ai::iswaypoint(node) && node != n) { + // try to reroute above their head? if(!find(node, d)) { pos = ai::waypoints[node].o; @@ -394,8 +307,7 @@ namespace ai } else return retry ? n : -1; } - else - { + else { vec old = d->o; d->o = vec(above).add(vec(0, 0, d->eyeheight)); bool col = collide(d, vec(0, 0, 1)); @@ -414,37 +326,25 @@ namespace ai } return n; } - static inline float heapscore(waypoint *q) { return q->score(); } - - bool route(fpsent *d, int node, int goal, vector &route, const avoidset &obstacles, int retries) - { + bool route(fpsent *d, int node, int goal, vector &route, const avoidset &obstacles, int retries) { if(waypoints.empty() || !iswaypoint(node) || !iswaypoint(goal) || goal == node || !waypoints[node].links[0]) return false; - static ushort routeid = 1; static vector queue; - - if(!routeid) - { + if(!routeid) { loopv(waypoints) waypoints[i].route = 0; routeid = 1; } - - if(d) - { - if(retries <= 1 && d->ai) loopi(ai::NUMPREVNODES) if(d->ai->prevnodes[i] != node && iswaypoint(d->ai->prevnodes[i])) - { + if(d) { + if(retries <= 1 && d->ai) loopi(ai::NUMPREVNODES) if(d->ai->prevnodes[i] != node && iswaypoint(d->ai->prevnodes[i])) { waypoints[d->ai->prevnodes[i]].route = routeid; waypoints[d->ai->prevnodes[i]].curscore = -1; waypoints[d->ai->prevnodes[i]].estscore = 0; } - if(retries <= 0) - { - loopavoid(obstacles, d, - { - if(iswaypoint(wp) && wp != node && wp != goal && waypoints[node].find(wp) < 0 && waypoints[goal].find(wp) < 0) - { + if(retries <= 0) { + loopavoid(obstacles, d, { + if(iswaypoint(wp) && wp != node && wp != goal && waypoints[node].find(wp) < 0 && waypoints[goal].find(wp) < 0) { waypoints[wp].route = routeid; waypoints[wp].curscore = -1; waypoints[wp].estscore = 0; @@ -452,34 +352,28 @@ namespace ai }); } } - waypoints[node].route = routeid; waypoints[node].curscore = waypoints[node].estscore = 0; waypoints[node].prev = 0; queue.setsize(0); queue.add(&waypoints[node]); route.setsize(0); - int lowest = -1; - while(!queue.empty()) - { + while(!queue.empty()) { waypoint &m = *queue.removeheap(); float prevscore = m.curscore; m.curscore = -1; - loopi(MAXWAYPOINTLINKS) - { + loopi(MAXWAYPOINTLINKS) { int link = m.links[i]; if(!link) break; - if(iswaypoint(link) && (link == node || link == goal || waypoints[link].links[0])) - { + if(iswaypoint(link) && (link == node || link == goal || waypoints[link].links[0])) { waypoint &n = waypoints[link]; int weight = max(n.weight, 1); float curscore = prevscore + n.o.dist(m.o)*weight; if(n.route == routeid && curscore >= n.curscore) continue; n.curscore = curscore; n.prev = ushort(&m - &waypoints[0]); - if(n.route != routeid) - { + if(n.route != routeid) { n.estscore = n.o.dist(waypoints[goal].o)*weight; if(n.estscore <= WAYPOINTRADIUS*4 && (lowest < 0 || n.estscore <= waypoints[lowest].estscore)) lowest = link; @@ -492,92 +386,68 @@ namespace ai } } foundgoal: - routeid++; - - if(lowest >= 0) // otherwise nothing got there - { + if(lowest >= 0) { // otherwise nothing got there { for(waypoint *m = &waypoints[lowest]; m > &waypoints[0]; m = &waypoints[m->prev]) route.add(m - &waypoints[0]); // just keep it stored backward } - return !route.empty(); } - VARF(dropwaypoints, 0, 0, 1, { player1->lastnode = -1; }); - - int addwaypoint(const vec &o, int weight = -1) - { + int addwaypoint(const vec &o, int weight = -1) { if(waypoints.length() > MAXWAYPOINTS) return -1; int n = waypoints.length(); waypoints.add(waypoint(o, weight >= 0 ? weight : getweight(o))); invalidatewpcache(n); return n; } - - void linkwaypoint(waypoint &a, int n) - { - loopi(MAXWAYPOINTLINKS) - { + void linkwaypoint(waypoint &a, int n) { + loopi(MAXWAYPOINTLINKS) { if(a.links[i] == n) return; if(!a.links[i]) { a.links[i] = n; return; } } a.links[rnd(MAXWAYPOINTLINKS)] = n; } - string loadedwaypoints = ""; - - static inline bool shouldnavigate() - { + static inline bool shouldnavigate() { if(dropwaypoints) return true; loopvrev(players) if(players[i]->aitype != AI_NONE) return true; return false; } - - static inline bool shoulddrop(fpsent *d) - { + static inline bool shoulddrop(fpsent *d) { return !d->ai && (dropwaypoints || !loadedwaypoints[0]); } - - void inferwaypoints(fpsent *d, const vec &o, const vec &v, float mindist) - { + void inferwaypoints(fpsent *d, const vec &o, const vec &v, float mindist) { if(!shouldnavigate()) return; - if(shoulddrop(d)) - { + if(shoulddrop(d)) { if(waypoints.empty()) seedwaypoints(); int from = closestwaypoint(o, mindist, false), to = closestwaypoint(v, mindist, false); if(!iswaypoint(from)) from = addwaypoint(o); if(!iswaypoint(to)) to = addwaypoint(v); if(d->lastnode != from && iswaypoint(d->lastnode) && iswaypoint(from)) linkwaypoint(waypoints[d->lastnode], from); - if(iswaypoint(to)) - { + if(iswaypoint(to)) { if(from != to && iswaypoint(from) && iswaypoint(to)) linkwaypoint(waypoints[from], to); d->lastnode = to; } } - else d->lastnode = closestwaypoint(v, WAYPOINTRADIUS*2, false, d); + else d->lastnode = closestwaypoint(v, WAYPOINTRADIUS*2, false); } - - void navigate(fpsent *d) - { + void navigate(fpsent *d) { vec v(d->feetpos()); if(d->state != CS_ALIVE) { d->lastnode = -1; return; } bool dropping = shoulddrop(d); int mat = lookupmaterial(v); if((mat&MATF_CLIP) == MAT_CLIP || mat&MAT_DEATH) dropping = false; float dist = dropping ? WAYPOINTRADIUS : (d->ai ? WAYPOINTRADIUS : SIGHTMIN); - int curnode = closestwaypoint(v, dist, false, d), prevnode = d->lastnode; - if(!iswaypoint(curnode) && dropping) - { + int curnode = closestwaypoint(v, dist, false), prevnode = d->lastnode; + if(!iswaypoint(curnode) && dropping) { if(waypoints.empty()) seedwaypoints(); curnode = addwaypoint(v); } - if(iswaypoint(curnode)) - { - if(dropping && d->lastnode != curnode && iswaypoint(d->lastnode)) - { + if(iswaypoint(curnode)) { + if(dropping && d->lastnode != curnode && iswaypoint(d->lastnode)) { linkwaypoint(waypoints[d->lastnode], curnode); if(!d->timeinair) linkwaypoint(waypoints[curnode], d->lastnode); } @@ -585,35 +455,26 @@ namespace ai if(d->ai && iswaypoint(prevnode) && d->lastnode != prevnode) d->ai->addprevnode(prevnode); } else if(!iswaypoint(d->lastnode) || waypoints[d->lastnode].o.squaredist(v) > SIGHTMIN*SIGHTMIN) - d->lastnode = closestwaypoint(v, SIGHTMAX, false, d); + d->lastnode = closestwaypoint(v, SIGHTMAX, false); } - - void navigate() - { + void navigate() { if(shouldnavigate()) loopv(players) ai::navigate(players[i]); if(invalidatedwpcaches) clearwpcache(false); } - - void clearwaypoints(bool full) - { + void clearwaypoints(bool full) { waypoints.setsize(0); clearwpcache(); - if(full) - { + if(full) { loadedwaypoints[0] = '\0'; dropwaypoints = 0; } } ICOMMAND(clearwaypoints, "", (), clearwaypoints()); - - void seedwaypoints() - { + void seedwaypoints() { if(waypoints.empty()) addwaypoint(vec(0, 0, 0)); - loopv(entities::ents) - { + loopv(entities::ents) { extentity &e = *entities::ents[i]; - switch(e.type) - { + switch(e.type) { case PLAYERSTART: case TELEPORT: case JUMPPAD: addwaypoint(e.o); break; @@ -623,21 +484,17 @@ namespace ai } } } - - void remapwaypoints() - { + void remapwaypoints() { vector remap; int total = 0; loopv(waypoints) remap.add(waypoints[i].links[1] == 0xFFFF ? 0 : total++); total = 0; - loopvj(waypoints) - { + loopvj(waypoints) { if(waypoints[j].links[1] == 0xFFFF) continue; waypoint &w = waypoints[total]; if(j != total) w = waypoints[j]; int k = 0; - loopi(MAXWAYPOINTLINKS) - { + loopi(MAXWAYPOINTLINKS) { int link = w.links[i]; if(!link) break; if((w.links[k] = remap[link])) k++; @@ -647,22 +504,17 @@ namespace ai } waypoints.setsize(total); } - - bool cleanwaypoints() - { + bool cleanwaypoints() { int cleared = 0; - for(int i = 1; i < waypoints.length(); i++) - { + for(int i = 1; i < waypoints.length(); i++) { waypoint &w = waypoints[i]; - if(clipped(w.o)) - { + if(clipped(w.o)) { w.links[0] = 0; w.links[1] = 0xFFFF; cleared++; } } - if(cleared) - { + if(cleared) { player1->lastnode = -1; loopv(players) if(players[i]) players[i]->lastnode = -1; remapwaypoints(); @@ -671,37 +523,28 @@ namespace ai } return false; } - - bool getwaypointfile(const char *mname, char *wptname) - { + bool getwaypointfile(const char *mname, char *wptname) { if(!mname || !*mname) mname = getclientmap(); if(!*mname) return false; - string pakname, mapname, cfgname; getmapfilenames(mname, NULL, pakname, mapname, cfgname); nformatstring(wptname, MAXSTRLEN, "packages/%s.wpt", mapname); path(wptname); return true; } - - void loadwaypoints(bool force, const char *mname) - { + void loadwaypoints(bool force, const char *mname) { string wptname; if(!getwaypointfile(mname, wptname)) return; if(!force && (waypoints.length() || !strcmp(loadedwaypoints, wptname))) return; - stream *f = opengzfile(wptname, "rb"); if(!f) return; char magic[4]; if(f->read(magic, 4) < 4 || memcmp(magic, "OWPT", 4)) { delete f; return; } - copystring(loadedwaypoints, wptname); - waypoints.setsize(0); waypoints.add(vec(0, 0, 0)); ushort numwp = f->getlil(); - loopi(numwp) - { + loopi(numwp) { if(f->end()) break; vec o; o.x = f->getlil(); @@ -709,35 +552,26 @@ namespace ai o.z = f->getlil(); waypoint &w = waypoints.add(waypoint(o, getweight(o))); int numlinks = f->getchar(), k = 0; - loopi(numlinks) - { - if((w.links[k] = f->getlil())) - { + loopi(numlinks) { + if((w.links[k] = f->getlil())) { if(++k >= MAXWAYPOINTLINKS) break; } } } - delete f; conoutf("loaded %d waypoints from %s", numwp, wptname); - if(!cleanwaypoints()) clearwpcache(); } ICOMMAND(loadwaypoints, "s", (char *mname), loadwaypoints(true, mname)); - - void savewaypoints(bool force, const char *mname) - { + void savewaypoints(bool force, const char *mname) { if((!dropwaypoints && !force) || waypoints.empty()) return; - string wptname; if(!getwaypointfile(mname, wptname)) return; - stream *f = opengzfile(wptname, "wb"); if(!f) return; f->write("OWPT", 4); f->putlil(waypoints.length()-1); - for(int i = 1; i < waypoints.length(); i++) - { + for(int i = 1; i < waypoints.length(); i++) { waypoint &w = waypoints[i]; f->putlil(w.o.x); f->putlil(w.o.y); @@ -747,55 +581,43 @@ namespace ai f->putchar(numlinks); loopj(numlinks) f->putlil(w.links[j]); } - delete f; conoutf("saved %d waypoints to %s", waypoints.length()-1, wptname); } - ICOMMAND(savewaypoints, "s", (char *mname), savewaypoints(true, mname)); - - void delselwaypoints() - { + void delselwaypoints() { if(noedit(true)) return; vec o = vec(sel.o).sub(0.1f), s = vec(sel.s).mul(sel.grid).add(o).add(0.1f); int cleared = 0; - for(int i = 1; i < waypoints.length(); i++) - { + for(int i = 1; i < waypoints.length(); i++) { waypoint &w = waypoints[i]; - if(w.o.x >= o.x && w.o.x <= s.x && w.o.y >= o.y && w.o.y <= s.y && w.o.z >= o.z && w.o.z <= s.z) - { + if(w.o.x >= o.x && w.o.x <= s.x && w.o.y >= o.y && w.o.y <= s.y && w.o.z >= o.z && w.o.z <= s.z) { w.links[0] = 0; w.links[1] = 0xFFFF; cleared++; } } - if(cleared) - { + if(cleared) { player1->lastnode = -1; remapwaypoints(); clearwpcache(); } } COMMAND(delselwaypoints, ""); - - void movewaypoints(const vec &d) - { + void movewaypoints(const vec &d) { if(noedit(true)) return; int worldsize = getworldsize(); - if(d.x < -worldsize || d.x > worldsize || d.y < -worldsize || d.y > worldsize || d.z < -worldsize || d.z > worldsize) - { + if(d.x < -worldsize || d.x > worldsize || d.y < -worldsize || d.y > worldsize || d.z < -worldsize || d.z > worldsize) { clearwaypoints(); return; } int cleared = 0; - for(int i = 1; i < waypoints.length(); i++) - { + for(int i = 1; i < waypoints.length(); i++) { waypoint &w = waypoints[i]; w.o.add(d); if(!insideworld(w.o)) { w.links[0] = 0; w.links[1] = 0xFFFF; cleared++; } } - if(cleared) - { + if(cleared) { player1->lastnode = -1; remapwaypoints(); } diff --git a/src/fpsgame/weapon.cpp b/src/fpsgame/weapon.cpp index 1bdb302..c486110 100644 --- a/src/fpsgame/weapon.cpp +++ b/src/fpsgame/weapon.cpp @@ -1,37 +1,27 @@ // weapon.cpp: all shooting and effects code, projectile management #include "game.h" -namespace game -{ +namespace game { static const int OFFSETMILLIS = 500; vec rays[MAXRAYS]; - - struct hitmsg - { + struct hitmsg { int target, lifesequence, info1, info2; ivec dir; }; vector hits; - ICOMMAND(getweapon, "", (), intret(player1->gunselect)); - - void gunselect(int gun, fpsent *d) - { - if(gun!=d->gunselect) - { + void gunselect(int gun, fpsent *d) { + if(gun!=d->gunselect) { addmsg(N_GUNSELECT, "rci", d, gun); playsound(S_WEAPLOAD, d == player1 ? NULL : &d->o); } d->gunselect = gun; } - - void nextweapon(int dir, bool force = false) - { + void nextweapon(int dir, bool force = false) { if(player1->state!=CS_ALIVE) return; dir = (dir < 0 ? NUMGUNS-1 : 1); int gun = player1->gunselect; - loopi(NUMGUNS) - { + loopi(NUMGUNS) { gun = (gun + dir)%NUMGUNS; if(force || player1->ammo[gun]) break; } @@ -39,50 +29,39 @@ namespace game else playsound(S_NOAMMO); } ICOMMAND(nextweapon, "ii", (int *dir, int *force), nextweapon(*dir, *force!=0)); - - int getweapon(const char *name) - { + int getweapon(const char *name) { const char *abbrevs[] = { "FI", "SG", "CG", "RL", "RI", "GL", "PI" }; if(isdigit(name[0])) return parseint(name); else loopi(sizeof(abbrevs)/sizeof(abbrevs[0])) if(!strcasecmp(abbrevs[i], name)) return i; return -1; } - - void setweapon(const char *name, bool force = false) - { + void setweapon(const char *name, bool force = false) { int gun = getweapon(name); if(player1->state!=CS_ALIVE || gunGUN_PISTOL) return; if(force || player1->ammo[gun]) gunselect(gun, player1); else playsound(S_NOAMMO); } ICOMMAND(setweapon, "si", (char *name, int *force), setweapon(name, *force!=0)); - - void cycleweapon(int numguns, int *guns, bool force = false) - { + void cycleweapon(int numguns, int *guns, bool force = false) { if(numguns<=0 || player1->state!=CS_ALIVE) return; int offset = 0; loopi(numguns) if(guns[i] == player1->gunselect) { offset = i+1; break; } - loopi(numguns) - { + loopi(numguns) { int gun = guns[(i+offset)%numguns]; - if(gun>=0 && gunammo[gun])) - { + if(gun>=0 && gunammo[gun])) { gunselect(gun, player1); return; } } playsound(S_NOAMMO); } - ICOMMAND(cycleweapon, "V", (tagval *args, int numargs), - { + ICOMMAND(cycleweapon, "V", (tagval *args, int numargs), { int numguns = min(numargs, 7); int guns[7]; loopi(numguns) guns[i] = getweapon(args[i].getstr()); cycleweapon(numguns, guns); }); - - void weaponswitch(fpsent *d) - { + void weaponswitch(fpsent *d) { if(d->state!=CS_ALIVE) return; int s = d->gunselect; if (s!=GUN_CG && d->ammo[GUN_CG]) s = GUN_CG; @@ -92,49 +71,36 @@ namespace game else if(s!=GUN_GL && d->ammo[GUN_GL]) s = GUN_GL; else if(s!=GUN_PISTOL && d->ammo[GUN_PISTOL]) s = GUN_PISTOL; else s = GUN_FIST; - gunselect(s, d); } - - ICOMMAND(weapon, "V", (tagval *args, int numargs), - { + ICOMMAND(weapon, "V", (tagval *args, int numargs), { if(player1->state!=CS_ALIVE) return; - loopi(7) - { + loopi(7) { const char *name = i < numargs ? args[i].getstr() : ""; - if(name[0]) - { + if(name[0]) { int gun = getweapon(name); if(gun >= GUN_FIST && gun <= GUN_PISTOL && gun != player1->gunselect && player1->ammo[gun]) { gunselect(gun, player1); return; } } else { weaponswitch(player1); return; } } playsound(S_NOAMMO); }); - - void offsetray(const vec &from, const vec &to, int spread, float range, vec &dest) - { + void offsetray(const vec &from, const vec &to, int spread, float range, vec &dest) { vec offset; do offset = vec(rndscale(1), rndscale(1), rndscale(1)).sub(0.5f); while(offset.squaredlen() > 0.5f*0.5f); offset.mul((to.dist(from)/1024)*spread); offset.z /= 2; dest = vec(offset).add(to); - if(dest != from) - { + if(dest != from) { vec dir = vec(dest).sub(from).normalize(); raycubepos(from, dir, dest, range, RAY_CLIPMAT|RAY_ALPHAPOLY); } } - - void createrays(int gun, const vec &from, const vec &to) // create random spread of rays - { + void createrays(int gun, const vec &from, const vec &to) { // create random spread of rays { loopi(guns[gun].rays) offsetray(from, to, guns[gun].spread, guns[gun].range, rays[i]); } - enum { BNC_GRENADE }; - - struct bouncer : physent - { + struct bouncer : physent { int lifetime, bounces; float lastyaw, roll; bool local; @@ -145,37 +111,26 @@ namespace game float offsetheight; int id; entitylight light; - - bouncer() : bounces(0), roll(0), variant(0) - { + bouncer() : bounces(0), roll(0), variant(0) { type = ENT_BOUNCE; } - - vec offsetpos() - { + vec offsetpos() { vec pos(o); - if(offsetmillis > 0) - { + if(offsetmillis > 0) { pos.add(vec(offset).mul(offsetmillis/float(OFFSETMILLIS))); if(offsetheight >= 0) pos.z = max(pos.z, o.z - max(offsetheight - eyeheight, 0.0f)); } return pos; } - - void limitoffset() - { + void limitoffset() { if(bouncetype == BNC_GRENADE && offsetmillis > 0 && offset.z < 0) offsetheight = raycube(vec(o.x + offset.x, o.y + offset.y, o.z), vec(0, 0, -1), -offset.z); else offsetheight = -1; } }; - vector bouncers; - vec hudgunorigin(int gun, const vec &from, const vec &to, fpsent *d); - - void newbouncer(const vec &from, const vec &to, bool local, int id, fpsent *owner, int type, int lifetime, int speed, entitylight *light = NULL) - { + void newbouncer(const vec &from, const vec &to, bool local, int id, fpsent *owner, int type, int lifetime, int speed, entitylight *light = NULL) { bouncer &bnc = *bouncers.add(new bouncer); bnc.o = from; bnc.radius = bnc.xradius = bnc.yradius = 1.5f; @@ -187,18 +142,13 @@ namespace game bnc.bouncetype = type; bnc.id = local ? lastmillis : id; if(light) bnc.light = *light; - bnc.collidetype = COLLIDE_ELLIPSE_PRECISE; - vec dir(to); dir.sub(from).safenormalize(); bnc.vel = dir; bnc.vel.mul(speed); - avoidcollision(&bnc, dir, owner, 0.1f); - - if(type==BNC_GRENADE) - { + if(type==BNC_GRENADE) { bnc.offset = hudgunorigin(GUN_GL, from, to, owner); if(owner==followingplayer(player1) && !isthirdperson()) bnc.offset.sub(owner->o).rescale(16).add(owner->o); } @@ -206,37 +156,27 @@ namespace game bnc.offset.sub(bnc.o); bnc.offsetmillis = OFFSETMILLIS; bnc.limitoffset(); - bnc.resetinterp(); } - - void bounced(physent *d, const vec &surface) - { + void bounced(physent *d, const vec &surface) { if(d->type != ENT_BOUNCE) return; bouncer *b = (bouncer *)d; if(b->bounces >= 2) return; b->bounces++; adddecal(DECAL_BLOOD, vec(b->o).sub(vec(surface).mul(b->radius)), surface, 2.96f/b->bounces, bvec(0x60, 0xFF, 0xFF), rnd(4)); } - - void updatebouncers(int time) - { - loopv(bouncers) - { + void updatebouncers(int time) { + loopv(bouncers) { bouncer &bnc = *bouncers[i]; - if(bnc.bouncetype==BNC_GRENADE && bnc.vel.magnitude() > 50.0f) - { + if(bnc.bouncetype==BNC_GRENADE && bnc.vel.magnitude() > 50.0f) { vec pos = bnc.offsetpos(); regular_particle_splash(PART_SMOKE, 1, 150, pos, 0x404040, 2.4f, 50, -20); } vec old(bnc.o); bool stopped = false; if(bnc.bouncetype==BNC_GRENADE) stopped = bounce(&bnc, 0.6f, 0.5f, 0.8f) || (bnc.lifetime -= time)<0; - - if(stopped) - { - if(bnc.bouncetype==BNC_GRENADE) - { + if(stopped) { + if(bnc.bouncetype==BNC_GRENADE) { int qdam = guns[GUN_GL].damage*(bnc.owner->quadmillis ? 4 : 1); hits.setsize(0); explode(bnc.local, bnc.owner, bnc.o, NULL, qdam, GUN_GL); @@ -247,24 +187,18 @@ namespace game } delete bouncers.remove(i--); } - else - { + else { bnc.roll += old.sub(bnc.o).magnitude()/(4*RAD); bnc.offsetmillis = max(bnc.offsetmillis-time, 0); bnc.limitoffset(); } } } - - void removebouncers(fpsent *owner) - { + void removebouncers(fpsent *owner) { loopv(bouncers) if(bouncers[i]->owner==owner) { delete bouncers[i]; bouncers.remove(i--); } } - void clearbouncers() { bouncers.deletecontents(); } - - struct projectile - { + struct projectile { vec dir, o, to, offset; float speed; fpsent *owner; @@ -275,11 +209,8 @@ namespace game entitylight light; }; vector projs; - void clearprojectiles() { projs.shrink(0); } - - void newprojectile(const vec &from, const vec &to, float speed, bool local, int id, fpsent *owner, int gun) - { + void newprojectile(const vec &from, const vec &to, float speed, bool local, int id, fpsent *owner, int gun) { projectile &p = projs.add(); p.dir = vec(to).sub(from).safenormalize(); p.o = from; @@ -293,69 +224,51 @@ namespace game p.offsetmillis = OFFSETMILLIS; p.id = local ? lastmillis : id; } - - void removeprojectiles(fpsent *owner) - { + void removeprojectiles(fpsent *owner) { // can't use loopv here due to strange GCC optimizer bug int len = projs.length(); loopi(len) if(projs[i].owner==owner) { projs.remove(i--); len--; } } - VARP(blood, 0, 1, 1); - - void damageeffect(int damage, fpsent *d, bool thirdperson) - { + void damageeffect(int damage, fpsent *d, bool thirdperson) { vec p = d->o; p.z += 0.6f*(d->eyeheight + d->aboveeye) - d->eyeheight; if(blood) particle_splash(PART_BLOOD, damage/10, 1000, p, 0x60FFFF, 2.96f); - if(thirdperson) - { + if(thirdperson) { defformatstring(ds, "%d", damage); particle_textcopy(d->abovehead(), ds, PART_TEXT, 2000, 0xFF4B19, 4.0f, -8); } } - - void spawnbouncer(const vec &p, const vec &vel, fpsent *d, int type, entitylight *light = NULL) - { - vec to(rnd(100)-50, rnd(100)-50, rnd(100)-50); - if(to.iszero()) to.z += 1; - to.normalize(); - to.add(p); - newbouncer(p, to, true, 0, d, type, rnd(1000)+1000, rnd(100)+20, light); - } - - void hit(int damage, dynent *d, fpsent *at, const vec &vel, int gun, float info1, int info2 = 1) - { - if(at==player1 && d!=at) - { + //~void spawnbouncer(const vec &p, const vec &vel, fpsent *d, int type, entitylight *light = NULL) + //~{ + //~vec to(rnd(100)-50, rnd(100)-50, rnd(100)-50); + //~if(to.iszero()) to.z += 1; + //~to.normalize(); + //~to.add(p); + //~newbouncer(p, to, true, 0, d, type, rnd(1000)+1000, rnd(100)+20, light); + //~} + void hit(int damage, dynent *d, fpsent *at, const vec &vel, int gun, float info1, int info2 = 1) { + if(at==player1 && d!=at) { extern int hitsound; if(hitsound && lasthit != lastmillis) playsound(S_HIT); lasthit = lastmillis; } - fpsent *f = (fpsent *)d; - f->lastpain = lastmillis; if(at->type==ENT_PLAYER && !isteam(at->team, f->team)) at->totaldamage += damage; - if(f->type==ENT_AI || !m_mp(gamemode) || f==at) f->hitpush(damage, vel, at, gun); - pwhit(gun, damage); - if(!m_mp(gamemode)) damaged(damage, f, at); - else - { + else { hitmsg &h = hits.add(); h.target = f->clientnum; h.lifesequence = f->lifesequence; h.info1 = int(info1*DMF); h.info2 = info2; h.dir = f==at ? ivec(0, 0, 0) : ivec(vec(vel).mul(DNF)); - if(at==player1) - { + if(at==player1) { damageeffect(damage, f); - if(f==player1) - { + if(f==player1) { damagecompass(damage, at ? at->o : f->o); playsound(S_PAIN6); } @@ -363,14 +276,10 @@ namespace game } } } - - void hitpush(int damage, dynent *d, fpsent *at, vec &from, vec &to, int gun, int rays) - { + void hitpush(int damage, dynent *d, fpsent *at, vec &from, vec &to, int gun, int rays) { hit(damage, d, at, vec(to).sub(from).safenormalize(), gun, from.dist(to), rays); } - - float projdist(dynent *o, vec &dir, const vec &v) - { + float projdist(dynent *o, vec &dir, const vec &v) { vec middle = o->o; middle.z += (o->aboveeye-o->eyeheight)/2; float dist = middle.dist(v, dir); @@ -378,68 +287,53 @@ namespace game if(dist<0) dist = 0; return dist; } - - void radialeffect(dynent *o, const vec &v, int qdam, fpsent *at, int gun) - { + void radialeffect(dynent *o, const vec &v, int qdam, fpsent *at, int gun) { if(o->state!=CS_ALIVE) return; vec dir; float dist = projdist(o, dir, v); - if(disto.reject(v, o->radius + guns[gun].exprad) || o==safe) continue; radialeffect(o, v, damage, owner, gun); } } - - void projsplash(projectile &p, vec &v, dynent *safe, int damage) - { - if(guns[p.gun].part) - { + void projsplash(projectile &p, vec &v, dynent *safe, int damage) { + if(guns[p.gun].part) { particle_splash(PART_SPARK, 100, 200, v, 0xB49B4B, 0.24f); playsound(S_FEXPLODE, &v); // no push? } - else - { + else { explode(p.local, p.owner, v, safe, damage, GUN_RL); adddecal(DECAL_SCORCH, v, vec(p.dir).neg(), guns[p.gun].exprad/2); } } - - void explodeeffects(int gun, fpsent *d, bool local, int id) - { + void explodeeffects(int gun, fpsent *d, bool local, int id) { if(local) return; - switch(gun) - { + switch(gun) { case GUN_RL: - loopv(projs) - { + loopv(projs) { projectile &p = projs[i]; - if(p.gun == gun && p.owner == d && p.id == id && !p.local) - { + if(p.gun == gun && p.owner == d && p.id == id && !p.local) { vec pos(p.o); pos.add(vec(p.offset).mul(p.offsetmillis/float(OFFSETMILLIS))); explode(p.local, p.owner, pos, NULL, 0, GUN_RL); @@ -450,11 +344,9 @@ namespace game } break; case GUN_GL: - loopv(bouncers) - { + loopv(bouncers) { bouncer &b = *bouncers[i]; - if(b.bouncetype == BNC_GRENADE && b.owner == d && b.id == id && !b.local) - { + if(b.bouncetype == BNC_GRENADE && b.owner == d && b.id == id && !b.local) { vec pos = b.offsetpos(); explode(b.local, b.owner, pos, NULL, 0, GUN_GL); adddecal(DECAL_SCORCH, pos, vec(0, 0, 1), guns[gun].exprad/2); @@ -467,9 +359,7 @@ namespace game break; } } - - bool projdamage(dynent *o, projectile &p, vec &v, int qdam) - { + bool projdamage(dynent *o, projectile &p, vec &v, int qdam) { if(o->state!=CS_ALIVE) return false; if(!intersect(o, p.o, v)) return false; projsplash(p, v, o, qdam); @@ -478,11 +368,8 @@ namespace game hit(qdam, o, p.owner, dir, p.gun, 0); return true; } - - void updateprojectiles(int time) - { - loopv(projs) - { + void updateprojectiles(int time) { + loopv(projs) { projectile &p = projs[i]; p.offsetmillis = max(p.offsetmillis-time, 0); int qdam = guns[p.gun].damage*(p.owner->quadmillis ? 4 : 1); @@ -492,37 +379,30 @@ namespace game vec v = vec(p.o).add(dv); bool exploded = false; hits.setsize(0); - if(p.local) - { + if(p.local) { vec halfdv = vec(dv).mul(0.5f), bo = vec(p.o).add(halfdv); float br = max(fabs(halfdv.x), fabs(halfdv.y)) + 1; - loopj(numdynents()) - { + loopj(numdynents()) { dynent *o = iterdynents(j); if(p.owner==o || o->o.reject(bo, o->radius + br)) continue; if(projdamage(o, p, v, qdam)) { exploded = true; break; } } } - if(!exploded) - { - if(dist<4) - { - if(p.o!=p.to) // if original target was moving, reevaluate endpoint - { + if(!exploded) { + if(dist<4) { + if(p.o!=p.to) { // if original target was moving, reevaluate endpoint { if(raycubepos(p.o, p.dir, p.to, 0, RAY_CLIPMAT|RAY_ALPHAPOLY)>=4) continue; } projsplash(p, v, NULL, qdam); exploded = true; } - else - { + else { vec pos(v); pos.add(vec(p.offset).mul(p.offsetmillis/float(OFFSETMILLIS))); regular_particle_splash(PART_SMOKE, 2, 300, pos, 0x404040, 2.4f, 50, -20); } } - if(exploded) - { + if(exploded) { if(p.local) addmsg(N_EXPLODE, "rci3iv", p.owner, lastmillis-maptime, p.gun, p.id-maptime, hits.length(), hits.length()*sizeof(hitmsg)/sizeof(int), hits.getbuf()); @@ -531,28 +411,20 @@ namespace game else p.o = v; } } - extern int chainsawhudgun; - VARP(muzzleflash, 0, 1, 1); VARP(muzzlelight, 0, 1, 1); - - void shoteffects(int gun, const vec &from, const vec &to, fpsent *d, bool local, int id, int prevaction) // create visual effect from a shot - { + void shoteffects(int gun, const vec &from, const vec &to, fpsent *d, bool local, int id, int prevaction) { // create visual effect from a shot { int sound = guns[gun].sound, pspeed = 25; - switch(gun) - { + switch(gun) { case GUN_FIST: if(d->type==ENT_PLAYER && chainsawhudgun) sound = S_CHAINSAW_ATTACK; break; - - case GUN_SG: - { + case GUN_SG: { if(!local) createrays(gun, from, to); if(muzzleflash && d->muzzle.x >= 0) particle_flare(d->muzzle, d->muzzle, 200, PART_MUZZLE_FLASH3, 0xFFFFFF, 2.75f, d); - loopi(guns[gun].rays) - { + loopi(guns[gun].rays) { if(d->quadmillis) particle_trail(PART_FLAME, 400, hudgunorigin(gun, from, rays[i], d), rays[i], 0x802010, 0.6f, 36); particle_splash(PART_SPARK, 20, 250, rays[i], 0xB49B4B, 0.24f); @@ -562,10 +434,8 @@ namespace game if(muzzlelight) adddynlight(hudgunorigin(gun, d->o, to, d), 30, vec(0.5f, 0.375f, 0.25f), 100, 100, DL_FLASH, 0, vec(0, 0, 0), d); break; } - case GUN_CG: - case GUN_PISTOL: - { + case GUN_PISTOL: { particle_splash(PART_SPARK, 200, 250, to, 0xB49B4B, 0.24f); if(d->quadmillis) particle_trail(PART_FLAME, 400, hudgunorigin(gun, from, to, d), to, 0x802010, 0.6f, 36); @@ -576,7 +446,6 @@ namespace game if(muzzlelight) adddynlight(hudgunorigin(gun, d->o, to, d), gun==GUN_CG ? 30 : 15, vec(0.5f, 0.375f, 0.25f), gun==GUN_CG ? 50 : 100, gun==GUN_CG ? 50 : 100, DL_FLASH, 0, vec(0, 0, 0), d); break; } - case GUN_RL: if(d->quadmillis) particle_trail(PART_FLAME, 400, hudgunorigin(gun, from, to, d), to, 0x802010, 0.6f, 36); @@ -585,9 +454,7 @@ namespace game pspeed = guns[gun].projspeed; newprojectile(from, to, (float)pspeed, local, id, d, gun); break; - - case GUN_GL: - { + case GUN_GL: { float dist = from.dist(to); vec up = to; up.z += dist/8; @@ -597,7 +464,6 @@ namespace game newbouncer(from, up, local, id, d, BNC_GRENADE, guns[gun].ttl, guns[gun].projspeed); break; } - case GUN_RIFLE: particle_splash(PART_SPARK, 200, 250, to, 0xB49B4B, 0.24f); if(d->quadmillis) @@ -609,13 +475,11 @@ namespace game if(muzzlelight) adddynlight(hudgunorigin(gun, d->o, to, d), 25, vec(0.5f, 0.375f, 0.25f), 75, 75, DL_FLASH, 0, vec(0, 0, 0), d); break; } - bool looped = false; if(d->attacksound >= 0 && d->attacksound != sound) d->stopattacksound(); if(d->idlesound >= 0) d->stopidlesound(); fpsent *h = followingplayer(player1); - switch(sound) - { + switch(sound) { case S_CHAINSAW_ATTACK: if(d->attacksound >= 0) looped = true; d->attacksound = sound; @@ -627,114 +491,89 @@ namespace game } if(d->quadmillis && lastmillis-prevaction>200 && !looped) playsound(S_ITEMPUP, d==h ? NULL : &d->o); } - - void particletrack(physent *owner, vec &o, vec &d) - { + void particletrack(physent *owner, vec &o, vec &d) { if(owner->type!=ENT_PLAYER && owner->type!=ENT_AI) return; fpsent *pl = (fpsent *)owner; if(pl->muzzle.x < 0 || pl->lastattackgun != pl->gunselect) return; float dist = o.dist(d); o = pl->muzzle; if(dist <= 0) d = o; - else - { + else { vecfromyawpitch(owner->yaw, owner->pitch, 1, 0, d); float newdist = raycube(owner->o, d, dist, RAY_CLIPMAT|RAY_ALPHAPOLY); d.mul(min(newdist, dist)).add(owner->o); } } - - void dynlighttrack(physent *owner, vec &o, vec &hud) - { + void dynlighttrack(physent *owner, vec &o, vec &hud) { if(owner->type!=ENT_PLAYER && owner->type!=ENT_AI) return; fpsent *pl = (fpsent *)owner; if(pl->muzzle.x < 0 || pl->lastattackgun != pl->gunselect) return; o = pl->muzzle; hud = owner == followingplayer(player1) ? vec(pl->o).add(vec(0, 0, 2)) : pl->muzzle; } - float intersectdist = 1e16f; - - bool intersect(dynent *d, const vec &from, const vec &to, float &dist) // if lineseg hits entity bounding box - { + bool intersect(dynent *d, const vec &from, const vec &to, float &dist) { // if lineseg hits entity bounding box { vec bottom(d->o), top(d->o); bottom.z -= d->eyeheight; top.z += d->aboveeye; return linecylinderintersect(from, to, bottom, top, d->radius, dist); } - - dynent *intersectclosest(const vec &from, const vec &to, fpsent *at, float &bestdist) - { + dynent *intersectclosest(const vec &from, const vec &to, fpsent *at, float &bestdist) { dynent *best = NULL; bestdist = 1e16f; - loopi(numdynents()) - { + loopi(numdynents()) { dynent *o = iterdynents(i); if(o==at || o->state!=CS_ALIVE) continue; float dist; if(!intersect(o, from, to, dist)) continue; - if(distgunselect].damage; if(d->quadmillis) qdam *= 4; dynent *o; float dist; - if(guns[d->gunselect].rays > 1) - { + if(guns[d->gunselect].rays > 1) { dynent *hits[MAXRAYS]; int maxrays = guns[d->gunselect].rays; - loopi(maxrays) - { + loopi(maxrays) { if((hits[i] = intersectclosest(from, rays[i], d, dist))) shorten(from, rays[i], dist); else adddecal(DECAL_BULLET, rays[i], vec(from).sub(rays[i]).safenormalize(), 2.0f); } - loopi(maxrays) if(hits[i]) - { + loopi(maxrays) if(hits[i]) { o = hits[i]; hits[i] = NULL; int numhits = 1; - for(int j = i+1; j < maxrays; j++) if(hits[j] == o) - { + for(int j = i+1; j < maxrays; j++) if(hits[j] == o) { hits[j] = NULL; numhits++; } hitpush(numhits*qdam, o, d, from, to, d->gunselect, numhits); } } - else if((o = intersectclosest(from, to, d, dist))) - { + else if((o = intersectclosest(from, to, d, dist))) { shorten(from, to, dist); hitpush(qdam, o, d, from, to, d->gunselect, 1); } else if(d->gunselect!=GUN_FIST) adddecal(DECAL_BULLET, to, vec(from).sub(to).safenormalize(), d->gunselect==GUN_RIFLE ? 3.0f : 2.0f); } - - void shoot(fpsent *d, const vec &targ) - { + void shoot(fpsent *d, const vec &targ) { int prevaction = d->lastaction, attacktime = lastmillis-prevaction; if(attacktimegunwait) return; d->gunwait = 0; if((d==player1 || d->ai) && !d->attacking) return; d->lastaction = lastmillis; d->lastattackgun = d->gunselect; - if(!d->ammo[d->gunselect]) - { - if(d==player1) - { + if(!d->ammo[d->gunselect]) { + if(d==player1) { msgsound(S_NOAMMO, d); d->gunwait = 600; d->lastattackgun = -1; @@ -743,9 +582,7 @@ namespace game return; } if(d->gunselect) d->ammo[d->gunselect]--; - pwshot(d->gunselect); /// PW - vec from = d->o, to = targ, dir = vec(to).sub(from).safenormalize(); float dist = to.dist(from); vec kickback = vec(dir).mul(guns[d->gunselect].kickamount*-2.5f); @@ -757,65 +594,48 @@ namespace game if(barrier > 0 && barrier < dist && (!shorten || barrier < shorten)) shorten = barrier; if(shorten) to = vec(dir).mul(shorten).add(from); - if(guns[d->gunselect].rays > 1) createrays(d->gunselect, from, to); else if(guns[d->gunselect].spread) offsetray(from, to, guns[d->gunselect].spread, guns[d->gunselect].range, to); - hits.setsize(0); - if(!guns[d->gunselect].projspeed) raydamage(from, to, d); - shoteffects(d->gunselect, from, to, d, true, 0, prevaction); - - if(d==player1 || d->ai) - { + if(d==player1 || d->ai) { addmsg(N_SHOOT, "rci2i6iv", d, lastmillis-maptime, d->gunselect, (int)(from.x*DMF), (int)(from.y*DMF), (int)(from.z*DMF), (int)(to.x*DMF), (int)(to.y*DMF), (int)(to.z*DMF), hits.length(), hits.length()*sizeof(hitmsg)/sizeof(int), hits.getbuf()); } - d->gunwait = guns[d->gunselect].attackdelay; if(d->gunselect == GUN_PISTOL && d->ai) d->gunwait += int(d->gunwait*(((101-d->skill)+rnd(111-d->skill))/100.f)); d->totalshots += guns[d->gunselect].damage*(d->quadmillis ? 4 : 1)*guns[d->gunselect].rays; } - - void adddynlights() - { - loopv(projs) - { + void adddynlights() { + loopv(projs) { projectile &p = projs[i]; if(p.gun!=GUN_RL) continue; vec pos(p.o); pos.add(vec(p.offset).mul(p.offsetmillis/float(OFFSETMILLIS))); adddynlight(pos, 20, vec(1, 0.75f, 0.5f)); } - loopv(bouncers) - { + loopv(bouncers) { bouncer &bnc = *bouncers[i]; if(bnc.bouncetype!=BNC_GRENADE) continue; vec pos = bnc.offsetpos(); adddynlight(pos, 8, vec(0.25f, 1, 1)); } } - static const char * const projnames[2] = { "projectiles/grenade", "projectiles/rocket" }; - void preloadbouncers() { loopi(sizeof(projnames)/sizeof(projnames[0])) preloadmodel(projnames[i]); } - - void renderbouncers() - { + void renderbouncers() { float yaw, pitch; - loopv(bouncers) - { + loopv(bouncers) { bouncer &bnc = *bouncers[i]; vec pos = bnc.offsetpos(); vec vel(bnc.vel); if(vel.magnitude() <= 25.0f) yaw = bnc.lastyaw; - else - { + else { vectoyawpitch(vel, yaw, pitch); yaw += 90; bnc.lastyaw = yaw; @@ -823,8 +643,7 @@ namespace game pitch = -bnc.roll; if(bnc.bouncetype==BNC_GRENADE) rendermodel(&bnc.light, "projectiles/grenade", ANIM_MAPMODEL|ANIM_LOOP, pos, yaw, pitch, MDL_CULL_VFC|MDL_CULL_OCCLUDED|MDL_LIGHT|MDL_LIGHT_FAST|MDL_DYNSHADOW); - else - { + else { const char *mdl = NULL; int cull = MDL_CULL_VFC|MDL_CULL_DIST|MDL_CULL_OCCLUDED; float fade = 1; @@ -833,12 +652,9 @@ namespace game } } } - - void renderprojectiles() - { + void renderprojectiles() { float yaw, pitch; - loopv(projs) - { + loopv(projs) { projectile &p = projs[i]; if(p.gun!=GUN_RL) continue; float dist = min(p.o.dist(p.to)/32.0f, 1.0f); @@ -852,12 +668,9 @@ namespace game rendermodel(&p.light, "projectiles/rocket", ANIM_MAPMODEL|ANIM_LOOP, v, yaw, pitch, MDL_CULL_VFC|MDL_CULL_OCCLUDED|MDL_LIGHT|MDL_LIGHT_FAST); } } - - void checkattacksound(fpsent *d, bool local) - { + void checkattacksound(fpsent *d, bool local) { int gun = -1; - switch(d->attacksound) - { + switch(d->attacksound) { case S_CHAINSAW_ATTACK: if(chainsawhudgun) gun = GUN_FIST; break; @@ -866,74 +679,57 @@ namespace game } if(gun >= 0 && gun < NUMGUNS && d->clientnum >= 0 && d->state == CS_ALIVE && - d->lastattackgun == gun && lastmillis - d->lastaction < guns[gun].attackdelay + 50) - { + d->lastattackgun == gun && lastmillis - d->lastaction < guns[gun].attackdelay + 50) { d->attackchan = playsound(d->attacksound, local ? NULL : &d->o, NULL, 0, -1, -1, d->attackchan); if(d->attackchan < 0) d->attacksound = -1; } else d->stopattacksound(); } - - void checkidlesound(fpsent *d, bool local) - { + void checkidlesound(fpsent *d, bool local) { int sound = -1, radius = 0; - if(d->clientnum >= 0 && d->state == CS_ALIVE) switch(d->gunselect) - { + if(d->clientnum >= 0 && d->state == CS_ALIVE) switch(d->gunselect) { case GUN_FIST: - if(chainsawhudgun && d->attacksound < 0) - { + if(chainsawhudgun && d->attacksound < 0) { sound = S_CHAINSAW_IDLE; radius = 50; } break; } - if(d->idlesound != sound) - { + if(d->idlesound != sound) { if(d->idlesound >= 0) d->stopidlesound(); - if(sound >= 0) - { + if(sound >= 0) { d->idlechan = playsound(sound, local ? NULL : &d->o, NULL, 0, -1, 100, d->idlechan, radius); if(d->idlechan >= 0) d->idlesound = sound; } } - else if(sound >= 0) - { + else if(sound >= 0) { d->idlechan = playsound(sound, local ? NULL : &d->o, NULL, 0, -1, -1, d->idlechan, radius); if(d->idlechan < 0) d->idlesound = -1; } } - - void removeweapons(fpsent *d) - { + void removeweapons(fpsent *d) { removebouncers(d); removeprojectiles(d); } - - void updateweapons(int curtime) - { + void updateweapons(int curtime) { updateprojectiles(curtime); pwcalcaccuracy(); if(player1->clientnum>=0 && player1->state==CS_ALIVE) shoot(player1, worldpos); // only shoot when connected to server updatebouncers(curtime); // need to do this after the player shoots so grenades don't end up inside player's BB next frame fpsent *following = followingplayer(); if(!following) following = player1; - loopv(players) - { + loopv(players) { fpsent *d = players[i]; checkattacksound(d, d==following); checkidlesound(d, d==following); } } - - void avoidweapons(ai::avoidset &obstacles, float radius) - { - loopv(projs) - { + void avoidweapons(ai::avoidset &obstacles, float radius) { + loopv(projs) { projectile &p = projs[i]; obstacles.avoidnear(NULL, p.o.z + guns[p.gun].exprad + 1, p.o, radius + guns[p.gun].exprad); } - loopv(bouncers) - { + loopv(bouncers) { bouncer &bnc = *bouncers[i]; if(bnc.bouncetype != BNC_GRENADE) continue; obstacles.avoidnear(NULL, bnc.o.z + guns[GUN_GL].exprad + 1, bnc.o, radius + guns[GUN_GL].exprad); diff --git a/src/shared/command.h b/src/shared/command.h index ffb2115..1c6a95c 100644 --- a/src/shared/command.h +++ b/src/shared/command.h @@ -2,8 +2,7 @@ enum { VAL_NULL = 0, VAL_INT, VAL_FLOAT, VAL_STR, VAL_ANY, VAL_CODE, VAL_MACRO, VAL_IDENT }; -enum -{ +enum { CODE_START = 0, CODE_OFFSET, CODE_POP, @@ -26,11 +25,9 @@ enum CODE_LOOKUP, CODE_LOOKUPU, CODE_LOOKUPARG, CODE_ALIAS, CODE_ALIASU, CODE_ALIASARG, CODE_CALL, CODE_CALLU, CODE_CALLARG, CODE_PRINT, CODE_LOCAL, - CODE_OP_MASK = 0x3F, CODE_RET = 6, CODE_RET_MASK = 0xC0, - /* return type flags */ RET_NULL = VAL_NULL< x ? IDF_READONLY : 0)), name(n), minval(m), maxval(x), fun((identfun)f) - { storage.i = s; } + : type(t), flags(flags | (m > x ? IDF_READONLY : 0)), name(n), minval(m), maxval(x), fun((identfun)f) { + storage.i = s; } // ID_FVAR ident(int t, const char *n, float m, float x, float *s, void *f = NULL, int flags = 0) - : type(t), flags(flags | (m > x ? IDF_READONLY : 0)), name(n), minvalf(m), maxvalf(x), fun((identfun)f) - { storage.f = s; } + : type(t), flags(flags | (m > x ? IDF_READONLY : 0)), name(n), minvalf(m), maxvalf(x), fun((identfun)f) { + storage.f = s; } // ID_SVAR ident(int t, const char *n, char **s, void *f = NULL, int flags = 0) - : type(t), flags(flags), name(n), fun((identfun)f) - { storage.s = s; } + : type(t), flags(flags), name(n), fun((identfun)f) { + storage.s = s; } // ID_ALIAS ident(int t, const char *n, char *a, int flags) - : type(t), valtype(VAL_STR), flags(flags), name(n), code(NULL), stack(NULL) - { val.s = a; } + : type(t), valtype(VAL_STR), flags(flags), name(n), code(NULL), stack(NULL) { + val.s = a; } ident(int t, const char *n, int a, int flags) - : type(t), valtype(VAL_INT), flags(flags), name(n), code(NULL), stack(NULL) - { val.i = a; } + : type(t), valtype(VAL_INT), flags(flags), name(n), code(NULL), stack(NULL) { + val.i = a; } ident(int t, const char *n, float a, int flags) - : type(t), valtype(VAL_FLOAT), flags(flags), name(n), code(NULL), stack(NULL) - { val.f = a; } + : type(t), valtype(VAL_FLOAT), flags(flags), name(n), code(NULL), stack(NULL) { + val.f = a; } ident(int t, const char *n, int flags) - : type(t), valtype(VAL_NULL), flags(flags), name(n), code(NULL), stack(NULL) - {} + : type(t), valtype(VAL_NULL), flags(flags), name(n), code(NULL), stack(NULL) { + } ident(int t, const char *n, const tagval &v, int flags) - : type(t), valtype(v.type), flags(flags), name(n), code(NULL), stack(NULL) - { val = v; } + : type(t), valtype(v.type), flags(flags), name(n), code(NULL), stack(NULL) { + val = v; } // ID_COMMAND ident(int t, const char *n, const char *args, uint argmask, int numargs, void *f = NULL, int flags = 0) - : type(t), numargs(numargs), flags(flags), name(n), args(args), argmask(argmask), fun((identfun)f) - {} - + : type(t), numargs(numargs), flags(flags), name(n), args(args), argmask(argmask), fun((identfun)f) { + } void changed() { if(fun) fun(); } - - void setval(const tagval &v) - { + void setval(const tagval &v) { valtype = v.type; val = v; } - - void setval(const identstack &v) - { + void setval(const identstack &v) { valtype = v.valtype; val = v.val; } - - void forcenull() - { + void forcenull() { if(valtype==VAL_STR) delete[] val.s; valtype = VAL_NULL; } - float getfloat() const; int getint() const; const char *getstr() const; @@ -200,13 +173,11 @@ extern void stringret(char *s); extern void result(tagval &v); extern void result(const char *s); -static inline int parseint(const char *s) -{ +static inline int parseint(const char *s) { return int(strtoul(s, NULL, 0)); } -static inline float parsefloat(const char *s) -{ +static inline float parsefloat(const char *s) { // not all platforms (windows) can parse hexadecimal integers via strtod char *end; double val = strtod(s, &end); @@ -216,10 +187,8 @@ static inline float parsefloat(const char *s) static inline void intformat(char *buf, int v, int len = 20) { nformatstring(buf, len, "%d", v); } static inline void floatformat(char *buf, float v, int len = 20) { nformatstring(buf, len, v==int(v) ? "%.1f" : "%.6g", v); } -static inline const char *getstr(const identval &v, int type) -{ - switch(type) - { +static inline const char *getstr(const identval &v, int type) { + switch(type) { case VAL_STR: case VAL_MACRO: return v.s; case VAL_INT: return intstr(v.i); case VAL_FLOAT: return floatstr(v.f); @@ -229,10 +198,8 @@ static inline const char *getstr(const identval &v, int type) inline const char *tagval::getstr() const { return ::getstr(*this, type); } inline const char *ident::getstr() const { return ::getstr(val, valtype); } -static inline int getint(const identval &v, int type) -{ - switch(type) - { +static inline int getint(const identval &v, int type) { + switch(type) { case VAL_INT: return v.i; case VAL_FLOAT: return int(v.f); case VAL_STR: case VAL_MACRO: return parseint(v.s); @@ -242,10 +209,8 @@ static inline int getint(const identval &v, int type) inline int tagval::getint() const { return ::getint(*this, type); } inline int ident::getint() const { return ::getint(val, valtype); } -static inline float getfloat(const identval &v, int type) -{ - switch(type) - { +static inline float getfloat(const identval &v, int type) { + switch(type) { case VAL_FLOAT: return v.f; case VAL_INT: return float(v.i); case VAL_STR: case VAL_MACRO: return parsefloat(v.s); @@ -255,10 +220,8 @@ static inline float getfloat(const identval &v, int type) inline float tagval::getfloat() const { return ::getfloat(*this, type); } inline float ident::getfloat() const { return ::getfloat(val, valtype); } -inline void ident::getval(tagval &v) const -{ - switch(valtype) - { +inline void ident::getval(tagval &v) const { + switch(valtype) { case VAL_STR: case VAL_MACRO: v.setstr(newstring(val.s)); break; case VAL_INT: v.setint(val.i); break; case VAL_FLOAT: v.setfloat(val.f); break; @@ -325,8 +288,7 @@ inline void ident::getval(tagval &v) const #define SVARFR(name, cur, body) _SVARF(name, name, cur, body, IDF_OVERRIDE) // anonymous inline commands, uses nasty template trick with line numbers to keep names unique -#define ICOMMANDNS(name, cmdname, nargs, proto, b) template struct cmdname; template<> struct cmdname<__LINE__> { static bool init; static void run proto; }; bool cmdname<__LINE__>::init = addcommand(name, (identfun)cmdname<__LINE__>::run, nargs); void cmdname<__LINE__>::run proto \ - { b; } +#define ICOMMANDNS(name, cmdname, nargs, proto, b) template struct cmdname; template<> struct cmdname<__LINE__> { static bool init; static void run proto; }; bool cmdname<__LINE__>::init = addcommand(name, (identfun)cmdname<__LINE__>::run, nargs); void cmdname<__LINE__>::run proto { b; } #define ICOMMANDN(name, cmdname, nargs, proto, b) ICOMMANDNS(#name, cmdname, nargs, proto, b) #define ICOMMANDNAME(name) _icmd_##name #define ICOMMAND(name, nargs, proto, b) ICOMMANDN(name, ICOMMANDNAME(name), nargs, proto, b) diff --git a/src/shared/crypto.cpp b/src/shared/crypto.cpp index fd0a950..3b56904 100644 --- a/src/shared/crypto.cpp +++ b/src/shared/crypto.cpp @@ -9,39 +9,27 @@ #define TIGER_PASSES 3 -namespace tiger -{ +namespace tiger { typedef unsigned long long int chunk; - - union hashval - { + union hashval { uchar bytes[3*8]; chunk chunks[3]; }; - chunk sboxes[4*256]; - - void compress(const chunk *str, chunk state[3]) - { + void compress(const chunk *str, chunk state[3]) { chunk a, b, c; chunk aa, bb, cc; chunk x0, x1, x2, x3, x4, x5, x6, x7; - a = state[0]; b = state[1]; c = state[2]; - x0=str[0]; x1=str[1]; x2=str[2]; x3=str[3]; x4=str[4]; x5=str[5]; x6=str[6]; x7=str[7]; - aa = a; bb = b; cc = c; - - loop(pass_no, TIGER_PASSES) - { - if(pass_no) - { + loop(pass_no, TIGER_PASSES) { + if(pass_no) { x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5ULL; x1 ^= x0; x2 += x1; x3 -= x2 ^ ((~x1)<<19); x4 ^= x3; x5 += x4; x6 -= x5 ^ ((~x4)>>23); x7 ^= x6; x0 += x7; x1 -= x0 ^ ((~x7)<<19); x2 ^= x1; x3 += x2; @@ -60,85 +48,63 @@ namespace tiger b += sb4[((c)>>(1*8))&0xFF] ^ sb3[((c)>>(3*8))&0xFF] ^ \ sb2[((c)>>(5*8))&0xFF] ^ sb1[((c)>>(7*8))&0xFF] ; \ b *= mul; - uint mul = !pass_no ? 5 : (pass_no==1 ? 7 : 9); round(a, b, c, x0) round(b, c, a, x1) round(c, a, b, x2) round(a, b, c, x3) round(b, c, a, x4) round(c, a, b, x5) round(a, b, c, x6) round(b, c, a, x7) - chunk tmp = a; a = c; c = b; b = tmp; } - a ^= aa; b -= bb; c += cc; - state[0] = a; state[1] = b; state[2] = c; } - - void gensboxes() - { + void gensboxes() { const char *str = "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham"; chunk state[3] = { 0x0123456789ABCDEFULL, 0xFEDCBA9876543210ULL, 0xF096A5B4C3B2E187ULL }; uchar temp[64]; - if(!*(const uchar *)&islittleendian) loopj(64) temp[j^7] = str[j]; else loopj(64) temp[j] = str[j]; loopi(1024) loop(col, 8) ((uchar *)&sboxes[i])[col] = i&0xFF; - int abc = 2; - loop(pass, 5) loopi(256) for(int sb = 0; sb < 1024; sb += 256) - { + loop(pass, 5) loopi(256) for(int sb = 0; sb < 1024; sb += 256) { abc++; if(abc >= 3) { abc = 0; compress((chunk *)temp, state); } - loop(col, 8) - { + loop(col, 8) { uchar val = ((uchar *)&sboxes[sb+i])[col]; ((uchar *)&sboxes[sb+i])[col] = ((uchar *)&sboxes[sb + ((uchar *)&state[abc])[col]])[col]; ((uchar *)&sboxes[sb + ((uchar *)&state[abc])[col]])[col] = val; } } } - - void hash(const uchar *str, int length, hashval &val) - { + void hash(const uchar *str, int length, hashval &val) { static bool init = false; if(!init) { gensboxes(); init = true; } - uchar temp[65]; - val.chunks[0] = 0x0123456789ABCDEFULL; val.chunks[1] = 0xFEDCBA9876543210ULL; val.chunks[2] = 0xF096A5B4C3B2E187ULL; - int i = length; - for(; i >= 64; i -= 64, str += 64) - { - if(!*(const uchar *)&islittleendian) - { + for(; i >= 64; i -= 64, str += 64) { + if(!*(const uchar *)&islittleendian) { loopj(64) temp[j^7] = str[j]; compress((chunk *)temp, val.chunks); } else compress((chunk *)str, val.chunks); } - int j; - if(!*(const uchar *)&islittleendian) - { + if(!*(const uchar *)&islittleendian) { for(j = 0; j < i; j++) temp[j^7] = str[j]; temp[j^7] = 0x01; while(++j&7) temp[j^7] = 0; } - else - { + else { for(j = 0; j < i; j++) temp[j] = str[j]; temp[j] = 0x01; while(++j&7) temp[j] = 0; } - - if(j > 56) - { + if(j > 56) { while(j < 64) temp[j++] = 0; compress((chunk *)temp, val.chunks); j = 0; @@ -146,10 +112,8 @@ namespace tiger while(j < 56) temp[j++] = 0; *(chunk *)(temp+56) = (chunk)length<<3; compress((chunk *)temp, val.chunks); - if(!*(const uchar *)&islittleendian) - { - loopk(3) - { + if(!*(const uchar *)&islittleendian) { + loopk(3) { uchar *c = &val.bytes[k*sizeof(chunk)]; loopl(sizeof(chunk)/2) swap(c[l], c[sizeof(chunk)-1-l]); } @@ -162,28 +126,22 @@ namespace tiger #define BI_DIGIT_BITS 16 #define BI_DIGIT_MASK ((1< struct bigint -{ +template struct bigint { typedef ushort digit; typedef uint dbldigit; - int len; digit digits[BI_DIGITS]; - bigint() {} bigint(digit n) { if(n) { len = 1; digits[0] = n; } else len = 0; } bigint(const char *s) { parse(s); } template bigint(const bigint &y) { *this = y; } - - static int parsedigits(ushort *digits, int maxlen, const char *s) - { + static int parsedigits(ushort *digits, int maxlen, const char *s) { int slen = 0; while(isxdigit(s[slen])) slen++; int len = (slen+2*sizeof(ushort)-1)/(2*sizeof(ushort)); if(len>maxlen) return 0; memset(digits, 0, len*sizeof(ushort)); - loopi(slen) - { + loopi(slen) { int c = s[slen-i-1]; if(isalpha(c)) c = toupper(c) - 'A' + 10; else if(isdigit(c)) c -= '0'; @@ -192,29 +150,20 @@ template struct bigint } return len; } - - void parse(const char *s) - { + void parse(const char *s) { len = parsedigits(digits, BI_DIGITS, s); shrink(); } - void zero() { len = 0; } - - void print(stream *out) const - { + void print(stream *out) const { vector buf; printdigits(buf); out->write(buf.getbuf(), buf.length()); } - - void printdigits(vector &buf) const - { - loopi(len) - { + void printdigits(vector &buf) const { + loopi(len) { digit d = digits[len-i-1]; - loopj(BI_DIGIT_BITS/4) - { + loopj(BI_DIGIT_BITS/4) { uint shift = BI_DIGIT_BITS - (j+1)*4; int val = (d >> shift) & 0xF; if(val < 10) buf.add('0' + val); @@ -222,41 +171,30 @@ template struct bigint } } } - - template bigint &operator=(const bigint &y) - { + template bigint &operator=(const bigint &y) { len = y.len; memcpy(digits, y.digits, len*sizeof(digit)); return *this; } - bool iszero() const { return !len; } bool isone() const { return len==1 && digits[0]==1; } - - int numbits() const - { + int numbits() const { if(!len) return 0; int bits = len*BI_DIGIT_BITS; digit last = digits[len-1], mask = 1<<(BI_DIGIT_BITS-1); - while(mask) - { + while(mask) { if(last&mask) return bits; bits--; mask >>= 1; } return 0; } - bool hasbit(int n) const { return n/BI_DIGIT_BITS < len && ((digits[n/BI_DIGIT_BITS]>>(n%BI_DIGIT_BITS))&1); } - bool morebits(int n) const { return len > n/BI_DIGIT_BITS; } - - template bigint &add(const bigint &x, const bigint &y) - { + template bigint &add(const bigint &x, const bigint &y) { dbldigit carry = 0; int maxlen = max(x.len, y.len), i; - for(i = 0; i < y.len || carry; i++) - { + for(i = 0; i < y.len || carry; i++) { carry += (i < x.len ? (dbldigit)x.digits[i] : 0) + (i < y.len ? (dbldigit)y.digits[i] : 0); digits[i] = (digit)carry; carry >>= BI_DIGIT_BITS; @@ -266,14 +204,11 @@ template struct bigint return *this; } template bigint &add(const bigint &y) { return add(*this, y); } - - template bigint &sub(const bigint &x, const bigint &y) - { + template bigint &sub(const bigint &x, const bigint &y) { ASSERT(x >= y); dbldigit borrow = 0; int i; - for(i = 0; i < y.len || borrow; i++) - { + for(i = 0; i < y.len || borrow; i++) { borrow = (1<>BI_DIGIT_BITS)^1; @@ -284,31 +219,23 @@ template struct bigint return *this; } template bigint &sub(const bigint &y) { return sub(*this, y); } - void shrink() { while(len > 0 && !digits[len-1]) len--; } void shrinkdigits(int n) { len = n; shrink(); } void shrinkbits(int n) { shrinkdigits(n/BI_DIGIT_BITS); } - - template void copyshrinkdigits(const bigint &y, int n) - { + template void copyshrinkdigits(const bigint &y, int n) { len = clamp(y.len, 0, n); memcpy(digits, y.digits, len*sizeof(digit)); shrink(); } - template void copyshrinkbits(const bigint &y, int n) - { + template void copyshrinkbits(const bigint &y, int n) { copyshrinkdigits(y, n/BI_DIGIT_BITS); } - - template bigint &mul(const bigint &x, const bigint &y) - { + template bigint &mul(const bigint &x, const bigint &y) { if(!x.len || !y.len) { len = 0; return *this; } memset(digits, 0, y.len*sizeof(digit)); - loopi(x.len) - { + loopi(x.len) { dbldigit carry = 0; - loopj(y.len) - { + loopj(y.len) { carry += (dbldigit)x.digits[i] * (dbldigit)y.digits[j] + (dbldigit)digits[i+j]; digits[i+j] = (digit)carry; carry >>= BI_DIGIT_BITS; @@ -319,17 +246,14 @@ template struct bigint shrink(); return *this; } - - bigint &rshift(int n) - { + bigint &rshift(int n) { assert(len <= BI_DIGITS); if(!len || n<=0) return *this; if(n >= len*BI_DIGIT_BITS) { len = 0; return *this; } int dig = (n-1)/BI_DIGIT_BITS; n = ((n-1) % BI_DIGIT_BITS)+1; digit carry = digit(digits[dig]>>n); - for(int i = dig+1; i < len; i++) - { + for(int i = dig+1; i < len; i++) { digit tmp = digits[i]; digits[i-dig-1] = digit((tmp<<(BI_DIGIT_BITS-n)) | carry); carry = digit(tmp>>n); @@ -339,15 +263,12 @@ template struct bigint shrink(); return *this; } - - bigint &lshift(int n) - { + bigint &lshift(int n) { if(!len || n<=0) return *this; int dig = n/BI_DIGIT_BITS; n %= BI_DIGIT_BITS; digit carry = 0; - loopirev(len) - { + loopirev(len) { digit tmp = digits[i]; digits[i+dig] = digit((tmp<>(BI_DIGIT_BITS-n)); @@ -357,49 +278,36 @@ template struct bigint if(dig) memset(digits, 0, dig*sizeof(digit)); return *this; } - - void zerodigits(int i, int n) - { + void zerodigits(int i, int n) { memset(&digits[i], 0, n*sizeof(digit)); } - void zerobits(int i, int n) - { + void zerobits(int i, int n) { zerodigits(i/BI_DIGIT_BITS, n/BI_DIGIT_BITS); } - - template void copydigits(int to, const bigint &y, int from, int n) - { + template void copydigits(int to, const bigint &y, int from, int n) { int avail = clamp(y.len-from, 0, n); memcpy(&digits[to], &y.digits[from], avail*sizeof(digit)); if(avail < n) memset(&digits[to+avail], 0, (n-avail)*sizeof(digit)); } - template void copybits(int to, const bigint &y, int from, int n) - { + template void copybits(int to, const bigint &y, int from, int n) { copydigits(to/BI_DIGIT_BITS, y, from/BI_DIGIT_BITS, n/BI_DIGIT_BITS); } - - void dupdigits(int to, int from, int n) - { + void dupdigits(int to, int from, int n) { memcpy(&digits[to], &digits[from], n*sizeof(digit)); } - void dupbits(int to, int from, int n) - { + void dupbits(int to, int from, int n) { dupdigits(to/BI_DIGIT_BITS, from/BI_DIGIT_BITS, n/BI_DIGIT_BITS); } - - template bool operator==(const bigint &y) const - { + template bool operator==(const bigint &y) const { if(len!=y.len) return false; loopirev(len) if(digits[i]!=y.digits[i]) return false; return true; } template bool operator!=(const bigint &y) const { return !(*this==y); } - template bool operator<(const bigint &y) const - { + template bool operator<(const bigint &y) const { if(leny.len) return false; - loopirev(len) - { + loopirev(len) { if(digits[i]y.digits[i]) return false; } @@ -418,44 +326,31 @@ typedef bigint gfint; /* NIST prime Galois fields. * Currently only supports NIST P-192, where P=2^192-2^64-1, and P-256, where P=2^256-2^224+2^192+2^96-1. */ -struct gfield : gfint -{ +struct gfield : gfint { static const gfield P; - gfield() {} gfield(digit n) : gfint(n) {} gfield(const char *s) : gfint(s) {} - template gfield(const bigint &y) : gfint(y) {} - - template gfield &operator=(const bigint &y) - { + template gfield &operator=(const bigint &y) { gfint::operator=(y); return *this; } - - template gfield &add(const bigint &x, const bigint &y) - { + template gfield &add(const bigint &x, const bigint &y) { gfint::add(x, y); if(*this >= P) gfint::sub(*this, P); return *this; } template gfield &add(const bigint &y) { return add(*this, y); } - template gfield &mul2(const bigint &x) { return add(x, x); } gfield &mul2() { return mul2(*this); } - - gfield &div2() - { + gfield &div2() { if(hasbit(0)) gfint::add(*this, P); rshift(1); return *this; } - - template gfield &sub(const bigint &x, const bigint &y) - { - if(x < y) - { + template gfield &sub(const bigint &x, const bigint &y) { + if(x < y) { gfint tmp; /* necessary if this==&y, using this instead would clobber y */ tmp.add(x, P); gfint::sub(tmp, y); @@ -464,50 +359,37 @@ struct gfield : gfint return *this; } template gfield &sub(const bigint &y) { return sub(*this, y); } - - template gfield &neg(const bigint &x) - { + template gfield &neg(const bigint &x) { gfint::sub(P, x); return *this; } gfield &neg() { return neg(*this); } - template gfield &square(const bigint &x) { return mul(x, x); } gfield &square() { return square(*this); } - - template gfield &mul(const bigint &x, const bigint &y) - { + template gfield &mul(const bigint &x, const bigint &y) { bigint result; result.mul(x, y); reduce(result); return *this; } template gfield &mul(const bigint &y) { return mul(*this, y); } - - template void reduce(const bigint &result) - { + template void reduce(const bigint &result) { #if GF_BITS==192 // B = T + S1 + S2 + S3 mod p copyshrinkdigits(result, GF_DIGITS); // T - - if(result.morebits(192)) - { + if(result.morebits(192)) { gfield s; s.copybits(0, result, 192, 64); s.dupbits(64, 0, 64); s.shrinkbits(128); add(s); // S1 - - if(result.morebits(256)) - { + if(result.morebits(256)) { s.zerobits(0, 64); s.copybits(64, result, 256, 64); s.dupbits(128, 64, 64); s.shrinkdigits(GF_DIGITS); add(s); // S2 - - if(result.morebits(320)) - { + if(result.morebits(320)) { s.copybits(0, result, 320, 64); s.dupbits(64, 0, 64); s.dupbits(128, 0, 64); @@ -520,60 +402,49 @@ struct gfield : gfint #elif GF_BITS==256 // B = T + 2*S1 + 2*S2 + S3 + S4 - D1 - D2 - D3 - D4 mod p copyshrinkdigits(result, GF_DIGITS); // T - - if(result.morebits(256)) - { + if(result.morebits(256)) { gfield s; - if(result.morebits(352)) - { + if(result.morebits(352)) { s.zerobits(0, 96); s.copybits(96, result, 352, 160); s.shrinkdigits(GF_DIGITS); add(s); add(s); // S1 - - if(result.morebits(384)) - { + if(result.morebits(384)) { //s.zerobits(0, 96); s.copybits(96, result, 384, 128); s.shrinkbits(224); add(s); add(s); // S2 } } - s.copybits(0, result, 256, 96); s.zerobits(96, 96); s.copybits(192, result, 448, 64); s.shrinkdigits(GF_DIGITS); add(s); // S3 - s.copybits(0, result, 288, 96); s.copybits(96, result, 416, 96); s.dupbits(192, 96, 32); s.copybits(224, result, 256, 32); s.shrinkdigits(GF_DIGITS); add(s); // S4 - s.copybits(0, result, 352, 96); s.zerobits(96, 96); s.copybits(192, result, 256, 32); s.copybits(224, result, 320, 32); s.shrinkdigits(GF_DIGITS); sub(s); // D1 - s.copybits(0, result, 384, 128); //s.zerobits(128, 64); s.copybits(192, result, 288, 32); s.copybits(224, result, 352, 32); s.shrinkdigits(GF_DIGITS); sub(s); // D2 - s.copybits(0, result, 416, 96); s.copybits(96, result, 256, 96); s.zerobits(192, 32); s.copybits(224, result, 384, 32); s.shrinkdigits(GF_DIGITS); sub(s); // D3 - s.copybits(0, result, 448, 64); s.zerobits(64, 32); s.copybits(96, result, 288, 96); @@ -587,38 +458,29 @@ struct gfield : gfint #error Unsupported GF #endif } - - template gfield &pow(const bigint &x, const bigint &y) - { + template gfield &pow(const bigint &x, const bigint &y) { gfield a(x); if(y.hasbit(0)) *this = a; - else - { + else { len = 1; digits[0] = 1; if(!y.len) return *this; } - for(int i = 1, j = y.numbits(); i < j; i++) - { + for(int i = 1, j = y.numbits(); i < j; i++) { a.square(); if(y.hasbit(i)) mul(a); } return *this; } template gfield &pow(const bigint &y) { return pow(*this, y); } - - bool invert(const gfield &x) - { + bool invert(const gfield &x) { if(!x.len) return false; gfint u(x), v(P), A((gfint::digit)1), C((gfint::digit)0); - while(!u.iszero()) - { + while(!u.iszero()) { int ushift = 0, ashift = 0; - while(!u.hasbit(ushift)) - { + while(!u.hasbit(ushift)) { ushift++; - if(A.hasbit(ashift)) - { + if(A.hasbit(ashift)) { if(ashift) { A.rshift(ashift); ashift = 0; } A.add(P); } @@ -627,11 +489,9 @@ struct gfield : gfint if(ushift) u.rshift(ushift); if(ashift) A.rshift(ashift); int vshift = 0, cshift = 0; - while(!v.hasbit(vshift)) - { + while(!v.hasbit(vshift)) { vshift++; - if(C.hasbit(cshift)) - { + if(C.hasbit(cshift)) { if(cshift) { C.rshift(cshift); cshift = 0; } C.add(P); } @@ -639,14 +499,12 @@ struct gfield : gfint } if(vshift) v.rshift(vshift); if(cshift) C.rshift(cshift); - if(u >= v) - { + if(u >= v) { u.sub(v); if(A < C) A.add(P); A.sub(C); } - else - { + else { v.sub(v, u); if(C < A) C.add(P); C.sub(A); @@ -658,9 +516,7 @@ struct gfield : gfint return true; } void invert() { invert(*this); } - - template static int legendre(const bigint &x) - { + template static int legendre(const bigint &x) { static const gfint Psub1div2(gfint(P).sub(bigint<1>(1)).rshift(1)); gfield L; L.pow(x, Psub1div2); @@ -669,17 +525,14 @@ struct gfield : gfint return -1; } int legendre() const { return legendre(*this); } - - bool sqrt(const gfield &x) - { + bool sqrt(const gfield &x) { if(!x.len) { len = 0; return true; } #if GF_BITS==224 #error Unsupported GF #else ASSERT((P.digits[0]%4)==3); static const gfint Padd1div4(gfint(P).add(bigint<1>(1)).rshift(2)); - switch(legendre(x)) - { + switch(legendre(x)) { case 0: len = 0; return true; case -1: return false; default: pow(x, Padd1div4); return true; @@ -689,20 +542,15 @@ struct gfield : gfint bool sqrt() { return sqrt(*this); } }; -struct ecjacobian -{ +struct ecjacobian { static const gfield B; static const ecjacobian base; static const ecjacobian origin; - gfield x, y, z; - ecjacobian() {} ecjacobian(const gfield &x, const gfield &y) : x(x), y(y), z(bigint<1>(1)) {} ecjacobian(const gfield &x, const gfield &y, const gfield &z) : x(x), y(y), z(z) {} - - void mul2() - { + void mul2() { if(z.iszero()) return; else if(y.iszero()) { *this = origin; return; } gfield a, b, c, d; @@ -717,24 +565,20 @@ struct ecjacobian a.square(b).add(a); y.sub(d, x).mul(c).sub(a); } - - void add(const ecjacobian &q) - { + void add(const ecjacobian &q) { if(q.z.iszero()) return; else if(z.iszero()) { *this = q; return; } gfield a, b, c, d, e, f; a.square(z); b.mul(q.y, a).mul(z); a.mul(q.x); - if(q.z.isone()) - { + if(q.z.isone()) { c.add(x, a); d.add(y, b); a.sub(x, a); b.sub(y, b); } - else - { + else { f.mul(y, e.square(q.z)).mul(q.z); e.mul(x); c.add(e, a); @@ -748,20 +592,15 @@ struct ecjacobian x.square(b).sub(f.mul(c, e.square(a))); y.sub(f, x).sub(x).mul(b).sub(e.mul(a).mul(d)).div2(); } - - template void mul(const ecjacobian &p, const bigint &q) - { + template void mul(const ecjacobian &p, const bigint &q) { *this = origin; - loopirev(q.numbits()) - { + loopirev(q.numbits()) { mul2(); if(q.hasbit(i)) add(p); } } template void mul(const bigint &q) { ecjacobian tmp(*this); mul(tmp, q); } - - void normalize() - { + void normalize() { if(z.iszero() || z.isone()) return; gfield tmp; z.invert(); @@ -770,25 +609,19 @@ struct ecjacobian y.mul(tmp).mul(z); z = bigint<1>(1); } - - bool calcy(bool ybit) - { + bool calcy(bool ybit) { gfield y2, tmp; y2.square(x).mul(x).sub(tmp.add(x, x).add(x)).add(B); if(!y.sqrt(y2)) { y.zero(); return false; } if(y.hasbit(0) != ybit) y.neg(); return true; } - - void print(vector &buf) - { + void print(vector &buf) { normalize(); buf.add(y.hasbit(0) ? '-' : '+'); x.printdigits(buf); } - - void parse(const char *s) - { + void parse(const char *s) { bool ybit = *s++ == '-'; x.parse(s); calcy(ybit); @@ -837,8 +670,7 @@ const ecjacobian ecjacobian::base( #error Unsupported GF #endif -void calcpubkey(gfint privkey, vector &pubstr) -{ +void calcpubkey(gfint privkey, vector &pubstr) { ecjacobian c(ecjacobian::base); c.mul(privkey); c.normalize(); @@ -846,8 +678,7 @@ void calcpubkey(gfint privkey, vector &pubstr) pubstr.add('\0'); } -bool calcpubkey(const char *privstr, vector &pubstr) -{ +bool calcpubkey(const char *privstr, vector &pubstr) { if(!privstr[0]) return false; gfint privkey; privkey.parse(privstr); @@ -855,8 +686,7 @@ bool calcpubkey(const char *privstr, vector &pubstr) return true; } -void genprivkey(const char *seed, vector &privstr, vector &pubstr) -{ +void genprivkey(const char *seed, vector &privstr, vector &pubstr) { tiger::hashval hash; tiger::hash((const uchar *)seed, (int)strlen(seed), hash); bigint<8*sizeof(hash.bytes)/BI_DIGIT_BITS> privkey; @@ -865,17 +695,14 @@ void genprivkey(const char *seed, vector &privstr, vector &pubstr) privkey.shrink(); privkey.printdigits(privstr); privstr.add('\0'); - calcpubkey(privkey, pubstr); } -bool hashstring(const char *str, char *result, int maxlen) -{ +bool hashstring(const char *str, char *result, int maxlen) { tiger::hashval hv; if(maxlen < 2*(int)sizeof(hv.bytes) + 1) return false; tiger::hash((uchar *)str, strlen(str), hv); - loopi(sizeof(hv.bytes)) - { + loopi(sizeof(hv.bytes)) { uchar c = hv.bytes[i]; *result++ = "0123456789abcdef"[c&0xF]; *result++ = "0123456789abcdef"[c>>4]; @@ -884,8 +711,7 @@ bool hashstring(const char *str, char *result, int maxlen) return true; } -void answerchallenge(const char *privstr, const char *challenge, vector &answerstr) -{ +void answerchallenge(const char *privstr, const char *challenge, vector &answerstr) { gfint privkey; privkey.parse(privstr); ecjacobian answer; @@ -896,48 +722,39 @@ void answerchallenge(const char *privstr, const char *challenge, vector &a answerstr.add('\0'); } -void *parsepubkey(const char *pubstr) -{ +void *parsepubkey(const char *pubstr) { ecjacobian *pubkey = new ecjacobian; pubkey->parse(pubstr); return pubkey; } -void freepubkey(void *pubkey) -{ +void freepubkey(void *pubkey) { delete (ecjacobian *)pubkey; } -void *genchallenge(void *pubkey, const void *seed, int seedlen, vector &challengestr) -{ +void *genchallenge(void *pubkey, const void *seed, int seedlen, vector &challengestr) { tiger::hashval hash; tiger::hash((const uchar *)seed, seedlen, hash); gfint challenge; memcpy(challenge.digits, hash.bytes, sizeof(hash.bytes)); challenge.len = 8*sizeof(hash.bytes)/BI_DIGIT_BITS; challenge.shrink(); - ecjacobian answer(*(ecjacobian *)pubkey); answer.mul(challenge); answer.normalize(); - ecjacobian secret(ecjacobian::base); secret.mul(challenge); secret.normalize(); - secret.print(challengestr); challengestr.add('\0'); - return new gfield(answer.x); } -void freechallenge(void *answer) -{ +void freechallenge(void *answer) { delete (gfint *)answer; } -bool checkchallenge(const char *answerstr, void *correct) -{ +bool checkchallenge(const char *answerstr, void *correct) { gfint answer(answerstr); return answer == *(gfint *)correct; } diff --git a/src/shared/cube2font.c b/src/shared/cube2font.c index 75ea8ff..bbd8878 100644 --- a/src/shared/cube2font.c +++ b/src/shared/cube2font.c @@ -16,8 +16,8 @@ typedef unsigned int uint; int imin(int a, int b) { return a < b ? a : b; } int imax(int a, int b) { return a > b ? a : b; } -void fatal(const char *fmt, ...) -{ +void fatal(const char *fmt, ...) { + va_list v; va_start(v, fmt); vfprintf(stderr, fmt, v); @@ -27,20 +27,20 @@ void fatal(const char *fmt, ...) exit(EXIT_FAILURE); } -uint bigswap(uint n) -{ +uint bigswap(uint n) { + const int islittleendian = 1; return *(const uchar *)&islittleendian ? (n<<24) | (n>>24) | ((n>>8)&0xFF00) | ((n<<8)&0xFF0000) : n; } -size_t writebig(FILE *f, uint n) -{ +size_t writebig(FILE *f, uint n) { + n = bigswap(n); return fwrite(&n, 1, sizeof(n), f); } -void writepngchunk(FILE *f, const char *type, uchar *data, uint len) -{ +void writepngchunk(FILE *f, const char *type, uchar *data, uint len) { + uint crc; writebig(f, len); fwrite(type, 1, 4, f); @@ -52,14 +52,14 @@ void writepngchunk(FILE *f, const char *type, uchar *data, uint len) writebig(f, crc); } -struct pngihdr -{ +struct pngihdr { + uint width, height; uchar bitdepth, colortype, compress, filter, interlace; }; -void savepng(const char *filename, uchar *data, int w, int h, int bpp, int flip) -{ +void savepng(const char *filename, uchar *data, int w, int h, int bpp, int flip) { + const uchar signature[] = { 137, 80, 78, 71, 13, 10, 26, 10 }; struct pngihdr ihdr; FILE *f; @@ -73,8 +73,8 @@ void savepng(const char *filename, uchar *data, int w, int h, int bpp, int flip) ihdr.width = bigswap(w); ihdr.height = bigswap(h); ihdr.bitdepth = 8; - switch(bpp) - { + switch(bpp) { + case 1: ihdr.colortype = 0; break; case 2: ihdr.colortype = 4; break; case 3: ihdr.colortype = 2; break; @@ -104,15 +104,15 @@ void savepng(const char *filename, uchar *data, int w, int h, int bpp, int flip) z.next_out = (Bytef *)buf; z.avail_out = sizeof(buf); - for(i = 0; i < h; i++) - { + for(i = 0; i < h; i++) { + uchar filter = 0; - for(j = 0; j < 2; j++) - { + for(j = 0; j < 2; j++) { + z.next_in = j ? (Bytef *)data + (flip ? h-i-1 : i)*w*bpp : (Bytef *)&filter; z.avail_in = j ? w*bpp : 1; - while(z.avail_in > 0) - { + while(z.avail_in > 0) { + if(deflate(&z, Z_NO_FLUSH) != Z_OK) goto cleanuperror; #define FLUSHZ do { \ int flush = sizeof(buf) - z.avail_out; \ @@ -127,8 +127,8 @@ void savepng(const char *filename, uchar *data, int w, int h, int bpp, int flip) } } - for(;;) - { + for(;;) { + int err = deflate(&z, Z_FINISH); if(err != Z_OK && err != Z_STREAM_END) goto cleanuperror; FLUSHZ; @@ -156,8 +156,8 @@ error: fatal("cube2font: failed saving PNG to %s", filename); } -enum -{ +enum { + CT_PRINT = 1<<0, CT_SPACE = 1<<1, CT_DIGIT = 1<<2, @@ -183,8 +183,8 @@ enum U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, \ U, U, U, U, u, u, u, u, u, u, u, u, u, u, u, u, \ u, u, u, u, u, u, u, u, u, u, u, u, u, u, U, u -const uchar cubectype[256] = -{ +const uchar cubectype[256] = { + CUBECTYPE(CT_SPACE, CT_PRINT, CT_PRINT|CT_DIGIT, @@ -199,8 +199,8 @@ int iscubealpha(uchar c) { return cubectype[c]&CT_ALPHA; } int iscubealnum(uchar c) { return cubectype[c]&(CT_ALPHA|CT_DIGIT); } int iscubelower(uchar c) { return cubectype[c]&CT_LOWER; } int iscubeupper(uchar c) { return cubectype[c]&CT_UPPER; } -const int cube2unichars[256] = -{ +const int cube2unichars[256] = { + 0, 192, 193, 194, 195, 196, 197, 198, 199, 9, 10, 11, 12, 13, 200, 201, 202, 203, 204, 205, 206, 207, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, @@ -218,13 +218,13 @@ const int cube2unichars[256] = 0x42C, 0x42D, 0x42E, 0x42F, 0x431, 0x432, 0x433, 0x434, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43F, 0x442, 0x444, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x454, 0x490, 0x491 }; -int cube2uni(uchar c) -{ +int cube2uni(uchar c) { + return cube2unichars[c]; } -const char *encodeutf8(int uni) -{ +const char *encodeutf8(int uni) { + static char buf[7]; char *dst = buf; if(uni <= 0x7F) { *dst++ = uni; goto uni1; } @@ -247,41 +247,41 @@ struct fontchar { int code, uni, tex, x, y, w, h, offx, offy, offset, advance; F const char *texdir = ""; -const char *texfilename(const char *name, int texnum) -{ +const char *texfilename(const char *name, int texnum) { + static char file[256]; snprintf(file, sizeof(file), "%s%d.png", name, texnum); return file; } -const char *texname(const char *name, int texnum) -{ +const char *texname(const char *name, int texnum) { + static char file[512]; snprintf(file, sizeof(file), "%s%s", texdir, texfilename(name, texnum)); return file; } -void writetexs(const char *name, struct fontchar *chars, int numchars, int numtexs, int tw, int th) -{ +void writetexs(const char *name, struct fontchar *chars, int numchars, int numtexs, int tw, int th) { + int tex; uchar *pixels = (uchar *)malloc(tw*th*2); if(!pixels) fatal("cube2font: failed allocating textures"); - for(tex = 0; tex < numtexs; tex++) - { + for(tex = 0; tex < numtexs; tex++) { + const char *file = texfilename(name, tex); int texchars = 0, i; uchar *dst, *src; memset(pixels, 0, tw*th*2); - for(i = 0; i < numchars; i++) - { + for(i = 0; i < numchars; i++) { + struct fontchar *c = &chars[i]; int x, y; if(c->tex != tex) continue; texchars++; dst = &pixels[2*((c->y + c->offy - c->color->top)*tw + c->x + c->color->left - c->offx)]; src = (uchar *)c->color->bitmap.buffer; - for(y = 0; y < c->color->bitmap.rows; y++) - { + for(y = 0; y < c->color->bitmap.rows; y++) { + for(x = 0; x < c->color->bitmap.width; x++) dst[2*x] = src[x]; src += c->color->bitmap.pitch; @@ -289,8 +289,8 @@ void writetexs(const char *name, struct fontchar *chars, int numchars, int numte } dst = &pixels[2*((c->y + c->offy - c->alpha->top)*tw + c->x + c->alpha->left - c->offx)]; src = (uchar *)c->alpha->bitmap.buffer; - for(y = 0; y < c->alpha->bitmap.rows; y++) - { + for(y = 0; y < c->alpha->bitmap.rows; y++) { + for(x = 0; x < c->alpha->bitmap.width; x++) dst[2*x+1] = src[x]; src += c->alpha->bitmap.pitch; @@ -303,8 +303,8 @@ void writetexs(const char *name, struct fontchar *chars, int numchars, int numte free(pixels); } -void writecfg(const char *name, struct fontchar *chars, int numchars, int x1, int y1, int x2, int y2, int sw, int sh, int argc, char **argv) -{ +void writecfg(const char *name, struct fontchar *chars, int numchars, int x1, int y1, int x2, int y2, int sw, int sh, int argc, char **argv) { + FILE *f; char file[256]; int i, lastcode = 0, lasttex = 0; @@ -317,24 +317,24 @@ void writecfg(const char *name, struct fontchar *chars, int numchars, int x1, in fprintf(f, " %s", argv[i]); fprintf(f, "\n"); fprintf(f, "font \"%s\" \"%s\" %d %d\n", name, texname(name, 0), sw, sh); - for(i = 0; i < numchars; i++) - { + for(i = 0; i < numchars; i++) { + struct fontchar *c = &chars[i]; - if(!lastcode && lastcode < c->code) - { + if(!lastcode && lastcode < c->code) { + fprintf(f, "fontoffset \"%s\"\n", encodeutf8(c->uni)); lastcode = c->code; } - else if(lastcode < c->code) - { + else if(lastcode < c->code) { + if(lastcode + 1 == c->code) fprintf(f, "fontskip // %d\n", lastcode); else fprintf(f, "fontskip %d // %d .. %d\n", c->code - lastcode, lastcode, c->code-1); lastcode = c->code; } - if(lasttex != c->tex) - { + if(lasttex != c->tex) { + fprintf(f, "\nfonttex \"%s\"\n", texname(name, c->tex)); lasttex = c->tex; } @@ -347,10 +347,10 @@ void writecfg(const char *name, struct fontchar *chars, int numchars, int x1, in fclose(f); } -int groupchar(int c) -{ - switch(c) - { +int groupchar(int c) { + + switch(c) { + case 0x152: case 0x153: case 0x178: return 1; } if(c < 127 || c >= 0x2000) return 0; @@ -359,8 +359,8 @@ int groupchar(int c) return 3; } -int sortchars(const void *x, const void *y) -{ +int sortchars(const void *x, const void *y) { + const struct fontchar *xc = *(const struct fontchar **)x, *yc = *(const struct fontchar **)y; int xg = groupchar(xc->uni), yg = groupchar(yc->uni); if(xg < yg) return -1; @@ -370,16 +370,16 @@ int sortchars(const void *x, const void *y) return yc->uni - xc->uni; } -int scorechar(struct fontchar *f, int pad, int tw, int th, int rw, int rh, int ry) -{ +int scorechar(struct fontchar *f, int pad, int tw, int th, int rw, int rh, int ry) { + int score = 0; if(rw + f->w > tw) { ry += rh + pad; score = 1; } if(ry + f->h > th) score = 2; return score; } -int main(int argc, char **argv) -{ +int main(int argc, char **argv) { + FT_Library l; FT_Face f; FT_Stroker s, s2; @@ -411,8 +411,8 @@ int main(int argc, char **argv) fatal("cube2font: failed loading font %s", argv[1]); if(outborder > 0) FT_Stroker_Set(s, (FT_Fixed)(outborder * 64), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); if(inborder > 0) FT_Stroker_Set(s2, (FT_Fixed)(inborder * 64), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); - for(c = 0; c < 256; c++) if(iscubeprint(c)) - { + for(c = 0; c < 256; c++) if(iscubeprint(c)) { + FT_Glyph p, p2; FT_BitmapGlyph b, b2; struct fontchar *dst = &chars[numchars]; @@ -443,38 +443,38 @@ int main(int argc, char **argv) order[numchars++] = dst; } qsort(order, numchars, sizeof(order[0]), sortchars); - for(i = 0; i < numchars;) - { + for(i = 0; i < numchars;) { + struct fontchar *dst; int j, k, trial0, prevscore, dstscore, fitscore; - for(trial0 = trial, prevscore = -1; (trial -= 2) >= trial0-512;) - { + for(trial0 = trial, prevscore = -1; (trial -= 2) >= trial0-512;) { + int g, fw = rw, fh = rh, fy = ry, curscore = 0, reused = 0; - for(j = i; j < numchars; j++) - { + for(j = i; j < numchars; j++) { + dst = order[j]; if(dst->tex >= 0 || dst->tex <= trial) continue; g = groupchar(dst->uni); dstscore = scorechar(dst, pad, tw, th, fw, fh, fy); - for(k = j; k < numchars; k++) - { + for(k = j; k < numchars; k++) { + struct fontchar *fit = order[k]; if(fit->tex >= 0 || fit->tex <= trial) continue; if(fit->tex >= trial0 && groupchar(fit->uni) != g) break; fitscore = scorechar(fit, pad, tw, th, fw, fh, fy); - if(fitscore < dstscore || (fitscore == dstscore && fit->h > dst->h)) - { + if(fitscore < dstscore || (fitscore == dstscore && fit->h > dst->h)) { + dst = fit; dstscore = fitscore; } } - if(fw + dst->w > tw) - { + if(fw + dst->w > tw) { + fy += fh + pad; fw = fh = 0; } - if(fy + dst->h > th) - { + if(fy + dst->h > th) { + fy = fw = fh = 0; if(curscore > 0) break; } @@ -488,30 +488,30 @@ int main(int argc, char **argv) if(reused < prevscore || curscore <= prevscore) break; prevscore = curscore; } - for(; i < numchars; i++) - { + for(; i < numchars; i++) { + dst = order[i]; if(dst->tex >= 0) continue; dstscore = scorechar(dst, pad, tw, th, rw, rh, ry); - for(j = i; j < numchars; j++) - { + for(j = i; j < numchars; j++) { + struct fontchar *fit = order[j]; if(fit->tex < trial || fit->tex > trial+2) continue; fitscore = scorechar(fit, pad, tw, th, rw, rh, ry); - if(fitscore < dstscore || (fitscore == dstscore && fit->h > dst->h)) - { + if(fitscore < dstscore || (fitscore == dstscore && fit->h > dst->h)) { + dst = fit; dstscore = fitscore; } } if(dst->tex < trial || dst->tex > trial+2) break; - if(rw + dst->w > tw) - { + if(rw + dst->w > tw) { + ry += rh + pad; rw = rh = 0; } - if(ry + dst->h > th) - { + if(ry + dst->h > th) { + ry = rw = rh = 0; numtex++; } @@ -531,8 +531,8 @@ int main(int argc, char **argv) } if(rh > 0) numtex++; #if 0 - if(sw <= 0) - { + if(sw <= 0) { + if(FT_Load_Char(f, ' ', FT_LOAD_DEFAULT)) fatal("cube2font: failed loading space character"); sw = (f->glyph->advance.x+0x3F)>>6; @@ -542,8 +542,8 @@ int main(int argc, char **argv) if(sw <= 0) sw = sh/3; writetexs(argv[2], chars, numchars, numtex, tw, th); writecfg(argv[2], chars, numchars, x1, y1, x2, y2, sw, sh, argc, argv); - for(i = 0; i < numchars; i++) - { + for(i = 0; i < numchars; i++) { + if(chars[i].alpha != chars[i].color) FT_Done_Glyph((FT_Glyph)chars[i].alpha); FT_Done_Glyph((FT_Glyph)chars[i].color); } diff --git a/src/shared/ents.h b/src/shared/ents.h index 3ceccf4..6b1dfca 100644 --- a/src/shared/ents.h +++ b/src/shared/ents.h @@ -5,24 +5,21 @@ enum { ET_EMPTY=0, ET_LIGHT, ET_MAPMODEL, ET_PLAYERSTART, ET_PARTICLES, ET_SOUND, ET_SPOTLIGHT, ET_GAMESPECIFIC }; -struct entity // persistent map entity -{ +// persistent map entity +struct entity { vec o; // position short attr1, attr2, attr3, attr4, attr5; uchar type; // type is one of the above uchar reserved; }; -struct entitylight -{ +struct entitylight { vec color, dir; int millis; - entitylight() : color(1, 1, 1), dir(0, 0, 1), millis(-1) {} }; -enum -{ +enum { EF_NOVIS = 1<<0, EF_NOSHADOW = 1<<1, EF_NOCOLLIDE = 1<<2, @@ -34,19 +31,16 @@ enum EF_NOPICKUP = 1<<8 }; -struct extentity : entity // part of the entity that doesn't get saved to disk -{ +// part of the entity that doesn't get saved to disk +struct extentity : entity { int flags; // the only dynamic state of a map entity entitylight light; extentity *attached; - extentity() : flags(0), attached(NULL) {} - bool spawned() const { return (flags&EF_SPAWNED) != 0; } void setspawned(bool val) { if(val) flags |= EF_SPAWNED; else flags &= ~EF_SPAWNED; } void setspawned() { flags |= EF_SPAWNED; } void clearspawned() { flags &= ~EF_SPAWNED; } - bool nopickup() const { return (flags&EF_NOPICKUP) != 0; } void setnopickup(bool val) { if(val) flags |= EF_NOPICKUP; else flags &= ~EF_NOPICKUP; } void setnopickup() { flags |= EF_NOPICKUP; } @@ -65,8 +59,7 @@ enum { ENT_PLAYER = 0, ENT_AI, ENT_INANIMATE, ENT_CAMERA, ENT_BOUNCE }; enum { COLLIDE_NONE = 0, COLLIDE_ELLIPSE, COLLIDE_OBB, COLLIDE_ELLIPSE_PRECISE }; -struct physent // base entity type, can be affected by physics -{ +struct physent { // base entity type, can be affected by physics { vec o, vel, falling; // origin, velocity vec deltapos, newpos; // movement interpolation float yaw, pitch, roll; @@ -74,34 +67,26 @@ struct physent // base entity type, can be affected by physics float radius, eyeheight, aboveeye; // bounding box size float xradius, yradius, zmargin; vec floor; // the normal of floor the dynent is on - ushort timeinair; uchar inwater; bool jumping; schar move, strafe; - uchar physstate; // one of PHYS_* above uchar state, editstate; // one of CS_* above uchar type; // one of ENT_* above uchar collidetype; // one of COLLIDE_* above - bool blocked; // used by physics to signal ai - physent() : o(0, 0, 0), deltapos(0, 0, 0), newpos(0, 0, 0), yaw(0), pitch(0), roll(0), maxspeed(100), radius(4.1f), eyeheight(14), aboveeye(1), xradius(4.1f), yradius(4.1f), zmargin(0), state(CS_ALIVE), editstate(CS_ALIVE), type(ENT_PLAYER), collidetype(COLLIDE_ELLIPSE), blocked(false) - { reset(); } - - void resetinterp() - { + { reset(); } + void resetinterp() { newpos = o; deltapos = vec(0, 0, 0); } - - void reset() - { + void reset() { inwater = 0; timeinair = 0; jumping = false; @@ -110,15 +95,12 @@ struct physent // base entity type, can be affected by physics vel = falling = vec(0, 0, 0); floor = vec(0, 0, 1); } - vec feetpos(float offset = 0) const { return vec(o).add(vec(0, 0, offset - eyeheight)); } vec headpos(float offset = 0) const { return vec(o).add(vec(0, 0, offset)); } - bool maymove() const { return timeinair || physstate < PHYS_FLOOR || vel.squaredlen() > 1e-4f || deltapos.squaredlen() > 1e-4f; } }; -enum -{ +enum { ANIM_DEAD = 0, ANIM_DYING, ANIM_IDLE, ANIM_FORWARD, ANIM_BACKWARD, ANIM_LEFT, ANIM_RIGHT, ANIM_HOLD1, ANIM_HOLD2, ANIM_HOLD3, ANIM_HOLD4, ANIM_HOLD5, ANIM_HOLD6, ANIM_HOLD7, @@ -132,8 +114,7 @@ enum NUMANIMS }; -static const char * const animnames[] = -{ +static const char * const animnames[] = { "dead", "dying", "idle", "forward", "backward", "left", "right", "hold 1", "hold 2", "hold 3", "hold 4", "hold 5", "hold 6", "hold 7", @@ -166,26 +147,20 @@ static const char * const animnames[] = #define ANIM_GHOST (1<<30) #define ANIM_FLAGS (0x1FF<<22) -struct animinfo // description of a character's animation -{ +struct animinfo { // description of a character's animation { int anim, frame, range, basetime; float speed; uint varseed; - animinfo() : anim(0), frame(0), range(0), basetime(0), speed(100.0f), varseed(0) { } - bool operator==(const animinfo &o) const { return frame==o.frame && range==o.range && (anim&(ANIM_SETTIME|ANIM_DIR))==(o.anim&(ANIM_SETTIME|ANIM_DIR)) && (anim&ANIM_SETTIME || basetime==o.basetime) && speed==o.speed; } bool operator!=(const animinfo &o) const { return frame!=o.frame || range!=o.range || (anim&(ANIM_SETTIME|ANIM_DIR))!=(o.anim&(ANIM_SETTIME|ANIM_DIR)) || (!(anim&ANIM_SETTIME) && basetime!=o.basetime) || speed!=o.speed; } }; -struct animinterpinfo // used for animation blending of animated characters -{ +struct animinterpinfo { // used for animation blending of animated characters { animinfo prev, cur; int lastswitch; void *lastmodel; - animinterpinfo() : lastswitch(-1), lastmodel(NULL) {} - void reset() { lastswitch = -1; } }; @@ -194,44 +169,31 @@ struct animinterpinfo // used for animation blending of animated characters struct occludequery; struct ragdolldata; -struct dynent : physent // animated characters, or characters that can receive input -{ +struct dynent : physent { // animated characters, or characters that can receive input { bool k_left, k_right, k_up, k_down; // see input code - entitylight light; animinterpinfo animinterp[MAXANIMPARTS]; ragdolldata *ragdoll; occludequery *query; int lastrendered; uchar occluded; - - dynent() : ragdoll(NULL), query(NULL), lastrendered(0), occluded(0) - { + dynent() : ragdoll(NULL), query(NULL), lastrendered(0), occluded(0) { reset(); } - - ~dynent() - { + ~dynent() { #ifndef STANDALONE extern void cleanragdoll(dynent *d); if(ragdoll) cleanragdoll(this); #endif } - - void stopmoving() - { + void stopmoving() { k_left = k_right = k_up = k_down = jumping = false; move = strafe = 0; } - - void reset() - { + void reset() { physent::reset(); stopmoving(); loopi(MAXANIMPARTS) animinterp[i].reset(); } - vec abovehead() { return vec(o).add(vec(0, 0, aboveeye+4)); } }; - - diff --git a/src/shared/geom.cpp b/src/shared/geom.cpp index a5192e4..ad71841 100644 --- a/src/shared/geom.cpp +++ b/src/shared/geom.cpp @@ -4,15 +4,13 @@ static inline double det2x2(double a, double b, double c, double d) { return a*d - b*c; } static inline double det3x3(double a1, double a2, double a3, double b1, double b2, double b3, - double c1, double c2, double c3) -{ + double c1, double c2, double c3) { return a1 * det2x2(b2, b3, c2, c3) - b1 * det2x2(a2, a3, c2, c3) + c1 * det2x2(a2, a3, b2, b3); } -bool matrix4::invert(const matrix4 &m, double mindet) -{ +bool matrix4::invert(const matrix4 &m, double mindet) { double a1 = m.a.x, a2 = m.a.y, a3 = m.a.z, a4 = m.a.w, b1 = m.b.x, b2 = m.b.y, b3 = m.b.z, b4 = m.b.w, c1 = m.c.x, c2 = m.c.y, c3 = m.c.z, c4 = m.c.w, @@ -22,36 +20,28 @@ bool matrix4::invert(const matrix4 &m, double mindet) det3 = det3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4), det4 = -det3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4), det = a1*det1 + b1*det2 + c1*det3 + d1*det4; - if(fabs(det) < mindet) return false; - double invdet = 1/det; - a.x = det1 * invdet; a.y = det2 * invdet; a.z = det3 * invdet; a.w = det4 * invdet; - b.x = -det3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4) * invdet; b.y = det3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4) * invdet; b.z = -det3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4) * invdet; b.w = det3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4) * invdet; - c.x = det3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4) * invdet; c.y = -det3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4) * invdet; c.z = det3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4) * invdet; c.w = -det3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4) * invdet; - d.x = -det3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3) * invdet; d.y = det3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3) * invdet; d.z = -det3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3) * invdet; d.w = det3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3) * invdet; - return true; } -bool raysphereintersect(const vec ¢er, float radius, const vec &o, const vec &ray, float &dist) -{ +bool raysphereintersect(const vec ¢er, float radius, const vec &o, const vec &ray, float &dist) { vec c(center); c.sub(o); float v = c.dot(ray), @@ -63,17 +53,14 @@ bool raysphereintersect(const vec ¢er, float radius, const vec &o, const vec return true; } -bool rayboxintersect(const vec &b, const vec &s, const vec &o, const vec &ray, float &dist, int &orient) -{ - loop(d, 3) if(ray[d]) - { +bool rayboxintersect(const vec &b, const vec &s, const vec &o, const vec &ray, float &dist, int &orient) { + loop(d, 3) if(ray[d]) { int dc = ray[d]<0 ? 1 : 0; float pdist = (b[d]+s[d]*dc - o[d]) / ray[d]; vec v(ray); v.mul(pdist).add(o); if(v[R[d]] >= b[R[d]] && v[R[d]] <= b[R[d]]+s[R[d]] - && v[C[d]] >= b[C[d]] && v[C[d]] <= b[C[d]]+s[C[d]]) - { + && v[C[d]] >= b[C[d]] && v[C[d]] <= b[C[d]]+s[C[d]]) { dist = pdist; orient = 2*d+dc; return true; @@ -82,8 +69,7 @@ bool rayboxintersect(const vec &b, const vec &s, const vec &o, const vec &ray, f return false; } -bool linecylinderintersect(const vec &from, const vec &to, const vec &start, const vec &end, float radius, float &dist) -{ +bool linecylinderintersect(const vec &from, const vec &to, const vec &start, const vec &end, float radius, float &dist) { vec d(end), m(from), n(to); d.sub(start); m.sub(start); @@ -98,16 +84,14 @@ bool linecylinderintersect(const vec &from, const vec &to, const vec &start, con a = dd*nn - nd*nd, k = m.squaredlen() - radius*radius, c = dd*k - md*md; - if(fabs(a) < 0.005f) - { + if(fabs(a) < 0.005f) { if(c > 0) return false; if(md < 0) dist = -mn / nn; else if(md > dd) dist = (nd - mn) / nn; else dist = 0; return true; } - else if(c > 0) - { + else if(c > 0) { float b = dd*mn - nd*md, discrim = b*b - a*c; if(discrim < 0) return false; @@ -115,14 +99,12 @@ bool linecylinderintersect(const vec &from, const vec &to, const vec &start, con } else dist = 0; float offset = md + dist*nd; - if(offset < 0) - { + if(offset < 0) { if(nd <= 0) return false; dist = -md / nd; if(k + dist*(2*mn + dist*nn) > 0) return false; } - else if(offset > dd) - { + else if(offset > dd) { if(nd >= 0) return false; dist = (dd - md) / nd; if(k + dd - 2*md + dist*(2*(mn-nd) + dist*nn) > 0) return false; @@ -130,8 +112,7 @@ bool linecylinderintersect(const vec &from, const vec &to, const vec &start, con return dist >= 0 && dist <= 1; } -extern const vec2 sincos360[721] = -{ +extern const vec2 sincos360[721] = { vec2(1.00000000, 0.00000000), vec2(0.99984770, 0.01745241), vec2(0.99939083, 0.03489950), vec2(0.99862953, 0.05233596), vec2(0.99756405, 0.06975647), vec2(0.99619470, 0.08715574), // 0 vec2(0.99452190, 0.10452846), vec2(0.99254615, 0.12186934), vec2(0.99026807, 0.13917310), vec2(0.98768834, 0.15643447), vec2(0.98480775, 0.17364818), vec2(0.98162718, 0.19080900), // 6 vec2(0.97814760, 0.20791169), vec2(0.97437006, 0.22495105), vec2(0.97029573, 0.24192190), vec2(0.96592583, 0.25881905), vec2(0.96126170, 0.27563736), vec2(0.95630476, 0.29237170), // 12 diff --git a/src/shared/geom.h b/src/shared/geom.h index a0ef7c8..745ff37 100644 --- a/src/shared/geom.h +++ b/src/shared/geom.h @@ -1,48 +1,41 @@ struct vec; struct vec4; -struct vec2 -{ - union - { +struct vec2 { + union { struct { float x, y; }; float v[2]; }; - vec2() {} vec2(float x, float y) : x(x), y(y) {} explicit vec2(const vec &v); explicit vec2(const vec4 &v); - - float &operator[](int i) { return v[i]; } + float &operator[](int i) { return v[i]; } float operator[](int i) const { return v[i]; } - bool operator==(const vec2 &o) const { return x == o.x && y == o.y; } bool operator!=(const vec2 &o) const { return x != o.x || y != o.y; } - bool iszero() const { return x==0 && y==0; } - float dot(const vec2 &o) const { return x*o.x + y*o.y; } + float dot(const vec2 &o) const { return x*o.x + y*o.y; } float squaredlen() const { return dot(*this); } - float magnitude() const { return sqrtf(squaredlen()); } + float magnitude() const { return sqrtf(squaredlen()); } vec2 &normalize() { mul(1/magnitude()); return *this; } vec2 &safenormalize() { float m = magnitude(); if(m) mul(1/m); return *this; } float cross(const vec2 &o) const { return x*o.y - y*o.x; } - - vec2 &mul(float f) { x *= f; y *= f; return *this; } + vec2 &mul(float f) { x *= f; y *= f; return *this; } vec2 &mul(const vec2 &o) { x *= o.x; y *= o.y; return *this; } - vec2 &square() { mul(*this); return *this; } - vec2 &div(float f) { x /= f; y /= f; return *this; } + vec2 &square() { mul(*this); return *this; } + vec2 &div(float f) { x /= f; y /= f; return *this; } vec2 &div(const vec2 &o) { x /= o.x; y /= o.y; return *this; } vec2 &recip() { x = 1/x; y = 1/y; return *this; } - vec2 &add(float f) { x += f; y += f; return *this; } + vec2 &add(float f) { x += f; y += f; return *this; } vec2 &add(const vec2 &o) { x += o.x; y += o.y; return *this; } - vec2 &sub(float f) { x -= f; y -= f; return *this; } + vec2 &sub(float f) { x -= f; y -= f; return *this; } vec2 &sub(const vec2 &o) { x -= o.x; y -= o.y; return *this; } - vec2 &neg() { x = -x; y = -y; return *this; } + vec2 &neg() { x = -x; y = -y; return *this; } vec2 &min(const vec2 &o) { x = ::min(x, o.x); y = ::min(y, o.y); return *this; } vec2 &max(const vec2 &o) { x = ::max(x, o.x); y = ::max(y, o.y); return *this; } - vec2 &min(float f) { x = ::min(x, f); y = ::min(y, f); return *this; } - vec2 &max(float f) { x = ::max(x, f); y = ::max(y, f); return *this; } + vec2 &min(float f) { x = ::min(x, f); y = ::min(y, f); return *this; } + vec2 &max(float f) { x = ::max(x, f); y = ::max(y, f); return *this; } vec2 &abs() { x = fabs(x); y = fabs(y); return *this; } vec2 &clamp(float l, float h) { x = ::clamp(x, l, h); y = ::clamp(y, l, h); return *this; } vec2 &reflect(const vec2 &n) { float k = 2*dot(n); x -= k*n.x; y -= k*n.y; return *this; } @@ -52,13 +45,11 @@ struct vec2 template vec2 &msub(const vec2 &a, const B &b) { return sub(vec2(a).mul(b)); } }; -static inline bool htcmp(const vec2 &x, const vec2 &y) -{ +static inline bool htcmp(const vec2 &x, const vec2 &y) { return x == y; } -static inline uint hthash(const vec2 &k) -{ +static inline uint hthash(const vec2 &k) { union { uint i; float f; } x, y; x.f = k.x; y.f = k.y; uint v = x.i^y.i; @@ -67,15 +58,12 @@ static inline uint hthash(const vec2 &k) struct ivec; -struct vec -{ - union - { +struct vec { + union { struct { float x, y, z; }; struct { float r, g, b; }; float v[3]; }; - vec() {} explicit vec(int a) : x(a), y(a), z(a) {} explicit vec(float a) : x(a), y(a), z(a) {} @@ -85,50 +73,45 @@ struct vec explicit vec(const vec2 &v, float z = 0) : x(v.x), y(v.y), z(z) {} explicit vec(const vec4 &v); explicit vec(const ivec &v); - vec(float yaw, float pitch) : x(-sinf(yaw)*cosf(pitch)), y(cosf(yaw)*cosf(pitch)), z(sinf(pitch)) {} - - float &operator[](int i) { return v[i]; } + float &operator[](int i) { return v[i]; } float operator[](int i) const { return v[i]; } - vec &set(int i, float f) { v[i] = f; return *this; } - bool operator==(const vec &o) const { return x == o.x && y == o.y && z == o.z; } bool operator!=(const vec &o) const { return x != o.x || y != o.y || z != o.z; } - bool iszero() const { return x==0 && y==0 && z==0; } float squaredlen() const { return x*x + y*y + z*z; } template float dot2(const T &o) const { return x*o.x + y*o.y; } float dot(const vec &o) const { return x*o.x + y*o.y + z*o.z; } float absdot(const vec &o) const { return fabs(x*o.x) + fabs(y*o.y) + fabs(z*o.z); } vec &pow(float f) { x = ::pow(x, f); y = ::pow(y, f); z = ::pow(z, f); return *this; } - vec &exp() { x = ::exp(x); y = ::exp(y); z = ::exp(z); return *this; } - vec &exp2() { x = ::exp2(x); y = ::exp2(y); z = ::exp2(z); return *this; } - vec &sqrt() { x = sqrtf(x); y = sqrtf(y); z = sqrtf(z); return *this; } - vec &mul(const vec &o) { x *= o.x; y *= o.y; z *= o.z; return *this; } + vec &exp() { x = ::exp(x); y = ::exp(y); z = ::exp(z); return *this; } + vec &exp2() { x = ::exp2(x); y = ::exp2(y); z = ::exp2(z); return *this; } + vec &sqrt() { x = sqrtf(x); y = sqrtf(y); z = sqrtf(z); return *this; } + vec &mul(const vec &o) { x *= o.x; y *= o.y; z *= o.z; return *this; } vec &mul(float f) { x *= f; y *= f; z *= f; return *this; } vec &square() { mul(*this); return *this; } - vec &div(const vec &o) { x /= o.x; y /= o.y; z /= o.z; return *this; } + vec &div(const vec &o) { x /= o.x; y /= o.y; z /= o.z; return *this; } vec &div(float f) { x /= f; y /= f; z /= f; return *this; } vec &recip() { x = 1/x; y = 1/y; z = 1/z; return *this; } - vec &add(const vec &o) { x += o.x; y += o.y; z += o.z; return *this; } + vec &add(const vec &o) { x += o.x; y += o.y; z += o.z; return *this; } vec &add(float f) { x += f; y += f; z += f; return *this; } - vec &add2(float f) { x += f; y += f; return *this; } - vec &addz(float f) { z += f; return *this; } - vec &sub(const vec &o) { x -= o.x; y -= o.y; z -= o.z; return *this; } + vec &add2(float f) { x += f; y += f; return *this; } + vec &addz(float f) { z += f; return *this; } + vec &sub(const vec &o) { x -= o.x; y -= o.y; z -= o.z; return *this; } vec &sub(float f) { x -= f; y -= f; z -= f; return *this; } - vec &sub2(float f) { x -= f; y -= f; return *this; } - vec &subz(float f) { z -= f; return *this; } - vec &neg2() { x = -x; y = -y; return *this; } - vec &neg() { x = -x; y = -y; z = -z; return *this; } - vec &min(const vec &o) { x = ::min(x, o.x); y = ::min(y, o.y); z = ::min(z, o.z); return *this; } - vec &max(const vec &o) { x = ::max(x, o.x); y = ::max(y, o.y); z = ::max(z, o.z); return *this; } + vec &sub2(float f) { x -= f; y -= f; return *this; } + vec &subz(float f) { z -= f; return *this; } + vec &neg2() { x = -x; y = -y; return *this; } + vec &neg() { x = -x; y = -y; z = -z; return *this; } + vec &min(const vec &o) { x = ::min(x, o.x); y = ::min(y, o.y); z = ::min(z, o.z); return *this; } + vec &max(const vec &o) { x = ::max(x, o.x); y = ::max(y, o.y); z = ::max(z, o.z); return *this; } vec &min(float f) { x = ::min(x, f); y = ::min(y, f); z = ::min(z, f); return *this; } vec &max(float f) { x = ::max(x, f); y = ::max(y, f); z = ::max(z, f); return *this; } vec &clamp(float f, float h) { x = ::clamp(x, f, h); y = ::clamp(y, f, h); z = ::clamp(z, f, h); return *this; } vec &abs() { x = fabs(x); y = fabs(y); z = fabs(z); return *this; } float magnitude2() const { return sqrtf(dot2(*this)); } - float magnitude() const { return sqrtf(squaredlen()); } + float magnitude() const { return sqrtf(squaredlen()); } vec &normalize() { div(magnitude()); return *this; } vec &safenormalize() { float m = magnitude(); if(m) div(m); return *this; } bool isnormalized() const { float m = squaredlen(); return (m>0.99f && m<1.01f); } @@ -145,15 +128,13 @@ struct vec vec &reflect(const vec &n) { float k = 2*dot(n); x -= k*n.x; y -= k*n.y; z -= k*n.z; return *this; } vec &project(const vec &n) { float k = dot(n); x -= k*n.x; y -= k*n.y; z -= k*n.z; return *this; } vec &projectxydir(const vec &n) { if(n.z) z = -(x*n.x/n.z + y*n.y/n.z); return *this; } - vec &projectxy(const vec &n) - { + vec &projectxy(const vec &n) { float m = squaredlen(), k = dot(n); projectxydir(n); rescale(sqrtf(::max(m - k*k, 0.0f))); return *this; } - vec &projectxy(const vec &n, float threshold) - { + vec &projectxy(const vec &n, float threshold) { float m = squaredlen(), k = ::min(dot(n), threshold); projectxydir(n); rescale(sqrtf(::max(m - k*k, 0.0f))); @@ -163,28 +144,21 @@ struct vec vec &lerp(const vec &a, const vec &b, float t) { x = a.x + (b.x-a.x)*t; y = a.y + (b.y-a.y)*t; z = a.z + (b.z-a.z)*t; return *this; } template vec &madd(const vec &a, const B &b) { return add(vec(a).mul(b)); } template vec &msub(const vec &a, const B &b) { return sub(vec(a).mul(b)); } - - vec &rescale(float k) - { + vec &rescale(float k) { float mag = magnitude(); if(mag > 1e-6f) mul(k / mag); return *this; } - vec &rotate_around_z(float c, float s) { float rx = x, ry = y; x = c*rx-s*ry; y = c*ry+s*rx; return *this; } vec &rotate_around_x(float c, float s) { float ry = y, rz = z; y = c*ry-s*rz; z = c*rz+s*ry; return *this; } vec &rotate_around_y(float c, float s) { float rx = x, rz = z; x = c*rx+s*rz; z = c*rz-s*rx; return *this; } - vec &rotate_around_z(float angle) { return rotate_around_z(cosf(angle), sinf(angle)); } vec &rotate_around_x(float angle) { return rotate_around_x(cosf(angle), sinf(angle)); } vec &rotate_around_y(float angle) { return rotate_around_y(cosf(angle), sinf(angle)); } - vec &rotate_around_z(const vec2 &sc) { return rotate_around_z(sc.x, sc.y); } vec &rotate_around_x(const vec2 &sc) { return rotate_around_x(sc.x, sc.y); } vec &rotate_around_y(const vec2 &sc) { return rotate_around_y(sc.x, sc.y); } - - vec &rotate(float c, float s, const vec &d) - { + vec &rotate(float c, float s, const vec &d) { *this = vec(x*(d.x*d.x*(1-c)+c) + y*(d.x*d.y*(1-c)-d.z*s) + z*(d.x*d.z*(1-c)+d.y*s), x*(d.y*d.x*(1-c)+d.z*s) + y*(d.y*d.y*(1-c)+c) + z*(d.y*d.z*(1-c)-d.x*s), x*(d.x*d.z*(1-c)-d.y*s) + y*(d.y*d.z*(1-c)+d.x*s) + z*(d.z*d.z*(1-c)+c)); @@ -192,49 +166,34 @@ struct vec } vec &rotate(float angle, const vec &d) { return rotate(cosf(angle), sinf(angle), d); } vec &rotate(const vec2 &sc, const vec &d) { return rotate(sc.x, sc.y, d); } - - void orthogonal(const vec &d) - { + void orthogonal(const vec &d) { *this = fabs(d.x) > fabs(d.z) ? vec(-d.y, d.x, 0) : vec(0, -d.z, d.y); } - - void orthonormalize(vec &s, vec &t) const - { + void orthonormalize(vec &s, vec &t) const { s.sub(vec(*this).mul(dot(s))); t.sub(vec(*this).mul(dot(t))) .sub(vec(s).mul(s.dot(t))); } - template - bool insidebb(const T &bbmin, const T &bbmax) const - { + bool insidebb(const T &bbmin, const T &bbmax) const { return x >= bbmin.x && x <= bbmax.x && y >= bbmin.y && y <= bbmax.y && z >= bbmin.z && z <= bbmax.z; } - template - bool insidebb(const T &o, U size) const - { + bool insidebb(const T &o, U size) const { return x >= o.x && x <= o.x + size && y >= o.y && y <= o.y + size && z >= o.z && z <= o.z + size; } - - template float dist_to_bb(const T &min, const T &max) const - { + template float dist_to_bb(const T &min, const T &max) const { float sqrdist = 0; - loopi(3) - { + loopi(3) { if (v[i] < min[i]) { float delta = v[i]-min[i]; sqrdist += delta*delta; } else if(v[i] > max[i]) { float delta = max[i]-v[i]; sqrdist += delta*delta; } } return sqrtf(sqrdist); } - - template float dist_to_bb(const T &o, S size) const - { + template float dist_to_bb(const T &o, S size) const { return dist_to_bb(o, T(o).add(size)); } - - static vec hexcolor(int color) - { + static vec hexcolor(int color) { return vec(((color>>16)&0xFF)*(1.0f/255.0f), ((color>>8)&0xFF)*(1.0f/255.0f), (color&0xFF)*(1.0f/255.0f)); } int tohexcolor() const { return (int(::clamp(r, 0.0f, 1.0f)*255)<<16)|(int(::clamp(g, 0.0f, 1.0f)*255)<<8)|int(::clamp(b, 0.0f, 1.0f)*255); } @@ -242,85 +201,71 @@ struct vec inline vec2::vec2(const vec &v) : x(v.x), y(v.y) {} -static inline bool htcmp(const vec &x, const vec &y) -{ +static inline bool htcmp(const vec &x, const vec &y) { return x == y; } -static inline uint hthash(const vec &k) -{ +static inline uint hthash(const vec &k) { union { uint i; float f; } x, y, z; x.f = k.x; y.f = k.y; z.f = k.z; uint v = x.i^y.i^z.i; return v + (v>>12); } -struct vec4 -{ - union - { +struct vec4 { + union { struct { float x, y, z, w; }; struct { float r, g, b, a; }; float v[4]; }; - vec4() {} explicit vec4(const vec &p, float w = 0) : x(p.x), y(p.y), z(p.z), w(w) {} vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {} explicit vec4(const float *v) : x(v[0]), y(v[1]), z(v[2]), w(v[3]) {} - - float &operator[](int i) { return v[i]; } + float &operator[](int i) { return v[i]; } float operator[](int i) const { return v[i]; } - template float dot3(const T &o) const { return x*o.x + y*o.y + z*o.z; } float dot(const vec4 &o) const { return dot3(o) + w*o.w; } - float dot(const vec &o) const { return x*o.x + y*o.y + z*o.z + w; } + float dot(const vec &o) const { return x*o.x + y*o.y + z*o.z + w; } float squaredlen() const { return dot(*this); } - float magnitude() const { return sqrtf(squaredlen()); } + float magnitude() const { return sqrtf(squaredlen()); } float magnitude3() const { return sqrtf(dot3(*this)); } vec4 &normalize() { mul(1/magnitude()); return *this; } vec4 &safenormalize() { float m = magnitude(); if(m) mul(1/m); return *this; } - - vec4 &lerp(const vec4 &b, float t) - { + vec4 &lerp(const vec4 &b, float t) { x += (b.x-x)*t; y += (b.y-y)*t; z += (b.z-z)*t; w += (b.w-w)*t; return *this; } - vec4 &lerp(const vec4 &a, const vec4 &b, float t) - { + vec4 &lerp(const vec4 &a, const vec4 &b, float t) { x = a.x+(b.x-a.x)*t; y = a.y+(b.y-a.y)*t; z = a.z+(b.z-a.z)*t; w = a.w+(b.w-a.w)*t; return *this; } - - vec4 &mul3(float f) { x *= f; y *= f; z *= f; return *this; } - vec4 &mul(float f) { mul3(f); w *= f; return *this; } + vec4 &mul3(float f) { x *= f; y *= f; z *= f; return *this; } + vec4 &mul(float f) { mul3(f); w *= f; return *this; } vec4 &mul(const vec4 &o) { x *= o.x; y *= o.y; z *= o.z; w *= o.w; return *this; } - vec4 &square() { mul(*this); return *this; } - vec4 &div3(float f) { x /= f; y /= f; z /= f; return *this; } - vec4 &div(float f) { div3(f); w /= f; return *this; } + vec4 &square() { mul(*this); return *this; } + vec4 &div3(float f) { x /= f; y /= f; z /= f; return *this; } + vec4 &div(float f) { div3(f); w /= f; return *this; } vec4 &div(const vec4 &o) { x /= o.x; y /= o.y; z /= o.z; w /= o.w; return *this; } vec4 &recip() { x = 1/x; y = 1/y; z = 1/z; w = 1/w; return *this; } vec4 &add(const vec4 &o) { x += o.x; y += o.y; z += o.z; w += o.w; return *this; } - vec4 &addw(float f) { w += f; return *this; } + vec4 &addw(float f) { w += f; return *this; } vec4 &sub(const vec4 &o) { x -= o.x; y -= o.y; z -= o.z; w -= o.w; return *this; } - vec4 &subw(float f) { w -= f; return *this; } + vec4 &subw(float f) { w -= f; return *this; } vec4 &neg3() { x = -x; y = -y; z = -z; return *this; } - vec4 &neg() { neg3(); w = -w; return *this; } + vec4 &neg() { neg3(); w = -w; return *this; } template vec4 &madd(const vec4 &a, const B &b) { return add(vec4(a).mul(b)); } template vec4 &msub(const vec4 &a, const B &b) { return sub(vec4(a).mul(b)); } - void setxyz(const vec &v) { x = v.x; y = v.y; z = v.z; } - vec4 &rotate_around_z(float c, float s) { float rx = x, ry = y; x = c*rx-s*ry; y = c*ry+s*rx; return *this; } vec4 &rotate_around_x(float c, float s) { float ry = y, rz = z; y = c*ry-s*rz; z = c*rz+s*ry; return *this; } vec4 &rotate_around_y(float c, float s) { float rx = x, rz = z; x = c*rx+s*rz; z = c*rz-s*rx; return *this; } - vec4 &rotate_around_z(float angle) { return rotate_around_z(cosf(angle), sinf(angle)); } vec4 &rotate_around_x(float angle) { return rotate_around_x(cosf(angle), sinf(angle)); } vec4 &rotate_around_y(float angle) { return rotate_around_y(cosf(angle), sinf(angle)); } @@ -332,20 +277,17 @@ struct matrix3; struct matrix4x3; struct matrix4; -struct quat : vec4 -{ +struct quat : vec4 { quat() {} quat(float x, float y, float z, float w) : vec4(x, y, z, w) {} - quat(const vec &axis, float angle) - { + quat(const vec &axis, float angle) { w = cosf(angle/2); float s = sinf(angle/2); x = s*axis.x; y = s*axis.y; z = s*axis.z; } - explicit quat(const vec &v) - { + explicit quat(const vec &v) { x = v.x; y = v.y; z = v.z; @@ -354,15 +296,11 @@ struct quat : vec4 explicit quat(const matrix3 &m) { convertmatrix(m); } explicit quat(const matrix4x3 &m) { convertmatrix(m); } explicit quat(const matrix4 &m) { convertmatrix(m); } - void restorew() { w = 1.0f-x*x-y*y-z*z; w = w<0 ? 0 : -sqrtf(w); } - quat &add(const vec4 &o) { vec4::add(o); return *this; } quat &sub(const vec4 &o) { vec4::sub(o); return *this; } quat &mul(float k) { vec4::mul(k); return *this; } - - quat &mul(const quat &p, const quat &o) - { + quat &mul(const quat &p, const quat &o) { x = p.w*o.x + p.x*o.w + p.y*o.z - p.z*o.y; y = p.w*o.y - p.x*o.z + p.y*o.w + p.z*o.x; z = p.w*o.z + p.x*o.y - p.y*o.x + p.z*o.w; @@ -370,60 +308,46 @@ struct quat : vec4 return *this; } quat &mul(const quat &o) { return mul(quat(*this), o); } - quat &invert() { neg3(); return *this; } - - void calcangleaxis(float &angle, vec &axis) - { + void calcangleaxis(float &angle, vec &axis) { float rr = dot3(*this); - if(rr>0) - { + if(rr>0) { angle = 2*acosf(w); axis = vec(x, y, z).mul(1/rr); } else { angle = 0; axis = vec(0, 0, 1); } } - - vec rotate(const vec &v) const - { + vec rotate(const vec &v) const { return vec().cross(*this, vec().cross(*this, v).add(vec(v).mul(w))).mul(2).add(v); } - - vec invertedrotate(const vec &v) const - { + vec invertedrotate(const vec &v) const { return vec().cross(*this, vec().cross(*this, v).sub(vec(v).mul(w))).mul(2).add(v); } - template - void convertmatrix(const M &m) - { + void convertmatrix(const M &m) { float trace = m.a.x + m.b.y + m.c.z; - if(trace>0) - { + if(trace>0) { float r = sqrtf(1 + trace), inv = 0.5f/r; w = 0.5f*r; x = (m.b.z - m.c.y)*inv; y = (m.c.x - m.a.z)*inv; z = (m.a.y - m.b.x)*inv; } - else if(m.a.x > m.b.y && m.a.x > m.c.z) - { + else if(m.a.x > m.b.y && m.a.x > m.c.z) { float r = sqrtf(1 + m.a.x - m.b.y - m.c.z), inv = 0.5f/r; x = 0.5f*r; y = (m.a.y + m.b.x)*inv; z = (m.c.x + m.a.z)*inv; w = (m.b.z - m.c.y)*inv; } - else if(m.b.y > m.c.z) - { + else if(m.b.y > m.c.z) { float r = sqrtf(1 + m.b.y - m.a.x - m.c.z), inv = 0.5f/r; x = (m.a.y + m.b.x)*inv; y = 0.5f*r; z = (m.b.z + m.c.y)*inv; w = (m.c.x - m.a.z)*inv; } - else - { + else { float r = sqrtf(1 + m.c.z - m.a.x - m.b.y), inv = 0.5f/r; x = (m.c.x + m.a.z)*inv; y = (m.b.z + m.c.y)*inv; @@ -433,147 +357,105 @@ struct quat : vec4 } }; -struct dualquat -{ +struct dualquat { quat real, dual; - dualquat() {} dualquat(const quat &q, const vec &p) : real(q), dual(0.5f*( p.x*q.w + p.y*q.z - p.z*q.y), 0.5f*(-p.x*q.z + p.y*q.w + p.z*q.x), 0.5f*( p.x*q.y - p.y*q.x + p.z*q.w), - -0.5f*( p.x*q.x + p.y*q.y + p.z*q.z)) - { + -0.5f*( p.x*q.x + p.y*q.y + p.z*q.z)) { } explicit dualquat(const quat &q) : real(q), dual(0, 0, 0, 0) {} explicit dualquat(const matrix4x3 &m); - dualquat &mul(float k) { real.mul(k); dual.mul(k); return *this; } dualquat &add(const dualquat &d) { real.add(d.real); dual.add(d.dual); return *this; } - - dualquat &lerp(const dualquat &to, float t) - { + dualquat &lerp(const dualquat &to, float t) { float k = real.dot(to.real) < 0 ? -t : t; real.mul(1-t).add(vec4(to.real).mul(k)); dual.mul(1-t).add(vec4(to.dual).mul(k)); return *this; } - dualquat &lerp(const dualquat &from, const dualquat &to, float t) - { + dualquat &lerp(const dualquat &from, const dualquat &to, float t) { float k = from.real.dot(to.real) < 0 ? -t : t; (real = from.real).mul(1-t).add(vec4(to.real).mul(k)); (dual = from.dual).mul(1-t).add(vec4(to.dual).mul(k)); return *this; } - - dualquat &invert() - { + dualquat &invert() { real.invert(); dual.invert(); dual.sub(quat(real).mul(2*real.dot(dual))); return *this; } - - void mul(const dualquat &p, const dualquat &o) - { + void mul(const dualquat &p, const dualquat &o) { real.mul(p.real, o.real); dual.mul(p.real, o.dual).add(quat().mul(p.dual, o.real)); } void mul(const dualquat &o) { mul(dualquat(*this), o); } - - void mulorient(const quat &q) - { + void mulorient(const quat &q) { real.mul(q, quat(real)); dual.mul(quat(q).invert(), quat(dual)); } - - void mulorient(const quat &q, const dualquat &base) - { + void mulorient(const quat &q, const dualquat &base) { quat trans; trans.mul(base.dual, quat(base.real).invert()); dual.mul(quat(q).invert(), quat(real).mul(trans).add(dual)); - real.mul(q, quat(real)); dual.add(quat().mul(real, trans.invert())).sub(quat(real).mul(2*base.real.dot(base.dual))); } - - void normalize() - { + void normalize() { float invlen = 1/real.magnitude(); real.mul(invlen); dual.mul(invlen); } - - void translate(const vec &p) - { + void translate(const vec &p) { dual.x += 0.5f*( p.x*real.w + p.y*real.z - p.z*real.y); dual.y += 0.5f*(-p.x*real.z + p.y*real.w + p.z*real.x); dual.z += 0.5f*( p.x*real.y - p.y*real.x + p.z*real.w); dual.w += -0.5f*( p.x*real.x + p.y*real.y + p.z*real.z); } - - void scale(float k) - { + void scale(float k) { dual.mul(k); } - - void fixantipodal(const dualquat &d) - { - if(real.dot(d.real) < 0) - { + void fixantipodal(const dualquat &d) { + if(real.dot(d.real) < 0) { real.neg(); dual.neg(); } } - - void accumulate(const dualquat &d, float k) - { + void accumulate(const dualquat &d, float k) { if(real.dot(d.real) < 0) k = -k; real.add(vec4(d.real).mul(k)); dual.add(vec4(d.dual).mul(k)); } - - vec transform(const vec &v) const - { + vec transform(const vec &v) const { return vec().cross(real, vec().cross(real, v).add(vec(v).mul(real.w)).add(vec(dual))).add(vec(dual).mul(real.w)).sub(vec(real).mul(dual.w)).mul(2).add(v); } - - quat transform(const quat &q) const - { + quat transform(const quat &q) const { return quat().mul(real, q); } - - vec transposedtransform(const vec &v) const - { + vec transposedtransform(const vec &v) const { return dualquat(*this).invert().transform(v); } - - vec transformnormal(const vec &v) const - { + vec transformnormal(const vec &v) const { return real.rotate(v); } - - vec transposedtransformnormal(const vec &v) const - { + vec transposedtransformnormal(const vec &v) const { return real.invertedrotate(v); } - - vec gettranslation() const - { + vec gettranslation() const { return vec().cross(real, dual).add(vec(dual).mul(real.w)).sub(vec(real).mul(dual.w)).mul(2); } }; -struct matrix3 -{ +struct matrix3 { vec a, b, c; - matrix3() {} matrix3(const vec &a, const vec &b, const vec &c) : a(a), b(b), c(c) {} explicit matrix3(float angle, const vec &axis) { rotate(angle, axis); } - explicit matrix3(const quat &q) - { + explicit matrix3(const quat &q) { float x = q.x, y = q.y, z = q.z, w = q.w, tx = 2*x, ty = 2*y, tz = 2*z, txx = tx*x, tyy = ty*y, tzz = tz*z, @@ -585,47 +467,35 @@ struct matrix3 } explicit matrix3(const matrix4x3 &m); explicit matrix3(const matrix4 &m); - - void mul(const matrix3 &m, const matrix3 &n) - { + void mul(const matrix3 &m, const matrix3 &n) { a = vec(m.a).mul(n.a.x).madd(m.b, n.a.y).madd(m.c, n.a.z); b = vec(m.a).mul(n.b.x).madd(m.b, n.b.y).madd(m.c, n.b.z); c = vec(m.a).mul(n.c.x).madd(m.b, n.c.y).madd(m.c, n.c.z); } void mul(const matrix3 &n) { mul(matrix3(*this), n); } - - void multranspose(const matrix3 &m, const matrix3 &n) - { + void multranspose(const matrix3 &m, const matrix3 &n) { a = vec(m.a).mul(n.a.x).madd(m.b, n.b.x).madd(m.c, n.c.x); b = vec(m.a).mul(n.a.y).madd(m.b, n.b.y).madd(m.c, n.c.y); c = vec(m.a).mul(n.a.z).madd(m.b, n.b.z).madd(m.c, n.c.z); } void multranspose(const matrix3 &n) { multranspose(matrix3(*this), n); } - - void transposemul(const matrix3 &m, const matrix3 &n) - { + void transposemul(const matrix3 &m, const matrix3 &n) { a = vec(m.a.dot(n.a), m.b.dot(n.a), m.c.dot(n.a)); b = vec(m.a.dot(n.b), m.b.dot(n.b), m.c.dot(n.b)); c = vec(m.a.dot(n.c), m.b.dot(n.c), m.c.dot(n.c)); } void transposemul(const matrix3 &n) { transposemul(matrix3(*this), n); } - - void transpose() - { + void transpose() { swap(a.y, b.x); swap(a.z, c.x); swap(b.z, c.y); } - template - void transpose(const M &m) - { + void transpose(const M &m) { a = vec(m.a.x, m.b.x, m.c.x); b = vec(m.a.y, m.b.y, m.c.y); c = vec(m.a.z, m.b.z, m.c.z); } - - void invert(const matrix3 &o) - { + void invert(const matrix3 &o) { vec unscale(1/o.a.squaredlen(), 1/o.b.squaredlen(), 1/o.c.squaredlen()); transpose(o); a.mul(unscale); @@ -633,53 +503,36 @@ struct matrix3 c.mul(unscale); } void invert() { invert(matrix3(*this)); } - - void normalize() - { + void normalize() { a.normalize(); b.normalize(); c.normalize(); } - - void scale(float k) - { + void scale(float k) { a.mul(k); b.mul(k); c.mul(k); } - - void rotate(float angle, const vec &axis) - { + void rotate(float angle, const vec &axis) { rotate(cosf(angle), sinf(angle), axis); } - - void rotate(float ck, float sk, const vec &axis) - { + void rotate(float ck, float sk, const vec &axis) { a = vec(axis.x*axis.x*(1-ck)+ck, axis.x*axis.y*(1-ck)+axis.z*sk, axis.x*axis.z*(1-ck)-axis.y*sk); b = vec(axis.x*axis.y*(1-ck)-axis.z*sk, axis.y*axis.y*(1-ck)+ck, axis.y*axis.z*(1-ck)+axis.x*sk); c = vec(axis.x*axis.z*(1-ck)+axis.y*sk, axis.y*axis.z*(1-ck)-axis.x*sk, axis.z*axis.z*(1-ck)+ck); } - - void setyaw(float ck, float sk) - { + void setyaw(float ck, float sk) { a = vec(ck, sk, 0); b = vec(-sk, ck, 0); c = vec(0, 0, 1); } - - void setyaw(float angle) - { + void setyaw(float angle) { setyaw(cosf(angle), sinf(angle)); } - float trace() const { return a.x + b.y + c.z; } - - bool calcangleaxis(float tr, float &angle, vec &axis, float threshold = 1e-16f) const - { - if(tr <= -1) - { - if(a.x >= b.y && a.x >= c.z) - { + bool calcangleaxis(float tr, float &angle, vec &axis, float threshold = 1e-16f) const { + if(tr <= -1) { + if(a.x >= b.y && a.x >= c.z) { float r = 1 + a.x - b.y - c.z; if(r <= threshold) return false; r = sqrtf(r); @@ -687,8 +540,7 @@ struct matrix3 axis.y = b.x/r; axis.z = c.x/r; } - else if(b.y >= c.z) - { + else if(b.y >= c.z) { float r = 1 + b.y - a.x - c.z; if(r <= threshold) return false; r = sqrtf(r); @@ -696,8 +548,7 @@ struct matrix3 axis.x = b.x/r; axis.z = c.y/r; } - else - { + else { float r = 1 + b.y - a.x - c.z; if(r <= threshold) return false; r = sqrtf(r); @@ -707,13 +558,11 @@ struct matrix3 } angle = M_PI; } - else if(tr >= 3) - { + else if(tr >= 3) { axis = vec(0, 0, 1); angle = 0; } - else - { + else { axis = vec(b.z - c.y, c.x - a.z, a.y - b.x); float r = axis.squaredlen(); if(r <= threshold) return false; @@ -722,32 +571,23 @@ struct matrix3 } return true; } - bool calcangleaxis(float &angle, vec &axis, float threshold = 1e-16f) const { return calcangleaxis(trace(), angle, axis, threshold); } - - vec transform(const vec &o) const - { + vec transform(const vec &o) const { return vec(a).mul(o.x).madd(b, o.y).madd(c, o.z); } vec transposedtransform(const vec &o) const { return vec(a.dot(o), b.dot(o), c.dot(o)); } - vec abstransform(const vec &o) const - { + vec abstransform(const vec &o) const { return vec(a).mul(o.x).abs().add(vec(b).mul(o.y).abs()).add(vec(c).mul(o.z).abs()); } - vec abstransposedtransform(const vec &o) const - { + vec abstransposedtransform(const vec &o) const { return vec(a.absdot(o), b.absdot(o), c.absdot(o)); } - - void identity() - { + void identity() { a = vec(1, 0, 0); b = vec(0, 1, 0); c = vec(0, 0, 1); } - - void rotate_around_x(float ck, float sk) - { + void rotate_around_x(float ck, float sk) { vec rb = vec(b).mul(ck).madd(c, sk), rc = vec(c).mul(ck).msub(b, sk); b = rb; @@ -755,9 +595,7 @@ struct matrix3 } void rotate_around_x(float angle) { rotate_around_x(cosf(angle), sinf(angle)); } void rotate_around_x(const vec2 &sc) { rotate_around_x(sc.x, sc.y); } - - void rotate_around_y(float ck, float sk) - { + void rotate_around_y(float ck, float sk) { vec rc = vec(c).mul(ck).madd(a, sk), ra = vec(a).mul(ck).msub(c, sk); c = rc; @@ -765,9 +603,7 @@ struct matrix3 } void rotate_around_y(float angle) { rotate_around_y(cosf(angle), sinf(angle)); } void rotate_around_y(const vec2 &sc) { rotate_around_y(sc.x, sc.y); } - - void rotate_around_z(float ck, float sk) - { + void rotate_around_z(float ck, float sk) { vec ra = vec(a).mul(ck).madd(b, sk), rb = vec(b).mul(ck).msub(a, sk); a = ra; @@ -775,24 +611,19 @@ struct matrix3 } void rotate_around_z(float angle) { rotate_around_z(cosf(angle), sinf(angle)); } void rotate_around_z(const vec2 &sc) { rotate_around_z(sc.x, sc.y); } - vec transform(const vec2 &o) { return vec(a).mul(o.x).madd(b, o.y); } vec transposedtransform(const vec2 &o) const { return vec(a.dot2(o), b.dot2(o), c.dot2(o)); } - vec rowx() const { return vec(a.x, b.x, c.x); } vec rowy() const { return vec(a.y, b.y, c.y); } vec rowz() const { return vec(a.z, b.z, c.z); } }; -struct matrix4x3 -{ +struct matrix4x3 { vec a, b, c, d; - matrix4x3() {} matrix4x3(const vec &a, const vec &b, const vec &c, const vec &d) : a(a), b(b), c(c), d(d) {} matrix4x3(const matrix3 &rot, const vec &trans) : a(rot.a), b(rot.b), c(rot.c), d(trans) {} - matrix4x3(const dualquat &dq) - { + matrix4x3(const dualquat &dq) { vec4 r = vec4(dq.real).mul(1/dq.real.squaredlen()), rr = vec4(r).mul(dq.real); r.mul(2); float xy = r.x*dq.real.y, xz = r.x*dq.real.z, yz = r.y*dq.real.z, @@ -803,138 +634,104 @@ struct matrix4x3 d = vec(-(dq.dual.w*r.x - dq.dual.x*r.w + dq.dual.y*r.z - dq.dual.z*r.y), -(dq.dual.w*r.y - dq.dual.x*r.z - dq.dual.y*r.w + dq.dual.z*r.x), -(dq.dual.w*r.z + dq.dual.x*r.y - dq.dual.y*r.x - dq.dual.z*r.w)); - } explicit matrix4x3(const matrix4 &m); - - void mul(float k) - { + void mul(float k) { a.mul(k); b.mul(k); c.mul(k); d.mul(k); } - void setscale(float x, float y, float z) { a.x = x; b.y = y; c.z = z; } void setscale(const vec &v) { setscale(v.x, v.y, v.z); } void setscale(float n) { setscale(n, n, n); } - - void scale(float x, float y, float z) - { + void scale(float x, float y, float z) { a.mul(x); b.mul(y); c.mul(z); } void scale(const vec &v) { scale(v.x, v.y, v.z); } void scale(float n) { scale(n, n, n); } - void settranslation(const vec &p) { d = p; } void settranslation(float x, float y, float z) { d = vec(x, y, z); } - void translate(const vec &p) { d.madd(a, p.x).madd(b, p.y).madd(c, p.z); } void translate(float x, float y, float z) { translate(vec(x, y, z)); } void translate(const vec &p, float scale) { translate(vec(p).mul(scale)); } - void posttranslate(const vec &p) { d.add(p); } void posttranslate(float x, float y, float z) { posttranslate(vec(x, y, z)); } void posttranslate(const vec &p, float scale) { d.madd(p, scale); } - - void accumulate(const matrix4x3 &m, float k) - { + void accumulate(const matrix4x3 &m, float k) { a.madd(m.a, k); b.madd(m.b, k); c.madd(m.c, k); d.madd(m.d, k); } - - void normalize() - { + void normalize() { a.normalize(); b.normalize(); c.normalize(); } - - void lerp(const matrix4x3 &to, float t) - { + void lerp(const matrix4x3 &to, float t) { a.lerp(to.a, t); b.lerp(to.b, t); c.lerp(to.c, t); d.lerp(to.d, t); } - void lerp(const matrix4x3 &from, const matrix4x3 &to, float t) - { + void lerp(const matrix4x3 &from, const matrix4x3 &to, float t) { a.lerp(from.a, to.a, t); b.lerp(from.b, to.b, t); c.lerp(from.c, to.c, t); d.lerp(from.d, to.d, t); } - - void identity() - { + void identity() { a = vec(1, 0, 0); b = vec(0, 1, 0); c = vec(0, 0, 1); d = vec(0, 0, 0); } - - void mul(const matrix4x3 &m, const matrix4x3 &n) - { + void mul(const matrix4x3 &m, const matrix4x3 &n) { a = vec(m.a).mul(n.a.x).madd(m.b, n.a.y).madd(m.c, n.a.z); b = vec(m.a).mul(n.b.x).madd(m.b, n.b.y).madd(m.c, n.b.z); c = vec(m.a).mul(n.c.x).madd(m.b, n.c.y).madd(m.c, n.c.z); d = vec(m.d).madd(m.a, n.d.x).madd(m.b, n.d.y).madd(m.c, n.d.z); } void mul(const matrix4x3 &n) { mul(matrix4x3(*this), n); } - - void mul(const matrix3 &m, const matrix4x3 &n) - { + void mul(const matrix3 &m, const matrix4x3 &n) { a = vec(m.a).mul(n.a.x).madd(m.b, n.a.y).madd(m.c, n.a.z); b = vec(m.a).mul(n.b.x).madd(m.b, n.b.y).madd(m.c, n.b.z); c = vec(m.a).mul(n.c.x).madd(m.b, n.c.y).madd(m.c, n.c.z); d = vec(m.a).mul(n.d.x).madd(m.b, n.d.y).madd(m.c, n.d.z); } - - void mul(const matrix3 &rot, const vec &trans, const matrix4x3 &n) - { + void mul(const matrix3 &rot, const vec &trans, const matrix4x3 &n) { mul(rot, n); d.add(trans); } - - void transpose() - { + void transpose() { d = vec(a.dot(d), b.dot(d), c.dot(d)).neg(); swap(a.y, b.x); swap(a.z, c.x); swap(b.z, c.y); } - - void transpose(const matrix4x3 &o) - { + void transpose(const matrix4x3 &o) { a = vec(o.a.x, o.b.x, o.c.x); b = vec(o.a.y, o.b.y, o.c.y); c = vec(o.a.z, o.b.z, o.c.z); d = vec(o.a.dot(o.d), o.b.dot(o.d), o.c.dot(o.d)).neg(); } - - void transposemul(const matrix4x3 &m, const matrix4x3 &n) - { + void transposemul(const matrix4x3 &m, const matrix4x3 &n) { vec t(m.a.dot(m.d), m.b.dot(m.d), m.c.dot(m.d)); a = vec(m.a.dot(n.a), m.b.dot(n.a), m.c.dot(n.a)); b = vec(m.a.dot(n.b), m.b.dot(n.b), m.c.dot(n.b)); c = vec(m.a.dot(n.c), m.b.dot(n.c), m.c.dot(n.c)); d = vec(m.a.dot(n.d), m.b.dot(n.d), m.c.dot(n.d)).sub(t); } - - void multranspose(const matrix4x3 &m, const matrix4x3 &n) - { + void multranspose(const matrix4x3 &m, const matrix4x3 &n) { vec t(n.a.dot(n.d), n.b.dot(n.d), n.c.dot(n.d)); a = vec(m.a).mul(n.a.x).madd(m.b, n.b.x).madd(m.c, n.c.x); b = vec(m.a).mul(n.a.y).madd(m.b, n.b.y).madd(m.c, n.c.y); c = vec(m.a).mul(n.a.z).madd(m.b, n.b.z).madd(m.c, n.c.z); d = vec(m.d).msub(m.a, t.x).msub(m.b, t.y).msub(m.c, t.z); } - - void invert(const matrix4x3 &o) - { + void invert(const matrix4x3 &o) { vec unscale(1/o.a.squaredlen(), 1/o.b.squaredlen(), 1/o.c.squaredlen()); transpose(o); a.mul(unscale); @@ -943,21 +740,15 @@ struct matrix4x3 d.mul(unscale); } void invert() { invert(matrix4x3(*this)); } - - void rotate(float angle, const vec &d) - { + void rotate(float angle, const vec &d) { rotate(cosf(angle), sinf(angle), d); } - - void rotate(float ck, float sk, const vec &axis) - { + void rotate(float ck, float sk, const vec &axis) { matrix3 m; m.rotate(ck, sk, axis); *this = matrix4x3(m, vec(0, 0, 0)); } - - void rotate_around_x(float ck, float sk) - { + void rotate_around_x(float ck, float sk) { vec rb = vec(b).mul(ck).madd(c, sk), rc = vec(c).mul(ck).msub(b, sk); b = rb; @@ -965,9 +756,7 @@ struct matrix4x3 } void rotate_around_x(float angle) { rotate_around_x(cosf(angle), sinf(angle)); } void rotate_around_x(const vec2 &sc) { rotate_around_x(sc.x, sc.y); } - - void rotate_around_y(float ck, float sk) - { + void rotate_around_y(float ck, float sk) { vec rc = vec(c).mul(ck).madd(a, sk), ra = vec(a).mul(ck).msub(c, sk); c = rc; @@ -975,9 +764,7 @@ struct matrix4x3 } void rotate_around_y(float angle) { rotate_around_y(cosf(angle), sinf(angle)); } void rotate_around_y(const vec2 &sc) { rotate_around_y(sc.x, sc.y); } - - void rotate_around_z(float ck, float sk) - { + void rotate_around_z(float ck, float sk) { vec ra = vec(a).mul(ck).madd(b, sk), rb = vec(b).mul(ck).msub(a, sk); a = ra; @@ -985,20 +772,17 @@ struct matrix4x3 } void rotate_around_z(float angle) { rotate_around_z(cosf(angle), sinf(angle)); } void rotate_around_z(const vec2 &sc) { rotate_around_z(sc.x, sc.y); } - vec transform(const vec &o) const { return vec(d).madd(a, o.x).madd(b, o.y).madd(c, o.z); } vec transposedtransform(const vec &o) const { vec p = vec(o).sub(d); return vec(a.dot(p), b.dot(p), c.dot(p)); } vec transformnormal(const vec &o) const { return vec(a).mul(o.x).madd(b, o.y).madd(c, o.z); } vec transposedtransformnormal(const vec &o) const { return vec(a.dot(o), b.dot(o), c.dot(o)); } vec transform(const vec2 &o) const { return vec(d).madd(a, o.x).madd(b, o.y); } - vec4 rowx() const { return vec4(a.x, b.x, c.x, d.x); } vec4 rowy() const { return vec4(a.y, b.y, c.y, d.y); } vec4 rowz() const { return vec4(a.z, b.z, c.z, d.z); } }; -inline dualquat::dualquat(const matrix4x3 &m) : real(m) -{ +inline dualquat::dualquat(const matrix4x3 &m) : real(m) { dual.x = 0.5f*( m.d.x*real.w + m.d.y*real.z - m.d.z*real.y); dual.y = 0.5f*(-m.d.x*real.z + m.d.y*real.w + m.d.z*real.x); dual.z = 0.5f*( m.d.x*real.y - m.d.y*real.x + m.d.z*real.w); @@ -1007,34 +791,26 @@ inline dualquat::dualquat(const matrix4x3 &m) : real(m) inline matrix3::matrix3(const matrix4x3 &m) : a(m.a), b(m.b), c(m.c) {} -struct plane : vec -{ +struct plane : vec { float offset; - float dist(const vec &p) const { return dot(p)+offset; } float dist(const vec4 &p) const { return p.dot3(*this) + p.w*offset; } bool operator==(const plane &p) const { return x==p.x && y==p.y && z==p.z && offset==p.offset; } bool operator!=(const plane &p) const { return x!=p.x || y!=p.y || z!=p.z || offset!=p.offset; } - plane() {} plane(const vec &c, float off) : vec(c), offset(off) {} plane(const vec4 &p) : vec(p), offset(p.w) {} - plane(int d, float off) - { + plane(int d, float off) { x = y = z = 0.0f; v[d] = 1.0f; offset = -off; } plane(float a, float b, float c, float d) : vec(a, b, c), offset(d) {} - - void toplane(const vec &n, const vec &p) - { + void toplane(const vec &n, const vec &p) { x = n.x; y = n.y; z = n.z; offset = -dot(p); } - - bool toplane(const vec &a, const vec &b, const vec &c) - { + bool toplane(const vec &a, const vec &b, const vec &c) { cross(vec(b).sub(a), vec(c).sub(a)); float mag = magnitude(); if(!mag) return false; @@ -1042,65 +818,48 @@ struct plane : vec offset = -dot(a); return true; } - - bool rayintersect(const vec &o, const vec &ray, float &dist) - { + bool rayintersect(const vec &o, const vec &ray, float &dist) { float cosalpha = dot(ray); if(cosalpha==0) return false; float deltac = offset+dot(o); dist -= deltac/cosalpha; return true; } - - plane &reflectz(float rz) - { + plane &reflectz(float rz) { offset += 2*rz*z; z = -z; return *this; } - - plane &invert() - { + plane &invert() { neg(); offset = -offset; return *this; } - - plane &scale(float k) - { + plane &scale(float k) { mul(k); return *this; } - - plane &translate(const vec &p) - { + plane &translate(const vec &p) { offset += dot(p); return *this; } - - plane &normalize() - { + plane &normalize() { float mag = magnitude(); div(mag); offset /= mag; return *this; } - float zintersect(const vec &p) const { return -(x*p.x+y*p.y+offset)/z; } float zdelta(const vec &p) const { return -(x*p.x+y*p.y)/z; } float zdist(const vec &p) const { return p.z-zintersect(p); } }; -struct triangle -{ +struct triangle { vec a, b, c; - triangle(const vec &a, const vec &b, const vec &c) : a(a), b(b), c(c) {} triangle() {} - triangle &add(const vec &o) { a.add(o); b.add(o); c.add(o); return *this; } triangle &sub(const vec &o) { a.sub(o); b.sub(o); c.sub(o); return *this; } - bool operator==(const triangle &t) const { return a == t.a && b == t.b && c == t.c; } }; @@ -1131,20 +890,16 @@ struct ivec2; struct usvec; struct svec; -struct ivec -{ - union - { +struct ivec { + union { struct { int x, y, z; }; struct { int r, g, b; }; int v[3]; }; - ivec() {} explicit ivec(const vec &v) : x(int(v.x)), y(int(v.y)), z(int(v.z)) {} ivec(int a, int b, int c) : x(a), y(b), z(c) {} - ivec(int d, int row, int col, int depth) - { + ivec(int d, int row, int col, int depth) { v[R[d]] = row; v[C[d]] = col; v[D[d]] = depth; @@ -1154,10 +909,8 @@ struct ivec explicit ivec(const ivec2 &v, int z = 0); explicit ivec(const usvec &v); explicit ivec(const svec &v); - - int &operator[](int i) { return v[i]; } + int &operator[](int i) { return v[i]; } int operator[](int i) const { return v[i]; } - //int idx(int i) { return v[i]; } bool operator==(const ivec &v) const { return x==v.x && y==v.y && z==v.z; } bool operator!=(const ivec &v) const { return x!=v.x || y!=v.y || z!=v.z; } @@ -1183,42 +936,33 @@ struct ivec ivec &cross(const ivec &a, const ivec &b) { x = a.y*b.z-a.z*b.y; y = a.z*b.x-a.x*b.z; z = a.x*b.y-a.y*b.x; return *this; } int dot(const ivec &o) const { return x*o.x + y*o.y + z*o.z; } float dist(const plane &p) const { return x*p.x + y*p.y + z*p.z + p.offset; } - static inline ivec floor(const vec &o) { return ivec(int(::floor(o.x)), int(::floor(o.y)), int(::floor(o.z))); } static inline ivec ceil(const vec &o) { return ivec(int(::ceil(o.x)), int(::ceil(o.y)), int(::ceil(o.z))); } }; inline vec::vec(const ivec &v) : x(v.x), y(v.y), z(v.z) {} -static inline bool htcmp(const ivec &x, const ivec &y) -{ +static inline bool htcmp(const ivec &x, const ivec &y) { return x == y; } -static inline uint hthash(const ivec &k) -{ +static inline uint hthash(const ivec &k) { return k.x^k.y^k.z; } -struct ivec2 -{ - union - { +struct ivec2 { + union { struct { int x, y; }; int v[2]; }; - ivec2() {} ivec2(int x, int y) : x(x), y(y) {} explicit ivec2(const vec2 &v) : x(int(v.x)), y(int(v.y)) {} explicit ivec2(const ivec &v) : x(v.x), y(v.y) {} - - int &operator[](int i) { return v[i]; } + int &operator[](int i) { return v[i]; } int operator[](int i) const { return v[i]; } - bool operator==(const ivec2 &o) const { return x == o.x && y == o.y; } bool operator!=(const ivec2 &o) const { return x != o.x || y != o.y; } - bool iszero() const { return x==0 && y==0; } ivec2 &shl(int n) { x<<= n; y<<= n; return *this; } ivec2 &shr(int n) { x>>= n; y>>= n; return *this; } @@ -1243,74 +987,57 @@ struct ivec2 inline ivec::ivec(const ivec2 &v, int z) : x(v.x), y(v.y), z(z) {} -static inline bool htcmp(const ivec2 &x, const ivec2 &y) -{ +static inline bool htcmp(const ivec2 &x, const ivec2 &y) { return x == y; } -static inline uint hthash(const ivec2 &k) -{ +static inline uint hthash(const ivec2 &k) { return k.x^k.y; } -struct ivec4 -{ - union - { +struct ivec4 { + union { struct { int x, y, z, w; }; struct { int r, g, b, a; }; int v[4]; }; - ivec4() {} explicit ivec4(const ivec &p, int w = 0) : x(p.x), y(p.y), z(p.z), w(w) {} ivec4(int x, int y, int z, int w) : x(x), y(y), z(z), w(w) {} explicit ivec4(const vec4 &v) : x(int(v.x)), y(int(v.y)), z(int(v.z)), w(int(v.w)) {} - bool operator==(const ivec4 &o) const { return x == o.x && y == o.y && z == o.z && w == o.w; } bool operator!=(const ivec4 &o) const { return x != o.x || y != o.y || z != o.z || w != o.w; } }; inline ivec::ivec(const ivec4 &v) : x(v.x), y(v.y), z(v.z) {} -static inline bool htcmp(const ivec4 &x, const ivec4 &y) -{ +static inline bool htcmp(const ivec4 &x, const ivec4 &y) { return x == y; } -static inline uint hthash(const ivec4 &k) -{ +static inline uint hthash(const ivec4 &k) { return k.x^k.y^k.z^k.w; } struct bvec4; -struct bvec -{ - union - { +struct bvec { + union { struct { uchar x, y, z; }; struct { uchar r, g, b; }; uchar v[3]; }; - bvec() {} bvec(uchar x, uchar y, uchar z) : x(x), y(y), z(z) {} explicit bvec(const vec &v) : x(uchar((v.x+1)*(255.0f/2.0f))), y(uchar((v.y+1)*(255.0f/2.0f))), z(uchar((v.z+1)*(255.0f/2.0f))) {} explicit bvec(const bvec4 &v); - - uchar &operator[](int i) { return v[i]; } + uchar &operator[](int i) { return v[i]; } uchar operator[](int i) const { return v[i]; } - bool operator==(const bvec &v) const { return x==v.x && y==v.y && z==v.z; } bool operator!=(const bvec &v) const { return x!=v.x || y!=v.y || z!=v.z; } - bool iszero() const { return x==0 && y==0 && z==0; } - vec tonormal() const { return vec(x*(2.0f/255.0f)-1.0f, y*(2.0f/255.0f)-1.0f, z*(2.0f/255.0f)-1.0f); } - - bvec &normalize() - { + bvec &normalize() { vec n(x-127.5f, y-127.5f, z-127.5f); float mag = 127.5f/n.magnitude(); x = uchar(n.x*mag+127.5f); @@ -1318,193 +1045,144 @@ struct bvec z = uchar(n.z*mag+127.5f); return *this; } - void lerp(const bvec &a, const bvec &b, float t) { x = uchar(a.x + (b.x-a.x)*t); y = uchar(a.y + (b.y-a.y)*t); z = uchar(a.z + (b.z-a.z)*t); } - - void lerp(const bvec &a, const bvec &b, int ka, int kb, int d) - { + void lerp(const bvec &a, const bvec &b, int ka, int kb, int d) { x = uchar((a.x*ka + b.x*kb)/d); y = uchar((a.y*ka + b.y*kb)/d); z = uchar((a.z*ka + b.z*kb)/d); } - void flip() { x ^= 0x80; y ^= 0x80; z ^= 0x80; } - void scale(int k, int d) { x = uchar((x*k)/d); y = uchar((y*k)/d); z = uchar((z*k)/d); } - bvec &shl(int n) { x<<= n; y<<= n; z<<= n; return *this; } bvec &shr(int n) { x>>= n; y>>= n; z>>= n; return *this; } - static bvec fromcolor(const vec &v) { return bvec(uchar(v.x*255.0f), uchar(v.y*255.0f), uchar(v.z*255.0f)); } vec tocolor() const { return vec(x*(1.0f/255.0f), y*(1.0f/255.0f), z*(1.0f/255.0f)); } - static bvec from565(ushort c) { return bvec((((c>>11)&0x1F)*527 + 15) >> 6, (((c>>5)&0x3F)*259 + 35) >> 6, ((c&0x1F)*527 + 15) >> 6); } - - static bvec hexcolor(int color) - { + static bvec hexcolor(int color) { return bvec((color>>16)&0xFF, (color>>8)&0xFF, color&0xFF); } int tohexcolor() const { return (int(r)<<16)|(int(g)<<8)|int(b); } }; -struct bvec4 -{ - union - { +struct bvec4 { + union { struct { uchar x, y, z, w; }; struct { uchar r, g, b, a; }; uchar v[4]; uint mask; }; - bvec4() {} bvec4(uchar x, uchar y, uchar z, uchar w = 0) : x(x), y(y), z(z), w(w) {} bvec4(const bvec &v, uchar w = 0) : x(v.x), y(v.y), z(v.z), w(w) {} - - uchar &operator[](int i) { return v[i]; } + uchar &operator[](int i) { return v[i]; } uchar operator[](int i) const { return v[i]; } - bool operator==(const bvec4 &v) const { return mask==v.mask; } bool operator!=(const bvec4 &v) const { return mask!=v.mask; } - bool iszero() const { return mask==0; } - vec tonormal() const { return vec(x*(2.0f/255.0f)-1.0f, y*(2.0f/255.0f)-1.0f, z*(2.0f/255.0f)-1.0f); } - - void lerp(const bvec4 &a, const bvec4 &b, float t) - { + void lerp(const bvec4 &a, const bvec4 &b, float t) { x = uchar(a.x + (b.x-a.x)*t); y = uchar(a.y + (b.y-a.y)*t); z = uchar(a.z + (b.z-a.z)*t); w = a.w; } - - void lerp(const bvec4 &a, const bvec4 &b, int ka, int kb, int d) - { + void lerp(const bvec4 &a, const bvec4 &b, int ka, int kb, int d) { x = uchar((a.x*ka + b.x*kb)/d); y = uchar((a.y*ka + b.y*kb)/d); z = uchar((a.z*ka + b.z*kb)/d); w = a.w; } - void flip() { mask ^= 0x80808080; } }; inline bvec::bvec(const bvec4 &v) : x(v.x), y(v.y), z(v.z) {} -struct usvec -{ - union - { +struct usvec { + union { struct { ushort x, y, z; }; ushort v[3]; }; - ushort &operator[](int i) { return v[i]; } ushort operator[](int i) const { return v[i]; } }; inline ivec::ivec(const usvec &v) : x(v.x), y(v.y), z(v.z) {} -struct svec -{ - union - { +struct svec { + union { struct { short x, y, z; }; short v[3]; }; - svec() {} svec(short x, short y, short z) : x(x), y(y), z(z) {} explicit svec(const ivec &v) : x(v.x), y(v.y), z(v.z) {} - short &operator[](int i) { return v[i]; } short operator[](int i) const { return v[i]; } }; inline ivec::ivec(const svec &v) : x(v.x), y(v.y), z(v.z) {} -struct svec2 -{ - union - { +struct svec2 { + union { struct { short x, y; }; short v[2]; }; - svec2() {} svec2(short x, short y) : x(x), y(y) {} - short &operator[](int i) { return v[i]; } short operator[](int i) const { return v[i]; } - bool operator==(const svec2 &o) const { return x == o.x && y == o.y; } bool operator!=(const svec2 &o) const { return x != o.x || y != o.y; } - bool iszero() const { return x==0 && y==0; } }; -struct dvec4 -{ +struct dvec4 { double x, y, z, w; - dvec4() {} dvec4(double x, double y, double z, double w) : x(x), y(y), z(z), w(w) {} dvec4(const vec4 &v) : x(v.x), y(v.y), z(v.z), w(v.w) {} - template dvec4 &madd(const dvec4 &a, const B &b) { return add(dvec4(a).mul(b)); } - dvec4 &mul(double f) { x *= f; y *= f; z *= f; w *= f; return *this; } + dvec4 &mul(double f) { x *= f; y *= f; z *= f; w *= f; return *this; } dvec4 &mul(const dvec4 &o) { x *= o.x; y *= o.y; z *= o.z; w *= o.w; return *this; } - dvec4 &add(double f) { x += f; y += f; z += f; w += f; return *this; } + dvec4 &add(double f) { x += f; y += f; z += f; w += f; return *this; } dvec4 &add(const dvec4 &o) { x += o.x; y += o.y; z += o.z; w += o.w; return *this; } - operator vec4() const { return vec4(x, y, z, w); } }; -struct matrix4 -{ +struct matrix4 { vec4 a, b, c, d; - matrix4() {} matrix4(const float *m) : a(m), b(m+4), c(m+8), d(m+12) {} matrix4(const vec &a, const vec &b, const vec &c = vec(0, 0, 1)) - : a(a.x, b.x, c.x, 0), b(a.y, b.y, c.y, 0), c(a.z, b.z, c.z, 0), d(0, 0, 0, 1) - {} + : a(a.x, b.x, c.x, 0), b(a.y, b.y, c.y, 0), c(a.z, b.z, c.z, 0), d(0, 0, 0, 1) { + } matrix4(const vec4 &a, const vec4 &b, const vec4 &c, const vec4 &d = vec4(0, 0, 0, 1)) - : a(a), b(b), c(c), d(d) - {} + : a(a), b(b), c(c), d(d) { + } matrix4(const matrix4x3 &m) - : a(m.a, 0), b(m.b, 0), c(m.c, 0), d(m.d, 1) - {} + : a(m.a, 0), b(m.b, 0), c(m.c, 0), d(m.d, 1) { + } matrix4(const matrix3 &rot, const vec &trans) - : a(rot.a, 0), b(rot.b, 0), c(rot.c, 0), d(trans, 1) - {} - - void mul(const matrix4 &x, const matrix3 &y) - { + : a(rot.a, 0), b(rot.b, 0), c(rot.c, 0), d(trans, 1) { + } + void mul(const matrix4 &x, const matrix3 &y) { a = vec4(x.a).mul(y.a.x).madd(x.b, y.a.y).madd(x.c, y.a.z); b = vec4(x.a).mul(y.b.x).madd(x.b, y.b.y).madd(x.c, y.b.z); c = vec4(x.a).mul(y.c.x).madd(x.b, y.c.y).madd(x.c, y.c.z); d = x.d; } void mul(const matrix3 &y) { mul(matrix4(*this), y); } - - template void mult(const matrix4 &x, const matrix4 &y) - { + template void mult(const matrix4 &x, const matrix4 &y) { a = T(x.a).mul(y.a.x).madd(x.b, y.a.y).madd(x.c, y.a.z).madd(x.d, y.a.w); b = T(x.a).mul(y.b.x).madd(x.b, y.b.y).madd(x.c, y.b.z).madd(x.d, y.b.w); c = T(x.a).mul(y.c.x).madd(x.b, y.c.y).madd(x.c, y.c.z).madd(x.d, y.c.w); d = T(x.a).mul(y.d.x).madd(x.b, y.d.y).madd(x.c, y.d.z).madd(x.d, y.d.w); } - void mul(const matrix4 &x, const matrix4 &y) { mult(x, y); } void mul(const matrix4 &y) { mult(matrix4(*this), y); } - void muld(const matrix4 &x, const matrix4 &y) { mult(x, y); } void muld(const matrix4 &y) { mult(matrix4(*this), y); } - - void rotate_around_x(float ck, float sk) - { + void rotate_around_x(float ck, float sk) { vec4 rb = vec4(b).mul(ck).madd(c, sk), rc = vec4(c).mul(ck).msub(b, sk); b = rb; @@ -1512,9 +1190,7 @@ struct matrix4 } void rotate_around_x(float angle) { rotate_around_x(cosf(angle), sinf(angle)); } void rotate_around_x(const vec2 &sc) { rotate_around_x(sc.x, sc.y); } - - void rotate_around_y(float ck, float sk) - { + void rotate_around_y(float ck, float sk) { vec4 rc = vec4(c).mul(ck).madd(a, sk), ra = vec4(a).mul(ck).msub(c, sk); c = rc; @@ -1522,9 +1198,7 @@ struct matrix4 } void rotate_around_y(float angle) { rotate_around_y(cosf(angle), sinf(angle)); } void rotate_around_y(const vec2 &sc) { rotate_around_y(sc.x, sc.y); } - - void rotate_around_z(float ck, float sk) - { + void rotate_around_z(float ck, float sk) { vec4 ra = vec4(a).mul(ck).madd(b, sk), rb = vec4(b).mul(ck).msub(a, sk); a = ra; @@ -1532,68 +1206,51 @@ struct matrix4 } void rotate_around_z(float angle) { rotate_around_z(cosf(angle), sinf(angle)); } void rotate_around_z(const vec2 &sc) { rotate_around_z(sc.x, sc.y); } - - void rotate(float ck, float sk, const vec &axis) - { + void rotate(float ck, float sk, const vec &axis) { matrix3 m; m.rotate(ck, sk, axis); mul(m); } void rotate(float angle, const vec &dir) { rotate(cosf(angle), sinf(angle), dir); } void rotate(const vec2 &sc, const vec &dir) { rotate(sc.x, sc.y, dir); } - - void identity() - { + void identity() { a = vec4(1, 0, 0, 0); b = vec4(0, 1, 0, 0); c = vec4(0, 0, 1, 0); d = vec4(0, 0, 0, 1); } - void settranslation(const vec &v) { d.setxyz(v); } void settranslation(float x, float y, float z) { d.x = x; d.y = y; d.z = z; } - void translate(const vec &p) { d.madd(a, p.x).madd(b, p.y).madd(c, p.z); } void translate(float x, float y, float z) { translate(vec(x, y, z)); } void translate(const vec &p, float scale) { translate(vec(p).mul(scale)); } - void setscale(float x, float y, float z) { a.x = x; b.y = y; c.z = z; } void setscale(const vec &v) { setscale(v.x, v.y, v.z); } void setscale(float n) { setscale(n, n, n); } - - void scale(float x, float y, float z) - { + void scale(float x, float y, float z) { a.mul(x); b.mul(y); c.mul(z); } void scale(const vec &v) { scale(v.x, v.y, v.z); } void scale(float n) { scale(n, n, n); } - - void scalexy(float x, float y) - { + void scalexy(float x, float y) { a.x *= x; a.y *= y; b.x *= x; b.y *= y; c.x *= x; c.y *= y; d.x *= x; d.y *= y; } - - void scalez(float k) - { + void scalez(float k) { a.z *= k; b.z *= k; c.z *= k; d.z *= k; } - - void reflectz(float z) - { + void reflectz(float z) { d.add(vec4(c).mul(2*z)); c.neg(); } - - void projective(float zscale = 0.5f, float zoffset = 0.5f) - { + void projective(float zscale = 0.5f, float zoffset = 0.5f) { a.x = 0.5f*(a.x + a.w); a.y = 0.5f*(a.y + a.w); b.x = 0.5f*(b.x + b.w); @@ -1607,9 +1264,7 @@ struct matrix4 c.z = zscale*c.z + zoffset*c.w; d.z = zscale*d.z + zoffset*d.w; } - - void jitter(float x, float y) - { + void jitter(float x, float y) { a.x += x * a.w; a.y += y * a.w; b.x += x * b.w; @@ -1619,48 +1274,36 @@ struct matrix4 d.x += x * d.w; d.y += y * d.w; } - - void transpose() - { + void transpose() { swap(a.y, b.x); swap(a.z, c.x); swap(a.w, d.x); swap(b.z, c.y); swap(b.w, d.y); swap(c.w, d.z); } - - void transpose(const matrix4 &m) - { + void transpose(const matrix4 &m) { a = vec4(m.a.x, m.b.x, m.c.x, m.d.x); b = vec4(m.a.y, m.b.y, m.c.y, m.d.y); c = vec4(m.a.z, m.b.z, m.c.z, m.d.z); d = vec4(m.a.w, m.b.w, m.c.w, m.d.w); } - - void frustum(float left, float right, float bottom, float top, float znear, float zfar) - { + void frustum(float left, float right, float bottom, float top, float znear, float zfar) { float width = right - left, height = top - bottom, zrange = znear - zfar; a = vec4(2*znear/width, 0, 0, 0); b = vec4(0, 2*znear/height, 0, 0); c = vec4((right + left)/width, (top + bottom)/height, (zfar + znear)/zrange, -1); d = vec4(0, 0, 2*znear*zfar/zrange, 0); } - - void perspective(float fovy, float aspect, float znear, float zfar) - { + void perspective(float fovy, float aspect, float znear, float zfar) { float ydist = znear * tan(fovy/2*RAD), xdist = ydist * aspect; frustum(-xdist, xdist, -ydist, ydist, znear, zfar); } - - void ortho(float left, float right, float bottom, float top, float znear, float zfar) - { + void ortho(float left, float right, float bottom, float top, float znear, float zfar) { float width = right - left, height = top - bottom, zrange = znear - zfar; a = vec4(2/width, 0, 0, 0); b = vec4(0, 2/height, 0, 0); c = vec4(0, 0, 2/zrange, 0); d = vec4(-(right+left)/width, -(top+bottom)/height, (zfar+znear)/zrange, 1); } - - void clip(const plane &p, const matrix4 &m) - { + void clip(const plane &p, const matrix4 &m) { float x = ((p.x<0 ? -1 : (p.x>0 ? 1 : 0)) + m.c.x) / m.a.x, y = ((p.y<0 ? -1 : (p.y>0 ? 1 : 0)) + m.c.y) / m.b.y, w = (1 + m.c.z) / m.d.z, @@ -1670,134 +1313,96 @@ struct matrix4 c = vec4(m.c.x, m.c.y, p.z*scale + 1.0f, m.c.w); d = vec4(m.d.x, m.d.y, p.offset*scale, m.d.w); } - - void transform(const vec &in, vec &out) const - { + void transform(const vec &in, vec &out) const { out = vec(a).mul(in.x).add(vec(b).mul(in.y)).add(vec(c).mul(in.z)).add(vec(d)); } - - void transform(const vec4 &in, vec &out) const - { + void transform(const vec4 &in, vec &out) const { out = vec(a).mul(in.x).add(vec(b).mul(in.y)).add(vec(c).mul(in.z)).add(vec(d).mul(in.w)); } - - void transform(const vec &in, vec4 &out) const - { + void transform(const vec &in, vec4 &out) const { out = vec4(a).mul(in.x).madd(b, in.y).madd(c, in.z).add(d); } - - void transform(const vec4 &in, vec4 &out) const - { + void transform(const vec4 &in, vec4 &out) const { out = vec4(a).mul(in.x).madd(b, in.y).madd(c, in.z).madd(d, in.w); } - - template T transform(const U &in) const - { + template T transform(const U &in) const { T v; transform(in, v); return v; } - - template vec perspectivetransform(const T &in) const - { + template vec perspectivetransform(const T &in) const { vec4 v; transform(in, v); return vec(v).div(v.w); } - - void transformnormal(const vec &in, vec &out) const - { + void transformnormal(const vec &in, vec &out) const { out = vec(a).mul(in.x).add(vec(b).mul(in.y)).add(vec(c).mul(in.z)); } - - void transformnormal(const vec &in, vec4 &out) const - { + void transformnormal(const vec &in, vec4 &out) const { out = vec4(a).mul(in.x).madd(b, in.y).madd(c, in.z); } - - template T transformnormal(const U &in) const - { + template T transformnormal(const U &in) const { T v; transformnormal(in, v); return v; } - - void transposedtransform(const vec &in, vec &out) const - { + void transposedtransform(const vec &in, vec &out) const { vec p = vec(in).sub(vec(d)); out.x = a.dot3(p); out.y = b.dot3(p); out.z = c.dot3(p); } - - void transposedtransformnormal(const vec &in, vec &out) const - { + void transposedtransformnormal(const vec &in, vec &out) const { out.x = a.dot3(in); out.y = b.dot3(in); out.z = c.dot3(in); } - - void transposedtransform(const plane &in, plane &out) const - { + void transposedtransform(const plane &in, plane &out) const { out.x = in.dist(a); out.y = in.dist(b); out.z = in.dist(c); out.offset = in.dist(d); } - - float getscale() const - { + float getscale() const { return sqrtf(a.x*a.y + b.x*b.x + c.x*c.x); } - - vec gettranslation() const - { + vec gettranslation() const { return vec(d); } - vec4 rowx() const { return vec4(a.x, b.x, c.x, d.x); } vec4 rowy() const { return vec4(a.y, b.y, c.y, d.y); } vec4 rowz() const { return vec4(a.z, b.z, c.z, d.z); } vec4 roww() const { return vec4(a.w, b.w, c.w, d.w); } - bool invert(const matrix4 &m, double mindet = 1.0e-12); }; inline matrix3::matrix3(const matrix4 &m) - : a(m.a), b(m.b), c(m.c) -{} + : a(m.a), b(m.b), c(m.c) { +} inline matrix4x3::matrix4x3(const matrix4 &m) - : a(m.a), b(m.b), c(m.c), d(m.d) -{} + : a(m.a), b(m.b), c(m.c), d(m.d) { +} -struct matrix2 -{ +struct matrix2 { vec2 a, b; - matrix2() {} matrix2(const vec2 &a, const vec2 &b) : a(a), b(b) {} explicit matrix2(const matrix4 &m) : a(m.a), b(m.b) {} explicit matrix2(const matrix3 &m) : a(m.a), b(m.b) {} }; -struct squat -{ +struct squat { short x, y, z, w; - squat() {} squat(const vec4 &q) { convert(q); } - - void convert(const vec4 &q) - { + void convert(const vec4 &q) { x = short(q.x*32767.5f-0.5f); y = short(q.y*32767.5f-0.5f); z = short(q.z*32767.5f-0.5f); w = short(q.w*32767.5f-0.5f); } - - void lerp(const vec4 &a, const vec4 &b, float t) - { + void lerp(const vec4 &a, const vec4 &b, float t) { vec4 q; q.lerp(a, b, t); convert(q); @@ -1809,8 +1414,7 @@ extern bool rayboxintersect(const vec &b, const vec &s, const vec &o, const vec extern bool linecylinderintersect(const vec &from, const vec &to, const vec &start, const vec &end, float radius, float &dist); extern const vec2 sincos360[]; -static inline int mod360(int angle) -{ +static inline int mod360(int angle) { if(angle < 0) angle = 360 + (angle <= -360 ? angle%360 : angle); else if(angle >= 360) angle %= 360; return angle; diff --git a/src/shared/glemu.cpp b/src/shared/glemu.cpp index 58e071d..c728b9f 100644 --- a/src/shared/glemu.cpp +++ b/src/shared/glemu.cpp @@ -3,25 +3,18 @@ extern int glversion; extern int intel_mapbufferrange_bug; -namespace gle -{ - struct attribinfo - { +namespace gle { + struct attribinfo { int type, size, formatsize, offset; GLenum format; - attribinfo() : type(0), size(0), formatsize(0), offset(0), format(GL_FALSE) {} - - bool operator==(const attribinfo &a) const - { + bool operator==(const attribinfo &a) const { return type == a.type && size == a.size && format == a.format && offset == a.offset; } - bool operator!=(const attribinfo &a) const - { + bool operator!=(const attribinfo &a) const { return type != a.type || size != a.size || format != a.format || offset != a.offset; } }; - extern const char * const attribnames[MAXATTRIBS] = { "vvertex", "vcolor", "vtexcoord0", "vtexcoord1", "vnormal", "vtangent", "vboneweight", "vboneindex" }; ucharbuf attribbuf; static uchar *attribdata; @@ -33,33 +26,23 @@ namespace gle static bool changedattribs = false; static vector multidrawstart; static vector multidrawcount; - #define MAXQUADS (0x10000/4) static GLuint quadindexes = 0; static bool quadsenabled = false; - #define MAXVBOSIZE (4*1024*1024) static GLuint vbo = 0; static int vbooffset = MAXVBOSIZE; - static GLuint defaultvao = 0; - - void enablequads() - { + void enablequads() { quadsenabled = true; - if(glversion < 300) return; - - if(quadindexes) - { + if(quadindexes) { glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER, quadindexes); return; } - glGenBuffers_(1, &quadindexes); ushort *data = new ushort[MAXQUADS*6], *dst = data; - for(int idx = 0; idx < MAXQUADS*4; idx += 4, dst += 6) - { + for(int idx = 0; idx < MAXQUADS*4; idx += 4, dst += 6) { dst[0] = idx; dst[1] = idx + 1; dst[2] = idx + 2; @@ -71,36 +54,25 @@ namespace gle glBufferData_(GL_ELEMENT_ARRAY_BUFFER, MAXQUADS*6*sizeof(ushort), data, GL_STATIC_DRAW); delete[] data; } - - void disablequads() - { + void disablequads() { quadsenabled = false; - if(glversion < 300) return; - glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER, 0); } - - void drawquads(int offset, int count) - { + void drawquads(int offset, int count) { if(count <= 0) return; - if(glversion < 300) - { + if(glversion < 300) { glDrawArrays(GL_QUADS, offset*4, count*4); return; } - if(offset + count > MAXQUADS) - { + if(offset + count > MAXQUADS) { if(offset >= MAXQUADS) return; count = MAXQUADS - offset; } glDrawRangeElements_(GL_TRIANGLES, offset*4, (offset + count)*4-1, count*6, GL_UNSIGNED_SHORT, (ushort *)0 + offset*6); } - - void defattrib(int type, int size, int format) - { - if(type == ATTRIB_VERTEX) - { + void defattrib(int type, int size, int format) { + if(type == ATTRIB_VERTEX) { numattribs = attribmask = 0; vertexsize = 0; } @@ -110,8 +82,7 @@ namespace gle a.type = type; a.size = size; a.format = format; - switch(format) - { + switch(format) { case 'B': case GL_UNSIGNED_BYTE: a.formatsize = 1; a.format = GL_UNSIGNED_BYTE; break; case 'b': case GL_BYTE: a.formatsize = 1; a.format = GL_BYTE; break; case 'S': case GL_UNSIGNED_SHORT: a.formatsize = 2; a.format = GL_UNSIGNED_SHORT; break; @@ -126,14 +97,10 @@ namespace gle a.offset = vertexsize; vertexsize += a.formatsize; } - - void defattribs(const char *fmt) - { - for(;; fmt += 3) - { + void defattribs(const char *fmt) { + for(;; fmt += 3) { GLenum format; - switch(fmt[0]) - { + switch(fmt[0]) { case 'v': format = ATTRIB_VERTEX; break; case 'c': format = ATTRIB_COLOR; break; case 't': format = ATTRIB_TEXCOORD0; break; @@ -147,11 +114,8 @@ namespace gle defattrib(format, fmt[1]-'0', fmt[2]); } } - - static inline void setattrib(const attribinfo &a, uchar *buf) - { - switch(a.type) - { + static inline void setattrib(const attribinfo &a, uchar *buf) { + switch(a.type) { case ATTRIB_VERTEX: case ATTRIB_TEXCOORD0: case ATTRIB_TEXCOORD1: @@ -165,36 +129,27 @@ namespace gle glVertexAttribPointer_(a.type, a.size, a.format, GL_TRUE, vertexsize, buf); break; } - if(!(enabled&(1<= 300 && !intel_mapbufferrange_bug) - { + if(glversion >= 300 && !intel_mapbufferrange_bug) { int len = numverts * vertexsize; - if(vbooffset + len >= MAXVBOSIZE) - { + if(vbooffset + len >= MAXVBOSIZE) { len = min(len, MAXVBOSIZE); if(!vbo) glGenBuffers_(1, &vbo); glBindBuffer_(GL_ARRAY_BUFFER, vbo); @@ -232,37 +181,27 @@ namespace gle if(buf) attribbuf.reset((uchar *)buf, len); } } - - void multidraw() - { + void multidraw() { int start = multidrawstart.length() ? multidrawstart.last() + multidrawcount.last() : 0, count = attribbuf.length()/vertexsize - start; - if(count > 0) - { + if(count > 0) { multidrawstart.add(start); multidrawcount.add(count); } } - - int end() - { + int end() { uchar *buf = attribbuf.getbuf(); - if(attribbuf.empty()) - { - if(buf != attribdata) - { + if(attribbuf.empty()) { + if(buf != attribdata) { glUnmapBuffer_(GL_ARRAY_BUFFER); attribbuf.reset(attribdata, MAXVBOSIZE); } return 0; } int start = 0; - if(glversion >= 300) - { - if(buf == attribdata) - { - if(vbooffset + attribbuf.length() >= MAXVBOSIZE) - { + if(glversion >= 300) { + if(buf == attribdata) { + if(vbooffset + attribbuf.length() >= MAXVBOSIZE) { if(!vbo) glGenBuffers_(1, &vbo); glBindBuffer_(GL_ARRAY_BUFFER, vbo); glBufferData_(GL_ARRAY_BUFFER, MAXVBOSIZE, NULL, GL_STREAM_DRAW); @@ -271,8 +210,7 @@ namespace gle else if(!lastvertexsize) glBindBuffer_(GL_ARRAY_BUFFER, vbo); void *dst = intel_mapbufferrange_bug ? NULL : glMapBufferRange_(GL_ARRAY_BUFFER, vbooffset, attribbuf.length(), GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_RANGE_BIT|GL_MAP_UNSYNCHRONIZED_BIT); - if(dst) - { + if(dst) { memcpy(dst, attribbuf.getbuf(), attribbuf.length()); glUnmapBuffer_(GL_ARRAY_BUFFER); } @@ -280,8 +218,7 @@ namespace gle } else glUnmapBuffer_(GL_ARRAY_BUFFER); buf = (uchar *)0 + vbooffset; - if(vertexsize == lastvertexsize && buf >= lastbuf) - { + if(vertexsize == lastvertexsize && buf >= lastbuf) { start = int(buf - lastbuf)/vertexsize; if(primtype == GL_QUADS && (start%4 || start + attribbuf.length()/vertexsize >= 4*MAXQUADS)) start = 0; @@ -291,11 +228,9 @@ namespace gle } setattribs(buf); int numvertexes = attribbuf.length()/vertexsize; - if(primtype == GL_QUADS) - { + if(primtype == GL_QUADS) { if(!quadsenabled) enablequads(); - for(int quads = numvertexes/4;;) - { + for(int quads = numvertexes/4;;) { int count = min(quads, MAXQUADS); drawquads(start/4, count); quads -= count; @@ -304,10 +239,8 @@ namespace gle start = 0; } } - else - { - if(multidrawstart.length()) - { + else { + if(multidrawstart.length()) { multidraw(); if(start) loopv(multidrawstart) multidrawstart[i] += start; glMultiDrawArrays_(primtype, multidrawstart.getbuf(), multidrawcount.getbuf(), multidrawstart.length()); @@ -319,36 +252,26 @@ namespace gle attribbuf.reset(attribdata, MAXVBOSIZE); return numvertexes; } - - void forcedisable() - { + void forcedisable() { for(int i = 0; enabled; i++) if(enabled&(1<= 300) glBindBuffer_(GL_ARRAY_BUFFER, 0); } - - void setup() - { - if(glversion >= 300) - { + void setup() { + if(glversion >= 300) { if(!defaultvao) glGenVertexArrays_(1, &defaultvao); glBindVertexArray_(defaultvao); } attribdata = new uchar[MAXVBOSIZE]; attribbuf.reset(attribdata, MAXVBOSIZE); } - - void cleanup() - { + void cleanup() { disable(); - if(quadindexes) { glDeleteBuffers_(1, &quadindexes); quadindexes = 0; } - if(vbo) { glDeleteBuffers_(1, &vbo); vbo = 0; } vbooffset = MAXVBOSIZE; - if(defaultvao) { glDeleteVertexArrays_(1, &defaultvao); defaultvao = 0; } } } diff --git a/src/shared/glemu.h b/src/shared/glemu.h index e4f4d26..be4ea9f 100644 --- a/src/shared/glemu.h +++ b/src/shared/glemu.h @@ -1,7 +1,5 @@ -namespace gle -{ - enum - { +namespace gle { + enum { ATTRIB_VERTEX = 0, ATTRIB_COLOR = 1, ATTRIB_TEXCOORD0 = 2, @@ -12,22 +10,17 @@ namespace gle ATTRIB_BONEINDEX = 7, MAXATTRIBS = 8 }; - extern const char * const attribnames[MAXATTRIBS]; extern ucharbuf attribbuf; - extern int enabled; extern void forcedisable(); static inline void disable() { if(enabled) forcedisable(); } - extern void begin(GLenum mode); extern void begin(GLenum mode, int numverts); extern void defattribs(const char *fmt); extern void defattrib(int type, int size, int format); - #define GLE_DEFATTRIB(name, type, defaultsize, defaultformat) \ static inline void def##name(int size = defaultsize, int format = defaultformat) { defattrib(type, size, format); } - GLE_DEFATTRIB(vertex, ATTRIB_VERTEX, 3, GL_FLOAT) GLE_DEFATTRIB(color, ATTRIB_COLOR, 3, GL_FLOAT) GLE_DEFATTRIB(texcoord0, ATTRIB_TEXCOORD0, 2, GL_FLOAT) @@ -36,7 +29,6 @@ namespace gle GLE_DEFATTRIB(tangent, ATTRIB_TANGENT, 4, GL_FLOAT) GLE_DEFATTRIB(boneweight, ATTRIB_BONEWEIGHT, 4, GL_UNSIGNED_BYTE) GLE_DEFATTRIB(boneindex, ATTRIB_BONEINDEX, 4, GL_UNSIGNED_BYTE) - #define GLE_INITATTRIB(name, index, suffix, type) \ static inline void name##suffix(type x) { glVertexAttrib1##suffix##_(index, x); } \ static inline void name##suffix(type x, type y) { glVertexAttrib2##suffix##_(index, x, y); } \ @@ -50,7 +42,6 @@ namespace gle static inline void name(const vec4 &v) { glVertexAttrib4fv_(index, v.v); } #define GLE_INITATTRIBN(name, index, suffix, type, defaultw) \ static inline void name##suffix(type x, type y, type z, type w = defaultw) { glVertexAttrib4N##suffix##_(index, x, y, z, w); } - GLE_INITATTRIBF(vertex, ATTRIB_VERTEX) GLE_INITATTRIBF(color, ATTRIB_COLOR) static inline void color(const bvec4 &v) { glVertexAttrib4Nubv_(ATTRIB_COLOR, v.v); } @@ -63,7 +54,6 @@ namespace gle static inline void tangent(float x, float y, float z, float w = 1.0f) { glVertexAttrib4f_(ATTRIB_TANGENT, x, y, z, w); } static inline void tangent(const vec &v, float w = 1.0f) { glVertexAttrib4f_(ATTRIB_TANGENT, v.x, v.y, v.z, w); } static inline void tangent(const vec4 &v) { glVertexAttrib4fv_(ATTRIB_TANGENT, v.v); } - #define GLE_ATTRIBPOINTER(name, index, defaultnormalized, defaultsize, defaulttype, prepare) \ static inline void enable##name() { prepare; glEnableVertexAttribArray_(index); } \ static inline void disable##name() { glDisableVertexAttribArray_(index); } \ @@ -71,7 +61,6 @@ namespace gle prepare; \ glVertexAttribPointer_(index, size, type, normalized, stride, data); \ } - static inline void enableattrib(int index) { disable(); glEnableVertexAttribArray_(index); } static inline void disableattrib(int index) { glDisableVertexAttribArray_(index); } GLE_ATTRIBPOINTER(vertex, ATTRIB_VERTEX, GL_FALSE, 3, GL_FLOAT, disable()) @@ -82,50 +71,37 @@ namespace gle GLE_ATTRIBPOINTER(tangent, ATTRIB_TANGENT, GL_TRUE, 4, GL_FLOAT, ) GLE_ATTRIBPOINTER(boneweight, ATTRIB_BONEWEIGHT, GL_TRUE, 4, GL_UNSIGNED_BYTE, ) GLE_ATTRIBPOINTER(boneindex, ATTRIB_BONEINDEX, GL_FALSE, 4, GL_UNSIGNED_BYTE, ) - static inline void bindebo(GLuint ebo) { disable(); glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER, ebo); } static inline void clearebo() { glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER, 0); } static inline void bindvbo(GLuint vbo) { disable(); glBindBuffer_(GL_ARRAY_BUFFER, vbo); } static inline void clearvbo() { glBindBuffer_(GL_ARRAY_BUFFER, 0); } - template - static inline void attrib(T x) - { - if(attribbuf.check(sizeof(T))) - { + static inline void attrib(T x) { + if(attribbuf.check(sizeof(T))) { T *buf = (T *)attribbuf.pad(sizeof(T)); buf[0] = x; } } - template - static inline void attrib(T x, T y) - { - if(attribbuf.check(2*sizeof(T))) - { + static inline void attrib(T x, T y) { + if(attribbuf.check(2*sizeof(T))) { T *buf = (T *)attribbuf.pad(2*sizeof(T)); buf[0] = x; buf[1] = y; } } - template - static inline void attrib(T x, T y, T z) - { - if(attribbuf.check(3*sizeof(T))) - { + static inline void attrib(T x, T y, T z) { + if(attribbuf.check(3*sizeof(T))) { T *buf = (T *)attribbuf.pad(3*sizeof(T)); buf[0] = x; buf[1] = y; buf[2] = z; } } - template - static inline void attrib(T x, T y, T z, T w) - { - if(attribbuf.check(4*sizeof(T))) - { + static inline void attrib(T x, T y, T z, T w) { + if(attribbuf.check(4*sizeof(T))) { T *buf = (T *)attribbuf.pad(4*sizeof(T)); buf[0] = x; buf[1] = y; @@ -133,19 +109,15 @@ namespace gle buf[3] = w; } } - template - static inline void attribv(const T *v) - { + static inline void attribv(const T *v) { attribbuf.put((const uchar *)v, N*sizeof(T)); } - #define GLE_ATTRIB(suffix, type) \ static inline void attrib##suffix(type x) { attrib(x); } \ static inline void attrib##suffix(type x, type y) { attrib(x, y); } \ static inline void attrib##suffix(type x, type y, type z) { attrib(x, y, z); } \ static inline void attrib##suffix(type x, type y, type z, type w) { attrib(x, y, z, w); } - GLE_ATTRIB(f, float) GLE_ATTRIB(d, double) GLE_ATTRIB(b, char) @@ -154,7 +126,6 @@ namespace gle GLE_ATTRIB(us, ushort) GLE_ATTRIB(i, int) GLE_ATTRIB(ui, uint) - static inline void attrib(const vec &v) { attribf(v.x, v.y, v.z); } static inline void attrib(const vec &v, float w) { attribf(v.x, v.y, v.z, w); } static inline void attrib(const vec2 &v) { attribf(v.x, v.y); } @@ -166,14 +137,11 @@ namespace gle static inline void attrib(const bvec &b) { attribub(b.x, b.y, b.z); } static inline void attrib(const bvec &b, uchar w) { attribub(b.x, b.y, b.z, w); } static inline void attrib(const bvec4 &b) { attribub(b.x, b.y, b.z, b.w); } - extern void multidraw(); extern int end(); - extern void enablequads(); extern void disablequads(); extern void drawquads(int offset, int count); - extern void setup(); extern void cleanup(); } diff --git a/src/shared/iengine.h b/src/shared/iengine.h index 74a6634..f4e822d 100644 --- a/src/shared/iengine.h +++ b/src/shared/iengine.h @@ -7,25 +7,20 @@ extern int totalmillis; // total elapsed time extern uint totalsecs; extern int gamespeed, paused; -enum -{ +enum { MATF_INDEX_SHIFT = 0, MATF_CLIP_SHIFT = 5, MATF_FLAG_SHIFT = 8, - MATF_INDEX = 3 << MATF_INDEX_SHIFT, MATF_CLIP = 7 << MATF_CLIP_SHIFT, MATF_FLAGS = 0xFF << MATF_FLAG_SHIFT }; -enum // cube empty-space materials -{ +enum { // cube empty-space materials { MAT_AIR = 0, // the default, fill the empty space with air - MAT_NOCLIP = 1 << MATF_CLIP_SHIFT, // collisions always treat cube as empty MAT_CLIP = 2 << MATF_CLIP_SHIFT, // collisions always treat cube as solid MAT_GAMECLIP = 3 << MATF_CLIP_SHIFT, // game specific clip material - MAT_DEATH = 1 << MATF_FLAG_SHIFT, // force player suicide MAT_ALPHA = 4 << MATF_FLAG_SHIFT // alpha blended }; @@ -50,8 +45,7 @@ extern bool settexture(const char *name, int clamp = 0); enum { EDIT_FACE = 0, EDIT_TEX, EDIT_MAT, EDIT_FLIP, EDIT_COPY, EDIT_PASTE, EDIT_ROTATE, EDIT_REPLACE, EDIT_DELCUBE, EDIT_REMIP, EDIT_VSLOT, EDIT_UNDO, EDIT_REDO }; -struct selinfo -{ +struct selinfo { int corner; int cx, cxs, cy, cys; ivec o, s; @@ -60,8 +54,7 @@ struct selinfo int size() const { return s.x*s.y*s.z; } int us(int d) const { return s[d]*grid; } bool operator==(const selinfo &sel) const { return o==sel.o && s==sel.s && grid==sel.grid && orient==sel.orient; } - bool validate() - { + bool validate() { extern int worldsize; if(grid <= 0 || grid >= worldsize) return false; if(o.x >= worldsize || o.y >= worldsize || o.z >= worldsize) return false; @@ -176,15 +169,13 @@ static inline void loopiter(ident *id, identstack &stack, const char *s) { tagva // console -enum -{ +enum { CON_INFO = 1<<0, CON_WARN = 1<<1, CON_ERROR = 1<<2, CON_DEBUG = 1<<3, CON_INIT = 1<<4, CON_ECHO = 1<<5, - CON_FLAGS = 0xFFFF, CON_TAG_SHIFT = 16, CON_TAG_MASK = (0x7FFF << CON_TAG_SHIFT) @@ -210,14 +201,12 @@ extern int cleargui(int n = 0); // octa extern int lookupmaterial(const vec &o); -static inline bool insideworld(const vec &o) -{ +static inline bool insideworld(const vec &o) { extern int worldsize; return o.x>=0 && o.x=0 && o.y=0 && o.z &args); - extern void gamedisconnect(bool cleanup); extern void parsepacketclient(int chan, packetbuf &p); extern void connectattempt(const char *name, const char *password, const ENetAddress &address); @@ -36,7 +33,6 @@ namespace game extern bool ispaused(); extern int scaletime(int t); extern bool allowmouselook(); - extern const char *gameident(); extern const char *savedconfig(); extern const char *restoreconfig(); @@ -44,7 +40,6 @@ namespace game extern const char *autoexec(); extern const char *savedservers(); extern void loadconfigs(); - extern void updateworld(); extern void initclient(); extern void physicstrigger(physent *d, bool local, int floorlevel, int material = 0); @@ -92,8 +87,7 @@ namespace game extern bool serverinfoentry(g3d_gui *g, int i, const char *name, int port, const char *desc, const char *map, int ping, const vector &attr, int np); } -namespace server -{ +namespace server { extern void *newclientinfo(); extern void deleteclientinfo(void *ci); extern void serverinit(); @@ -115,7 +109,7 @@ namespace server extern int serverport(int infoport = -1); extern const char *defaultmaster(); extern int masterport(); - extern void processmasterinput(const char *cmd, int cmdlen, const char *args); + extern void processmasterinput(const char *cmd, int cmdlen); extern void masterconnected(); extern void masterdisconnected(); extern bool ispaused(); diff --git a/src/shared/stream.cpp b/src/shared/stream.cpp index 8f218ad..1878801 100644 --- a/src/shared/stream.cpp +++ b/src/shared/stream.cpp @@ -2,24 +2,21 @@ ///////////////////////////// console //////////////////////// -void conoutf(const char *fmt, ...) -{ +void conoutf(const char *fmt, ...) { va_list args; va_start(args, fmt); conoutfv(CON_INFO, fmt, args); va_end(args); } -void conoutf(int type, const char *fmt, ...) -{ +void conoutf(int type, const char *fmt, ...) { va_list args; va_start(args, fmt); conoutfv(type, fmt, args); va_end(args); } -void conoutf(int type, int tag, const char *fmt, ...) -{ +void conoutf(int type, int tag, const char *fmt, ...) { va_list args; va_start(args, fmt); conoutfv(type | ((tag << CON_TAG_SHIFT) & CON_TAG_MASK), fmt, args); @@ -46,8 +43,7 @@ void conoutf(int type, int tag, const char *fmt, ...) U, U, U, U, u, u, u, u, u, u, u, u, u, u, u, u, \ u, u, u, u, u, u, u, u, u, u, u, u, u, u, U, u -extern const uchar cubectype[256] = -{ +extern const uchar cubectype[256] = { CUBECTYPE(CT_SPACE, CT_PRINT, CT_PRINT|CT_DIGIT, @@ -56,8 +52,7 @@ extern const uchar cubectype[256] = CT_PRINT|CT_UNICODE|CT_ALPHA|CT_LOWER, CT_PRINT|CT_UNICODE|CT_ALPHA|CT_UPPER) }; -extern const int cube2unichars[256] = -{ +extern const int cube2unichars[256] = { 0, 192, 193, 194, 195, 196, 197, 198, 199, 9, 10, 11, 12, 13, 200, 201, 202, 203, 204, 205, 206, 207, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, @@ -75,12 +70,10 @@ extern const int cube2unichars[256] = 0x42C, 0x42D, 0x42E, 0x42F, 0x431, 0x432, 0x433, 0x434, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43F, 0x442, 0x444, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x454, 0x490, 0x491 }; -extern const int uni2cubeoffsets[8] = -{ +extern const int uni2cubeoffsets[8] = { 0, 256, 658, 658, 512, 658, 658, 658 }; -extern const uchar uni2cubechars[878] = -{ +extern const uchar uni2cubechars[878] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 11, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, @@ -110,8 +103,7 @@ extern const uchar uni2cubechars[878] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -extern const uchar cubelowerchars[256] = -{ +extern const uchar cubelowerchars[256] = { 0, 130, 131, 132, 133, 134, 135, 136, 137, 9, 10, 11, 12, 13, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, @@ -129,8 +121,7 @@ extern const uchar cubelowerchars[256] = 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 }; -extern const uchar cubeupperchars[256] = -{ +extern const uchar cubeupperchars[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, @@ -149,12 +140,10 @@ extern const uchar cubeupperchars[256] = 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 }; -size_t decodeutf8(uchar *dstbuf, size_t dstlen, const uchar *srcbuf, size_t srclen, size_t *carry) -{ +size_t decodeutf8(uchar *dstbuf, size_t dstlen, const uchar *srcbuf, size_t srclen, size_t *carry) { uchar *dst = dstbuf, *dstend = &dstbuf[dstlen]; const uchar *src = srcbuf, *srcend = &srcbuf[srclen]; - if(dstbuf == srcbuf) - { + if(dstbuf == srcbuf) { int len = min(dstlen, srclen); for(const uchar *end4 = &srcbuf[len&~3]; src < end4; src += 4) if(*(const int *)src & 0x80808080) goto decode; for(const uchar *end = &srcbuf[len]; src < end; src++) if(*src & 0x80) goto decode; @@ -164,21 +153,15 @@ size_t decodeutf8(uchar *dstbuf, size_t dstlen, const uchar *srcbuf, size_t srcl decode: dst += src - srcbuf; - while(src < srcend && dst < dstend) - { + while(src < srcend && dst < dstend) { int c = *src++; if(c < 0x80) *dst++ = c; - else if(c >= 0xC0) - { + else if(c >= 0xC0) { int uni; - if(c >= 0xE0) - { - if(c >= 0xF0) - { - if(c >= 0xF8) - { - if(c >= 0xFC) - { + if(c >= 0xE0) { + if(c >= 0xF0) { + if(c >= 0xF8) { + if(c >= 0xFC) { if(c >= 0xFE) continue; uni = c&1; if(srcend - src < 5) break; c = *src; if((c&0xC0) != 0x80) continue; src++; uni = (uni<<6) | (c&0x3F); @@ -203,21 +186,16 @@ decode: return dst - dstbuf; } -size_t encodeutf8(uchar *dstbuf, size_t dstlen, const uchar *srcbuf, size_t srclen, size_t *carry) -{ +size_t encodeutf8(uchar *dstbuf, size_t dstlen, const uchar *srcbuf, size_t srclen, size_t *carry) { uchar *dst = dstbuf, *dstend = &dstbuf[dstlen]; const uchar *src = srcbuf, *srcend = &srcbuf[srclen]; - if(src < srcend && dst < dstend) do - { + if(src < srcend && dst < dstend) do { int uni = cube2uni(*src); - if(uni <= 0x7F) - { + if(uni <= 0x7F) { if(dst >= dstend) goto done; const uchar *end = min(srcend, &src[dstend-dst]); - do - { - if(uni == '\f') - { + do { + if(uni == '\f') { if(++src >= srcend) goto done; goto uni1; } @@ -255,31 +233,26 @@ done: #include string homedir = ""; -struct packagedir -{ +struct packagedir { char *dir, *filter; size_t dirlen, filterlen; }; vector packagedirs; -char *makerelpath(const char *dir, const char *file, const char *prefix, const char *cmd) -{ +char *makerelpath(const char *dir, const char *file, const char *prefix, const char *cmd) { static string tmp; if(prefix) copystring(tmp, prefix); else tmp[0] = '\0'; - if(file[0]=='<') - { + if(file[0]=='<') { const char *end = strrchr(file, '>'); - if(end) - { + if(end) { size_t len = strlen(tmp); copystring(&tmp[len], file, min(sizeof(tmp)-len, size_t(end+2-file))); file = end+1; } } if(cmd) concatstring(tmp, cmd); - if(dir) - { + if(dir) { defformatstring(pname, "%s/%s", dir, file); concatstring(tmp, pname); } @@ -288,43 +261,35 @@ char *makerelpath(const char *dir, const char *file, const char *prefix, const c } -char *path(char *s) -{ - for(char *curpart = s;;) - { +char *path(char *s) { + for(char *curpart = s;;) { char *endpart = strchr(curpart, '&'); if(endpart) *endpart = '\0'; - if(curpart[0]=='<') - { + if(curpart[0]=='<') { char *file = strrchr(curpart, '>'); if(!file) return s; curpart = file+1; } for(char *t = curpart; (t = strpbrk(t, "/\\")); *t++ = PATHDIV); - for(char *prevdir = NULL, *curdir = curpart;;) - { + for(char *prevdir = NULL, *curdir = curpart;;) { prevdir = curdir[0]==PATHDIV ? curdir+1 : curdir; curdir = strchr(prevdir, PATHDIV); if(!curdir) break; - if(prevdir+1==curdir && prevdir[0]=='.') - { + if(prevdir+1==curdir && prevdir[0]=='.') { memmove(prevdir, curdir+1, strlen(curdir+1)+1); curdir = prevdir; } - else if(curdir[1]=='.' && curdir[2]=='.' && curdir[3]==PATHDIV) - { + else if(curdir[1]=='.' && curdir[2]=='.' && curdir[3]==PATHDIV) { if(prevdir+2==curdir && prevdir[0]=='.' && prevdir[1]=='.') continue; memmove(prevdir, curdir+4, strlen(curdir+4)+1); - if(prevdir-2 >= curpart && prevdir[-1]==PATHDIV) - { + if(prevdir-2 >= curpart && prevdir[-1]==PATHDIV) { prevdir -= 2; while(prevdir-1 >= curpart && prevdir[-1] != PATHDIV) --prevdir; } curdir = prevdir; } } - if(endpart) - { + if(endpart) { *endpart = '&'; curpart = endpart+1; } @@ -333,16 +298,14 @@ char *path(char *s) return s; } -char *path(const char *s, bool copy) -{ +char *path(const char *s, bool copy) { static string tmp; copystring(tmp, s); path(tmp); return tmp; } -const char *parentdir(const char *directory) -{ +const char *parentdir(const char *directory) { const char *p = directory + strlen(directory); while(p > directory && *p != '/' && *p != '\\') p--; static string parent; @@ -351,43 +314,36 @@ const char *parentdir(const char *directory) return parent; } -bool fileexists(const char *path, const char *mode) -{ +bool fileexists(const char *path, const char *mode) { bool exists = true; if(mode[0]=='w' || mode[0]=='a') path = parentdir(path); if(access(path[0] ? path : ".", mode[0]=='w' || mode[0]=='a' ? W_OK : (mode[0]=='d' ? X_OK : R_OK)) == -1) exists = false; return exists; } -bool createdir(const char *path) -{ +bool createdir(const char *path) { size_t len = strlen(path); - if(path[len-1]==PATHDIV) - { + if(path[len-1]==PATHDIV) { static string strip; path = copystring(strip, path, len); } return mkdir(path, 0777)==0; } -size_t fixpackagedir(char *dir) -{ +size_t fixpackagedir(char *dir) { path(dir); size_t len = strlen(dir); - if(len > 0 && dir[len-1] != PATHDIV) - { + if(len > 0 && dir[len-1] != PATHDIV) { dir[len] = PATHDIV; dir[len+1] = '\0'; } return len; } -bool subhomedir(char *dst, int len, const char *src) -{ +bool subhomedir(char *dst, int len, const char *src) { const char *sub = strstr(src, "$HOME"); if(!sub) sub = strchr(src, '~'); - if(sub && sub-src < len) - { + if(sub && sub-src < len) { const char *home = getenv("HOME"); if(!home || !home[0]) return false; dst[sub-src] = '\0'; @@ -397,8 +353,7 @@ bool subhomedir(char *dst, int len, const char *src) return true; } -const char *sethomedir(const char *dir) -{ +const char *sethomedir(const char *dir) { string pdir; copystring(pdir, dir); if(!subhomedir(pdir, sizeof(pdir), dir) || !fixpackagedir(pdir)) return NULL; @@ -406,14 +361,12 @@ const char *sethomedir(const char *dir) return homedir; } -const char *addpackagedir(const char *dir) -{ +const char *addpackagedir(const char *dir) { string pdir; copystring(pdir, dir); if(!subhomedir(pdir, sizeof(pdir), dir) || !fixpackagedir(pdir)) return NULL; char *filter = pdir; - for(;;) - { + for(;;) { static int len = strlen("packages"); filter = strstr(filter, "packages"); if(!filter) break; @@ -428,20 +381,16 @@ const char *addpackagedir(const char *dir) return pf.dir; } -const char *findfile(const char *filename, const char *mode) -{ +const char *findfile(const char *filename, const char *mode) { static string s; - if(homedir[0]) - { + if(homedir[0]) { formatstring(s, "%s%s", homedir, filename); if(fileexists(s, mode)) return s; - if(mode[0]=='w' || mode[0]=='a') - { + if(mode[0]=='w' || mode[0]=='a') { string dirs; copystring(dirs, s); char *dir = strchr(dirs[0]==PATHDIV ? dirs+1 : dirs, PATHDIV); - while(dir) - { + while(dir) { *dir = '\0'; if(!fileexists(dirs, "d") && !createdir(dirs)) return s; *dir = PATHDIV; @@ -451,8 +400,7 @@ const char *findfile(const char *filename, const char *mode) } } if(mode[0]=='w' || mode[0]=='a') return filename; - loopv(packagedirs) - { + loopv(packagedirs) { packagedir &pf = packagedirs[i]; if(pf.filter && strncmp(filename, pf.filter, pf.filterlen)) continue; formatstring(s, "%s%s", pf.dir, filename); @@ -462,22 +410,17 @@ const char *findfile(const char *filename, const char *mode) return filename; } -bool listdir(const char *dirname, bool rel, const char *ext, vector &files) -{ +bool listdir(const char *dirname, bool rel, const char *ext, vector &files) { size_t extsize = ext ? strlen(ext)+1 : 0; defformatstring(pathname, rel ? "./%s" : "%s", dirname); DIR *d = opendir(pathname); - if(d) - { + if(d) { struct dirent *de; - while((de = readdir(d)) != NULL) - { + while((de = readdir(d)) != NULL) { if(!ext) files.add(newstring(de->d_name)); - else - { + else { size_t namelen = strlen(de->d_name); - if(namelen > extsize) - { + if(namelen > extsize) { namelen -= extsize; if(de->d_name[namelen] == '.' && strncmp(de->d_name+namelen+1, ext, extsize-1)==0) files.add(newstring(de->d_name, namelen)); @@ -490,8 +433,7 @@ bool listdir(const char *dirname, bool rel, const char *ext, vector &fil else return false; } -int listfiles(const char *dir, const char *ext, vector &files) -{ +int listfiles(const char *dir, const char *ext, vector &files) { string dirname; copystring(dirname, dir); path(dirname); @@ -500,13 +442,11 @@ int listfiles(const char *dir, const char *ext, vector &files) int dirs = 0; if(listdir(dirname, true, ext, files)) dirs++; string s; - if(homedir[0]) - { + if(homedir[0]) { formatstring(s, "%s%s", homedir, dirname); if(listdir(s, false, ext, files)) dirs++; } - loopv(packagedirs) - { + loopv(packagedirs) { packagedir &pf = packagedirs[i]; if(pf.filter && strncmp(dirname, pf.filter, dirlen == pf.filterlen-1 ? dirlen : pf.filterlen)) continue; @@ -520,32 +460,27 @@ int listfiles(const char *dir, const char *ext, vector &files) } #ifndef STANDALONE -static Sint64 rwopsseek(SDL_RWops *rw, Sint64 pos, int whence) -{ +static Sint64 rwopsseek(SDL_RWops *rw, Sint64 pos, int whence) { stream *f = (stream *)rw->hidden.unknown.data1; if((!pos && whence==SEEK_CUR) || f->seek(pos, whence)) return (int)f->tell(); return -1; } -static size_t rwopsread(SDL_RWops *rw, void *buf, size_t size, size_t nmemb) -{ +static size_t rwopsread(SDL_RWops *rw, void *buf, size_t size, size_t nmemb) { stream *f = (stream *)rw->hidden.unknown.data1; return f->read(buf, size*nmemb)/size; } -static size_t rwopswrite(SDL_RWops *rw, const void *buf, size_t size, size_t nmemb) -{ +static size_t rwopswrite(SDL_RWops *rw, const void *buf, size_t size, size_t nmemb) { stream *f = (stream *)rw->hidden.unknown.data1; return f->write(buf, size*nmemb)/size; } -static int rwopsclose(SDL_RWops *rw) -{ +static int rwopsclose(SDL_RWops *rw) { return 0; } -SDL_RWops *stream::rwops() -{ +SDL_RWops *stream::rwops() { SDL_RWops *rw = SDL_AllocRW(); if(!rw) return NULL; rw->hidden.unknown.data1 = this; @@ -557,18 +492,15 @@ SDL_RWops *stream::rwops() } #endif -stream::offset stream::size() -{ +stream::offset stream::size() { offset pos = tell(), endpos; if(pos < 0 || !seek(0, SEEK_END)) return -1; endpos = tell(); return pos == endpos || seek(pos, SEEK_SET) ? endpos : -1; } -bool stream::getline(char *str, size_t len) -{ - loopi(len-1) - { +bool stream::getline(char *str, size_t len) { + loopi(len-1) { if(read(&str[i], 1) != 1) { str[i] = '\0'; return i > 0; } else if(str[i] == '\n') { str[i+1] = '\0'; return true; } } @@ -576,8 +508,7 @@ bool stream::getline(char *str, size_t len) return true; } -size_t stream::printf(const char *fmt, ...) -{ +size_t stream::printf(const char *fmt, ...) { char buf[512]; char *str = buf; va_list args; @@ -585,8 +516,7 @@ size_t stream::printf(const char *fmt, ...) int len = vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); if(len <= 0) return 0; - if(len >= (int)sizeof(buf)) - { + if(len >= (int)sizeof(buf)) { str = new char[len+1]; va_start(args, fmt); vsnprintf(str, len+1, fmt, args); @@ -597,43 +527,31 @@ size_t stream::printf(const char *fmt, ...) return n; } -struct filestream : stream -{ +struct filestream : stream { FILE *file; - filestream() : file(NULL) {} ~filestream() { close(); } - - bool open(const char *name, const char *mode) - { + bool open(const char *name, const char *mode) { if(file) return false; file = fopen(name, mode); return file!=NULL; } - - bool opentemp(const char *name, const char *mode) - { + bool opentemp(const char *name, const char *mode) { if(file) return false; file = tmpfile(); return file!=NULL; } - - void close() - { + void close() { if(file) { fclose(file); file = NULL; } } - bool end() { return feof(file)!=0; } - offset tell() - { + offset tell() { offset off = ftello(file); return off + 1 >= 0 ? off : -1; } - bool seek(offset pos, int whence = SEEK_SET) - { + bool seek(offset pos, int whence = SEEK_SET) { return fseeko(file, pos, whence) >= 0; } - size_t read(void *buf, size_t len) { return fread(buf, 1, len, file); } size_t write(const void *buf, size_t len) { return fwrite(buf, 1, len, file); } bool flush() { return !fflush(file); } @@ -641,9 +559,7 @@ struct filestream : stream bool putchar(int c) { return fputc(c, file)!=EOF; } bool getline(char *str, size_t len) { return fgets(str, len, file)!=NULL; } bool putstring(const char *str) { return fputs(str, file)!=EOF; } - - size_t printf(const char *fmt, ...) - { + size_t printf(const char *fmt, ...) { va_list v; va_start(v, fmt); int result = vfprintf(file, fmt, v); @@ -652,18 +568,14 @@ struct filestream : stream } }; -struct gzstream : stream -{ - enum - { +struct gzstream : stream { + enum { MAGIC1 = 0x1F, MAGIC2 = 0x8B, BUFSIZE = 16384, OS_UNIX = 0x03 }; - - enum - { + enum { F_ASCII = 0x01, F_CRC = 0x02, F_EXTRA = 0x04, @@ -671,54 +583,40 @@ struct gzstream : stream F_COMMENT = 0x10, F_RESERVED = 0xE0 }; - stream *file; z_stream zfile; uchar *buf; bool reading, writing, autoclose; uint crc; size_t headersize; - - gzstream() : file(NULL), buf(NULL), reading(false), writing(false), autoclose(false), crc(0), headersize(0) - { + gzstream() : file(NULL), buf(NULL), reading(false), writing(false), autoclose(false), crc(0), headersize(0) { zfile.zalloc = NULL; zfile.zfree = NULL; zfile.opaque = NULL; zfile.next_in = zfile.next_out = NULL; zfile.avail_in = zfile.avail_out = 0; } - - ~gzstream() - { + ~gzstream() { close(); } - - void writeheader() - { + void writeheader() { uchar header[] = { MAGIC1, MAGIC2, Z_DEFLATED, 0, 0, 0, 0, 0, 0, OS_UNIX }; file->write(header, sizeof(header)); } - - void readbuf(size_t size = BUFSIZE) - { + void readbuf(size_t size = BUFSIZE) { if(!zfile.avail_in) zfile.next_in = (Bytef *)buf; size = min(size, size_t(&buf[BUFSIZE] - &zfile.next_in[zfile.avail_in])); size_t n = file->read(zfile.next_in + zfile.avail_in, size); if(n > 0) zfile.avail_in += n; } - - uchar readbyte(size_t size = BUFSIZE) - { + uchar readbyte(size_t size = BUFSIZE) { if(!zfile.avail_in) readbuf(size); if(!zfile.avail_in) return 0; zfile.avail_in--; return *(uchar *)zfile.next_in++; } - - void skipbytes(size_t n) - { - while(n > 0 && zfile.avail_in > 0) - { + void skipbytes(size_t n) { + while(n > 0 && zfile.avail_in > 0) { size_t skipped = min(n, size_t(zfile.avail_in)); zfile.avail_in -= skipped; zfile.next_in += skipped; @@ -727,16 +625,13 @@ struct gzstream : stream if(n <= 0) return; file->seek(n, SEEK_CUR); } - - bool checkheader() - { + bool checkheader() { readbuf(10); if(readbyte() != MAGIC1 || readbyte() != MAGIC2 || readbyte() != Z_DEFLATED) return false; uchar flags = readbyte(); if(flags & F_RESERVED) return false; skipbytes(6); - if(flags & F_EXTRA) - { + if(flags & F_EXTRA) { size_t len = readbyte(512); len |= size_t(readbyte(512))<<8; skipbytes(len); @@ -747,77 +642,56 @@ struct gzstream : stream headersize = size_t(file->tell() - zfile.avail_in); return zfile.avail_in > 0 || !file->end(); } - - bool open(stream *f, const char *mode, bool needclose, int level) - { + bool open(stream *f, const char *mode, bool needclose, int level) { if(file) return false; - for(; *mode; mode++) - { + for(; *mode; mode++) { if(*mode=='r') { reading = true; break; } else if(*mode=='w') { writing = true; break; } } - if(reading) - { + if(reading) { if(inflateInit2(&zfile, -MAX_WBITS) != Z_OK) reading = false; } else if(writing && deflateInit2(&zfile, level, Z_DEFLATED, -MAX_WBITS, min(MAX_MEM_LEVEL, 8), Z_DEFAULT_STRATEGY) != Z_OK) writing = false; if(!reading && !writing) return false; - file = f; crc = crc32(0, NULL, 0); buf = new uchar[BUFSIZE]; - - if(reading) - { + if(reading) { if(!checkheader()) { stopreading(); return false; } } else if(writing) writeheader(); - autoclose = needclose; return true; } - uint getcrc() { return crc; } - - void finishreading() - { + void finishreading() { if(!reading) return; } - - void stopreading() - { + void stopreading() { if(!reading) return; inflateEnd(&zfile); reading = false; } - - void finishwriting() - { + void finishwriting() { if(!writing) return; - for(;;) - { + for(;;) { int err = zfile.avail_out > 0 ? deflate(&zfile, Z_FINISH) : Z_OK; if(err != Z_OK && err != Z_STREAM_END) break; flushbuf(); if(err == Z_STREAM_END) break; } - uchar trailer[8] = - { + uchar trailer[8] = { uchar(crc&0xFF), uchar((crc>>8)&0xFF), uchar((crc>>16)&0xFF), uchar((crc>>24)&0xFF), uchar(zfile.total_in&0xFF), uchar((zfile.total_in>>8)&0xFF), uchar((zfile.total_in>>16)&0xFF), uchar((zfile.total_in>>24)&0xFF) }; file->write(trailer, sizeof(trailer)); } - - void stopwriting() - { + void stopwriting() { if(!writing) return; deflateEnd(&zfile); writing = false; } - - void close() - { + void close() { if(reading) finishreading(); stopreading(); if(writing) finishwriting(); @@ -825,72 +699,53 @@ struct gzstream : stream DELETEA(buf); if(autoclose) DELETEP(file); } - bool end() { return !reading && !writing; } offset tell() { return reading ? zfile.total_out : (writing ? zfile.total_in : offset(-1)); } offset rawtell() { return file ? file->tell() : offset(-1); } - - offset size() - { + offset size() { if(!file) return -1; offset pos = tell(); if(!file->seek(-4, SEEK_END)) return -1; uint isize = file->getlil(); return file->seek(pos, SEEK_SET) ? isize : offset(-1); } - offset rawsize() { return file ? file->size() : offset(-1); } - - bool seek(offset pos, int whence) - { + bool seek(offset pos, int whence) { if(writing || !reading) return false; - - if(whence == SEEK_END) - { + if(whence == SEEK_END) { uchar skip[512]; while(read(skip, sizeof(skip)) == sizeof(skip)); return !pos; } else if(whence == SEEK_CUR) pos += zfile.total_out; - if(pos >= (offset)zfile.total_out) pos -= zfile.total_out; else if(pos < 0 || !file->seek(headersize, SEEK_SET)) return false; - else - { - if(zfile.next_in && zfile.total_in <= uint(zfile.next_in - buf)) - { + else { + if(zfile.next_in && zfile.total_in <= uint(zfile.next_in - buf)) { zfile.avail_in += zfile.total_in; zfile.next_in -= zfile.total_in; } - else - { + else { zfile.avail_in = 0; zfile.next_in = NULL; } inflateReset(&zfile); crc = crc32(0, NULL, 0); } - uchar skip[512]; - while(pos > 0) - { + while(pos > 0) { size_t skipped = (size_t)min(pos, (offset)sizeof(skip)); if(read(skip, skipped) != skipped) { stopreading(); return false; } pos -= skipped; } - return true; } - - size_t read(void *buf, size_t len) - { + size_t read(void *buf, size_t len) { if(!reading || !buf || !len) return 0; zfile.next_out = (Bytef *)buf; zfile.avail_out = len; - while(zfile.avail_out > 0) - { - if(!zfile.avail_in) - { + while(zfile.avail_out > 0) { + if(!zfile.avail_in) { readbuf(BUFSIZE); if(!zfile.avail_in) { stopreading(); break; } } @@ -901,12 +756,9 @@ struct gzstream : stream crc = crc32(crc, (Bytef *)buf, len - zfile.avail_out); return len - zfile.avail_out; } - - bool flushbuf(bool full = false) - { + bool flushbuf(bool full = false) { if(full) deflate(&zfile, Z_SYNC_FLUSH); - if(zfile.next_out && zfile.avail_out < BUFSIZE) - { + if(zfile.next_out && zfile.avail_out < BUFSIZE) { if(file->write(buf, BUFSIZE - zfile.avail_out) != BUFSIZE - zfile.avail_out || (full && !file->flush())) return false; } @@ -914,16 +766,12 @@ struct gzstream : stream zfile.avail_out = BUFSIZE; return true; } - bool flush() { return flushbuf(true); } - - size_t write(const void *buf, size_t len) - { + size_t write(const void *buf, size_t len) { if(!writing || !buf || !len) return 0; zfile.next_in = (Bytef *)buf; zfile.avail_in = len; - while(zfile.avail_in > 0) - { + while(zfile.avail_in > 0) { if(!zfile.avail_out && !flushbuf()) { stopwriting(); break; } int err = deflate(&zfile, Z_NO_FLUSH); if(err != Z_OK) { stopwriting(); break; } @@ -933,10 +781,8 @@ struct gzstream : stream } }; -struct utf8stream : stream -{ - enum - { +struct utf8stream : stream { + enum { BUFSIZE = 4096 }; stream *file; @@ -944,18 +790,12 @@ struct utf8stream : stream size_t bufread, bufcarry, buflen; bool reading, writing, autoclose; uchar buf[BUFSIZE]; - - utf8stream() : file(NULL), pos(0), bufread(0), bufcarry(0), buflen(0), reading(false), writing(false), autoclose(false) - { + utf8stream() : file(NULL), pos(0), bufread(0), bufcarry(0), buflen(0), reading(false), writing(false), autoclose(false) { } - - ~utf8stream() - { + ~utf8stream() { close(); } - - bool readbuf(size_t size = BUFSIZE) - { + bool readbuf(size_t size = BUFSIZE) { if(bufread >= bufcarry) { if(bufcarry > 0 && bufcarry < buflen) memmove(buf, &buf[bufcarry], buflen - bufcarry); buflen -= bufcarry; bufread = bufcarry = 0; } size_t n = file->read(&buf[buflen], min(size, BUFSIZE - buflen)); if(n <= 0) return false; @@ -965,98 +805,69 @@ struct utf8stream : stream if(carry > bufcarry && carry < buflen) { memmove(&buf[bufcarry], &buf[carry], buflen - carry); buflen -= carry - bufcarry; } return true; } - - bool checkheader() - { + bool checkheader() { size_t n = file->read(buf, 3); if(n == 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF) return true; buflen = n; return false; } - - bool open(stream *f, const char *mode, bool needclose) - { + bool open(stream *f, const char *mode, bool needclose) { if(file) return false; - for(; *mode; mode++) - { + for(; *mode; mode++) { if(*mode=='r') { reading = true; break; } else if(*mode=='w') { writing = true; break; } } if(!reading && !writing) return false; - file = f; - if(reading) checkheader(); - autoclose = needclose; return true; } - - void finishreading() - { + void finishreading() { if(!reading) return; } - - void stopreading() - { + void stopreading() { if(!reading) return; reading = false; } - - void stopwriting() - { + void stopwriting() { if(!writing) return; writing = false; } - - void close() - { + void close() { stopreading(); stopwriting(); if(autoclose) DELETEP(file); } - bool end() { return !reading && !writing; } offset tell() { return reading || writing ? pos : offset(-1); } - - bool seek(offset off, int whence) - { + bool seek(offset off, int whence) { if(writing || !reading) return false; - - if(whence == SEEK_END) - { + if(whence == SEEK_END) { uchar skip[512]; while(read(skip, sizeof(skip)) == sizeof(skip)); return !off; } else if(whence == SEEK_CUR) off += pos; - if(off >= pos) off -= pos; else if(off < 0 || !file->seek(0, SEEK_SET)) return false; - else - { + else { bufread = bufcarry = buflen = 0; pos = 0; checkheader(); } - uchar skip[512]; - while(off > 0) - { + while(off > 0) { size_t skipped = (size_t)min(off, (offset)sizeof(skip)); if(read(skip, skipped) != skipped) { stopreading(); return false; } off -= skipped; } - return true; } - - size_t read(void *dst, size_t len) - { + size_t read(void *dst, size_t len) { if(!reading || !dst || !len) return 0; size_t next = 0; - while(next < len) - { + while(next < len) { if(bufread >= bufcarry) { if(readbuf(BUFSIZE)) continue; stopreading(); break; } size_t n = min(len - next, bufcarry - bufread); memcpy(&((uchar *)dst)[next], &buf[bufread], n); @@ -1066,14 +877,11 @@ struct utf8stream : stream pos += next; return next; } - - bool getline(char *dst, size_t len) - { + bool getline(char *dst, size_t len) { if(!reading || !dst || !len) return false; --len; size_t next = 0; - while(next < len) - { + while(next < len) { if(bufread >= bufcarry) { if(readbuf(BUFSIZE)) continue; stopreading(); if(!next) return false; break; } size_t n = min(len - next, bufcarry - bufread); uchar *endline = (uchar *)memchr(&buf[bufread], '\n', n); @@ -1086,14 +894,11 @@ struct utf8stream : stream pos += next; return true; } - - size_t write(const void *src, size_t len) - { + size_t write(const void *src, size_t len) { if(!writing || !src || !len) return 0; uchar dst[512]; size_t next = 0; - while(next < len) - { + while(next < len) { size_t carry = 0, n = encodeutf8(dst, sizeof(dst), &((uchar *)src)[next], len - next, &carry); if(n > 0 && file->write(dst, n) != n) { stopwriting(); break; } next += carry; @@ -1101,12 +906,10 @@ struct utf8stream : stream pos += next; return next; } - bool flush() { return file->flush(); } }; -stream *openrawfile(const char *filename, const char *mode) -{ +stream *openrawfile(const char *filename, const char *mode) { const char *found = findfile(filename, mode); if(!found) return NULL; filestream *file = new filestream; @@ -1114,8 +917,7 @@ stream *openrawfile(const char *filename, const char *mode) return file; } -stream *openfile(const char *filename, const char *mode) -{ +stream *openfile(const char *filename, const char *mode) { #ifndef STANDALONE stream *s = openzipfile(filename, mode); if(s) return s; @@ -1123,16 +925,14 @@ stream *openfile(const char *filename, const char *mode) return openrawfile(filename, mode); } -stream *opentempfile(const char *name, const char *mode) -{ +stream *opentempfile(const char *name, const char *mode) { const char *found = findfile(name, mode); filestream *file = new filestream; if(!file->opentemp(found ? found : name, mode)) { delete file; return NULL; } return file; } -stream *opengzfile(const char *filename, const char *mode, stream *file, int level) -{ +stream *opengzfile(const char *filename, const char *mode, stream *file, int level) { stream *source = file ? file : openfile(filename, mode); if(!source) return NULL; gzstream *gz = new gzstream; @@ -1140,8 +940,7 @@ stream *opengzfile(const char *filename, const char *mode, stream *file, int lev return gz; } -stream *openutf8file(const char *filename, const char *mode, stream *file) -{ +stream *openutf8file(const char *filename, const char *mode, stream *file) { stream *source = file ? file : openfile(filename, mode); if(!source) return NULL; utf8stream *utf8 = new utf8stream; @@ -1149,8 +948,7 @@ stream *openutf8file(const char *filename, const char *mode, stream *file) return utf8; } -char *loadfile(const char *fn, size_t *size, bool utf8) -{ +char *loadfile(const char *fn, size_t *size, bool utf8) { stream *f = openfile(fn, "rb"); if(!f) return NULL; stream::offset fsize = f->size(); @@ -1159,8 +957,7 @@ char *loadfile(const char *fn, size_t *size, bool utf8) char *buf = new (false) char[len+1]; if(!buf) { delete f; return NULL; } size_t offset = 0; - if(utf8 && len >= 3) - { + if(utf8 && len >= 3) { if(f->read(buf, 3) != 3) { delete f; delete[] buf; return NULL; } if(((uchar *)buf)[0] == 0xEF && ((uchar *)buf)[1] == 0xBB && ((uchar *)buf)[2] == 0xBF) len -= 3; else offset += 3; diff --git a/src/shared/tools.cpp b/src/shared/tools.cpp index 1b49a8c..7eae44a 100644 --- a/src/shared/tools.cpp +++ b/src/shared/tools.cpp @@ -2,15 +2,13 @@ #include "cube.h" -void *operator new(size_t size) -{ +void *operator new(size_t size) { void *p = malloc(size); if(!p) abort(); return p; } -void *operator new[](size_t size) -{ +void *operator new[](size_t size) { void *p = malloc(size); if(!p) abort(); return p; @@ -22,15 +20,13 @@ void operator delete[](void *p) { if(p) free(p); } void operator delete(void *p, size_t n) { (void) n; if(p) free(p); } void operator delete[](void *p, size_t n) { (void) n; if(p) free(p); } -void *operator new(size_t size, bool err) -{ +void *operator new(size_t size, bool err) { void *p = malloc(size); if(!p && err) abort(); return p; } -void *operator new[](size_t size, bool err) -{ +void *operator new[](size_t size, bool err) { void *p = malloc(size); if(!p && err) abort(); return p; @@ -45,19 +41,16 @@ void *operator new[](size_t size, bool err) static uint state[N]; static int next = N; -void seedMT(uint seed) -{ +void seedMT(uint seed) { state[0] = seed; for(uint i = 1; i < N; i++) state[i] = seed = 1812433253U * (seed ^ (seed >> 30)) + i; next = 0; } -uint randomMT() -{ +uint randomMT() { int cur = next; - if(++next >= N) - { + if(++next >= N) { if(next > N) { seedMT(5489U + time(NULL)); cur = next++; } else next = 0; } @@ -75,8 +68,7 @@ uint randomMT() // all network traffic is in 32bit ints, which are then compressed using the following simple scheme (assumes that most values are small). template -static inline void putint_(T &p, int n) -{ +static inline void putint_(T &p, int n) { if(n<128 && n>-127) p.put(n); else if(n<0x8000 && n>=-0x8000) { p.put(0x80); p.put(n); p.put(n>>8); } else { p.put(0x81); p.put(n); p.put(n>>8); p.put(n>>16); p.put(n>>24); } @@ -85,8 +77,7 @@ void putint(ucharbuf &p, int n) { putint_(p, n); } void putint(packetbuf &p, int n) { putint_(p, n); } void putint(vector &p, int n) { putint_(p, n); } -int getint(ucharbuf &p) -{ +int getint(ucharbuf &p) { int c = (schar)p.get(); if(c==-128) { int n = p.get(); n |= ((schar)p.get())<<8; return n; } else if(c==-127) { int n = p.get(); n |= p.get()<<8; n |= p.get()<<16; return n|(p.get()<<24); } @@ -95,23 +86,19 @@ int getint(ucharbuf &p) // much smaller encoding for unsigned integers up to 28 bits, but can handle signed template -static inline void putuint_(T &p, int n) -{ - if(n < 0 || n >= (1<<21)) - { +static inline void putuint_(T &p, int n) { + if(n < 0 || n >= (1<<21)) { p.put(0x80 | (n & 0x7F)); p.put(0x80 | ((n >> 7) & 0x7F)); p.put(0x80 | ((n >> 14) & 0x7F)); p.put(n >> 21); } else if(n < (1<<7)) p.put(n); - else if(n < (1<<14)) - { + else if(n < (1<<14)) { p.put(0x80 | (n & 0x7F)); p.put(n >> 7); } - else - { + else { p.put(0x80 | (n & 0x7F)); p.put(0x80 | ((n >> 7) & 0x7F)); p.put(n >> 14); @@ -121,11 +108,9 @@ void putuint(ucharbuf &p, int n) { putuint_(p, n); } void putuint(packetbuf &p, int n) { putuint_(p, n); } void putuint(vector &p, int n) { putuint_(p, n); } -int getuint(ucharbuf &p) -{ +int getuint(ucharbuf &p) { int n = p.get(); - if(n & 0x80) - { + if(n & 0x80) { n += (p.get() << 7) - 0x80; if(n & (1<<14)) n += (p.get() << 14) - (1<<14); if(n & (1<<21)) n += (p.get() << 21) - (1<<21); @@ -135,8 +120,7 @@ int getuint(ucharbuf &p) } template -static inline void putfloat_(T &p, float f) -{ +static inline void putfloat_(T &p, float f) { lilswap(&f, 1); p.put((uchar *)&f, sizeof(float)); } @@ -144,16 +128,14 @@ void putfloat(ucharbuf &p, float f) { putfloat_(p, f); } void putfloat(packetbuf &p, float f) { putfloat_(p, f); } void putfloat(vector &p, float f) { putfloat_(p, f); } -float getfloat(ucharbuf &p) -{ +float getfloat(ucharbuf &p) { float f; p.get((uchar *)&f, sizeof(float)); return lilswap(f); } template -static inline void sendstring_(const char *t, T &p) -{ +static inline void sendstring_(const char *t, T &p) { while(*t) putint(p, *t++); putint(p, 0); } @@ -161,11 +143,9 @@ void sendstring(const char *t, ucharbuf &p) { sendstring_(t, p); } void sendstring(const char *t, packetbuf &p) { sendstring_(t, p); } void sendstring(const char *t, vector &p) { sendstring_(t, p); } -void getstring(char *text, ucharbuf &p, size_t len) -{ +void getstring(char *text, ucharbuf &p, size_t len) { char *t = text; - do - { + do { if(t>=&text[len]) { text[len-1] = 0; return; } if(!p.remaining()) { *t = 0; return; } *t = getint(p); @@ -173,17 +153,13 @@ void getstring(char *text, ucharbuf &p, size_t len) while(*t++); } -void filtertext(char *dst, const char *src, bool whitespace, bool forcespace, size_t len) -{ - for(int c = uchar(*src); c; c = uchar(*++src)) - { - if(c == '\f') - { +void filtertext(char *dst, const char *src, bool whitespace, bool forcespace, size_t len) { + for(int c = uchar(*src); c; c = uchar(*++src)) { + if(c == '\f') { if(!*++src) break; continue; } - if(!iscubeprint(c)) - { + if(!iscubeprint(c)) { if(!iscubespace(c) || !whitespace) continue; if(forcespace) c = ' '; } @@ -193,24 +169,20 @@ void filtertext(char *dst, const char *src, bool whitespace, bool forcespace, si *dst = '\0'; } -void ipmask::parse(const char *name) -{ +void ipmask::parse(const char *name) { union { uchar b[sizeof(enet_uint32)]; enet_uint32 i; } ipconv, maskconv; ipconv.i = 0; maskconv.i = 0; - loopi(4) - { + loopi(4) { char *end = NULL; int n = strtol(name, &end, 10); if(!end) break; if(end > name) { ipconv.b[i] = n; maskconv.b[i] = 0xFF; } name = end; - while(int c = *name) - { + while(int c = *name) { ++name; if(c == '.') break; - if(c == '/') - { + if(c == '/') { int range = clamp(int(strtol(name, NULL, 10)), 0, 32); mask = range ? ENET_HOST_TO_NET_32(0xFFffFFff << (32 - range)) : maskconv.i; ip = ipconv.i & mask; @@ -222,15 +194,13 @@ void ipmask::parse(const char *name) mask = maskconv.i; } -int ipmask::print(char *buf) const -{ +int ipmask::print(char *buf) const { char *start = buf; union { uchar b[sizeof(enet_uint32)]; enet_uint32 i; } ipconv, maskconv; ipconv.i = ip; maskconv.i = mask; int lastdigit = -1; - loopi(4) if(maskconv.b[i]) - { + loopi(4) if(maskconv.b[i]) { if(lastdigit >= 0) *buf++ = '.'; loopj(i - lastdigit - 1) { *buf++ = '*'; *buf++ = '.'; } buf += sprintf(buf, "%d", ipconv.b[i]); diff --git a/src/shared/tools.h b/src/shared/tools.h index 0550668..709f056 100644 --- a/src/shared/tools.h +++ b/src/shared/tools.h @@ -31,8 +31,7 @@ inline void operator delete[](void *, void *) {} #undef swap #endif template -static inline void swap(T &a, T &b) -{ +static inline void swap(T &a, T &b) { T t = a; a = b; b = t; @@ -44,18 +43,15 @@ static inline void swap(T &a, T &b) #undef min #endif template -static inline T max(T a, T b) -{ +static inline T max(T a, T b) { return a > b ? a : b; } template -static inline T min(T a, T b) -{ +static inline T min(T a, T b) { return a < b ? a : b; } template -static inline T clamp(T a, U b, U c) -{ +static inline T clamp(T a, U b, U c) { return max(T(b), min(a, T(c))); } @@ -99,8 +95,7 @@ typedef char string[MAXSTRLEN]; inline void vformatstring(char *d, const char *fmt, va_list v, int len) { _vsnprintf(d, len, fmt, v); d[len-1] = 0; } template inline void vformatstring(char (&d)[N], const char *fmt, va_list v) { vformatstring(d, fmt, v, N); } -inline char *copystring(char *d, const char *s, size_t len) -{ +inline char *copystring(char *d, const char *s, size_t len) { size_t slen = min(strlen(s), len-1); memcpy(d, s, slen); d[slen] = 0; @@ -111,8 +106,7 @@ template inline char *copystring(char (&d)[N], const char *s) { return inline char *concatstring(char *d, const char *s, size_t len) { size_t used = strlen(d); return used < len ? copystring(d+used, s, len-used) : d; } template inline char *concatstring(char (&d)[N], const char *s) { return concatstring(d, s, N); } -inline char *prependstring(char *d, const char *s, size_t len) -{ +inline char *prependstring(char *d, const char *s, size_t len) { size_t slen = min(strlen(s), len); memmove(&d[slen], d, min(len - slen, strlen(d) + 1)); memcpy(d, s, slen); @@ -122,8 +116,7 @@ inline char *prependstring(char *d, const char *s, size_t len) template inline char *prependstring(char (&d)[N], const char *s) { return prependstring(d, s, N); } inline void nformatstring(char *d, int len, const char *fmt, ...) PRINTFARGS(3, 4); -inline void nformatstring(char *d, int len, const char *fmt, ...) -{ +inline void nformatstring(char *d, int len, const char *fmt, ...) { va_list v; va_start(v, fmt); vformatstring(d, fmt, v, len); @@ -131,8 +124,7 @@ inline void nformatstring(char *d, int len, const char *fmt, ...) } template inline void formatstring(char (&d)[N], const char *fmt, ...) PRINTFARGS(2, 3); -template inline void formatstring(char (&d)[N], const char *fmt, ...) -{ +template inline void formatstring(char (&d)[N], const char *fmt, ...) { va_list v; va_start(v, fmt); vformatstring(d, fmt, v, int(N)); @@ -140,8 +132,7 @@ template inline void formatstring(char (&d)[N], const char *fmt, ...) } template inline void concformatstring(char (&d)[N], const char *fmt, ...) PRINTFARGS(2, 3); -template inline void concformatstring(char (&d)[N], const char *fmt, ...) -{ +template inline void concformatstring(char (&d)[N], const char *fmt, ...) { va_list v; va_start(v, fmt); int len = strlen(d); @@ -152,14 +143,13 @@ template inline void concformatstring(char (&d)[N], const char *fmt, . #define defformatstring(d,...) string d; formatstring(d, __VA_ARGS__) #define defvformatstring(d,last,fmt) string d; { va_list ap; va_start(ap, last); vformatstring(d, fmt, ap); va_end(ap); } -template inline bool matchstring(const char *s, size_t len, const char (&d)[N]) -{ +template inline bool matchstring(const char *s, size_t len, const char (&d)[N]) { return len == N-1 && !memcmp(s, d, N-1); } inline char *newstring(size_t l) { return new char[l+1]; } inline char *newstring(const char *s, size_t l) { return copystring(newstring(l), s, l+1); } -inline char *newstring(const char *s) { size_t l = strlen(s); char *d = newstring(l); memcpy(d, s, l+1); return d; } +inline char *newstring(const char *s) { size_t l = strlen(s); char *d = newstring(l); memcpy(d, s, l+1); return d; } #define loopv(v) for(int i = 0; i<(v).length(); i++) #define loopvj(v) for(int j = 0; j<(v).length(); j++) @@ -171,99 +161,72 @@ template inline void memclear(T &p) { memset((void *)&p, 0, sizeof(T)); template inline void memclear(T (&p)[N]) { memset((void *)p, 0, N * sizeof(T)); } template -struct databuf -{ - enum - { +struct databuf { + enum { OVERREAD = 1<<0, OVERWROTE = 1<<1 }; - T *buf; int len, maxlen; uchar flags; - databuf() : buf(NULL), len(0), maxlen(0), flags(0) {} - template databuf(T *buf, U maxlen) : buf(buf), len(0), maxlen((int)maxlen), flags(0) {} - - void reset() - { + void reset() { len = 0; flags = 0; } - - void reset(T *buf_, int maxlen_) - { + void reset(T *buf_, int maxlen_) { reset(); buf = buf_; maxlen = maxlen_; } - - const T &get() - { + const T &get() { static T overreadval = 0; if(len= n; } - - void forceoverread() - { + void forceoverread() { len = maxlen; flags |= OVERREAD; } @@ -272,60 +235,42 @@ struct databuf typedef databuf charbuf; typedef databuf ucharbuf; -struct packetbuf : ucharbuf -{ +struct packetbuf : ucharbuf { ENetPacket *packet; int growth; - packetbuf(ENetPacket *packet) : ucharbuf(packet->data, packet->dataLength), packet(packet), growth(0) {} - packetbuf(int growth, int pflags = 0) : growth(growth) - { + packetbuf(int growth, int pflags = 0) : growth(growth) { packet = enet_packet_create(NULL, growth, pflags); buf = (uchar *)packet->data; maxlen = packet->dataLength; } ~packetbuf() { cleanup(); } - void reliable() { packet->flags |= ENET_PACKET_FLAG_RELIABLE; } - - void resize(int n) - { + void resize(int n) { enet_packet_resize(packet, n); buf = (uchar *)packet->data; maxlen = packet->dataLength; } - - void checkspace(int n) - { + void checkspace(int n) { if(len + n > maxlen && packet && growth > 0) resize(max(len + n, maxlen + growth)); } - - ucharbuf subbuf(int sz) - { + ucharbuf subbuf(int sz) { checkspace(sz); return ucharbuf::subbuf(sz); } - - void put(const uchar &val) - { + void put(const uchar &val) { checkspace(1); ucharbuf::put(val); } - - void put(const uchar *vals, int numvals) - { + void put(const uchar *vals, int numvals) { checkspace(numvals); ucharbuf::put(vals, numvals); } - - ENetPacket *finalize() - { + ENetPacket *finalize() { resize(len); return packet; } - - void cleanup() - { + void cleanup() { if(growth > 0 && packet && !packet->referenceCount) { enet_packet_destroy(packet); packet = NULL; buf = NULL; len = maxlen = 0; } } }; @@ -333,27 +278,22 @@ struct packetbuf : ucharbuf template static inline float heapscore(const T &n) { return n; } -struct sortless -{ +struct sortless { template bool operator()(const T &x, const T &y) const { return x < y; } bool operator()(char *x, char *y) const { return strcmp(x, y) < 0; } bool operator()(const char *x, const char *y) const { return strcmp(x, y) < 0; } }; -struct sortnameless -{ +struct sortnameless { template bool operator()(const T &x, const T &y) const { return sortless()(x.name, y.name); } template bool operator()(T *x, T *y) const { return sortless()(x->name, y->name); } template bool operator()(const T *x, const T *y) const { return sortless()(x->name, y->name); } }; template -static inline void insertionsort(T *start, T *end, F fun) -{ - for(T *i = start+1; i < end; i++) - { - if(fun(*i, i[-1])) - { +static inline void insertionsort(T *start, T *end, F fun) { + for(T *i = start+1; i < end; i++) { + if(fun(*i, i[-1])) { T tmp = *i; *i = i[-1]; T *j = i-1; @@ -366,25 +306,20 @@ static inline void insertionsort(T *start, T *end, F fun) } template -static inline void insertionsort(T *buf, int n, F fun) -{ +static inline void insertionsort(T *buf, int n, F fun) { insertionsort(buf, buf+n, fun); } template -static inline void insertionsort(T *buf, int n) -{ +static inline void insertionsort(T *buf, int n) { insertionsort(buf, buf+n, sortless()); } template -static inline void quicksort(T *start, T *end, F fun) -{ - while(end-start > 10) - { +static inline void quicksort(T *start, T *end, F fun) { + while(end-start > 10) { T *mid = &start[(end-start)/2], *i = start+1, *j = end-2, pivot; - if(fun(*start, *mid)) /* start < mid */ - { + if(fun(*start, *mid)) /* start < mid */ { if(fun(end[-1], *start)) { pivot = *start; *start = end[-1]; end[-1] = *mid; } /* end < start < mid */ else if(fun(end[-1], *mid)) { pivot = end[-1]; end[-1] = *mid; } /* start <= end < mid */ else { pivot = *mid; } /* start < mid <= end */ @@ -393,8 +328,7 @@ static inline void quicksort(T *start, T *end, F fun) else if(fun(*mid, end[-1])) { pivot = end[-1]; end[-1] = *start; *start = *mid; } /* mid < end <= start */ else { pivot = *mid; swap(*start, end[-1]); } /* end <= mid <= start */ *mid = end[-2]; - do - { + do { while(fun(*i, pivot)) if(++i >= j) goto partitioned; while(fun(pivot, *--j)) if(i >= j) goto partitioned; swap(*i, *j); @@ -403,61 +337,50 @@ static inline void quicksort(T *start, T *end, F fun) partitioned: end[-2] = *i; *i = pivot; - - if(i-start < end-(i+1)) - { + if(i-start < end-(i+1)) { quicksort(start, i, fun); start = i+1; } - else - { + else { quicksort(i+1, end, fun); end = i; } } - insertionsort(start, end, fun); } template -static inline void quicksort(T *buf, int n, F fun) -{ +static inline void quicksort(T *buf, int n, F fun) { quicksort(buf, buf+n, fun); } template -static inline void quicksort(T *buf, int n) -{ +static inline void quicksort(T *buf, int n) { quicksort(buf, buf+n, sortless()); } -template struct isclass -{ +template struct isclass { template static char test(void (C::*)(void)); template static int test(...); enum { yes = sizeof(test(0)) == 1 ? 1 : 0, no = yes^1 }; }; -static inline uint hthash(const char *key) -{ +static inline uint hthash(const char *key) { uint h = 5381; for(int i = 0, k; (k = key[i]); i++) h = ((h<<5)+h)^k; // bernstein k=33 xor return h; } -static inline bool htcmp(const char *x, const char *y) -{ +static inline bool htcmp(const char *x, const char *y) { return !strcmp(x, y); } -struct stringslice -{ +struct stringslice { const char *str; int len; stringslice() {} stringslice(const char *str, int len) : str(str), len(len) {} stringslice(const char *str, const char *end) : str(str), len(int(end-str)) {} - const char *end() const { return &str[len]; } }; @@ -467,8 +390,7 @@ inline const char *stringptr(const stringslice &s) { return s.str; } inline int stringlen(const char *s) { return int(strlen(s)); } inline int stringlen(const stringslice &s) { return s.len; } -inline char *copystring(char *d, const stringslice &s, size_t len) -{ +inline char *copystring(char *d, const stringslice &s, size_t len) { size_t slen = min(size_t(s.len), len-1); memcpy(d, s.str, slen); d[slen] = 0; @@ -476,8 +398,7 @@ inline char *copystring(char *d, const stringslice &s, size_t len) } template inline char *copystring(char (&d)[N], const stringslice &s) { return copystring(d, s, N); } -static inline uint memhash(const void *ptr, int len) -{ +static inline uint memhash(const void *ptr, int len) { const uchar *data = (const uchar *)ptr; uint h = 5381; loopi(len) h = ((h<<5)+h)^data[i]; @@ -486,269 +407,193 @@ static inline uint memhash(const void *ptr, int len) static inline uint hthash(const stringslice &s) { return memhash(s.str, s.len); } -static inline bool htcmp(const stringslice &x, const char *y) -{ +static inline bool htcmp(const stringslice &x, const char *y) { return x.len == (int)strlen(y) && !memcmp(x.str, y, x.len); } -static inline uint hthash(int key) -{ +static inline uint hthash(int key) { return key; } -static inline bool htcmp(int x, int y) -{ +static inline bool htcmp(int x, int y) { return x==y; } #ifndef STANDALONE -static inline uint hthash(GLuint key) -{ +static inline uint hthash(GLuint key) { return key; } -static inline bool htcmp(GLuint x, GLuint y) -{ +static inline bool htcmp(GLuint x, GLuint y) { return x==y; } #endif -template struct vector -{ +template struct vector { static const int MINSIZE = 8; - T *buf; int alen, ulen; - - vector() : buf(NULL), alen(0), ulen(0) - { + vector() : buf(NULL), alen(0), ulen(0) { } - - vector(const vector &v) : buf(NULL), alen(0), ulen(0) - { + vector(const vector &v) : buf(NULL), alen(0), ulen(0) { *this = v; } - ~vector() { shrink(0); if(buf) delete[] (uchar *)buf; } - - vector &operator=(const vector &v) - { + vector &operator=(const vector &v) { shrink(0); if(v.length() > alen) growbuf(v.length()); loopv(v) add(v[i]); return *this; } - - T &add(const T &x) - { + T &add(const T &x) { if(ulen==alen) growbuf(ulen+1); new (&buf[ulen]) T(x); return buf[ulen++]; } - - T &add() - { + T &add() { if(ulen==alen) growbuf(ulen+1); new (&buf[ulen]) T; return buf[ulen++]; } - - T &dup() - { + T &dup() { if(ulen==alen) growbuf(ulen+1); new (&buf[ulen]) T(buf[ulen-1]); return buf[ulen++]; } - - void move(vector &v) - { - if(!ulen) - { + void move(vector &v) { + if(!ulen) { swap(buf, v.buf); swap(ulen, v.ulen); swap(alen, v.alen); } - else - { + else { growbuf(ulen+v.ulen); if(v.ulen) memcpy(&buf[ulen], (void *)v.buf, v.ulen*sizeof(T)); ulen += v.ulen; v.ulen = 0; } } - bool inrange(size_t i) const { return i=0 && i=0 && i= 0 && i::no) ulen = i; else while(ulen>i) drop(); } void setsize(int i) { ASSERT(i<=ulen); ulen = i; } - void deletecontents() { while(!empty()) delete pop(); } void deletearrays() { while(!empty()) delete[] pop(); } - T *getbuf() { return buf; } const T *getbuf() const { return buf; } bool inbuf(const T *e) const { return e >= buf && e < &buf[ulen]; } - template - void sort(F fun, int i = 0, int n = -1) - { + void sort(F fun, int i = 0, int n = -1) { quicksort(&buf[i], n < 0 ? ulen-i : n, fun); } - void sort() { sort(sortless()); } void sortname() { sort(sortnameless()); } - - void growbuf(int sz) - { + void growbuf(int sz) { int olen = alen; if(alen <= 0) alen = max(MINSIZE, sz); else while(alen < sz) alen += alen/2; if(alen <= olen) return; uchar *newbuf = new uchar[alen*sizeof(T)]; - if(olen > 0) - { + if(olen > 0) { if(ulen > 0) memcpy(newbuf, (void *)buf, ulen*sizeof(T)); delete[] (uchar *)buf; } buf = (T *)newbuf; } - - databuf reserve(int sz) - { + databuf reserve(int sz) { if(alen-ulen < sz) growbuf(ulen+sz); return databuf(&buf[ulen], sz); } - - void advance(int sz) - { + void advance(int sz) { ulen += sz; } - - void addbuf(const databuf &p) - { + void addbuf(const databuf &p) { advance(p.length()); } - - T *pad(int n) - { + T *pad(int n) { T *buf = reserve(n).buf; advance(n); return buf; } - void put(const T &v) { add(v); } - - void put(const T *v, int n) - { + void put(const T *v, int n) { databuf buf = reserve(n); buf.put(v, n); addbuf(buf); } - - void remove(int i, int n) - { + void remove(int i, int n) { for(int p = i+n; p0) buf[i] = buf[ulen]; return e; } - template - int find(const U &o) - { + int find(const U &o) { loopi(ulen) if(buf[i]==o) return i; return -1; } - - void addunique(const T &o) - { + void addunique(const T &o) { if(find(o) < 0) add(o); } - - void removeobj(const T &o) - { - loopi(ulen) if(buf[i] == o) - { + void removeobj(const T &o) { + loopi(ulen) if(buf[i] == o) { int dst = i; for(int j = i+1; j < ulen; j++) if(!(buf[j] == o)) buf[dst++] = buf[j]; setsize(dst); break; } } - - void replacewithlast(const T &o) - { + void replacewithlast(const T &o) { if(!ulen) return; - loopi(ulen-1) if(buf[i]==o) - { + loopi(ulen-1) if(buf[i]==o) { buf[i] = buf[ulen-1]; break; } ulen--; } - - T &insert(int i, const T &e) - { + T &insert(int i, const T &e) { add(T()); for(int p = ulen-1; p>i; p--) buf[p] = buf[p-1]; buf[i] = e; return buf[i]; } - - T *insert(int i, const T *e, int n) - { + T *insert(int i, const T *e, int n) { if(alen-ulen < n) growbuf(ulen+n); loopj(n) add(T()); for(int p = ulen-1; p>=i+n; p--) buf[p] = buf[p-n]; loopj(n) buf[i+j] = e[j]; return &buf[i]; } - - void reverse() - { + void reverse() { loopi(ulen/2) swap(buf[i], buf[ulen-1-i]); } - static int heapparent(int i) { return (i - 1) >> 1; } static int heapchild(int i) { return (i << 1) + 1; } - - void buildheap() - { + void buildheap() { for(int i = ulen/2; i >= 0; i--) downheap(i); } - - int upheap(int i) - { + int upheap(int i) { float score = heapscore(buf[i]); - while(i > 0) - { + while(i > 0) { int pi = heapparent(i); if(score >= heapscore(buf[pi])) break; swap(buf[i], buf[pi]); @@ -756,23 +601,17 @@ template struct vector } return i; } - - T &addheap(const T &x) - { + T &addheap(const T &x) { add(x); return buf[upheap(ulen-1)]; } - - int downheap(int i) - { + int downheap(int i) { float score = heapscore(buf[i]); - for(;;) - { + for(;;) { int ci = heapchild(i); if(ci >= ulen) break; float cscore = heapscore(buf[ci]); - if(score > cscore) - { + if(score > cscore) { if(ci+1 < ulen && heapscore(buf[ci+1]) < cscore) { swap(buf[ci+1], buf[i]); i = ci+1; } else { swap(buf[ci], buf[i]); i = ci; } } @@ -781,62 +620,45 @@ template struct vector } return i; } - - T removeheap() - { + T removeheap() { T e = removeunordered(0); if(ulen) downheap(0); return e; } - template - int htfind(const K &key) - { + int htfind(const K &key) { loopi(ulen) if(htcmp(key, buf[i])) return i; return -1; } }; -template struct hashbase -{ +template struct hashbase { typedef E elemtype; typedef K keytype; typedef T datatype; - enum { CHUNKSIZE = 64 }; - struct chain { E elem; chain *next; }; struct chainchunk { chain chains[CHUNKSIZE]; chainchunk *next; }; - int size; int numelems; chain **chains; - chainchunk *chunks; chain *unused; - enum { DEFAULTSIZE = 1<<10 }; - hashbase(int size = DEFAULTSIZE) - : size(size) - { + : size(size) { numelems = 0; chunks = NULL; unused = NULL; chains = new chain *[size]; memset(chains, 0, size*sizeof(chain *)); } - - ~hashbase() - { + ~hashbase() { DELETEA(chains); deletechunks(); } - - chain *insert(uint h) - { - if(!unused) - { + chain *insert(uint h) { + if(!unused) { chainchunk *chunk = new chainchunk; chunk->next = chunks; chunks = chunk; @@ -851,61 +673,44 @@ template struct hashbase numelems++; return c; } - template - T &insert(uint h, const U &key) - { + T &insert(uint h, const U &key) { chain *c = insert(h); H::setkey(c->elem, key); return H::getdata(c->elem); } - #define HTFIND(success, fail) \ uint h = hthash(key)&(this->size-1); \ - for(chain *c = this->chains[h]; c; c = c->next) \ - { \ + for(chain *c = this->chains[h]; c; c = c->next) { \ + \ if(htcmp(key, H::getkey(c->elem))) return success H::getdata(c->elem); \ } \ return (fail); - template - T *access(const U &key) - { + T *access(const U &key) { HTFIND(&, NULL); } - template - T &access(const U &key, const V &elem) - { + T &access(const U &key, const V &elem) { HTFIND( , insert(h, key) = elem); } - template - T &operator[](const U &key) - { + T &operator[](const U &key) { HTFIND( , insert(h, key)); } - template - T &find(const U &key, T ¬found) - { + T &find(const U &key, T ¬found) { HTFIND( , notfound); } - template - const T &find(const U &key, const T ¬found) - { + const T &find(const U &key, const T ¬found) { HTFIND( , notfound); } - template - bool remove(const U &key) - { + bool remove(const U &key) { uint h = hthash(key)&(size-1); - for(chain **p = &chains[h], *c = chains[h]; c; p = &c->next, c = c->next) - { - if(htcmp(key, H::getkey(c->elem))) - { + for(chain **p = &chains[h], *c = chains[h]; c; p = &c->next, c = c->next) { + if(htcmp(key, H::getkey(c->elem))) { *p = c->next; c->elem.~E(); new (&c->elem) E; @@ -917,78 +722,58 @@ template struct hashbase } return false; } - - void deletechunks() - { - for(chainchunk *nextchunk; chunks; chunks = nextchunk) - { + void deletechunks() { + for(chainchunk *nextchunk; chunks; chunks = nextchunk) { nextchunk = chunks->next; delete chunks; } } - - void clear() - { + void clear() { if(!numelems) return; memset(chains, 0, size*sizeof(chain *)); numelems = 0; unused = NULL; deletechunks(); } - static inline chain *enumnext(void *i) { return ((chain *)i)->next; } static inline K &enumkey(void *i) { return H::getkey(((chain *)i)->elem); } static inline T &enumdata(void *i) { return H::getdata(((chain *)i)->elem); } }; -template struct hashset : hashbase, T, T, T> -{ +template struct hashset : hashbase, T, T, T> { typedef hashbase, T, T, T> basetype; - hashset(int size = basetype::DEFAULTSIZE) : basetype(size) {} - static inline const T &getkey(const T &elem) { return elem; } static inline T &getdata(T &elem) { return elem; } - template static inline void setkey(T &elem, const K &key) {} - + template static inline void setkey(T &, const K &) {} template - T &add(const V &elem) - { + T &add(const V &elem) { return basetype::access(elem, elem); } }; -template struct hashnameset : hashbase, T, const char *, T> -{ +template struct hashnameset : hashbase, T, const char *, T> { typedef hashbase, T, const char *, T> basetype; - hashnameset(int size = basetype::DEFAULTSIZE) : basetype(size) {} - template static inline const char *getkey(const U &elem) { return elem.name; } template static inline const char *getkey(U *elem) { return elem->name; } static inline T &getdata(T &elem) { return elem; } template static inline void setkey(T &elem, const K &key) {} - template - T &add(const V &elem) - { + T &add(const V &elem) { return basetype::access(getkey(elem), elem); } }; -template struct hashtableentry -{ +template struct hashtableentry { K key; T data; }; -template struct hashtable : hashbase, hashtableentry, K, T> -{ +template struct hashtable : hashbase, hashtableentry, K, T> { typedef hashbase, hashtableentry, K, T> basetype; typedef typename basetype::elemtype elemtype; - hashtable(int size = basetype::DEFAULTSIZE) : basetype(size) {} - static inline K &getkey(elemtype &elem) { return elem.key; } static inline T &getdata(elemtype &elem) { return elem.data; } template static inline void setkey(elemtype &elem, const U &key) { elem.key = key; } @@ -997,69 +782,51 @@ template struct hashtable : hashbase, hashtabl #define enumeratekt(ht,k,e,t,f,b) loopi((ht).size) for(void *ec = (ht).chains[i]; ec;) { k &e = (ht).enumkey(ec); t &f = (ht).enumdata(ec); ec = (ht).enumnext(ec); b; } #define enumerate(ht,t,e,b) loopi((ht).size) for(void *ec = (ht).chains[i]; ec;) { t &e = (ht).enumdata(ec); ec = (ht).enumnext(ec); b; } -struct unionfind -{ - struct ufval - { +struct unionfind { + struct ufval { int rank, next; - ufval() : rank(0), next(-1) {} }; - vector ufvals; - - int find(int k) - { + int find(int k) { if(k>=ufvals.length()) return k; while(ufvals[k].next>=0) k = ufvals[k].next; return k; } - - int compressfind(int k) - { + int compressfind(int k) { if(ufvals[k].next<0) return k; return ufvals[k].next = compressfind(ufvals[k].next); } - - void unite (int x, int y) - { + void unite (int x, int y) { while(ufvals.length() <= max(x, y)) ufvals.add(); x = compressfind(x); y = compressfind(y); if(x==y) return; ufval &xval = ufvals[x], &yval = ufvals[y]; if(xval.rank < yval.rank) xval.next = y; - else - { + else { yval.next = x; if(xval.rank==yval.rank) yval.rank++; } } }; -template struct queue -{ +template struct queue { int head, tail, len; T data[SIZE]; - queue() { clear(); } - void clear() { head = tail = len = 0; } - int capacity() const { return SIZE; } int length() const { return len; } bool empty() const { return !len; } bool full() const { return len == SIZE; } - bool inrange(size_t i) const { return i=0 && i 0 ? tail-1 : SIZE-1]; } T &added(int offset) { return data[tail-offset > 0 ? tail-offset-1 : tail-offset-1 + SIZE]; } T &adding() { return data[tail]; } T &adding(int offset) { return data[tail+offset >= SIZE ? tail+offset - SIZE : tail+offset]; } - T &add() - { + T &add() { T &t = data[tail]; tail++; if(tail >= SIZE) tail -= SIZE; @@ -1067,52 +834,39 @@ template struct queue return t; } T &add(const T &e) { return add() = e; } - - databuf reserve(int sz) - { + databuf reserve(int sz) { if(!len) head = tail = 0; return databuf(&data[tail], min(sz, SIZE-tail)); } - - void advance(int sz) - { + void advance(int sz) { if(len + sz > SIZE) sz = SIZE - len; tail += sz; if(tail >= SIZE) tail -= SIZE; len += sz; } - - void addbuf(const databuf &p) - { + void addbuf(const databuf &p) { advance(p.length()); } - - T &pop() - { + T &pop() { tail--; if(tail < 0) tail += SIZE; len--; return data[tail]; } - T &removing() { return data[head]; } T &removing(int offset) { return data[head+offset >= SIZE ? head+offset - SIZE : head+offset]; } - T &remove() - { + T &remove() { T &t = data[head]; head++; if(head >= SIZE) head -= SIZE; len--; return t; } - - T remove(int offset) - { + T remove(int offset) { T val = removing(offset); if(head+offset >= SIZE) for(int i = head+offset - SIZE + 1; i < tail; i++) data[i-1] = data[i]; else if(head < tail) for(int i = head+offset + 1; i < tail; i++) data[i-1] = data[i]; - else - { + else { for(int i = head+offset + 1; i < SIZE; i++) data[i-1] = data[i]; data[SIZE-1] = data[0]; for(int i = 1; i < tail; i++) data[i-1] = data[i]; @@ -1122,13 +876,11 @@ template struct queue len--; return val; } - T &operator[](int offset) { return removing(offset); } const T &operator[](int offset) const { return removing(offset); } }; -template struct reversequeue : queue -{ +template struct reversequeue : queue { T &operator[](int offset) { return queue::added(offset); } const T &operator[](int offset) const { return queue::added(offset); } }; @@ -1153,7 +905,8 @@ template<> inline llong endianswap(llong n) { return endianswap64(n); } template<> inline double endianswap(double n) { union { double t; uint i; } conv; conv.t = n; conv.i = endianswap64(conv.i); return conv.t; } template inline void endianswap(T *buf, size_t len) { for(T *end = &buf[len]; buf < end; buf++) *buf = endianswap(*buf); } template inline T endiansame(T n) { return n; } -template inline void endiansame(T *buf, size_t len) {} +//~template inline void endiansame(T *buf, size_t len) {} +template inline void endiansame(T *, size_t) {} #ifdef SDL_BYTEORDER #if SDL_BYTEORDER == SDL_LIL_ENDIAN #define lilswap endiansame @@ -1177,20 +930,18 @@ template inline T bigswap(T n) { return *(const uchar *)&islittleendian template inline void bigswap(T *buf, size_t len) { if(*(const uchar *)&islittleendian) endianswap(buf, len); } #endif -struct stream -{ +struct stream { typedef off_t offset; - virtual ~stream() {} virtual void close() = 0; virtual bool end() = 0; virtual offset tell() { return -1; } virtual offset rawtell() { return tell(); } - virtual bool seek(offset pos, int whence = SEEK_SET) { return false; } + virtual bool seek(offset pos, int whence = SEEK_SET) { (void) pos; (void) whence; return false; } virtual offset size(); virtual offset rawsize() { return size(); } - virtual size_t read(void *buf, size_t len) { return 0; } - virtual size_t write(const void *buf, size_t len) { return 0; } + virtual size_t read(void *buf, size_t len) { (void) buf; (void) len; return 0; } + virtual size_t write(const void *buf, size_t len) { (void) buf; (void) len; return 0; } virtual bool flush() { return true; } virtual int getchar() { uchar c; return read(&c, 1) == 1 ? c : -1; } virtual bool putchar(int n) { uchar c = n; return write(&c, 1) == 1; } @@ -1199,12 +950,10 @@ struct stream virtual bool putline(const char *str) { return putstring(str) && putchar('\n'); } virtual size_t printf(const char *fmt, ...) PRINTFARGS(2, 3); virtual uint getcrc() { return 0; } - template size_t put(const T *v, size_t n) { return write(v, n*sizeof(T))/sizeof(T); } template bool put(T n) { return write(&n, sizeof(n)) == sizeof(n); } template bool putlil(T n) { return put(lilswap(n)); } template bool putbig(T n) { return put(bigswap(n)); } - template size_t get(T *v, size_t n) { return read(v, n*sizeof(T))/sizeof(T); } template T get() { T n; return read(&n, sizeof(n)) == sizeof(n) ? n : 0; } template T getlil() { return lilswap(get()); } @@ -1216,12 +965,9 @@ struct stream }; template -struct streambuf -{ +struct streambuf { stream *s; - streambuf(stream *s) : s(s) {} - T get() { return s->get(); } size_t get(T *vals, size_t numvals) { return s->get(vals, numvals); } void put(const T &val) { s->put(&val, 1); } @@ -1229,8 +975,7 @@ struct streambuf size_t length() { return s->size(); } }; -enum -{ +enum { CT_PRINT = 1<<0, CT_SPACE = 1<<1, CT_DIGIT = 1<<2, @@ -1247,24 +992,20 @@ static inline int iscubealnum(uchar c) { return cubectype[c]&(CT_ALPHA|CT_DIGIT) static inline int iscubelower(uchar c) { return cubectype[c]&CT_LOWER; } static inline int iscubeupper(uchar c) { return cubectype[c]&CT_UPPER; } static inline int iscubepunct(uchar c) { return cubectype[c] == CT_PRINT; } -static inline int cube2uni(uchar c) -{ +static inline int cube2uni(uchar c) { extern const int cube2unichars[256]; return cube2unichars[c]; } -static inline uchar uni2cube(int c) -{ +static inline uchar uni2cube(int c) { extern const int uni2cubeoffsets[8]; extern const uchar uni2cubechars[]; return uint(c) <= 0x7FF ? uni2cubechars[uni2cubeoffsets[c>>8] + (c&0xFF)] : 0; } -static inline uchar cubelower(uchar c) -{ +static inline uchar cubelower(uchar c) { extern const uchar cubelowerchars[256]; return cubelowerchars[c]; } -static inline uchar cubeupper(uchar c) -{ +static inline uchar cubeupper(uchar c) { extern const uchar cubeupperchars[256]; return cubeupperchars[c]; } @@ -1317,10 +1058,8 @@ template static inline void getstring(char (&t)[N], ucharbuf &p) { get extern void filtertext(char *dst, const char *src, bool whitespace, bool forcespace, size_t len); template static inline void filtertext(char (&dst)[N], const char *src, bool whitespace = true, bool forcespace = false) { filtertext(dst, src, whitespace, forcespace, N-1); } -struct ipmask -{ +struct ipmask { enet_uint32 ip, mask; - void parse(const char *name); int print(char *buf) const; bool check(enet_uint32 host) const { return (host & mask) == ip; } diff --git a/src/shared/zip.cpp b/src/shared/zip.cpp index 83b2952..c60ea16 100644 --- a/src/shared/zip.cpp +++ b/src/shared/zip.cpp @@ -1,7 +1,6 @@ #include "cube.h" -enum -{ +enum { ZIP_LOCAL_FILE_SIGNATURE = 0x04034B50, ZIP_LOCAL_FILE_SIZE = 30, ZIP_FILE_SIGNATURE = 0x02014B50, @@ -10,16 +9,14 @@ enum ZIP_DIRECTORY_SIZE = 22 }; -struct ziplocalfileheader -{ +struct ziplocalfileheader { uint signature; ushort version, flags, compression, modtime, moddate; uint crc32, compressedsize, uncompressedsize; ushort namelength, extralength; }; -struct zipfileheader -{ +struct zipfileheader { uint signature; ushort version, needversion, flags, compression, modtime, moddate; uint crc32, compressedsize, uncompressedsize; @@ -27,62 +24,48 @@ struct zipfileheader uint externalattribs, offset; }; -struct zipdirectoryheader -{ +struct zipdirectoryheader { uint signature; ushort disknumber, directorydisk, diskentries, entries; uint size, offset; ushort commentlength; }; -struct zipfile -{ +struct zipfile { char *name; uint header, offset, size, compressedsize; - - zipfile() : name(NULL), header(0), offset(~0U), size(0), compressedsize(0) - { + zipfile() : name(NULL), header(0), offset(~0U), size(0), compressedsize(0) { } - ~zipfile() - { + ~zipfile() { DELETEA(name); } }; struct zipstream; -struct ziparchive -{ +struct ziparchive { char *name; FILE *data; hashnameset files; int openfiles; zipstream *owner; - - ziparchive() : name(NULL), data(NULL), files(512), openfiles(0), owner(NULL) - { + ziparchive() : name(NULL), data(NULL), files(512), openfiles(0), owner(NULL) { } - ~ziparchive() - { + ~ziparchive() { DELETEA(name); if(data) { fclose(data); data = NULL; } } }; -static bool findzipdirectory(FILE *f, zipdirectoryheader &hdr) -{ +static bool findzipdirectory(FILE *f, zipdirectoryheader &hdr) { if(fseek(f, 0, SEEK_END) < 0) return false; - long offset = ftell(f); if(offset < 0) return false; - uchar buf[1024], *src = NULL; long end = max(offset - 0xFFFFL - ZIP_DIRECTORY_SIZE, 0L); size_t len = 0; const uint signature = lilswap(ZIP_DIRECTORY_SIGNATURE); - - while(offset > end) - { + while(offset > end) { size_t carry = min(len, size_t(ZIP_DIRECTORY_SIZE-1)), next = min(sizeof(buf) - carry, size_t(offset - end)); offset -= next; memmove(&buf[next], buf, carry); @@ -92,9 +75,7 @@ static bool findzipdirectory(FILE *f, zipdirectoryheader &hdr) for(; search >= buf; search--) if(*(uint *)search == signature) break; if(search >= buf) { src = search; break; } } - if(!src || &buf[len] - src < ZIP_DIRECTORY_SIZE) return false; - hdr.signature = lilswap(*(uint *)src); src += 4; hdr.disknumber = lilswap(*(ushort *)src); src += 2; hdr.directorydisk = lilswap(*(ushort *)src); src += 2; @@ -103,20 +84,15 @@ static bool findzipdirectory(FILE *f, zipdirectoryheader &hdr) hdr.size = lilswap(*(uint *)src); src += 4; hdr.offset = lilswap(*(uint *)src); src += 4; hdr.commentlength = lilswap(*(ushort *)src); src += 2; - if(hdr.signature != ZIP_DIRECTORY_SIGNATURE || hdr.disknumber != hdr.directorydisk || hdr.diskentries != hdr.entries) return false; - return true; } -static bool readzipdirectory(const char *archname, FILE *f, int entries, int offset, uint size, vector &files) -{ +static bool readzipdirectory(const char *archname, FILE *f, int entries, int offset, uint size, vector &files) { uchar *buf = new (false) uchar[size], *src = buf; if(!buf || fseek(f, offset, SEEK_SET) < 0 || fread(buf, 1, size, f) != size) { delete[] buf; return false; } - loopi(entries) - { + loopi(entries) { if(src + ZIP_FILE_SIZE > &buf[size]) break; - zipfileheader hdr; hdr.signature = lilswap(*(uint *)src); src += 4; hdr.version = lilswap(*(ushort *)src); src += 2; @@ -136,35 +112,29 @@ static bool readzipdirectory(const char *archname, FILE *f, int entries, int off hdr.externalattribs = lilswap(*(uint *)src); src += 4; hdr.offset = lilswap(*(uint *)src); src += 4; if(hdr.signature != ZIP_FILE_SIGNATURE) break; - if(!hdr.namelength || !hdr.uncompressedsize || (hdr.compression && (hdr.compression != Z_DEFLATED || !hdr.compressedsize))) - { + if(!hdr.namelength || !hdr.uncompressedsize || (hdr.compression && (hdr.compression != Z_DEFLATED || !hdr.compressedsize))) { src += hdr.namelength + hdr.extralength + hdr.commentlength; continue; } if(src + hdr.namelength > &buf[size]) break; - string pname; int namelen = min((int)hdr.namelength, (int)sizeof(pname)-1); memcpy(pname, src, namelen); pname[namelen] = '\0'; path(pname); char *name = newstring(pname); - zipfile &f = files.add(); f.name = name; f.header = hdr.offset; f.size = hdr.uncompressedsize; f.compressedsize = hdr.compression ? hdr.compressedsize : 0; - src += hdr.namelength + hdr.extralength + hdr.commentlength; } delete[] buf; - return files.length() > 0; } -static bool readlocalfileheader(FILE *f, ziplocalfileheader &h, uint offset) -{ +static bool readlocalfileheader(FILE *f, ziplocalfileheader &h, uint offset) { uchar buf[ZIP_LOCAL_FILE_SIZE]; if(fseek(f, offset, SEEK_SET) < 0 || fread(buf, 1, ZIP_LOCAL_FILE_SIZE, f) != ZIP_LOCAL_FILE_SIZE) return false; @@ -187,48 +157,38 @@ static bool readlocalfileheader(FILE *f, ziplocalfileheader &h, uint offset) static vector archives; -ziparchive *findzip(const char *name) -{ +ziparchive *findzip(const char *name) { loopv(archives) if(!strcmp(name, archives[i]->name)) return archives[i]; return NULL; } -static bool checkprefix(vector &files, const char *prefix, int prefixlen) -{ - loopv(files) - { +static bool checkprefix(vector &files, const char *prefix, int prefixlen) { + loopv(files) { if(!strncmp(files[i].name, prefix, prefixlen)) return false; } return true; } -static void mountzip(ziparchive &arch, vector &files, const char *mountdir, const char *stripdir) -{ +static void mountzip(ziparchive &arch, vector &files, const char *mountdir, const char *stripdir) { string packagesdir = "packages/"; path(packagesdir); size_t striplen = stripdir ? strlen(stripdir) : 0; - if(!mountdir && !stripdir) loopv(files) - { + if(!mountdir && !stripdir) loopv(files) { zipfile &f = files[i]; const char *foundpackages = strstr(f.name, packagesdir); - if(foundpackages) - { - if(foundpackages > f.name) - { + if(foundpackages) { + if(foundpackages > f.name) { stripdir = f.name; striplen = foundpackages - f.name; } break; } const char *foundogz = strstr(f.name, ".ogz"); - if(foundogz) - { + if(foundogz) { const char *ogzdir = foundogz; while(--ogzdir >= f.name && *ogzdir != PATHDIV); - if(ogzdir < f.name || checkprefix(files, f.name, ogzdir + 1 - f.name)) - { - if(ogzdir >= f.name) - { + if(ogzdir < f.name || checkprefix(files, f.name, ogzdir + 1 - f.name)) { + if(ogzdir >= f.name) { stripdir = f.name; striplen = ogzdir + 1 - f.name; } @@ -238,13 +198,11 @@ static void mountzip(ziparchive &arch, vector &files, const char *mount } } string mdir = "", fname; - if(mountdir) - { + if(mountdir) { copystring(mdir, mountdir); if(fixpackagedir(mdir) <= 1) mdir[0] = '\0'; } - loopv(files) - { + loopv(files) { zipfile &f = files[i]; formatstring(fname, "%s%s", mdir, striplen && !strncmp(f.name, stripdir, striplen) ? &f.name[striplen] : f.name); if(arch.files.access(fname)) continue; @@ -255,61 +213,50 @@ static void mountzip(ziparchive &arch, vector &files, const char *mount } } -bool addzip(const char *name, const char *mount = NULL, const char *strip = NULL) -{ +bool addzip(const char *name, const char *mount = NULL, const char *strip = NULL) { string pname; copystring(pname, name); path(pname); size_t plen = strlen(pname); if(plen < 4 || !strchr(&pname[plen-4], '.')) concatstring(pname, ".zip"); - ziparchive *exists = findzip(pname); - if(exists) - { + if(exists) { conoutf(CON_ERROR, "already added zip %s", pname); return true; } - FILE *f = fopen(findfile(pname, "rb"), "rb"); - if(!f) - { + if(!f) { conoutf(CON_ERROR, "could not open file %s", pname); return false; } zipdirectoryheader h; vector files; - if(!findzipdirectory(f, h) || !readzipdirectory(pname, f, h.entries, h.offset, h.size, files)) - { + if(!findzipdirectory(f, h) || !readzipdirectory(pname, f, h.entries, h.offset, h.size, files)) { conoutf(CON_ERROR, "could not read directory in zip %s", pname); fclose(f); return false; } - ziparchive *arch = new ziparchive; arch->name = newstring(pname); arch->data = f; mountzip(*arch, files, mount, strip); archives.add(arch); - conoutf("added zip %s", pname); return true; } -bool removezip(const char *name) -{ +bool removezip(const char *name) { string pname; copystring(pname, name); path(pname); int plen = (int)strlen(pname); if(plen < 4 || !strchr(&pname[plen-4], '.')) concatstring(pname, ".zip"); ziparchive *exists = findzip(pname); - if(!exists) - { + if(!exists) { conoutf(CON_ERROR, "zip %s is not loaded", pname); return false; } - if(exists->openfiles) - { + if(exists->openfiles) { conoutf(CON_ERROR, "zip %s has open files", pname); return false; } @@ -319,40 +266,30 @@ bool removezip(const char *name) return true; } -struct zipstream : stream -{ - enum - { +struct zipstream : stream { + enum { BUFSIZE = 16384 }; - ziparchive *arch; zipfile *info; z_stream zfile; uchar *buf; uint reading; bool ended; - - zipstream() : arch(NULL), info(NULL), buf(NULL), reading(~0U), ended(false) - { + zipstream() : arch(NULL), info(NULL), buf(NULL), reading(~0U), ended(false) { zfile.zalloc = NULL; zfile.zfree = NULL; zfile.opaque = NULL; zfile.next_in = zfile.next_out = NULL; zfile.avail_in = zfile.avail_out = 0; } - - ~zipstream() - { + ~zipstream() { close(); } - - void readbuf(uint size = BUFSIZE) - { + void readbuf(uint size = BUFSIZE) { if(!zfile.avail_in) zfile.next_in = (Bytef *)buf; size = min(size, uint(&buf[BUFSIZE] - &zfile.next_in[zfile.avail_in])); - if(arch->owner != this) - { + if(arch->owner != this) { arch->owner = NULL; if(fseek(arch->data, reading, SEEK_SET) >= 0) arch->owner = this; else return; @@ -362,19 +299,14 @@ struct zipstream : stream zfile.avail_in += n; reading += n; } - - bool open(ziparchive *a, zipfile *f) - { - if(f->offset == ~0U) - { + bool open(ziparchive *a, zipfile *f) { + if(f->offset == ~0U) { ziplocalfileheader h; a->owner = NULL; if(!readlocalfileheader(a->data, h, f->header)) return false; f->offset = f->header + ZIP_LOCAL_FILE_SIZE + h.namelength + h.extralength; } - if(f->compressedsize && inflateInit2(&zfile, -MAX_WBITS) != Z_OK) return false; - a->openfiles++; arch = a; info = f; @@ -383,32 +315,23 @@ struct zipstream : stream if(f->compressedsize) buf = new uchar[BUFSIZE]; return true; } - - void stopreading() - { + void stopreading() { if(reading == ~0U) return; if(info->compressedsize) inflateEnd(&zfile); reading = ~0U; } - - void close() - { + void close() { stopreading(); DELETEA(buf); if(arch) { arch->owner = NULL; arch->openfiles--; arch = NULL; } } - offset size() { return info->size; } bool end() { return reading == ~0U || ended; } offset tell() { return reading != ~0U ? (info->compressedsize ? zfile.total_out : reading - info->offset) : offset(-1); } - - bool seek(offset pos, int whence) - { + bool seek(offset pos, int whence) { if(reading == ~0U) return false; - if(!info->compressedsize) - { - switch(whence) - { + if(!info->compressedsize) { + switch(whence) { case SEEK_END: pos += info->offset + info->size; break; case SEEK_CUR: pos += reading; break; case SEEK_SET: pos += info->offset; break; @@ -422,17 +345,13 @@ struct zipstream : stream ended = false; return true; } - - switch(whence) - { + switch(whence) { case SEEK_END: pos += info->size; break; case SEEK_CUR: pos += zfile.total_out; break; case SEEK_SET: break; default: return false; } - - if(pos >= (offset)info->size) - { + if(pos >= (offset)info->size) { reading = info->offset + info->compressedsize; zfile.next_in += zfile.avail_in; zfile.avail_in = 0; @@ -442,18 +361,14 @@ struct zipstream : stream ended = false; return true; } - if(pos < 0) return false; if(pos >= (offset)zfile.total_out) pos -= zfile.total_out; - else - { - if(zfile.next_in && zfile.total_in <= uint(zfile.next_in - buf)) - { + else { + if(zfile.next_in && zfile.total_in <= uint(zfile.next_in - buf)) { zfile.avail_in += zfile.total_in; zfile.next_in -= zfile.total_in; } - else - { + else { arch->owner = NULL; zfile.avail_in = 0; zfile.next_in = NULL; @@ -461,45 +376,34 @@ struct zipstream : stream } inflateReset(&zfile); } - uchar skip[512]; - while(pos > 0) - { + while(pos > 0) { size_t skipped = (size_t)min(pos, (offset)sizeof(skip)); if(read(skip, skipped) != skipped) return false; pos -= skipped; } - ended = false; return true; } - - size_t read(void *buf, size_t len) - { + size_t read(void *buf, size_t len) { if(reading == ~0U || !buf || !len) return 0; - if(!info->compressedsize) - { - if(arch->owner != this) - { + if(!info->compressedsize) { + if(arch->owner != this) { arch->owner = NULL; if(fseek(arch->data, reading, SEEK_SET) < 0) { stopreading(); return 0; } arch->owner = this; } - size_t n = fread(buf, 1, min(len, size_t(info->size + info->offset - reading)), arch->data); reading += n; if(n < len) ended = true; return n; } - zfile.next_out = (Bytef *)buf; zfile.avail_out = len; - while(zfile.avail_out > 0) - { + while(zfile.avail_out > 0) { if(!zfile.avail_in) readbuf(BUFSIZE); int err = inflate(&zfile, Z_NO_FLUSH); - if(err != Z_OK) - { + if(err != Z_OK) { if(err == Z_STREAM_END) ended = true; else stopreading(); break; @@ -509,11 +413,9 @@ struct zipstream : stream } }; -stream *openzipfile(const char *name, const char *mode) -{ +stream *openzipfile(const char *name, const char *mode) { for(; *mode; mode++) if(*mode=='w' || *mode=='a') return NULL; - loopvrev(archives) - { + loopvrev(archives) { ziparchive *arch = archives[i]; zipfile *f = arch->files.access(name); if(!f) continue; @@ -524,36 +426,29 @@ stream *openzipfile(const char *name, const char *mode) return NULL; } -bool findzipfile(const char *name) -{ - loopvrev(archives) - { +bool findzipfile(const char *name) { + loopvrev(archives) { ziparchive *arch = archives[i]; if(arch->files.access(name)) return true; } return false; } -int listzipfiles(const char *dir, const char *ext, vector &files) -{ +int listzipfiles(const char *dir, const char *ext, vector &files) { size_t extsize = ext ? strlen(ext)+1 : 0, dirsize = strlen(dir); int dirs = 0; - loopvrev(archives) - { + loopvrev(archives) { ziparchive *arch = archives[i]; int oldsize = files.length(); - enumerate(arch->files, zipfile, f, - { + enumerate(arch->files, zipfile, f, { if(strncmp(f.name, dir, dirsize)) continue; const char *name = f.name + dirsize; if(name[0] == PATHDIV) name++; if(strchr(name, PATHDIV)) continue; if(!ext) files.add(newstring(name)); - else - { + else { size_t namelen = strlen(name); - if(namelen > extsize) - { + if(namelen > extsize) { namelen -= extsize; if(name[namelen] == '.' && strncmp(name+namelen+1, ext, extsize-1)==0) files.add(newstring(name, namelen));