1
0
Fork 0
forked from fte/fteqw

terrain editor update, to implement some of the things epicenter asked for.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4687 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2014-06-16 20:45:44 +00:00
parent b026bbacfe
commit 84888e3ff2
8 changed files with 1301 additions and 384 deletions

View file

@ -644,15 +644,18 @@ enum terrainedit_e
ter_lower, //vector pos, float radius, float heightchange ter_lower, //vector pos, float radius, float heightchange
ter_tex_kill, //vector pos, void junk, void junk, string texname ter_tex_kill, //vector pos, void junk, void junk, string texname
ter_tex_get, //vector pos, void junk, float imagenum ter_tex_get, //vector pos, void junk, float imagenum
ter_mix_paint, //vector pos, float radius, float percent, string texname ter_tex_blend, //vector pos, float radius, float percent, string texname
ter_mix_concentrate, //vector pos, float radius, float percent ter_tex_concentrate, //vector pos, float radius, float percent
ter_mix_noise, //vector pos, float radius, float percent ter_tex_noise, //vector pos, float radius, float percent
ter_mix_blur, //vector pos, float radius, float percent ter_tex_blur, //vector pos, float radius, float percent
ter_water_set, //vector pos, float radius, float newwaterheight ter_water_set, //vector pos, float radius, float newwaterheight
ter_mesh_add, //entity ent ter_mesh_add, //entity ent
ter_mesh_kill, //vector pos, float radius ter_mesh_kill, //vector pos, float radius
ter_tint, //vector pos, float radius, float percent, vector newcol, float newalph ter_tint, //vector pos, float radius, float percent, vector newcol, float newalph
ter_height_flatten, //vector pos, float radius, float percent ter_height_flatten, //vector pos, float radius, float percent
ter_tex_replace, //vector pos, float radius, string texname
ter_reset, //vector pos, float radius
ter_reloadsect, //vector pos, float radius
// ter_poly_add, //add a poly, woo // ter_poly_add, //add a poly, woo
// ter_poly_remove, //remove polys // ter_poly_remove, //remove polys

View file

