drop leftover unused code, headers for texture.cc and shader.cc
This commit is contained in:
parent
768c588322
commit
949ec16cd7
|
@ -1,4 +1,5 @@
|
|||
#include "aa.hh"
|
||||
#include "texture.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "texture.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
||||
extern vec hitsurface;
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
#ifndef ENGINE_BIH_HH
|
||||
#define ENGINE_BIH_HH
|
||||
|
||||
#include <shared/geom.hh>
|
||||
|
||||
struct stainrenderer;
|
||||
struct Texture;
|
||||
|
||||
struct BIH
|
||||
{
|
||||
|
@ -91,3 +97,4 @@ struct BIH
|
|||
|
||||
extern bool mmintersect(const extentity &e, const vec &o, const vec &ray, float maxdist, int mode, float &dist);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "blend.hh"
|
||||
#include "texture.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#ifndef STANDALONE
|
||||
|
||||
#include "light.hh"
|
||||
#include "texture.hh"
|
||||
#include "bih.hh"
|
||||
#include "model.hh"
|
||||
|
||||
|
@ -53,6 +52,8 @@ struct font
|
|||
#define MINRESW 640
|
||||
#define MINRESH 480
|
||||
|
||||
struct Shader;
|
||||
|
||||
extern font *curfont;
|
||||
extern Shader *textshader;
|
||||
extern const matrix4x3 *textmatrix;
|
||||
|
@ -64,42 +65,11 @@ extern void reloadfonts();
|
|||
static inline void setfont(font *f) { if(f) curfont = f; }
|
||||
|
||||
// texture
|
||||
extern int hwtexsize, hwcubetexsize, hwmaxaniso, maxtexsize, hwtexunits, hwvtexunits;
|
||||
struct cubemapside;
|
||||
|
||||
extern Texture *textureload(const char *name, int clamp = 0, bool mipit = true, bool msg = true);
|
||||
extern int texalign(const void *data, int w, int bpp);
|
||||
extern bool floatformat(GLenum format);
|
||||
extern void cleanuptexture(Texture *t);
|
||||
extern uchar *loadalphamask(Texture *t);
|
||||
extern Texture *cubemapload(const char *name, bool mipit = true, bool msg = true, bool transient = false);
|
||||
extern void drawcubemap(int size, const vec &o, float yaw, float pitch, const cubemapside &side, bool onlysky = false);
|
||||
extern void loadshaders();
|
||||
extern void setuptexparameters(int tnum, const void *pixels, int clamp, int filter, GLenum format = GL_RGB, GLenum target = GL_TEXTURE_2D, bool swizzle = false);
|
||||
extern void createtexture(int tnum, int w, int h, const void *pixels, int clamp, int filter, GLenum component = GL_RGB, GLenum target = GL_TEXTURE_2D, int pw = 0, int ph = 0, int pitch = 0, bool resize = true, GLenum format = GL_FALSE, bool swizzle = false);
|
||||
extern void create3dtexture(int tnum, int w, int h, int d, const void *pixels, int clamp, int filter, GLenum component = GL_RGB, GLenum target = GL_TEXTURE_3D, bool swizzle = false);
|
||||
extern void blurtexture(int n, int bpp, int w, int h, uchar *dst, const uchar *src, int margin = 0);
|
||||
extern void blurnormals(int n, int w, int h, bvec *dst, const bvec *src, int margin = 0);
|
||||
extern GLuint setuppostfx(int w, int h, GLuint outfbo = 0);
|
||||
extern void cleanuppostfx(bool fullclean = false);
|
||||
extern void renderpostfx(GLuint outfbo = 0);
|
||||
extern void initenvmaps();
|
||||
extern void genenvmaps();
|
||||
extern ushort closestenvmap(const vec &o);
|
||||
extern ushort closestenvmap(int orient, const ivec &o, int size);
|
||||
extern GLuint lookupenvmap(ushort emid);
|
||||
extern GLuint lookupenvmap(Slot &slot);
|
||||
extern bool reloadtexture(Texture &tex);
|
||||
extern bool reloadtexture(const char *name);
|
||||
extern void setuptexcompress();
|
||||
extern void clearslots();
|
||||
extern void compacteditvslots();
|
||||
extern void compactmruvslots();
|
||||
extern void compactvslots(cube *c, int n = 8);
|
||||
extern void compactvslot(int &index);
|
||||
extern void compactvslot(VSlot &vs);
|
||||
extern int compactvslots(bool cull = false);
|
||||
extern void reloadtextures();
|
||||
extern void cleanuptextures();
|
||||
|
||||
// pvs
|
||||
extern void clearpvs();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "blend.hh"
|
||||
#include "texture.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "blend.hh"
|
||||
#include "texture.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// main.cpp: initialisation & main loop
|
||||
|
||||
#include "blend.hh"
|
||||
#include "shader.hh"
|
||||
#include "texture.hh"
|
||||
#include "world.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "material.hh"
|
||||
#include "texture.hh"
|
||||
#include "water.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
enum { MDL_MD2 = 0, MDL_MD3, MDL_MD5, MDL_OBJ, MDL_SMD, MDL_IQM, NUMMODELTYPES };
|
||||
|
||||
struct Shader;
|
||||
|
||||
struct model
|
||||
{
|
||||
char *name;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
// avidemux - ok - 3Apr09-RockKeyman:had to swap UV channels as it showed up blue
|
||||
// kino - ok
|
||||
|
||||
#include "texture.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
||||
VAR(dbgmovie, 0, 0, 1);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "texture.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
||||
struct normalkey
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "blend.hh"
|
||||
#include "material.hh"
|
||||
#include "texture.hh"
|
||||
#include "world.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "blend.hh"
|
||||
#include "material.hh"
|
||||
#include "texture.hh"
|
||||
#include "world.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "aa.hh"
|
||||
#include "blend.hh"
|
||||
#include "material.hh"
|
||||
#include "texture.hh"
|
||||
#include "water.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "aa.hh"
|
||||
#include "material.hh"
|
||||
#include "texture.hh"
|
||||
#include "world.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include "aa.hh"
|
||||
#include "shader.hh"
|
||||
#include "texture.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// renderparticles.cpp
|
||||
|
||||
#include "shader.hh"
|
||||
#include "texture.hh"
|
||||
#include "water.hh"
|
||||
#include "world.hh"
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "texture.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
||||
Texture *sky[6] = { 0, 0, 0, 0, 0, 0 }, *clouds[6] = { 0, 0, 0, 0, 0, 0 };
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "texture.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
||||
static hashnameset<font> fonts;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// renderva.cpp: handles the occlusion and rendering of vertex arrays
|
||||
|
||||
#include "blend.hh"
|
||||
#include "texture.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
// shader.cpp: OpenGL GLSL shader management
|
||||
|
||||
#include "shader.hh"
|
||||
#include "texture.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
||||
Shader *Shader::lastshader = NULL;
|
||||
|
|
499
src/engine/shader.hh
Normal file
499
src/engine/shader.hh
Normal file
|
@ -0,0 +1,499 @@
|
|||
#ifndef ENGINE_SHADER_HH
|
||||
#define ENGINE_SHADER_HH
|
||||
|
||||
#include <shared/glexts.hh>
|
||||
#include <shared/tools.hh>
|
||||
#include <shared/geom.hh>
|
||||
|
||||
struct Slot;
|
||||
struct VSlot;
|
||||
|
||||
struct GlobalShaderParamState
|
||||
{
|
||||
const char *name;
|
||||
union
|
||||
{
|
||||
float fval[32];
|
||||
int ival[32];
|
||||
uint uval[32];
|
||||
uchar buf[32*sizeof(float)];
|
||||
};
|
||||
int version;
|
||||
|
||||
static int nextversion;
|
||||
|
||||
void resetversions();
|
||||
|
||||
void changed()
|
||||
{
|
||||
if(++nextversion < 0) resetversions();
|
||||
version = nextversion;
|
||||
}
|
||||
};
|
||||
|
||||
struct ShaderParamBinding
|
||||
{
|
||||
int loc, size;
|
||||
GLenum format;
|
||||
};
|
||||
|
||||
struct GlobalShaderParamUse : ShaderParamBinding
|
||||
{
|
||||
|
||||
GlobalShaderParamState *param;
|
||||
int version;
|
||||
|
||||
void flush()
|
||||
{
|
||||
if(version == param->version) return;
|
||||
switch(format)
|
||||
{
|
||||
case GL_BOOL:
|
||||
case GL_FLOAT: glUniform1fv_(loc, size, param->fval); break;
|
||||
case GL_BOOL_VEC2:
|
||||
case GL_FLOAT_VEC2: glUniform2fv_(loc, size, param->fval); break;
|
||||
case GL_BOOL_VEC3:
|
||||
case GL_FLOAT_VEC3: glUniform3fv_(loc, size, param->fval); break;
|
||||
case GL_BOOL_VEC4:
|
||||
case GL_FLOAT_VEC4: glUniform4fv_(loc, size, param->fval); break;
|
||||
case GL_INT: glUniform1iv_(loc, size, param->ival); break;
|
||||
case GL_INT_VEC2: glUniform2iv_(loc, size, param->ival); break;
|
||||
case GL_INT_VEC3: glUniform3iv_(loc, size, param->ival); break;
|
||||
case GL_INT_VEC4: glUniform4iv_(loc, size, param->ival); break;
|
||||
case GL_UNSIGNED_INT: glUniform1uiv_(loc, size, param->uval); break;
|
||||
case GL_UNSIGNED_INT_VEC2: glUniform2uiv_(loc, size, param->uval); break;
|
||||
case GL_UNSIGNED_INT_VEC3: glUniform3uiv_(loc, size, param->uval); break;
|
||||
case GL_UNSIGNED_INT_VEC4: glUniform4uiv_(loc, size, param->uval); break;
|
||||
case GL_FLOAT_MAT2: glUniformMatrix2fv_(loc, 1, GL_FALSE, param->fval); break;
|
||||
case GL_FLOAT_MAT3: glUniformMatrix3fv_(loc, 1, GL_FALSE, param->fval); break;
|
||||
case GL_FLOAT_MAT4: glUniformMatrix4fv_(loc, 1, GL_FALSE, param->fval); break;
|
||||
}
|
||||
version = param->version;
|
||||
}
|
||||
};
|
||||
|
||||
struct LocalShaderParamState : ShaderParamBinding
|
||||
{
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct SlotShaderParam
|
||||
{
|
||||
enum
|
||||
{
|
||||
REUSE = 1<<0
|
||||
};
|
||||
|
||||
const char *name;
|
||||
int loc, flags;
|
||||
float val[4];
|
||||
};
|
||||
|
||||
struct SlotShaderParamState : LocalShaderParamState
|
||||
{
|
||||
int flags;
|
||||
float val[4];
|
||||
|
||||
SlotShaderParamState() {}
|
||||
SlotShaderParamState(const SlotShaderParam &p)
|
||||
{
|
||||
name = p.name;
|
||||
loc = -1;
|
||||
size = 1;
|
||||
format = GL_FLOAT_VEC4;
|
||||
flags = p.flags;
|
||||
memcpy(val, p.val, sizeof(val));
|
||||
}
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SHADER_DEFAULT = 0,
|
||||
SHADER_WORLD = 1<<0,
|
||||
SHADER_ENVMAP = 1<<1,
|
||||
SHADER_REFRACT = 1<<2,
|
||||
SHADER_OPTION = 1<<3,
|
||||
SHADER_DYNAMIC = 1<<4,
|
||||
SHADER_TRIPLANAR = 1<<5,
|
||||
|
||||
SHADER_INVALID = 1<<8,
|
||||
SHADER_DEFERRED = 1<<9
|
||||
};
|
||||
|
||||
#define MAXVARIANTROWS 32
|
||||
|
||||
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
|
||||
{
|
||||
const char *name;
|
||||
int loc;
|
||||
AttribLoc(const char *name = NULL, int loc = -1) : name(name), loc(loc) {}
|
||||
};
|
||||
|
||||
struct FragDataLoc
|
||||
{
|
||||
const char *name;
|
||||
int loc;
|
||||
GLenum format;
|
||||
int index;
|
||||
FragDataLoc(const char *name = NULL, int loc = -1, GLenum format = GL_FALSE, int index = 0) : name(name), loc(loc), format(format), index(index) {}
|
||||
};
|
||||
|
||||
struct Shader
|
||||
{
|
||||
static Shader *lastshader;
|
||||
|
||||
char *name, *vsstr, *psstr, *defer;
|
||||
int type;
|
||||
GLuint program, vsobj, psobj;
|
||||
vector<SlotShaderParamState> defaultparams;
|
||||
vector<GlobalShaderParamUse> globalparams;
|
||||
vector<LocalShaderParamState> localparams;
|
||||
vector<uchar> localparamremap;
|
||||
Shader *variantshader;
|
||||
vector<Shader *> variants;
|
||||
ushort *variantrows;
|
||||
bool standard, forced, used;
|
||||
Shader *reusevs, *reuseps;
|
||||
vector<UniformLoc> uniformlocs;
|
||||
vector<AttribLoc> attriblocs;
|
||||
vector<FragDataLoc> fragdatalocs;
|
||||
const void *owner;
|
||||
|
||||
Shader() : name(NULL), vsstr(NULL), psstr(NULL), defer(NULL), type(SHADER_DEFAULT), program(0), vsobj(0), psobj(0), variantshader(NULL), variantrows(NULL), standard(false), forced(false), used(false), reusevs(NULL), reuseps(NULL), owner(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
~Shader()
|
||||
{
|
||||
DELETEA(name);
|
||||
DELETEA(vsstr);
|
||||
DELETEA(psstr);
|
||||
DELETEA(defer);
|
||||
DELETEA(variantrows);
|
||||
}
|
||||
|
||||
void allocparams(Slot *slot = NULL);
|
||||
void setslotparams(Slot &slot);
|
||||
void setslotparams(Slot &slot, VSlot &vslot);
|
||||
void bindprograms();
|
||||
|
||||
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 !(type&(SHADER_DEFERRED|SHADER_INVALID)); }
|
||||
|
||||
bool hasoption() const { return (type&SHADER_OPTION)!=0; }
|
||||
|
||||
bool isdynamic() const { return (type&SHADER_DYNAMIC)!=0; }
|
||||
|
||||
static inline bool isnull(const Shader *s) { return !s; }
|
||||
|
||||
bool isnull() const { return isnull(this); }
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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 *s = this;
|
||||
if(variantrows)
|
||||
{
|
||||
int start = variantrows[row], end = variantrows[row+1];
|
||||
for(col = min(start + col, end-1); col >= start; --col) if(!variants[col]->invalid()) { s = variants[col]; break; }
|
||||
}
|
||||
if(lastshader!=s) s->bindprograms();
|
||||
}
|
||||
|
||||
void setvariant(int col, int row)
|
||||
{
|
||||
if(isnull() || !loaded()) return;
|
||||
setvariant_(col, row);
|
||||
lastshader->flushparams();
|
||||
}
|
||||
|
||||
void setvariant(int col, int row, Slot &slot)
|
||||
{
|
||||
if(isnull() || !loaded()) return;
|
||||
setvariant_(col, row);
|
||||
lastshader->flushparams(&slot);
|
||||
lastshader->setslotparams(slot);
|
||||
}
|
||||
|
||||
void setvariant(int col, int row, Slot &slot, VSlot &vslot)
|
||||
{
|
||||
if(isnull() || !loaded()) return;
|
||||
setvariant_(col, row);
|
||||
lastshader->flushparams(&slot);
|
||||
lastshader->setslotparams(slot, vslot);
|
||||
}
|
||||
|
||||
void set_()
|
||||
{
|
||||
if(lastshader!=this) bindprograms();
|
||||
}
|
||||
|
||||
void set()
|
||||
{
|
||||
if(isnull() || !loaded()) return;
|
||||
set_();
|
||||
lastshader->flushparams();
|
||||
}
|
||||
|
||||
void set(Slot &slot)
|
||||
{
|
||||
if(isnull() || !loaded()) return;
|
||||
set_();
|
||||
lastshader->flushparams(&slot);
|
||||
lastshader->setslotparams(slot);
|
||||
}
|
||||
|
||||
void set(Slot &slot, VSlot &vslot)
|
||||
{
|
||||
if(isnull() || !loaded()) return;
|
||||
set_();
|
||||
lastshader->flushparams(&slot);
|
||||
lastshader->setslotparams(slot, vslot);
|
||||
}
|
||||
|
||||
bool compile();
|
||||
void cleanup(bool full = false);
|
||||
|
||||
static int uniformlocversion();
|
||||
};
|
||||
|
||||
struct GlobalShaderParam
|
||||
{
|
||||
const char *name;
|
||||
GlobalShaderParamState *param;
|
||||
|
||||
GlobalShaderParam(const char *name) : name(name), param(NULL) {}
|
||||
|
||||
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)
|
||||
{
|
||||
GlobalShaderParamState *g = resolve();
|
||||
g->fval[0] = x;
|
||||
g->fval[1] = y;
|
||||
g->fval[2] = z;
|
||||
g->fval[3] = w;
|
||||
}
|
||||
void set(const vec &v, float w = 0) { setf(v.x, v.y, v.z, w); }
|
||||
void set(const vec2 &v, float z = 0, float w = 0) { setf(v.x, v.y, z, w); }
|
||||
void set(const vec4 &v) { setf(v.x, v.y, v.z, v.w); }
|
||||
void set(const plane &p) { setf(p.x, p.y, p.z, p.offset); }
|
||||
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<class T>
|
||||
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)
|
||||
{
|
||||
GlobalShaderParamState *g = resolve();
|
||||
g->ival[0] = x;
|
||||
g->ival[1] = y;
|
||||
g->ival[2] = z;
|
||||
g->ival[3] = w;
|
||||
}
|
||||
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)
|
||||
{
|
||||
GlobalShaderParamState *g = resolve();
|
||||
g->uval[0] = x;
|
||||
g->uval[1] = y;
|
||||
g->uval[2] = z;
|
||||
g->uval[3] = w;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T *reserve(int n = 1) { return (T *)resolve()->buf; }
|
||||
};
|
||||
|
||||
struct LocalShaderParam
|
||||
{
|
||||
const char *name;
|
||||
int loc;
|
||||
|
||||
LocalShaderParam(const char *name) : name(name), loc(-1) {}
|
||||
|
||||
LocalShaderParamState *resolve()
|
||||
{
|
||||
Shader *s = Shader::lastshader;
|
||||
if(!s) return NULL;
|
||||
if(!s->localparamremap.inrange(loc))
|
||||
{
|
||||
extern int getlocalparam(const char *name);
|
||||
if(loc == -1) loc = getlocalparam(name);
|
||||
if(!s->localparamremap.inrange(loc)) return NULL;
|
||||
}
|
||||
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)
|
||||
{
|
||||
ShaderParamBinding *b = resolve();
|
||||
if(b) switch(b->format)
|
||||
{
|
||||
case GL_BOOL:
|
||||
case GL_FLOAT: glUniform1f_(b->loc, x); break;
|
||||
case GL_BOOL_VEC2:
|
||||
case GL_FLOAT_VEC2: glUniform2f_(b->loc, x, y); break;
|
||||
case GL_BOOL_VEC3:
|
||||
case GL_FLOAT_VEC3: glUniform3f_(b->loc, x, y, z); break;
|
||||
case GL_BOOL_VEC4:
|
||||
case GL_FLOAT_VEC4: glUniform4f_(b->loc, x, y, z, w); break;
|
||||
case GL_INT: glUniform1i_(b->loc, int(x)); break;
|
||||
case GL_INT_VEC2: glUniform2i_(b->loc, int(x), int(y)); break;
|
||||
case GL_INT_VEC3: glUniform3i_(b->loc, int(x), int(y), int(z)); break;
|
||||
case GL_INT_VEC4: glUniform4i_(b->loc, int(x), int(y), int(z), int(w)); break;
|
||||
case GL_UNSIGNED_INT: glUniform1ui_(b->loc, uint(x)); break;
|
||||
case GL_UNSIGNED_INT_VEC2: glUniform2ui_(b->loc, uint(x), uint(y)); break;
|
||||
case GL_UNSIGNED_INT_VEC3: glUniform3ui_(b->loc, uint(x), uint(y), uint(z)); break;
|
||||
case GL_UNSIGNED_INT_VEC4: glUniform4ui_(b->loc, uint(x), uint(y), uint(z), uint(w)); break;
|
||||
}
|
||||
}
|
||||
void set(const vec &v, float w = 0) { setf(v.x, v.y, v.z, w); }
|
||||
void set(const vec2 &v, float z = 0, float w = 0) { setf(v.x, v.y, z, w); }
|
||||
void set(const vec4 &v) { setf(v.x, v.y, v.z, v.w); }
|
||||
void set(const plane &p) { setf(p.x, p.y, p.z, p.offset); }
|
||||
void setv(const float *f, int n = 1) { ShaderParamBinding *b = resolve(); if(b) glUniform1fv_(b->loc, n, f); }
|
||||
void setv(const vec *v, int n = 1) { ShaderParamBinding *b = resolve(); if(b) glUniform3fv_(b->loc, n, v->v); }
|
||||
void setv(const vec2 *v, int n = 1) { ShaderParamBinding *b = resolve(); if(b) glUniform2fv_(b->loc, n, v->v); }
|
||||
void setv(const vec4 *v, int n = 1) { ShaderParamBinding *b = resolve(); if(b) glUniform4fv_(b->loc, n, v->v); }
|
||||
void setv(const plane *p, int n = 1) { ShaderParamBinding *b = resolve(); if(b) glUniform4fv_(b->loc, n, p->v); }
|
||||
void setv(const matrix2 *m, int n = 1) { ShaderParamBinding *b = resolve(); if(b) glUniformMatrix2fv_(b->loc, n, GL_FALSE, m->a.v); }
|
||||
void setv(const matrix3 *m, int n = 1) { ShaderParamBinding *b = resolve(); if(b) glUniformMatrix3fv_(b->loc, n, GL_FALSE, m->a.v); }
|
||||
void setv(const matrix4 *m, int n = 1) { ShaderParamBinding *b = resolve(); if(b) glUniformMatrix4fv_(b->loc, n, GL_FALSE, m->a.v); }
|
||||
void set(const matrix2 &m) { setv(&m); }
|
||||
void set(const matrix3 &m) { setv(&m); }
|
||||
void set(const matrix4 &m) { setv(&m); }
|
||||
|
||||
template<class T>
|
||||
void sett(T x, T y, T z, T w)
|
||||
{
|
||||
ShaderParamBinding *b = resolve();
|
||||
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;
|
||||
case GL_FLOAT_VEC4: glUniform4f_(b->loc, x, y, z, w); break;
|
||||
case GL_BOOL:
|
||||
case GL_INT: glUniform1i_(b->loc, x); break;
|
||||
case GL_BOOL_VEC2:
|
||||
case GL_INT_VEC2: glUniform2i_(b->loc, x, y); break;
|
||||
case GL_BOOL_VEC3:
|
||||
case GL_INT_VEC3: glUniform3i_(b->loc, x, y, z); break;
|
||||
case GL_BOOL_VEC4:
|
||||
case GL_INT_VEC4: glUniform4i_(b->loc, x, y, z, w); break;
|
||||
case GL_UNSIGNED_INT: glUniform1ui_(b->loc, x); break;
|
||||
case GL_UNSIGNED_INT_VEC2: glUniform2ui_(b->loc, x, y); break;
|
||||
case GL_UNSIGNED_INT_VEC3: glUniform3ui_(b->loc, x, y, z); break;
|
||||
case GL_UNSIGNED_INT_VEC4: glUniform4ui_(b->loc, x, y, z, w); break;
|
||||
}
|
||||
}
|
||||
void seti(int x = 0, int y = 0, int z = 0, int w = 0) { sett<int>(x, y, z, w); }
|
||||
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 setv(const int *i, int n = 1) { ShaderParamBinding *b = resolve(); if(b) glUniform1iv_(b->loc, n, i); }
|
||||
void setv(const ivec *v, int n = 1) { ShaderParamBinding *b = resolve(); if(b) glUniform3iv_(b->loc, n, v->v); }
|
||||
void setv(const ivec2 *v, int n = 1) { ShaderParamBinding *b = resolve(); if(b) glUniform2iv_(b->loc, n, v->v); }
|
||||
void setv(const ivec4 *v, int n = 1) { ShaderParamBinding *b = resolve(); if(b) glUniform4iv_(b->loc, n, v->v); }
|
||||
|
||||
void setu(uint x = 0, uint y = 0, uint z = 0, uint w = 0) { sett<uint>(x, y, z, w); }
|
||||
void setv(const uint *u, int n = 1) { ShaderParamBinding *b = resolve(); if(b) glUniform1uiv_(b->loc, n, u); }
|
||||
};
|
||||
|
||||
#define LOCALPARAM(name, vals) do { static LocalShaderParam param( #name ); param.set(vals); } while(0)
|
||||
#define LOCALPARAMF(name, ...) do { static LocalShaderParam param( #name ); param.setf(__VA_ARGS__); } while(0)
|
||||
#define LOCALPARAMI(name, ...) do { static LocalShaderParam param( #name ); param.seti(__VA_ARGS__); } while(0)
|
||||
#define LOCALPARAMV(name, vals, num) do { static LocalShaderParam param( #name ); param.setv(vals, num); } while(0)
|
||||
#define GLOBALPARAM(name, vals) do { static GlobalShaderParam param( #name ); param.set(vals); } while(0)
|
||||
#define GLOBALPARAMF(name, ...) do { static GlobalShaderParam param( #name ); param.setf(__VA_ARGS__); } while(0)
|
||||
#define GLOBALPARAMI(name, ...) do { static GlobalShaderParam param( #name ); param.seti(__VA_ARGS__); } while(0)
|
||||
#define GLOBALPARAMV(name, vals, num) do { static GlobalShaderParam param( #name ); param.setv(vals, num); } while(0)
|
||||
|
||||
#define SETSHADER(name, ...) \
|
||||
do { \
|
||||
static Shader *name##shader = NULL; \
|
||||
if(!name##shader) name##shader = lookupshaderbyname(#name); \
|
||||
name##shader->set(__VA_ARGS__); \
|
||||
} while(0)
|
||||
#define SETVARIANT(name, ...) \
|
||||
do { \
|
||||
static Shader *name##shader = NULL; \
|
||||
if(!name##shader) name##shader = lookupshaderbyname(#name); \
|
||||
name##shader->setvariant(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
void resetslotshader();
|
||||
void setslotshader(Slot &s);
|
||||
void linkslotshader(Slot &s, bool load = true);
|
||||
void linkvslotshader(VSlot &s, bool load = true);
|
||||
|
||||
bool shouldreuseparams(Slot &s, VSlot &p);
|
||||
void setupshaders();
|
||||
void loadshaders();
|
||||
void reloadshaders();
|
||||
void cleanupshaders();
|
||||
|
||||
extern int maxvsuniforms, maxfsuniforms;
|
||||
|
||||
extern Shader *nullshader, *hudshader, *hudtextshader, *hudnotextureshader, *nocolorshader, *foggedshader, *foggednotextureshader, *ldrshader, *ldrnotextureshader, *stdworldshader;
|
||||
|
||||
const char *getshaderparamname(const char *name, bool insert = true);
|
||||
Shader *lookupshaderbyname(const char *name);
|
||||
Shader *useshaderbyname(const char *name);
|
||||
Shader *generateshader(const char *name, const char *cmd, ...);
|
||||
|
||||
GLuint setuppostfx(int w, int h, GLuint outfbo = 0);
|
||||
void cleanuppostfx(bool fullclean = false);
|
||||
void renderpostfx(GLuint outfbo = 0);
|
||||
|
||||
#endif
|
|
@ -1,4 +1,5 @@
|
|||
#include "material.hh"
|
||||
#include "texture.hh"
|
||||
|
||||
#include "engine.hh"
|
||||
|
||||
|
|
|
@ -1,790 +0,0 @@
|
|||
|
||||
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)
|
||||
{
|
||||
set(init);
|
||||
}
|
||||
|
||||
bool empty() { return len <= 0; }
|
||||
|
||||
void clear()
|
||||
{
|
||||
DELETEA(text);
|
||||
len = maxlen = 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vformatstring(newtext, fmt, args, maxlen);
|
||||
va_end(args);
|
||||
}
|
||||
else newtext[0] = '\0';
|
||||
DELETEA(text);
|
||||
text = newtext;
|
||||
return true;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
grow(slen);
|
||||
memcpy(text, str, slen);
|
||||
text[slen] = '\0';
|
||||
}
|
||||
len = slen;
|
||||
}
|
||||
|
||||
void prepend(const char *str)
|
||||
{
|
||||
int slen = strlen(str);
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if(chop < 0) chop = INT_MAX; else chop++;
|
||||
set("");
|
||||
while(len + 1 < chop && f->getline(&text[len], min(maxlen, chop) - len))
|
||||
{
|
||||
len += strlen(&text[len]);
|
||||
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)
|
||||
{
|
||||
char buf[CHUNKSIZE];
|
||||
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)
|
||||
{
|
||||
if(!text) return;
|
||||
if(start < 0) { count += start; start = 0; }
|
||||
if(count <= 0 || start >= len) return;
|
||||
if(start + count > len) count = len - start - 1;
|
||||
memmove(&text[start], &text[start+count], len + 1 - (start + count));
|
||||
len -= count;
|
||||
}
|
||||
|
||||
void chop(int newlen)
|
||||
{
|
||||
if(!text) return;
|
||||
len = clamp(newlen, 0, len);
|
||||
text[len] = '\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 : "");
|
||||
memmove(&text[start + count], &text[start], len - start + 1);
|
||||
memcpy(&text[start], str, count);
|
||||
len += count;
|
||||
}
|
||||
|
||||
void combinelines(vector<editline> &src)
|
||||
{
|
||||
if(src.empty()) set("");
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
enum { EDITORFOCUSED = 1, EDITORUSED, EDITORFOREVER };
|
||||
|
||||
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<editline> 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)
|
||||
{
|
||||
//printf("editor %08x '%s'\n", this, name);
|
||||
lines.add().set(initval ? initval : "");
|
||||
}
|
||||
|
||||
~editor()
|
||||
{
|
||||
//printf("~editor %08x '%s'\n", this, name);
|
||||
DELETEA(name);
|
||||
DELETEA(filename);
|
||||
clear(NULL);
|
||||
}
|
||||
|
||||
bool empty() { return lines.length() == 1 && lines[0].empty(); }
|
||||
|
||||
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 init(const char *inittext)
|
||||
{
|
||||
if(strcmp(lines[0].text, inittext)) clear(inittext);
|
||||
}
|
||||
|
||||
void updateheight()
|
||||
{
|
||||
int width;
|
||||
text_bounds(lines[0].text, width, pixelheight, pixelwidth);
|
||||
}
|
||||
|
||||
void setfile(const char *fname)
|
||||
{
|
||||
DELETEA(filename);
|
||||
if(fname) filename = newstring(fname);
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
if(!filename) return;
|
||||
clear(NULL);
|
||||
stream *file = openutf8file(filename, "r");
|
||||
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()
|
||||
{
|
||||
if(!filename) return;
|
||||
stream *file = openutf8file(filename, "w");
|
||||
if(!file) return;
|
||||
loopv(lines) file->putline(lines[i].text);
|
||||
delete file;
|
||||
}
|
||||
|
||||
void mark(bool enable)
|
||||
{
|
||||
mx = (enable) ? cx : -1;
|
||||
my = cy;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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(my < 0) my = 0; else if(my >= n) my = n-1;
|
||||
len = lines[my].len;
|
||||
if(mx > len) mx = len;
|
||||
sx = mx; sy = my;
|
||||
}
|
||||
else { sx = cx; sy = cy; }
|
||||
ex = cx;
|
||||
ey = cy;
|
||||
if(sy > ey) { swap(sy, ey); swap(sx, ex); }
|
||||
else if(sy==ey && sx > ex) swap(sx, ex);
|
||||
if(mx >= 0) 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()
|
||||
{
|
||||
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)
|
||||
{
|
||||
if(b==this) return;
|
||||
|
||||
b->clear(NULL);
|
||||
int sx, sy, ex, ey;
|
||||
region(sx, sy, ex, ey);
|
||||
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)
|
||||
{
|
||||
line += sx;
|
||||
len = ex - sx;
|
||||
}
|
||||
else if(y == sy) line += sx;
|
||||
else if(y == ey) len = ex;
|
||||
b->lines.add().set(line, len);
|
||||
}
|
||||
if(b->lines.empty()) b->lines.add().set("");
|
||||
}
|
||||
|
||||
char *tostring()
|
||||
{
|
||||
int len = 0;
|
||||
loopv(lines) len += lines[i].len + 1;
|
||||
char *str = newstring(len);
|
||||
int offset = 0;
|
||||
loopv(lines)
|
||||
{
|
||||
editline &l = lines[i];
|
||||
memcpy(&str[offset], l.text, l.len);
|
||||
offset += l.len;
|
||||
str[offset++] = '\n';
|
||||
}
|
||||
str[offset] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
char *selectiontostring()
|
||||
{
|
||||
vector<char> buf;
|
||||
int sx, sy, ex, ey;
|
||||
region(sx, sy, ex, ey);
|
||||
loopi(1+ey-sy)
|
||||
{
|
||||
int y = sy+i;
|
||||
char *line = lines[y].text;
|
||||
int len = lines[y].len;
|
||||
if(y == sy && y == ey)
|
||||
{
|
||||
line += sx;
|
||||
len = ex - sx;
|
||||
}
|
||||
else if(y == sy) line += sx;
|
||||
else if(y == ey) len = ex;
|
||||
buf.put(line, len);
|
||||
buf.add('\n');
|
||||
}
|
||||
buf.add('\0');
|
||||
return newstring(buf.getbuf(), buf.length()-1);
|
||||
}
|
||||
|
||||
void removelines(int start, int count)
|
||||
{
|
||||
loopi(count) lines[start+i].clear();
|
||||
lines.remove(start, count);
|
||||
}
|
||||
|
||||
bool del() // removes the current selection (if any)
|
||||
{
|
||||
int sx, sy, ex, ey;
|
||||
if(!region(sx, sy, ex, ey))
|
||||
{
|
||||
mark(false);
|
||||
return false;
|
||||
}
|
||||
if(sy == ey)
|
||||
{
|
||||
if(sx == 0 && ex == lines[ey].len) removelines(sy, 1);
|
||||
else lines[sy].del(sx, ex - sx);
|
||||
}
|
||||
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);
|
||||
}
|
||||
if(lines.empty()) lines.add().set("");
|
||||
mark(false);
|
||||
cx = sx;
|
||||
cy = sy;
|
||||
editline ¤t = currentline();
|
||||
if(cx >= current.len && cy < lines.length() - 1)
|
||||
{
|
||||
current.append(lines[cy+1].text);
|
||||
removelines(cy + 1, 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void insert(char ch)
|
||||
{
|
||||
del();
|
||||
editline ¤t = currentline();
|
||||
if(ch == '\n')
|
||||
{
|
||||
if(maxy == -1 || cy < maxy-1)
|
||||
{
|
||||
editline newline(¤t.text[cx]);
|
||||
current.chop(cx);
|
||||
cy = min(lines.length(), cy+1);
|
||||
lines.insert(cy, newline);
|
||||
}
|
||||
else current.chop(cx);
|
||||
cx = 0;
|
||||
}
|
||||
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)
|
||||
{
|
||||
while(*s) insert(*s++);
|
||||
}
|
||||
|
||||
void insertallfrom(editor *b)
|
||||
{
|
||||
if(b==this) return;
|
||||
|
||||
del();
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
lines[cy++].append(b->lines[i].text);
|
||||
}
|
||||
else if(i >= b->lines.length())
|
||||
{
|
||||
cx = b->lines[i].len;
|
||||
lines[cy].prepend(b->lines[i].text);
|
||||
}
|
||||
else if(maxy < 0 || lines.length() < maxy) lines.insert(cy++, editline(b->lines[i].text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scrollup()
|
||||
{
|
||||
cy--;
|
||||
}
|
||||
|
||||
void scrolldown()
|
||||
{
|
||||
cy++;
|
||||
}
|
||||
|
||||
void key(int code)
|
||||
{
|
||||
switch(code)
|
||||
{
|
||||
case SDLK_UP:
|
||||
if(linewrap)
|
||||
{
|
||||
int x, y;
|
||||
char *str = currentline().text;
|
||||
text_pos(str, cx+1, x, y, pixelwidth);
|
||||
if(y > 0) { cx = text_visible(str, x, y-FONTH, pixelwidth); break; }
|
||||
}
|
||||
cy--;
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
if(linewrap)
|
||||
{
|
||||
int x, y, width, height;
|
||||
char *str = currentline().text;
|
||||
text_pos(str, cx, x, y, pixelwidth);
|
||||
text_bounds(str, width, height, pixelwidth);
|
||||
y += FONTH;
|
||||
if(y < height) { cx = text_visible(str, x, y, pixelwidth); break; }
|
||||
}
|
||||
cy++;
|
||||
break;
|
||||
case SDLK_PAGEUP:
|
||||
cy-=pixelheight/FONTH;
|
||||
break;
|
||||
case SDLK_PAGEDOWN:
|
||||
cy+=pixelheight/FONTH;
|
||||
break;
|
||||
case SDLK_HOME:
|
||||
cx = cy = 0;
|
||||
break;
|
||||
case SDLK_END:
|
||||
cx = cy = INT_MAX;
|
||||
break;
|
||||
case SDLK_LEFT:
|
||||
cx--;
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
cx++;
|
||||
break;
|
||||
case SDLK_DELETE:
|
||||
if(!del())
|
||||
{
|
||||
editline ¤t = currentline();
|
||||
if(cx < current.len) current.del(cx, 1);
|
||||
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())
|
||||
{
|
||||
editline ¤t = currentline();
|
||||
if(cx > 0) current.del(--cx, 1);
|
||||
else if(cy > 0)
|
||||
{ //combine with previous line
|
||||
cx = lines[cy-1].len;
|
||||
lines[cy-1].append(current.text);
|
||||
removelines(cy--, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|