/*FTE has some special light editing builtins, I don't ever expect them to be standard or anything, but they're handy for this*/ /*you probably want to change this if you're running hexen2*/ var string autocvar_cg_editor_lightmodel = "progs/s_light.spr"; var float autocvar_r_editlights_import_ambient = 0; var float autocvar_r_editlights_import_diffuse = 1; var float autocvar_r_editlights_import_specular = 1; static float selectedlight; static float editfield; static string editvalue; static entity tempent; static float helphidden; void() editor_lights_addentities = { float l; if (!tempent) tempent = spawn(); l = (float)dynamiclight_get(-1, -1); precache_model(autocvar_cg_editor_lightmodel); /*just to silence it*/ setmodel(tempent, autocvar_cg_editor_lightmodel); while(l > 0) { l = l-1.0; if (l == selectedlight) { if (gettime(0)*5f & 1) continue; tempent.effects |= 8192f; } else tempent.effects &= ~8192f; if (!(float)dynamiclight_get(l, LFIELD_RADIUS)) continue; setorigin(tempent, dynamiclight_get(l, LFIELD_ORIGIN)); addentity(tempent); } }; #define NUMLFIELDS 15 #define NUMCMDS 7 static var string fldname[NUMLFIELDS+1+NUMCMDS] = { "bad", " num", " org", " rgb", " rad", " flg", " sty", " ang", " fov", " cmp", " cor", " csc", " amb", " dif", " spc", " avl", "Save", "World Lights", "Dynamic Lights", "Toggle Help", "Wipe All", "Import", "Reload" }; static string(int fld, float foredit) readfield = { switch(fld) { case 1: if (foredit) return ftos(selectedlight); return strcat(ftos(selectedlight), " / ", ftos(dynamiclight_get(-1f, -1f))); case 2: return sprintf("%v", (vector)dynamiclight_get(selectedlight, LFIELD_ORIGIN)); case 3: return sprintf("%v", (vector)dynamiclight_get(selectedlight, LFIELD_COLOUR)); case 4: return ftos(dynamiclight_get(selectedlight, LFIELD_RADIUS)); case 5: float fl = (float)dynamiclight_get(selectedlight, LFIELD_FLAGS); string ret; ret = strcat(ret, (fl & LFLAG_NORMALMODE)?"d":""); ret = strcat(ret, (fl & LFLAG_REALTIMEMODE)?"w":""); ret = strcat(ret, (fl & LFLAG_LIGHTMAP)?"l":""); ret = strcat(ret, (fl & LFLAG_FLASHBLEND)?"f":""); ret = strcat(ret, (fl & LFLAG_NOSHADOWS)?"c":""); ret = strcat(ret, (fl & LFLAG_SHADOWMAP)?"s":""); ret = strcat(ret, (fl & LFLAG_CREPUSCULAR)?"r":""); ret = strcat(ret, (fl & LFLAG_ORTHOSUN)?"o":""); return ret; case 6: return ftos(dynamiclight_get(selectedlight, LFIELD_STYLE)); case 7: return sprintf("%v", (vector)dynamiclight_get(selectedlight, LFIELD_ANGLES)); case 8: return ftos(dynamiclight_get(selectedlight, LFIELD_FOV)); case 9: return (string)dynamiclight_get(selectedlight, LFIELD_CUBEMAPNAME); case 10: return ftos(dynamiclight_get(selectedlight, LFIELD_CORONA)); case 11: return ftos(dynamiclight_get(selectedlight, LFIELD_CORONASCALE)); case 12: return ftos(dynamiclight_get(selectedlight, LFIELD_AMBIENTSCALE)); case 13: return ftos(dynamiclight_get(selectedlight, LFIELD_DIFFUSESCALE)); case 14: return ftos(dynamiclight_get(selectedlight, LFIELD_SPECULARSCALE)); case 15: return sprintf("%v", (vector)dynamiclight_get(selectedlight, LFIELD_ROTATION)); default: return ""; } }; static void(float fld, string newval) writefield = { switch(fld) { case 1: selectedlight = stof(newval); return; case 2: dynamiclight_set(selectedlight, LFIELD_ORIGIN, stov(newval)); return; case 3: dynamiclight_set(selectedlight, LFIELD_COLOUR, stov(newval)); return; case 4: dynamiclight_set(selectedlight, LFIELD_RADIUS, stof(newval)); return; case 5: var float fl = 0; if (strstrofs(newval, "d")>=0) fl |= LFLAG_NORMALMODE; if (strstrofs(newval, "w")>=0) fl |= LFLAG_REALTIMEMODE; if (strstrofs(newval, "l")>=0) fl |= LFLAG_LIGHTMAP; if (strstrofs(newval, "f")>=0) fl |= LFLAG_FLASHBLEND; if (strstrofs(newval, "c")>=0) fl |= LFLAG_NOSHADOWS; if (strstrofs(newval, "s")>=0) fl |= LFLAG_SHADOWMAP; if (strstrofs(newval, "r")>=0) fl |= LFLAG_CREPUSCULAR; if (strstrofs(newval, "o")>=0) fl |= LFLAG_ORTHOSUN; dynamiclight_set(selectedlight, LFIELD_FLAGS, (float)fl); return; case 6: dynamiclight_set(selectedlight, LFIELD_STYLE, stof(newval)); return; case 7: dynamiclight_set(selectedlight, LFIELD_ANGLES, stov(newval)); return; case 8: dynamiclight_set(selectedlight, LFIELD_FOV, stof(newval)); return; case 9: dynamiclight_set(selectedlight, LFIELD_CUBEMAPNAME, newval); return; case 10: dynamiclight_set(selectedlight, LFIELD_CORONA, stof(newval)); return; case 11: dynamiclight_set(selectedlight, LFIELD_CORONASCALE, stof(newval)); return; case 12: dynamiclight_set(selectedlight, LFIELD_AMBIENTSCALE, stof(newval)); return; case 13: dynamiclight_set(selectedlight, LFIELD_DIFFUSESCALE, stof(newval)); return; case 14: dynamiclight_set(selectedlight, LFIELD_SPECULARSCALE, stof(newval)); return; case 15: dynamiclight_set(selectedlight, LFIELD_ROTATION, stov(newval)); return; default: return; } }; void(vector m) editor_lights_overlay = { int i; string s; vector col; m_y = floor((m_y - 32f) / 8f); fldname[NUMLFIELDS+2] = strcat("realtime world: ", cvar("r_shadow_realtime_world")?"on":"off"); fldname[NUMLFIELDS+3] = strcat("realtime dlight: ", cvar("r_shadow_realtime_dlight")?"on":"off"); for (i = 1; i <= NUMLFIELDS; i++) { if (editfield == i) s = editvalue; else s = readfield(i, 0); s = strcat(ftos(i), " ", fldname[i], ": ", s); if (editfield == i) col = '1 0 0'; else if (m_y == i && m_x < 64) col = '0 0 1'; else col = '1 1 1'; drawrawstring('0 32 0' + '0 8 0' * (float)i, s, '8 8 0', col, 1); } for (i = NUMLFIELDS+1f; i <= NUMLFIELDS+NUMCMDS; i+=1) { s = strcat(ftos(i), " ", fldname[i]); if (editfield == i) col = '1 0 0'; else if (m_y == i && m_x < 64) col = '0 0 1'; else col = '1 1 1'; drawrawstring('0 32 0' + '0 8 0' * (float)i, s, '8 8 0', col, 1); } i+=1i; if (helphidden) return; if (editfield == 5) { drawrawstring('0 32 0' + '0 8 0' * (float)i, "d: dynamic mode\n", '8 8 0', '1 1 1', 1); i+=1i; drawrawstring('0 32 0' + '0 8 0' * (float)i, "w: realtime world lights mode\n", '8 8 0', '1 1 1', 1); i+=1i; drawrawstring('0 32 0' + '0 8 0' * (float)i, "l: lightmap hack (not valid above index 32)\n", '8 8 0', '1 1 1', 1); i+=1i; drawrawstring('0 32 0' + '0 8 0' * (float)i, "f: flashblend coronas\n", '8 8 0', '1 1 1', 1); i+=1i; drawrawstring('0 32 0' + '0 8 0' * (float)i, "c: does not cast shadows\n", '8 8 0', '1 1 1', 1); i+=1i; drawrawstring('0 32 0' + '0 8 0' * (float)i, "s: shadowmapped light\n", '8 8 0', '1 1 1', 1); i+=1i; drawrawstring('0 32 0' + '0 8 0' * (float)i, "r: crepuscular rays\n", '8 8 0', '1 1 1', 1); i+=1i; } else { drawrawstring('0 32 0' + '0 8 0' * (float)i, "+/- change selected light\n", '8 8 0', '1 1 1', 1); i+=1i; drawrawstring('0 32 0' + '0 8 0' * (float)i, "mouse also selects lights\n", '8 8 0', '1 1 1', 1); i+=1i; drawrawstring('0 32 0' + '0 8 0' * (float)i, "m moves the light to the cursor\n", '8 8 0', '1 1 1', 1); i+=1i; drawrawstring('0 32 0' + '0 8 0' * (float)i, "i inserts new light\n", '8 8 0', '1 1 1', 1); i+=1i; drawrawstring('0 32 0' + '0 8 0' * (float)i, "@ sets the light's radius to the cursor\n", '8 8 0', '1 1 1', 1); i+=1i; drawrawstring('0 32 0' + '0 8 0' * (float)i, "# changes the light's shadow flag\n", '8 8 0', '1 1 1', 1); i+=1i; drawrawstring('0 32 0' + '0 8 0' * (float)i, "p points the light to aim at the cursor\n", '8 8 0', '1 1 1', 1); i+=1i; drawrawstring('0 32 0' + '0 8 0' * (float)i, "[ and ] move the light towards/away from indicated plane\n", '8 8 0', '1 1 1', 1); i+=1i; drawrawstring('0 32 0' + '0 8 0' * (float)i, "don't forget to save\n", '8 8 0', '1 1 1', 1); i+=1i; } }; static void(vector fwd, vector vorg) selectbestlight = { float l, b=selectedlight, d, bd; vector ldir; l = (float)dynamiclight_get(-1f, -1f); bd = 0; while(l > 0) { l-=1; ldir = (vector)dynamiclight_get(l, LFIELD_ORIGIN); ldir = normalize(ldir - vorg); d = fwd*ldir; if (d > bd) { bd = d; b = l; } } selectedlight = b; }; float(float keyc, float unic, vector m) editor_lights_key = { vector t = unproject(m + '0 0 8192'); vector o = unproject(m); string ns; if (keyc == 512 || (!editfield && unic == 13 && m_x < 64)) { if (editfield) { writefield(editfield, editvalue); strunzone(editvalue); editfield = 0; } editfield = floor((m_y - 32f) / 8f); if (editfield <= 0 || editfield > NUMLFIELDS+NUMCMDS || m_x >= 64) { editfield = 0; selectbestlight(t - o, o); } else if (editfield > NUMLFIELDS) { switch(editfield - (NUMLFIELDS+1)) { case 0: localcmd("r_editlights_save\n"); break; case 1: localcmd("toggle r_shadow_realtime_world\n"); break; case 2: localcmd("toggle r_shadow_realtime_dlight\n"); break; case 3: helphidden = !helphidden; break; case 4: localcmd("r_editlights_reload none\n"); break; case 5: localcmd("r_editlights_reload bsp\n"); break; case 6: localcmd("r_editlights_reload\n"); break; } editfield = 0; } else editvalue = strzone(readfield(editfield, 1)); } else if (editfield) { ns = strcat(editvalue); if (keyc == 10 || keyc == 13) { writefield(editfield, ns); editfield = 0; } else if (keyc == 127) { if (ns != "") ns = substring(ns, 0, -2); } else if (keyc == 8) { ns = ""; } else ns = strcat(ns, chr2str(unic)); ns = strzone(ns); strunzone(editvalue); editvalue = ns; writefield(editfield, ns); } else if (unic >= '0' && unic <= '9') { editfield = unic - '0'; editvalue = strzone(readfield(editfield, 1)); } else if (unic == '=') selectedlight++; else if (unic == '-') selectedlight-=1; else if (unic == 'n' || unic == 'N') localcmd("noclip\n"); // else if (unic == 's' || unic == 'S') // { // selectbestlight(t - o, o); // } else if (unic == 'm' || unic == 'M') { traceline(o, t, TRUE, world); dynamiclight_set(selectedlight, LFIELD_ORIGIN, trace_endpos + trace_plane_normal*4); } else if (unic == 'p' || unic == 'P') { traceline(o, t, TRUE, world); vector ang = vectoangles((trace_endpos + trace_plane_normal*4f) - (vector)dynamiclight_get(selectedlight, LFIELD_ORIGIN)); ang_x *= -1f; dynamiclight_set(selectedlight, LFIELD_ANGLES, ang); /*if we're pointing the light at something, it should probably have a fov*/ if (!(float)dynamiclight_get(selectedlight, LFIELD_FOV)) dynamiclight_set(selectedlight, LFIELD_FOV, 90f); } else if (unic == 'i' || unic == 'I') { float oldl = selectedlight; for (selectedlight = 32; ; selectedlight+=1) { if (!(float)dynamiclight_get(selectedlight, LFIELD_RADIUS)) { if (oldl >= 32 && (!((float)dynamiclight_get(selectedlight, LFIELD_RADIUS) > 50))) { /*dupe the current light*/ dynamiclight_set(selectedlight, LFIELD_RADIUS, dynamiclight_get(oldl, LFIELD_RADIUS)); dynamiclight_set(selectedlight, LFIELD_COLOUR, dynamiclight_get(oldl, LFIELD_COLOUR)); dynamiclight_set(selectedlight, LFIELD_FOV, dynamiclight_get(oldl, LFIELD_FOV)); dynamiclight_set(selectedlight, LFIELD_STYLE, dynamiclight_get(oldl, LFIELD_STYLE)); dynamiclight_set(selectedlight, LFIELD_ANGLES, dynamiclight_get(oldl, LFIELD_ANGLES)); dynamiclight_set(selectedlight, LFIELD_FLAGS, dynamiclight_get(oldl, LFIELD_FLAGS)); dynamiclight_set(selectedlight, LFIELD_AMBIENTSCALE, dynamiclight_get(oldl, LFIELD_AMBIENTSCALE)); dynamiclight_set(selectedlight, LFIELD_DIFFUSESCALE, dynamiclight_get(oldl, LFIELD_DIFFUSESCALE)); dynamiclight_set(selectedlight, LFIELD_SPECULARSCALE, dynamiclight_get(oldl, LFIELD_SPECULARSCALE)); dynamiclight_set(selectedlight, LFIELD_CUBEMAPNAME, dynamiclight_get(oldl, LFIELD_CUBEMAPNAME)); dynamiclight_set(selectedlight, LFIELD_CORONA, dynamiclight_get(oldl, LFIELD_CORONA)); dynamiclight_set(selectedlight, LFIELD_CORONASCALE, dynamiclight_get(oldl, LFIELD_CORONASCALE)); dynamiclight_set(selectedlight, LFIELD_ROTATION, dynamiclight_get(oldl, LFIELD_ROTATION)); } else { /*reset the light's properties*/ dynamiclight_set(selectedlight, LFIELD_RADIUS, 300); dynamiclight_set(selectedlight, LFIELD_COLOUR, '1 1 1'); dynamiclight_set(selectedlight, LFIELD_FOV, 0); dynamiclight_set(selectedlight, LFIELD_STYLE, 0); dynamiclight_set(selectedlight, LFIELD_ANGLES, '0 0 0'); dynamiclight_set(selectedlight, LFIELD_FLAGS, LFLAG_REALTIMEMODE); dynamiclight_set(selectedlight, LFIELD_AMBIENTSCALE, autocvar_r_editlights_import_ambient); dynamiclight_set(selectedlight, LFIELD_DIFFUSESCALE, autocvar_r_editlights_import_diffuse); dynamiclight_set(selectedlight, LFIELD_SPECULARSCALE, autocvar_r_editlights_import_specular); dynamiclight_set(selectedlight, LFIELD_CUBEMAPNAME, ""); dynamiclight_set(selectedlight, LFIELD_CORONA, 0); dynamiclight_set(selectedlight, LFIELD_CORONASCALE, 1); dynamiclight_set(selectedlight, LFIELD_ROTATION, '0 0 0'); } /*place it at the pointed location*/ traceline(o, t, TRUE, world); dynamiclight_set(selectedlight, LFIELD_ORIGIN, trace_endpos + trace_plane_normal*4f); break; } } } else if (unic == '[') { traceline(o, t, TRUE, world); dynamiclight_set(selectedlight, LFIELD_ORIGIN, (vector)dynamiclight_get(selectedlight, LFIELD_ORIGIN) - trace_plane_normal); } else if (unic == ']') { traceline(o, t, TRUE, world); dynamiclight_set(selectedlight, LFIELD_ORIGIN, (vector)dynamiclight_get(selectedlight, LFIELD_ORIGIN) + trace_plane_normal); } else if (unic == '\'' || unic == '@') { traceline(o, t, TRUE, world); dynamiclight_set(selectedlight, LFIELD_RADIUS, 1.5*vlen(trace_endpos - (vector)dynamiclight_get(selectedlight, LFIELD_ORIGIN))); } else if (unic == '#') { float fl; fl = (float)dynamiclight_get(selectedlight, LFIELD_FLAGS); if (fl & LFLAG_NOSHADOWS) fl -= LFLAG_NOSHADOWS; else fl += LFLAG_NOSHADOWS; dynamiclight_set(selectedlight, LFIELD_FLAGS, (float)fl); } else if (unic == '{') dynamiclight_set(selectedlight, LFIELD_RADIUS, dynamiclight_get(selectedlight, LFIELD_RADIUS) - 15); else if (unic == '}') dynamiclight_set(selectedlight, LFIELD_RADIUS, dynamiclight_get(selectedlight, LFIELD_RADIUS) + 15); else if (keyc == 127) dynamiclight_set(selectedlight, LFIELD_RADIUS, 0); else return FALSE; return TRUE; };