@ -89,7 +89,7 @@ enum
TSF_COMPRESSED = 1u<<31, TSF_COMPRESSED = 1u<<31,
//these flags should not be found on disk //these flags should not be found on disk
TSF_FAILEDLOAD = 1u<<27, //placeholder to avoid excess disk access in border regions TSF_FAILEDLOAD = 1u<<27, //placeholder to avoid excess disk access in border regions, means it still has default settings (unless edited). not saved unless its edited.
TSF_NOTIFY = 1u<<28, //modified on server, waiting for clients to be told about the change. TSF_NOTIFY = 1u<<28, //modified on server, waiting for clients to be told about the change.
TSF_RELIGHT = 1u<<29, //height edited, needs relighting. TSF_RELIGHT = 1u<<29, //height edited, needs relighting.
TSF_DIRTY = 1u<<30, //its heightmap has changed, the mesh needs rebuilding TSF_DIRTY = 1u<<30, //its heightmap has changed, the mesh needs rebuilding
@ -1736,7 +1736,7 @@ static qboolean Terr_SaveSection(heightmap_t *hm, hmsection_t *s, int sx, int sy
for (x = 0; x < SECTIONSPERBLOCK; x++) for (x = 0; x < SECTIONSPERBLOCK; x++)
{ {
s = Terr_GetSection(hm, sx+x, sy+y, TGS_LOAD); s = Terr_GetSection(hm, sx+x, sy+y, TGS_LOAD);
if (s) if (s && (s->flags & (TSF_EDITED|TSF_FAILEDLOAD)) != TSF_FAILEDLOAD)
{ {
dbh.offset[y*SECTIONSPERBLOCK + x] = VFS_TELL(f); dbh.offset[y*SECTIONSPERBLOCK + x] = VFS_TELL(f);
Terr_Save(hm, s, f, sx+x, sy+y, writever); Terr_Save(hm, s, f, sx+x, sy+y, writever);
@ -1757,6 +1757,9 @@ static qboolean Terr_SaveSection(heightmap_t *hm, hmsection_t *s, int sx, int sy
dsection_t dsh; dsection_t dsh;
fname = Terr_DiskSectionName(hm, sx, sy); fname = Terr_DiskSectionName(hm, sx, sy);
if (s && (s->flags & (TSF_EDITED|TSF_FAILEDLOAD)) != TSF_FAILEDLOAD)
return FS_Remove(fname, FS_GAMEONLY); //delete the file if the section got reverted to default, and wasn't later modified.
FS_CreatePath(fname, FS_GAMEONLY); FS_CreatePath(fname, FS_GAMEONLY);
f = FS_OpenVFS(fname, "wb", FS_GAMEONLY); f = FS_OpenVFS(fname, "wb", FS_GAMEONLY);
if (!f) if (!f)
@ -1910,15 +1913,28 @@ qboolean Terrain_LocateSection(char *name, flocation_t *loc)
} }
#endif #endif
void Terr_DestroySection(heightmap_t *hm, hmsection_t *s, qboolean lightmapreusable) void Terr_ClearSection(hmsection_t *s)
{ {
struct hmwater_s *w;
int i; int i;
RemoveLink(&s->recycle);
for (i = 0; i < s->numents; i++) for (i = 0; i < s->numents; i++)
s->ents[i]->refs-=1; s->ents[i]->refs-=1;
s->numents = 0; s->numents = 0;
while(s->water)
{
w = s->water;
s->water = w->next;
Z_Free(w);
}
}
void Terr_DestroySection(heightmap_t *hm, hmsection_t *s, qboolean lightmapreusable)
{
RemoveLink(&s->recycle);
Terr_ClearSection(s);
#ifndef SERVERONLY #ifndef SERVERONLY
if (s->lightmap >= 0) if (s->lightmap >= 0)
{ {
@ -3856,7 +3872,7 @@ static void ted_waterset(void *ctx, hmsection_t *s, int idx, float wx, float wy,
//FIXME: what about holes? //FIXME: what about holes?
} }
static void ted_mixconcentrate(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w) static void ted_texconcentrate(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w)
{ {
unsigned char *lm = ted_getlightmap(s, idx); unsigned char *lm = ted_getlightmap(s, idx);
s->flags |= TSF_NOTIFY|TSF_EDITED; s->flags |= TSF_NOTIFY|TSF_EDITED;
@ -3888,7 +3904,7 @@ static void ted_mixconcentrate(void *ctx, hmsection_t *s, int idx, float wx, flo
} }
} }
static void ted_mixnoise(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w) static void ted_texnoise(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w)
{ {
unsigned char *lm = ted_getlightmap(s, idx); unsigned char *lm = ted_getlightmap(s, idx);
vec4_t v; vec4_t v;
@ -3909,7 +3925,7 @@ static void ted_mixnoise(void *ctx, hmsection_t *s, int idx, float wx, float wy,
lm[2] = lm[2]*(1-w) + (v[2]*(w)); lm[2] = lm[2]*(1-w) + (v[2]*(w));
} }
static void ted_mixpaint(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w) static void ted_texpaint(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w)
{ {
unsigned char *lm = ted_getlightmap(s, idx); unsigned char *lm = ted_getlightmap(s, idx);
const char *texname = ctx; const char *texname = ctx;
@ -3968,8 +3984,14 @@ static void ted_mixpaint(void *ctx, hmsection_t *s, int idx, float wx, float wy,
} }
} }
static void ted_texreplace(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w)
{
if (w > 0)
ted_texpaint(ctx, s, idx, wx, wy, 1);
}
/* /*
static void ted_mixlight(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w) static void ted_texlight(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w)
{ {
unsigned char *lm = ted_getlightmap(s, idx); unsigned char *lm = ted_getlightmap(s, idx);
vec3_t pos, pos2; vec3_t pos, pos2;
@ -4006,7 +4028,7 @@ static void ted_mixlight(void *ctx, hmsection_t *s, int idx, float wx, float wy,
lm[3] = d*255; lm[3] = d*255;
} }
*/ */
static void ted_mixset(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w) static void ted_texset(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w)
{ {
unsigned char *lm = ted_getlightmap(s, idx); unsigned char *lm = ted_getlightmap(s, idx);
if (w > 1) if (w > 1)
@ -4018,7 +4040,7 @@ static void ted_mixset(void *ctx, hmsection_t *s, int idx, float wx, float wy, f
lm[0] = lm[0]*(1-w) + (255*((float*)ctx)[2]*(w)); lm[0] = lm[0]*(1-w) + (255*((float*)ctx)[2]*(w));
} }
static void ted_mixtally(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w) static void ted_textally(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w)
{ {
unsigned char *lm = ted_getlightmap(s, idx); unsigned char *lm = ted_getlightmap(s, idx);
((float*)ctx)[0] += lm[0]*w; ((float*)ctx)[0] += lm[0]*w;
@ -4043,7 +4065,9 @@ static void ted_tint(void *ctx, hmsection_t *s, int idx, float wx, float wy, flo
enum enum
{ {
tid_linear, tid_linear,
tid_exponential tid_exponential,
tid_square_linear,
tid_square_exponential,
}; };
//calls 'func' for each tile upon the terrain. the 'tile' can be either height or texel //calls 'func' for each tile upon the terrain. the 'tile' can be either height or texel
static void ted_itterate(heightmap_t *hm, int distribution, float *pos, float radius, float strength, int steps, void(*func)(void *ctx, hmsection_t *s, int idx, float wx, float wy, float strength), void *ctx) static void ted_itterate(heightmap_t *hm, int distribution, float *pos, float radius, float strength, int steps, void(*func)(void *ctx, hmsection_t *s, int idx, float wx, float wy, float strength), void *ctx)
@ -4056,6 +4080,12 @@ static void ted_itterate(heightmap_t *hm, int distribution, float *pos, float ra
hmsection_t *s; hmsection_t *s;
float w, xd, yd; float w, xd, yd;
if (radius < 0)
{
radius *= -1;
distribution |= 2;
}
min[0] = floor((pos[0] - radius)/(hm->sectionsize) - 1.5); min[0] = floor((pos[0] - radius)/(hm->sectionsize) - 1.5);
min[1] = floor((pos[1] - radius)/(hm->sectionsize) - 1.5); min[1] = floor((pos[1] - radius)/(hm->sectionsize) - 1.5);
max[0] = ceil((pos[0] + radius)/(hm->sectionsize) + 1.5); max[0] = ceil((pos[0] + radius)/(hm->sectionsize) + 1.5);
@ -4091,14 +4121,30 @@ static void ted_itterate(heightmap_t *hm, int distribution, float *pos, float ra
// if (xd < 0) // if (xd < 0)
// xd = 0; // xd = 0;
if (radius*radius >= (xd*xd+yd*yd)) switch(distribution)
{ {
if (distribution == tid_exponential) case tid_exponential:
w = sqrt((radius*radius) - ((xd*xd)+(yd*yd))); w = radius*radius - (xd*xd+yd*yd);
else if (w > 0)
func(ctx, s, tx+ty*steps, wx, wy, sqrt(w)*strength/(radius));
break;
case tid_linear:
w = radius - sqrt(xd*xd+yd*yd); w = radius - sqrt(xd*xd+yd*yd);
if (w > 0) if (w > 0)
func(ctx, s, tx+ty*steps, wx, wy, w*strength/(radius)); func(ctx, s, tx+ty*steps, wx, wy, w*strength/(radius));
break;
case tid_square_exponential:
w = max(fabs(xd), fabs(yd));
w = radius*radius - w*w;
if (w > 0)
func(ctx, s, tx+ty*steps, wx, wy, sqrt(w)*strength/(radius));
break;
case tid_square_linear:
w = max(fabs(xd), fabs(yd));
w = radius - w;
if (w > 0)
func(ctx, s, tx+ty*steps, wx, wy, w*strength/(radius));
break;
} }
} }
} }
@ -4259,20 +4305,23 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
// case ter_mixset: // case ter_mixset:
// ted_itterate(hm, tid_exponential, pos, radius, 1, SECTTEXSIZE, ted_mixset, G_VECTOR(OFS_PARM4)); // ted_itterate(hm, tid_exponential, pos, radius, 1, SECTTEXSIZE, ted_mixset, G_VECTOR(OFS_PARM4));
// break; // break;
case ter_mix_paint: case ter_tex_blend:
ted_itterate(hm, tid_exponential, pos, radius, quant/10, SECTTEXSIZE, ted_mixpaint, (void*)PR_GetStringOfs(prinst, OFS_PARM4)); ted_itterate(hm, tid_exponential, pos, radius, quant/10, SECTTEXSIZE, ted_texpaint, (void*)PR_GetStringOfs(prinst, OFS_PARM4));
break; break;
case ter_mix_concentrate: case ter_tex_replace:
ted_itterate(hm, tid_exponential, pos, radius, 1, SECTTEXSIZE, ted_mixconcentrate, NULL); ted_itterate(hm, tid_exponential, pos, radius, 1, SECTTEXSIZE, ted_texreplace, (void*)PR_GetStringOfs(prinst, OFS_PARM3));
break; break;
case ter_mix_noise: case ter_tex_concentrate:
ted_itterate(hm, tid_exponential, pos, radius, 1, SECTTEXSIZE, ted_mixnoise, NULL); ted_itterate(hm, tid_exponential, pos, radius, 1, SECTTEXSIZE, ted_texconcentrate, NULL);
break; break;
case ter_mix_blur: case ter_tex_noise:
ted_itterate(hm, tid_exponential, pos, radius, 1, SECTTEXSIZE, ted_texnoise, NULL);
break;
case ter_tex_blur:
Vector4Set(tally, 0, 0, 0, 0); Vector4Set(tally, 0, 0, 0, 0);
ted_itterate(hm, tid_exponential, pos, radius, 1, SECTTEXSIZE, ted_mixtally, &tally); ted_itterate(hm, tid_exponential, pos, radius, 1, SECTTEXSIZE, ted_textally, &tally);
VectorScale(tally, 1/(tally[3]*255), tally); VectorScale(tally, 1/(tally[3]*255), tally);
ted_itterate(hm, tid_exponential, pos, radius, quant, SECTTEXSIZE, ted_mixset, &tally); ted_itterate(hm, tid_exponential, pos, radius, quant, SECTTEXSIZE, ted_texset, &tally);
break; break;
case ter_tex_get: case ter_tex_get:
{ {
@ -4301,6 +4350,23 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
ted_texkill(Terr_GetSection(hm, x, y, TGS_FORCELOAD), PR_GetStringOfs(prinst, OFS_PARM4)); ted_texkill(Terr_GetSection(hm, x, y, TGS_FORCELOAD), PR_GetStringOfs(prinst, OFS_PARM4));
} }
break; break;
case ter_reset:
{
int x, y;
hmsection_t *s;
x = pos[0] / hm->sectionsize;
y = pos[1] / hm->sectionsize;
x = bound(hm->firstsegx, x, hm->maxsegx-1);
y = bound(hm->firstsegy, y, hm->maxsegy-1);
s = Terr_GetSection(hm, x, y, TGS_LOAD);
if (s)
{
s->flags = (s->flags & ~TSF_EDITED) | TSF_FAILEDLOAD;
Terr_ClearSection(s);
Terr_GenerateDefault(hm, s);
}
}
break;
case ter_mesh_add: case ter_mesh_add:
{ {
vec3_t axis[3]; vec3_t axis[3];

View file

@ -10680,14 +10680,17 @@ void PR_DumpPlatform_f(void)
{"TEREDIT_HEIGHT_LOWER","const float", CS, NULL, ter_lower}, {"TEREDIT_HEIGHT_LOWER","const float", CS, NULL, ter_lower},
{"TEREDIT_TEX_KILL", "const float", CS, NULL, ter_tex_kill}, {"TEREDIT_TEX_KILL", "const float", CS, NULL, ter_tex_kill},
{"TEREDIT_TEX_GET", "const float", CS, NULL, ter_tex_get}, {"TEREDIT_TEX_GET", "const float", CS, NULL, ter_tex_get},
{"TEREDIT_MIX_PAINT", "const float", CS, NULL, ter_mix_paint}, {"TEREDIT_TEX_BLEND", "const float", CS, NULL, ter_tex_blend},
{"TEREDIT_MIX_UNIFY", "const float", CS, NULL, ter_mix_concentrate}, {"TEREDIT_TEX_UNIFY", "const float", CS, NULL, ter_tex_concentrate},
{"TEREDIT_MIX_NOISE", "const float", CS, NULL, ter_mix_noise}, {"TEREDIT_TEX_NOISE", "const float", CS, NULL, ter_tex_noise},
{"TEREDIT_MIX_BLUR", "const float", CS, NULL, ter_mix_blur}, {"TEREDIT_TEX_BLUR", "const float", CS, NULL, ter_tex_blur},
{"TEREDIT_WATER_SET", "const float", CS, NULL, ter_water_set}, {"TEREDIT_WATER_SET", "const float", CS, NULL, ter_water_set},
{"TEREDIT_MESH_ADD", "const float", CS, NULL, ter_mesh_add}, {"TEREDIT_MESH_ADD", "const float", CS, NULL, ter_mesh_add},
{"TEREDIT_MESH_KILL", "const float", CS, NULL, ter_mesh_kill}, {"TEREDIT_MESH_KILL", "const float", CS, NULL, ter_mesh_kill},
{"TEREDIT_TINT", "const float", CS, NULL, ter_tint}, {"TEREDIT_TINT", "const float", CS, NULL, ter_tint},
{"TEREDIT_TEX_REPLACE", "const float", CS, NULL, ter_tex_replace},
{"TEREDIT_RESET_SECT", "const float", CS, NULL, ter_reset},
{"TEREDIT_RELOAD_SECT", "const float", CS, NULL, ter_reloadsect},
{"SLIST_HOSTCACHEVIEWCOUNT", "const float", CS|MENU, NULL, SLIST_HOSTCACHEVIEWCOUNT}, {"SLIST_HOSTCACHEVIEWCOUNT", "const float", CS|MENU, NULL, SLIST_HOSTCACHEVIEWCOUNT},
{"SLIST_HOSTCACHETOTALCOUNT", "const float", CS|MENU, NULL, SLIST_HOSTCACHETOTALCOUNT}, {"SLIST_HOSTCACHETOTALCOUNT", "const float", CS|MENU, NULL, SLIST_HOSTCACHETOTALCOUNT},

View file

@ -917,7 +917,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
for (i = 1; exts[i]; i++) for (i = 1; exts[i]; i++)
{ {
depth = COM_FDepthFile(va(exts[i], server), false); depth = COM_FDepthFile(va(exts[i], server), false);
if (depth < 0) if (depth < bestdepth)
{ {
bestdepth = depth; bestdepth = depth;
Q_snprintfz (sv.modelname, sizeof(sv.modelname), exts[i], server); Q_snprintfz (sv.modelname, sizeof(sv.modelname), exts[i], server);

View file

@ -23,6 +23,8 @@ vector mousediff;
vector originalmousepos; vector originalmousepos;
float mousedown; float mousedown;
float shiftdown; float shiftdown;
vector mousenear;
vector mousefar;
string pointedshadername; string pointedshadername;
vector pointedsurfacenormal; vector pointedsurfacenormal;
@ -36,11 +38,21 @@ void() wrap_renderscene =
vector col; vector col;
local float i; local float i;
//don't do anything if this is a subview. this avoids getting confused.
if (!(float)getproperty(VF_DRAWWORLD))
{
renderscene();
return;
}
vidsize = getproperty(VF_SCREENVSIZE); vidsize = getproperty(VF_SCREENVSIZE);
/*inactive? then show nothing*/ /*inactive? then show nothing*/
if (!autocvar_ca_show) if (!autocvar_ca_show)
{ {
mousefar = unproject((vidsize*0.5) + '0 0 8192');
mousenear = unproject(vidsize*0.5);
if (isdemo()) if (isdemo())
spline_overrides(gettime(5)); spline_overrides(gettime(5));
renderscene(); renderscene();
@ -104,6 +116,9 @@ void() wrap_renderscene =
setproperty(VF_DRAWENGINESBAR, 0); setproperty(VF_DRAWENGINESBAR, 0);
setproperty(VF_DRAWCROSSHAIR, 0); setproperty(VF_DRAWCROSSHAIR, 0);
mousefar = unproject(curmousepos + '0 0 8192');
mousenear = unproject(curmousepos);
if (autocvar_ca_editormode == MODE_LIGHTEDIT) if (autocvar_ca_editormode == MODE_LIGHTEDIT)
editor_lights_add(); editor_lights_add();
else if (autocvar_ca_editormode == MODE_ENTSEDIT) else if (autocvar_ca_editormode == MODE_ENTSEDIT)
@ -276,8 +291,8 @@ void() CSQC_Input_Frame =
vector t, o; vector t, o;
if ((input_buttons & 1) && pointedshadername == "") if ((input_buttons & 1) && pointedshadername == "")
{ {
t = unproject((vidsize*0.5) + '0 0 8192'); t = mousefar;
o = unproject(vidsize*0.5); o = mousenear;
if (vlen(o - t) > 8192) if (vlen(o - t) > 8192)
t = o + normalize(t)*8192; t = o + normalize(t)*8192;
traceline(o, t, TRUE, world); traceline(o, t, TRUE, world);
@ -318,8 +333,8 @@ void() CSQC_Input_Frame =
} }
else else
{ {
t = unproject((vidsize*0.5) + '0 0 8192'); t = mousefar;
o = unproject(vidsize*0.5); o = mousenear;
if (vlen(o - t) > 8192) if (vlen(o - t) > 8192)
t = o + normalize(t)*8192; t = o + normalize(t)*8192;
traceline(o, t, TRUE, world); traceline(o, t, TRUE, world);

View file

@ -18,3 +18,6 @@ void() csfixups =
ptr_self = (entity*)externvalue(0, "&self"); ptr_self = (entity*)externvalue(0, "&self");
}; };
vector mousenear;
vector mousefar;

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,14 @@
/*
a)
b) Make a version of Mix Paint that just draws the texture onto tiles and replaces any other texture there instead of mixing, call it Tex Paint Single
b2) Rename Mix Paint to Tex Paint Mix
c) Add 2 buttons to incr/decrease Percentage setting
d) Add option to switch from circular selection reticle to square
e) Make reticle follow mouse properly (I can see it moving on the sonar map up above, but it's definitely not where I'm pointing the mouse)
f) Make Tex Kill choose the circular or square reticle you selected (suggestion D), right now it only uses square
g) Possibly an option to manually shrink the world bounds from the outside in (for eliminating unwanted space)
*/
enum enum
{ {
ter_reload, //reload the entire thing ter_reload, //reload the entire thing
@ -11,14 +22,17 @@ enum
ter_height_lower, //lower the terrain in a bell (negative value to raise) ter_height_lower, //lower the terrain in a bell (negative value to raise)
ter_tex_kill, //set section texture ter_tex_kill, //set section texture
ter_tex_get, //get section texture ter_tex_get, //get section texture
ter_mixpaint, //paint a specific texture ter_tex_paint, //paint a specific texture with gracefulish blending.
ter_tex_paint_single, //paint a texture with 100% opacity and no attenuation (other than radius)
ter_mixconcentrate, //figure out which is the strongest mixed texture and make it stronger ter_mixconcentrate, //figure out which is the strongest mixed texture and make it stronger
ter_mixnoise, //add random noise to the affected samples ter_mixnoise, //add random noise to the affected samples
ter_mixblur, //blur the texture mixture ter_mixblur, //blur the texture mixture
ter_water_set, //lower the terrain in a bell (negative value to raise) ter_water_set, //lower the terrain in a bell (negative value to raise)
ter_mesh_add, //add a mesh ter_mesh_add, //add a mesh
ter_mesh_kill, //remove meshes within the radius ter_mesh_kill, //remove meshes within the radius
ter_tint, //pants new colour modifiers/tints ter_tint, //paints new colour modifiers/tints
ter_reset, //destroy's the entire section completely, resetting it to default.
ter_reloadsect, //reload a section, reverting changes.
ter_blank, ter_blank,
ter_radius, ter_radius,
ter_quant, ter_quant,
@ -26,15 +40,18 @@ enum
ter_mesh, ter_mesh,
ter_tintval, ter_tintval,
ter_tex, ter_tex,
ter_roundpegsquarehole,
ter_count ter_count
}; };
static var float eradius = 256; static var float eradius = 256;
static var float equant = 8; static var float equant = 8;
static var float epercent = 40; static var float epercent = 40;
static var float squaretool = 0;
static string tex[8]; static string tex[8];
static var string tint[8] = {"1 1 1", "1.2 0.9 0.9", "0 1 0"}; static var string tint[8] = {"1 1 1", "1.2 0.9 0.9", "0 1 0"};
static string meshname; static string meshname;
static var float curtool = ter_blank; static var float curtool = ter_blank;
static var float lasttool = ter_blank;
static int painttex; static int painttex;
static float mautorepeattime; static float mautorepeattime;
static entity tempent; static entity tempent;
@ -60,14 +77,17 @@ static string toolname[ter_count] =
"height lower", "height lower",
"tex kill", "tex kill",
"tex get", "tex get",
"mix paint", "tex paint blend",
"mix concentrate", "tex paint single",
"mix noise", "tex concentrate",
"mix blur", "tex noise",
"tex blur",
"water set", "water set",
"mesh add", "mesh add",
"mesh kill", "mesh kill",
"mesh tint", "tex tint",
"revert to default",
"reload single section",
"", "",
"rad", "rad",
"quant", "quant",
@ -82,8 +102,8 @@ __variant(float action, ...) terrain_edit = #278;
void(vector m) editor_do = void(vector m) editor_do =
{ {
vector t = unproject(m + '0 0 8192'); vector t = mousefar;
vector o = unproject(m); vector o = mousenear;
if (vlen(o - t) > 8192) if (vlen(o - t) > 8192)
t = o + normalize(t)*8192; t = o + normalize(t)*8192;
traceline(o, t, TRUE, world); traceline(o, t, TRUE, world);
@ -163,11 +183,18 @@ void(vector m) editor_do =
// case ter_mixset: // case ter_mixset:
// terrain_edit(curtool, trace_endpos, eradius, equant, emix); // terrain_edit(curtool, trace_endpos, eradius, equant, emix);
// break; // break;
case ter_mixpaint: case ter_tex_paint:
if (autocvar_mod_terrain_networked && !isserver()) if (autocvar_mod_terrain_networked && !isserver())
sendevent("teredit", "fvffs", TEREDIT_MIX_PAINT, trace_endpos, eradius, epercent/100.0, tex[painttex]); sendevent("teredit", "fvffs", TEREDIT_TEX_BLEND, trace_endpos, eradius, epercent/100.0, tex[painttex]);
else else
terrain_edit(TEREDIT_MIX_PAINT, trace_endpos, eradius, epercent/100.0, tex[painttex]); terrain_edit(TEREDIT_TEX_BLEND, trace_endpos, eradius, epercent/100.0, tex[painttex]);
break;
case ter_tex_paint_single:
if (autocvar_mod_terrain_networked && !isserver())
sendevent("teredit", "fvfs", TEREDIT_TEX_REPLACE, trace_endpos, eradius, tex[painttex]);
else
terrain_edit(TEREDIT_TEX_REPLACE, trace_endpos, eradius, tex[painttex]);
break;
break; break;
case ter_tex_kill: case ter_tex_kill:
if (autocvar_mod_terrain_networked && !isserver()) if (autocvar_mod_terrain_networked && !isserver())
@ -175,23 +202,35 @@ void(vector m) editor_do =
else else
terrain_edit(TEREDIT_TEX_KILL, trace_endpos, eradius, equant, tex[painttex]); terrain_edit(TEREDIT_TEX_KILL, trace_endpos, eradius, equant, tex[painttex]);
break; break;
case ter_reset:
if (autocvar_mod_terrain_networked && !isserver())
sendevent("teredit", "fvf", TEREDIT_RESET_SECT, trace_endpos, eradius);
else
terrain_edit(TEREDIT_RESET_SECT, trace_endpos, eradius);
break;
case ter_reloadsect:
if (autocvar_mod_terrain_networked && !isserver())
sendevent("teredit", "fvf", TEREDIT_RELOAD_SECT, trace_endpos, eradius);
else
terrain_edit(TEREDIT_RELOAD_SECT, trace_endpos, eradius);
break;
case ter_mixconcentrate: case ter_mixconcentrate:
if (autocvar_mod_terrain_networked && !isserver()) if (autocvar_mod_terrain_networked && !isserver())
sendevent("teredit", "fvff", TEREDIT_MIX_UNIFY, trace_endpos, eradius, equant); sendevent("teredit", "fvff", TEREDIT_TEX_UNIFY, trace_endpos, eradius, equant);
else else
terrain_edit(TEREDIT_MIX_UNIFY, trace_endpos, eradius, equant); terrain_edit(TEREDIT_TEX_UNIFY, trace_endpos, eradius, equant);
break; break;
case ter_mixnoise: case ter_mixnoise:
if (autocvar_mod_terrain_networked && !isserver()) if (autocvar_mod_terrain_networked && !isserver())
sendevent("teredit", "fvff", TEREDIT_MIX_NOISE, trace_endpos, eradius, equant); sendevent("teredit", "fvff", TEREDIT_TEX_NOISE, trace_endpos, eradius, equant);
else else
terrain_edit(TEREDIT_MIX_NOISE, trace_endpos, eradius, equant); terrain_edit(TEREDIT_TEX_NOISE, trace_endpos, eradius, equant);
break; break;
case ter_mixblur: case ter_mixblur:
if (autocvar_mod_terrain_networked && !isserver()) if (autocvar_mod_terrain_networked && !isserver())
sendevent("teredit", "fvff", TEREDIT_MIX_BLUR, trace_endpos, eradius, equant); sendevent("teredit", "fvff", TEREDIT_TEX_BLUR, trace_endpos, eradius, equant);
else else
terrain_edit(TEREDIT_MIX_BLUR, trace_endpos, eradius, equant); terrain_edit(TEREDIT_TEX_BLUR, trace_endpos, eradius, equant);
break; break;
case ter_tint: case ter_tint:
@ -215,16 +254,17 @@ void(vector m) editor_do =
float(float keyc, float unic, vector m) editor_terrain_key = float(float keyc, float unic, vector m) editor_terrain_key =
{ {
float nt;
if (curtool >= ter_radius && curtool <= ter_tex) if (curtool >= ter_radius && curtool <= ter_tex)
{ {
string txt = ""; string txt = "";
float nt = curtool; nt = curtool;
if (curtool == ter_tex) if (curtool == ter_tex)
{ {
if (keyc == 512 && m_x > 128) if (keyc == 512 && m_x > 128)
{ {
txt = texturesearchhighlighted; txt = texturesearchhighlighted;
nt = ter_mixpaint; nt = ter_tex_paint;
} }
if (keyc == 515) if (keyc == 515)
texturesearchfirst += floor((vidsize_x)/128) - 1; texturesearchfirst += floor((vidsize_x)/128) - 1;
@ -233,7 +273,7 @@ float(float keyc, float unic, vector m) editor_terrain_key =
} }
if (curtool == ter_radius) if (curtool == ter_radius)
txt = itos((int)eradius); txt = itos((int)fabs(eradius));
if (curtool == ter_quant) if (curtool == ter_quant)
txt = itos((int)equant); txt = itos((int)equant);
if (curtool == ter_strength) if (curtool == ter_strength)
@ -246,14 +286,7 @@ float(float keyc, float unic, vector m) editor_terrain_key =
txt = tex[painttex]; txt = tex[painttex];
if (keyc == 10 || keyc == 13) if (keyc == 10 || keyc == 13)
{ nt = lasttool;
if (curtool == ter_mesh)
nt = ter_mesh_add;
else if (curtool == ter_tintval)
nt = ter_tint;
else
nt = ter_mixpaint;
}
else if (keyc == 127) else if (keyc == 127)
txt = substring(txt, 0, -2); txt = substring(txt, 0, -2);
else if (keyc == 8) else if (keyc == 8)
@ -262,7 +295,11 @@ float(float keyc, float unic, vector m) editor_terrain_key =
txt = strcat(txt, chr2str(unic)); txt = strcat(txt, chr2str(unic));
if (curtool == ter_radius) if (curtool == ter_radius)
eradius = stof(txt); {
eradius = fabs(stof(txt));
if (squaretool)
eradius *= -1;
}
if (curtool == ter_quant) if (curtool == ter_quant)
equant = stof(txt); equant = stof(txt);
if (curtool == ter_strength) if (curtool == ter_strength)
@ -286,21 +323,46 @@ float(float keyc, float unic, vector m) editor_terrain_key =
tint[painttex] = txt; tint[painttex] = txt;
} }
if (curtool != nt)
{
lasttool = curtool;
curtool = nt; curtool = nt;
} }
}
else if (keyc == 13 || (keyc == 512 && m_x < 128)) else if (keyc == 13 || (keyc == 512 && m_x < 128))
{ {
if (m_x < 128) if (m_x < 128)
curtool = floor((m_y-16) / 8); {
nt = floor((m_y-16) / 8);
if (nt != curtool)
{
if (nt == ter_roundpegsquarehole)
{
squaretool = !squaretool;
eradius = fabs(eradius);
if (squaretool) eradius *= -1;
}
else
{
lasttool = curtool;
curtool = nt;
}
}
}
else if (keyc == 13) else if (keyc == 13)
{ {
editor_do(m); editor_do(m);
} }
} }
else if (unic == '+' || unic == '=') else if (unic == '+' || unic == '=')
eradius += 16; eradius += squaretool?-16:16;
else if (unic == '-') else if (unic == '-')
eradius -= 16; {
eradius = fabs(eradius) - 16;
if (eradius < 0)
eradius = 0;
if (squaretool) eradius *= -1;
}
else if (curtool == ter_mesh_add && tempent) else if (curtool == ter_mesh_add && tempent)
{ {
if (unic == '[') if (unic == '[')
@ -330,6 +392,10 @@ float(float keyc, float unic, vector m) editor_terrain_key =
else else
return FALSE; return FALSE;
} }
else if (unic == '(')
epercent -= 10;
else if (unic == ')')
epercent += 10;
else if (unic == '[') else if (unic == '[')
equant -= 1; equant -= 1;
else if (unic == ']') else if (unic == ']')
@ -374,8 +440,8 @@ void(vector mousepos) editor_terrain_add =
if (mousepos_x < 128) if (mousepos_x < 128)
return; return;
vector t = unproject(mousepos + '0 0 8192'); vector t = mousefar;
vector o = unproject(mousepos); vector o = mousenear;
if (vlen(o - t) > 8192) if (vlen(o - t) > 8192)
t = o + normalize(t)*8192; t = o + normalize(t)*8192;
traceline(o, t, TRUE, world); traceline(o, t, TRUE, world);
@ -466,13 +532,15 @@ void(vector mousepos) editor_terrain_overlay =
colour = '1 1 1'; colour = '1 1 1';
if (i == ter_radius) if (i == ter_radius)
drawstring(pos, sprintf("radius: %g", eradius), '8 8 0', colour, 1, 0); drawstring(pos, sprintf("radius: %g", fabs(eradius)), '8 8 0', colour, 1, 0);
else if (i == ter_quant) else if (i == ter_quant)
drawstring(pos, sprintf("quantity: %g", equant), '8 8 0', colour, 1, 0); drawstring(pos, sprintf("quantity: %g", equant), '8 8 0', colour, 1, 0);
else if (i == ter_strength) else if (i == ter_strength)
drawstring(pos, sprintf("percent: %g%%", epercent), '8 8 0', colour, 1, 0); drawstring(pos, sprintf("percent: %g%%", epercent), '8 8 0', colour, 1, 0);
else if (i == ter_mesh) else if (i == ter_mesh)
drawstring(pos, sprintf("mesh: %s", meshname), '8 8 0', colour, 1, 0); drawstring(pos, sprintf("mesh: %s", meshname), '8 8 0', colour, 1, 0);
else if (i == ter_roundpegsquarehole)
drawstring(pos, sprintf("shape: %s", (squaretool?"square peg":"round")), '8 8 0', colour, 1, 0);
else if (i == ter_tex) else if (i == ter_tex)
{ {
if (curtool == ter_tex_get) if (curtool == ter_tex_get)