more eol-style
git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/branches/ZeroRadiant@185 8a3a26a2-13c4-0310-b231-cf6edde360e5
This commit is contained in:
@@ -1,175 +1,175 @@
|
||||
/*
|
||||
Copyright (C) 1999-2007 id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "entity_entitymodel.h"
|
||||
|
||||
//
|
||||
// CEntityEclassModel implementation
|
||||
//
|
||||
|
||||
CEntityEclassModel::CEntityEclassModel ()
|
||||
{
|
||||
refCount = 1;
|
||||
m_eclass = NULL;
|
||||
m_model = NULL;
|
||||
VectorSet(m_translate, 0,0,0);
|
||||
VectorSet(m_euler, 0,0,0);
|
||||
VectorSet(m_scale, 1,1,1);
|
||||
VectorSet(m_pivot, 0,0,0);
|
||||
m4x4_identity(m_transform);
|
||||
m4x4_identity(m_inverse_transform);
|
||||
}
|
||||
|
||||
CEntityEclassModel::~CEntityEclassModel ()
|
||||
{
|
||||
if(m_name.c_str()[0] != '\0'
|
||||
&& m_version.c_str()[0] != '\0')
|
||||
GetModelCache()->DeleteByID(m_name.c_str(), m_version.c_str());
|
||||
}
|
||||
|
||||
|
||||
// IRender
|
||||
|
||||
void CEntityEclassModel::Draw(int state, int rflags) const
|
||||
{
|
||||
// push the current modelview matrix
|
||||
// FIXME: put in a check for stack recursion depth..
|
||||
// or avoid recursion of opengl matrix stack
|
||||
g_QglTable.m_pfn_qglPushMatrix();
|
||||
// apply the parent-to-local transform
|
||||
g_QglTable.m_pfn_qglMultMatrixf(m_transform);
|
||||
|
||||
// draw children
|
||||
if(m_model && m_model->pRender)
|
||||
{
|
||||
m_model->pRender->Draw(state, rflags);
|
||||
}
|
||||
|
||||
g_QglTable.m_pfn_qglPopMatrix();
|
||||
}
|
||||
|
||||
// ISelect
|
||||
|
||||
bool CEntityEclassModel::TestRay(const ray_t *ray, vec_t *dist) const
|
||||
{
|
||||
vec_t dist_start = *dist;
|
||||
vec_t dist_local = *dist;
|
||||
ray_t ray_local = *ray;
|
||||
|
||||
if (aabb_intersect_ray(&m_BBox, &ray_local, &dist_local))
|
||||
*dist = dist_local;
|
||||
return *dist < dist_start;
|
||||
}
|
||||
|
||||
|
||||
//IEdit
|
||||
|
||||
void CEntityEclassModel::Translate(const vec3_t translation)
|
||||
{
|
||||
VectorIncrement(translation, m_translate);
|
||||
UpdateCachedData();
|
||||
}
|
||||
|
||||
void CEntityEclassModel::Rotate(const vec3_t pivot, const vec3_t rotation)
|
||||
{
|
||||
m4x4_t rotation_matrix;
|
||||
|
||||
m4x4_identity(rotation_matrix);
|
||||
m4x4_pivoted_rotate_by_vec3(rotation_matrix, rotation, eXYZ, pivot);
|
||||
m4x4_transform_point(rotation_matrix, m_translate);
|
||||
|
||||
VectorIncrement(rotation, m_euler);
|
||||
|
||||
UpdateCachedData();
|
||||
}
|
||||
|
||||
void CEntityEclassModel::OnKeyValueChanged(entity_t *e, const char *key, const char* value)
|
||||
{
|
||||
if(strcmp(key,"origin") == 0)
|
||||
{
|
||||
sscanf(value, "%f %f %f", &m_translate[0], &m_translate[1], &m_translate[2]);
|
||||
UpdateCachedData();
|
||||
}
|
||||
else if(strcmp(key,"angle") == 0)
|
||||
{
|
||||
VectorSet(m_euler, 0, 0, (float) atof(value));
|
||||
UpdateCachedData();
|
||||
}
|
||||
}
|
||||
|
||||
void CEntityEclassModel::SetEclass(const eclass_t* eclass)
|
||||
{
|
||||
m_eclass = eclass;
|
||||
}
|
||||
|
||||
void CEntityEclassModel::SetName(const char *name)
|
||||
{
|
||||
if(strcmp(m_name.c_str(), name) == 0)
|
||||
return;
|
||||
|
||||
if(m_name.c_str()[0] != '\0'
|
||||
&& m_version.c_str()[0] != '\0')
|
||||
GetModelCache()->DeleteByID(m_name.c_str(), m_version.c_str());
|
||||
|
||||
m_model = NULL;
|
||||
m_name = name;
|
||||
|
||||
if(m_name.c_str()[0] != '\0')
|
||||
{
|
||||
const char* dot = strrchr(m_name.c_str(), '.');
|
||||
if(dot != NULL)
|
||||
{
|
||||
m_version = ++dot;
|
||||
m_model = GetModelCache()->GetByID(m_name.c_str(), m_version.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
UpdateCachedData();
|
||||
}
|
||||
|
||||
//
|
||||
// CEntityEclassModel
|
||||
//
|
||||
|
||||
// private:
|
||||
|
||||
void CEntityEclassModel::UpdateCachedData()
|
||||
{
|
||||
aabb_t aabb_temp;
|
||||
|
||||
aabb_clear(&aabb_temp);
|
||||
|
||||
m4x4_identity(m_transform);
|
||||
m4x4_pivoted_transform_by_vec3(m_transform, m_translate, m_euler, eXYZ, m_scale, m_pivot);
|
||||
memcpy(m_inverse_transform, m_transform, sizeof(m4x4_t));
|
||||
if(m4x4_invert(m_inverse_transform) == 1) {
|
||||
Sys_Printf("ERROR: Singular Matrix, cannot invert");
|
||||
}
|
||||
|
||||
if(m_eclass)
|
||||
aabb_construct_for_vec3(&aabb_temp, m_eclass->mins, m_eclass->maxs);
|
||||
else
|
||||
VectorSet(aabb_temp.extents, 8, 8, 8);
|
||||
|
||||
aabb_for_transformed_aabb(&m_BBox, &aabb_temp, m_transform);
|
||||
}
|
||||
/*
|
||||
Copyright (C) 1999-2007 id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "entity_entitymodel.h"
|
||||
|
||||
//
|
||||
// CEntityEclassModel implementation
|
||||
//
|
||||
|
||||
CEntityEclassModel::CEntityEclassModel ()
|
||||
{
|
||||
refCount = 1;
|
||||
m_eclass = NULL;
|
||||
m_model = NULL;
|
||||
VectorSet(m_translate, 0,0,0);
|
||||
VectorSet(m_euler, 0,0,0);
|
||||
VectorSet(m_scale, 1,1,1);
|
||||
VectorSet(m_pivot, 0,0,0);
|
||||
m4x4_identity(m_transform);
|
||||
m4x4_identity(m_inverse_transform);
|
||||
}
|
||||
|
||||
CEntityEclassModel::~CEntityEclassModel ()
|
||||
{
|
||||
if(m_name.c_str()[0] != '\0'
|
||||
&& m_version.c_str()[0] != '\0')
|
||||
GetModelCache()->DeleteByID(m_name.c_str(), m_version.c_str());
|
||||
}
|
||||
|
||||
|
||||
// IRender
|
||||
|
||||
void CEntityEclassModel::Draw(int state, int rflags) const
|
||||
{
|
||||
// push the current modelview matrix
|
||||
// FIXME: put in a check for stack recursion depth..
|
||||
// or avoid recursion of opengl matrix stack
|
||||
g_QglTable.m_pfn_qglPushMatrix();
|
||||
// apply the parent-to-local transform
|
||||
g_QglTable.m_pfn_qglMultMatrixf(m_transform);
|
||||
|
||||
// draw children
|
||||
if(m_model && m_model->pRender)
|
||||
{
|
||||
m_model->pRender->Draw(state, rflags);
|
||||
}
|
||||
|
||||
g_QglTable.m_pfn_qglPopMatrix();
|
||||
}
|
||||
|
||||
// ISelect
|
||||
|
||||
bool CEntityEclassModel::TestRay(const ray_t *ray, vec_t *dist) const
|
||||
{
|
||||
vec_t dist_start = *dist;
|
||||
vec_t dist_local = *dist;
|
||||
ray_t ray_local = *ray;
|
||||
|
||||
if (aabb_intersect_ray(&m_BBox, &ray_local, &dist_local))
|
||||
*dist = dist_local;
|
||||
return *dist < dist_start;
|
||||
}
|
||||
|
||||
|
||||
//IEdit
|
||||
|
||||
void CEntityEclassModel::Translate(const vec3_t translation)
|
||||
{
|
||||
VectorIncrement(translation, m_translate);
|
||||
UpdateCachedData();
|
||||
}
|
||||
|
||||
void CEntityEclassModel::Rotate(const vec3_t pivot, const vec3_t rotation)
|
||||
{
|
||||
m4x4_t rotation_matrix;
|
||||
|
||||
m4x4_identity(rotation_matrix);
|
||||
m4x4_pivoted_rotate_by_vec3(rotation_matrix, rotation, eXYZ, pivot);
|
||||
m4x4_transform_point(rotation_matrix, m_translate);
|
||||
|
||||
VectorIncrement(rotation, m_euler);
|
||||
|
||||
UpdateCachedData();
|
||||
}
|
||||
|
||||
void CEntityEclassModel::OnKeyValueChanged(entity_t *e, const char *key, const char* value)
|
||||
{
|
||||
if(strcmp(key,"origin") == 0)
|
||||
{
|
||||
sscanf(value, "%f %f %f", &m_translate[0], &m_translate[1], &m_translate[2]);
|
||||
UpdateCachedData();
|
||||
}
|
||||
else if(strcmp(key,"angle") == 0)
|
||||
{
|
||||
VectorSet(m_euler, 0, 0, (float) atof(value));
|
||||
UpdateCachedData();
|
||||
}
|
||||
}
|
||||
|
||||
void CEntityEclassModel::SetEclass(const eclass_t* eclass)
|
||||
{
|
||||
m_eclass = eclass;
|
||||
}
|
||||
|
||||
void CEntityEclassModel::SetName(const char *name)
|
||||
{
|
||||
if(strcmp(m_name.c_str(), name) == 0)
|
||||
return;
|
||||
|
||||
if(m_name.c_str()[0] != '\0'
|
||||
&& m_version.c_str()[0] != '\0')
|
||||
GetModelCache()->DeleteByID(m_name.c_str(), m_version.c_str());
|
||||
|
||||
m_model = NULL;
|
||||
m_name = name;
|
||||
|
||||
if(m_name.c_str()[0] != '\0')
|
||||
{
|
||||
const char* dot = strrchr(m_name.c_str(), '.');
|
||||
if(dot != NULL)
|
||||
{
|
||||
m_version = ++dot;
|
||||
m_model = GetModelCache()->GetByID(m_name.c_str(), m_version.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
UpdateCachedData();
|
||||
}
|
||||
|
||||
//
|
||||
// CEntityEclassModel
|
||||
//
|
||||
|
||||
// private:
|
||||
|
||||
void CEntityEclassModel::UpdateCachedData()
|
||||
{
|
||||
aabb_t aabb_temp;
|
||||
|
||||
aabb_clear(&aabb_temp);
|
||||
|
||||
m4x4_identity(m_transform);
|
||||
m4x4_pivoted_transform_by_vec3(m_transform, m_translate, m_euler, eXYZ, m_scale, m_pivot);
|
||||
memcpy(m_inverse_transform, m_transform, sizeof(m4x4_t));
|
||||
if(m4x4_invert(m_inverse_transform) == 1) {
|
||||
Sys_Printf("ERROR: Singular Matrix, cannot invert");
|
||||
}
|
||||
|
||||
if(m_eclass)
|
||||
aabb_construct_for_vec3(&aabb_temp, m_eclass->mins, m_eclass->maxs);
|
||||
else
|
||||
VectorSet(aabb_temp.extents, 8, 8, 8);
|
||||
|
||||
aabb_for_transformed_aabb(&m_BBox, &aabb_temp, m_transform);
|
||||
}
|
||||
|
||||
@@ -1,377 +1,377 @@
|
||||
/*
|
||||
Copyright (C) 1999-2007 id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
#include "entity.h"
|
||||
#include "entity_entitymodel.h"
|
||||
#include "light.h"
|
||||
|
||||
int g_entityId = 1;
|
||||
|
||||
|
||||
|
||||
// internal
|
||||
|
||||
static void Entity_FreeEpairs(entity_t *e);
|
||||
|
||||
static void SetKeyValue (epair_t *&e, const char *key, const char *value);
|
||||
static void DeleteKey (epair_t *&e, const char *key);
|
||||
static const char *ValueForKey ( epair_t *&e, const char *key);
|
||||
|
||||
static void Entity_OnKeyValueChanged(entity_t *e, const char* key, const char* value);
|
||||
|
||||
// constructor
|
||||
entity_t *Entity_Alloc()
|
||||
{
|
||||
entity_t *e;
|
||||
e = (entity_t*)malloc (sizeof(*e));
|
||||
e->entityId = g_entityId++;
|
||||
VectorSet(e->origin, 0, 0, 0);
|
||||
VectorSet(e->color, 1, 1, 1);
|
||||
e->redoId = 0;
|
||||
e->undoId = 0;
|
||||
e->next = e->prev = NULL;
|
||||
e->brushes.onext = e->brushes.oprev = &e->brushes;
|
||||
e->epairs = NULL;
|
||||
e->eclass = NULL;
|
||||
e->model.pRender = NULL;
|
||||
e->model.pSelect = NULL;
|
||||
e->model.pEdit = NULL;
|
||||
return e;
|
||||
}
|
||||
|
||||
// destructor
|
||||
void Entity_Free (entity_t *e)
|
||||
{
|
||||
while (e->brushes.onext != &e->brushes)
|
||||
Brush_Free( e->brushes.onext, true );
|
||||
|
||||
if (e->next)
|
||||
{
|
||||
e->next->prev = e->prev;
|
||||
e->prev->next = e->next;
|
||||
}
|
||||
|
||||
Entity_FreeEpairs(e);
|
||||
|
||||
if (e->model.pRender)
|
||||
{
|
||||
e->model.pRender->DecRef();
|
||||
e->model.pRender = NULL;
|
||||
}
|
||||
if (e->model.pSelect)
|
||||
{
|
||||
e->model.pSelect->DecRef();
|
||||
e->model.pSelect = NULL;
|
||||
}
|
||||
if (e->model.pEdit)
|
||||
{
|
||||
e->model.pEdit->DecRef();
|
||||
e->model.pEdit = NULL;
|
||||
}
|
||||
|
||||
free (e);
|
||||
}
|
||||
|
||||
// construct from entity
|
||||
entity_t *Entity_Clone (entity_t *e)
|
||||
{
|
||||
entity_t *n;
|
||||
epair_t *ep;
|
||||
|
||||
n = Entity_Alloc();
|
||||
n->eclass = e->eclass;
|
||||
|
||||
for (ep = e->epairs ; ep ; ep=ep->next)
|
||||
SetKeyValue(n, ep->key, ep->value);
|
||||
|
||||
// copy some misc stuff as well
|
||||
VectorCopy( e->origin, n->origin );
|
||||
// VectorCopy( e->vRotation, n->vRotation );
|
||||
// VectorCopy( e->vScale, n->vScale );
|
||||
|
||||
// n->bDirty = true;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const char *ValueForKey ( epair_t *&e, const char *key)
|
||||
{
|
||||
epair_t *ep;
|
||||
for (ep=e ; ep ; ep=ep->next)
|
||||
{
|
||||
if (!strcmp (ep->key, key) )
|
||||
{
|
||||
return ep->value;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const char *ValueForKey (entity_t *ent, const char *key)
|
||||
{
|
||||
return ValueForKey(ent->epairs, key);
|
||||
}
|
||||
|
||||
void SetKeyValue (epair_t *&e, const char *key, const char *value)
|
||||
{
|
||||
epair_t *ep;
|
||||
for (ep=e ; ep ; ep=ep->next)
|
||||
{
|
||||
if (!strcmp (ep->key, key) )
|
||||
{
|
||||
free (ep->value);
|
||||
ep->value = (char*)malloc(strlen(value)+1);
|
||||
strcpy (ep->value, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ep = (epair_t*)malloc (sizeof(*ep));
|
||||
ep->next = e;
|
||||
e = ep;
|
||||
ep->key = (char*)malloc(strlen(key)+1);
|
||||
strcpy (ep->key, key);
|
||||
ep->value = (char*)malloc(strlen(value)+1);
|
||||
strcpy (ep->value, value);
|
||||
|
||||
}
|
||||
|
||||
void SetKeyValue (entity_t *ent, const char *key, const char *value)
|
||||
{
|
||||
if (ent == NULL)
|
||||
{
|
||||
Sys_FPrintf(SYS_ERR, "ERROR: SetKeyValue: NULL entity \n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!key || !key[0])
|
||||
{
|
||||
Sys_FPrintf(SYS_ERR, "ERROR: SetKeyValue: NULL or zero-length key\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SetKeyValue(ent->epairs, key, value);
|
||||
/*!
|
||||
\todo TODO broadcast this through a clean messaging API ;-)
|
||||
*/
|
||||
Entity_OnKeyValueChanged(ent, key, value);
|
||||
}
|
||||
|
||||
void DeleteKey (epair_t *&e, const char *key)
|
||||
{
|
||||
epair_t **ep, *next;
|
||||
|
||||
ep = &e;
|
||||
while (*ep)
|
||||
{
|
||||
next = *ep;
|
||||
if ( !strcmp (next->key, key) )
|
||||
{
|
||||
*ep = next->next;
|
||||
free(next->key);
|
||||
free(next->value);
|
||||
free(next);
|
||||
return;
|
||||
}
|
||||
ep = &next->next;
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteKey (entity_t *ent, const char *key)
|
||||
{
|
||||
DeleteKey(ent->epairs, key);
|
||||
Entity_OnKeyValueChanged(ent, key, "");
|
||||
}
|
||||
|
||||
float FloatForKey (entity_t *ent, const char *key)
|
||||
{
|
||||
const char *k;
|
||||
|
||||
k = ValueForKey (ent, key);
|
||||
return (float) atof(k);
|
||||
}
|
||||
|
||||
int IntForKey (entity_t *ent, const char *key)
|
||||
{
|
||||
const char *k;
|
||||
|
||||
k = ValueForKey (ent, key);
|
||||
return atoi(k);
|
||||
}
|
||||
|
||||
void GetVectorForKey (entity_t *ent, const char *key, vec3_t vec)
|
||||
{
|
||||
const char *k;
|
||||
|
||||
k = ValueForKey (ent, key);
|
||||
sscanf (k, "%f %f %f", &vec[0], &vec[1], &vec[2]);
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Entity_FreeEpairs
|
||||
|
||||
Frees the entity epairs.
|
||||
===============
|
||||
*/
|
||||
void Entity_FreeEpairs(entity_t *e)
|
||||
{
|
||||
epair_t *ep, *next;
|
||||
|
||||
for (ep = e->epairs; ep; ep = next)
|
||||
{
|
||||
next = ep->next;
|
||||
free (ep->key);
|
||||
free (ep->value);
|
||||
free (ep);
|
||||
}
|
||||
e->epairs = NULL;
|
||||
}
|
||||
|
||||
void Entity_AddToList(entity_t *e, entity_t *elist)
|
||||
{
|
||||
if (e->next || e->prev)
|
||||
Error ("Entity_AddToList: already linked");
|
||||
//e->next = elist->next;
|
||||
//elist->next->prev = e;
|
||||
//elist->next = e;
|
||||
//e->prev = elist;
|
||||
e->next = elist;
|
||||
e->prev = elist->prev;
|
||||
elist->prev->next = e;
|
||||
elist->prev = e;
|
||||
}
|
||||
|
||||
void Entity_RemoveFromList (entity_t *e)
|
||||
{
|
||||
if (!e->next || !e->prev)
|
||||
Error ("Entity_RemoveFromList: not linked");
|
||||
e->next->prev = e->prev;
|
||||
e->prev->next = e->next;
|
||||
e->next = e->prev = NULL;
|
||||
}
|
||||
|
||||
void Entity_LinkBrush (entity_t *e, brush_t *b)
|
||||
{
|
||||
if (b->oprev || b->onext)
|
||||
Error ("Entity_LinkBrush: Already linked");
|
||||
b->owner = e;
|
||||
|
||||
// b->onext = e->brushes.onext;
|
||||
// b->oprev = &e->brushes;
|
||||
// e->brushes.onext->oprev = b;
|
||||
// e->brushes.onext = b;
|
||||
/*
|
||||
SPoG - changed to add brushes to end of list instead of start - so this can be used by map loader.
|
||||
This could concievably cause a problem if someone is traversing e->brushes while calling this function.
|
||||
So don't.
|
||||
*/
|
||||
b->onext = &e->brushes;
|
||||
b->oprev = e->brushes.oprev;
|
||||
e->brushes.oprev->onext = b;
|
||||
e->brushes.oprev = b;
|
||||
}
|
||||
|
||||
void Entity_UnlinkBrush (brush_t *b)
|
||||
{
|
||||
if (!b->onext || !b->oprev)
|
||||
Error ("Entity_UnlinkBrush: Not currently linked");
|
||||
b->onext->oprev = b->oprev;
|
||||
b->oprev->onext = b->onext;
|
||||
b->onext = b->oprev = NULL;
|
||||
b->owner = NULL;
|
||||
}
|
||||
|
||||
// for undo
|
||||
int Entity_MemorySize(entity_t *e)
|
||||
{
|
||||
epair_t *ep;
|
||||
int size = 0;
|
||||
|
||||
for (ep = e->epairs; ep; ep = ep->next)
|
||||
{
|
||||
size += strlen(ep->key);
|
||||
size += strlen(ep->value);
|
||||
size += sizeof(epair_t);
|
||||
}
|
||||
size += sizeof(entity_t);
|
||||
return size;
|
||||
}
|
||||
|
||||
epair_t* Entity_AllocateEpair(const char *key, const char *value)
|
||||
{
|
||||
epair_t *ep = (epair_t*)malloc (sizeof(*ep));
|
||||
ep->key = (char*)malloc(strlen(key)+1);
|
||||
strcpy (ep->key, key);
|
||||
ep->value = (char*)malloc(strlen(value)+1);
|
||||
strcpy (ep->value, value);
|
||||
ep->next = NULL;
|
||||
return ep;
|
||||
}
|
||||
|
||||
epair_t** Entity_GetKeyValList(entity_t *e)
|
||||
{
|
||||
return &e->epairs;
|
||||
}
|
||||
|
||||
void Entity_SetKeyValList(entity_t *e, epair_t* ep)
|
||||
{
|
||||
if( e->epairs )
|
||||
Sys_Printf( "Warning : pe->epairs != NULL in Entity_SetKeyValList, will not set\n" );
|
||||
else {
|
||||
e->epairs = ep;
|
||||
|
||||
for (epair_t *pe_ep = e->epairs; pe_ep; pe_ep = pe_ep->next)
|
||||
Entity_OnKeyValueChanged(e, pe_ep->key, pe_ep->value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\todo FIXME TTimo
|
||||
this is meant to raise messages instead of calling the IEdit directly
|
||||
*/
|
||||
static void Entity_OnKeyValueChanged(entity_t *e, const char *key, const char* value)
|
||||
{
|
||||
if(strcmp(key,"classname") == 0)
|
||||
{
|
||||
e->eclass = Eclass_ForName(value, false);
|
||||
Entity_UpdateClass(e, value);
|
||||
if(strcmp(value,"light") == 0)
|
||||
for(epair_t* ep = e->epairs; ep != NULL; ep=ep->next)
|
||||
Light_OnKeyValueChanged(e, ep->key, ep->value);
|
||||
if(e->model.pEdit)
|
||||
for(epair_t* ep = e->epairs; ep != NULL; ep=ep->next)
|
||||
e->model.pEdit->OnKeyValueChanged(e, ep->key, ep->value);
|
||||
}
|
||||
else if(Entity_IsLight(e))
|
||||
Light_OnKeyValueChanged(e, key, value);
|
||||
else if(e->model.pEdit)
|
||||
e->model.pEdit->OnKeyValueChanged(e, key, value);
|
||||
|
||||
// update brush mins/maxs for legacy culling system
|
||||
if(e->model.pRender && e->brushes.onext != &e->brushes)
|
||||
Brush_Build( e->brushes.onext, true, true, false, true );
|
||||
}
|
||||
/*
|
||||
Copyright (C) 1999-2007 id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
#include "entity.h"
|
||||
#include "entity_entitymodel.h"
|
||||
#include "light.h"
|
||||
|
||||
int g_entityId = 1;
|
||||
|
||||
|
||||
|
||||
// internal
|
||||
|
||||
static void Entity_FreeEpairs(entity_t *e);
|
||||
|
||||
static void SetKeyValue (epair_t *&e, const char *key, const char *value);
|
||||
static void DeleteKey (epair_t *&e, const char *key);
|
||||
static const char *ValueForKey ( epair_t *&e, const char *key);
|
||||
|
||||
static void Entity_OnKeyValueChanged(entity_t *e, const char* key, const char* value);
|
||||
|
||||
// constructor
|
||||
entity_t *Entity_Alloc()
|
||||
{
|
||||
entity_t *e;
|
||||
e = (entity_t*)malloc (sizeof(*e));
|
||||
e->entityId = g_entityId++;
|
||||
VectorSet(e->origin, 0, 0, 0);
|
||||
VectorSet(e->color, 1, 1, 1);
|
||||
e->redoId = 0;
|
||||
e->undoId = 0;
|
||||
e->next = e->prev = NULL;
|
||||
e->brushes.onext = e->brushes.oprev = &e->brushes;
|
||||
e->epairs = NULL;
|
||||
e->eclass = NULL;
|
||||
e->model.pRender = NULL;
|
||||
e->model.pSelect = NULL;
|
||||
e->model.pEdit = NULL;
|
||||
return e;
|
||||
}
|
||||
|
||||
// destructor
|
||||
void Entity_Free (entity_t *e)
|
||||
{
|
||||
while (e->brushes.onext != &e->brushes)
|
||||
Brush_Free( e->brushes.onext, true );
|
||||
|
||||
if (e->next)
|
||||
{
|
||||
e->next->prev = e->prev;
|
||||
e->prev->next = e->next;
|
||||
}
|
||||
|
||||
Entity_FreeEpairs(e);
|
||||
|
||||
if (e->model.pRender)
|
||||
{
|
||||
e->model.pRender->DecRef();
|
||||
e->model.pRender = NULL;
|
||||
}
|
||||
if (e->model.pSelect)
|
||||
{
|
||||
e->model.pSelect->DecRef();
|
||||
e->model.pSelect = NULL;
|
||||
}
|
||||
if (e->model.pEdit)
|
||||
{
|
||||
e->model.pEdit->DecRef();
|
||||
e->model.pEdit = NULL;
|
||||
}
|
||||
|
||||
free (e);
|
||||
}
|
||||
|
||||
// construct from entity
|
||||
entity_t *Entity_Clone (entity_t *e)
|
||||
{
|
||||
entity_t *n;
|
||||
epair_t *ep;
|
||||
|
||||
n = Entity_Alloc();
|
||||
n->eclass = e->eclass;
|
||||
|
||||
for (ep = e->epairs ; ep ; ep=ep->next)
|
||||
SetKeyValue(n, ep->key, ep->value);
|
||||
|
||||
// copy some misc stuff as well
|
||||
VectorCopy( e->origin, n->origin );
|
||||
// VectorCopy( e->vRotation, n->vRotation );
|
||||
// VectorCopy( e->vScale, n->vScale );
|
||||
|
||||
// n->bDirty = true;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const char *ValueForKey ( epair_t *&e, const char *key)
|
||||
{
|
||||
epair_t *ep;
|
||||
for (ep=e ; ep ; ep=ep->next)
|
||||
{
|
||||
if (!strcmp (ep->key, key) )
|
||||
{
|
||||
return ep->value;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const char *ValueForKey (entity_t *ent, const char *key)
|
||||
{
|
||||
return ValueForKey(ent->epairs, key);
|
||||
}
|
||||
|
||||
void SetKeyValue (epair_t *&e, const char *key, const char *value)
|
||||
{
|
||||
epair_t *ep;
|
||||
for (ep=e ; ep ; ep=ep->next)
|
||||
{
|
||||
if (!strcmp (ep->key, key) )
|
||||
{
|
||||
free (ep->value);
|
||||
ep->value = (char*)malloc(strlen(value)+1);
|
||||
strcpy (ep->value, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ep = (epair_t*)malloc (sizeof(*ep));
|
||||
ep->next = e;
|
||||
e = ep;
|
||||
ep->key = (char*)malloc(strlen(key)+1);
|
||||
strcpy (ep->key, key);
|
||||
ep->value = (char*)malloc(strlen(value)+1);
|
||||
strcpy (ep->value, value);
|
||||
|
||||
}
|
||||
|
||||
void SetKeyValue (entity_t *ent, const char *key, const char *value)
|
||||
{
|
||||
if (ent == NULL)
|
||||
{
|
||||
Sys_FPrintf(SYS_ERR, "ERROR: SetKeyValue: NULL entity \n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!key || !key[0])
|
||||
{
|
||||
Sys_FPrintf(SYS_ERR, "ERROR: SetKeyValue: NULL or zero-length key\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SetKeyValue(ent->epairs, key, value);
|
||||
/*!
|
||||
\todo TODO broadcast this through a clean messaging API ;-)
|
||||
*/
|
||||
Entity_OnKeyValueChanged(ent, key, value);
|
||||
}
|
||||
|
||||
void DeleteKey (epair_t *&e, const char *key)
|
||||
{
|
||||
epair_t **ep, *next;
|
||||
|
||||
ep = &e;
|
||||
while (*ep)
|
||||
{
|
||||
next = *ep;
|
||||
if ( !strcmp (next->key, key) )
|
||||
{
|
||||
*ep = next->next;
|
||||
free(next->key);
|
||||
free(next->value);
|
||||
free(next);
|
||||
return;
|
||||
}
|
||||
ep = &next->next;
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteKey (entity_t *ent, const char *key)
|
||||
{
|
||||
DeleteKey(ent->epairs, key);
|
||||
Entity_OnKeyValueChanged(ent, key, "");
|
||||
}
|
||||
|
||||
float FloatForKey (entity_t *ent, const char *key)
|
||||
{
|
||||
const char *k;
|
||||
|
||||
k = ValueForKey (ent, key);
|
||||
return (float) atof(k);
|
||||
}
|
||||
|
||||
int IntForKey (entity_t *ent, const char *key)
|
||||
{
|
||||
const char *k;
|
||||
|
||||
k = ValueForKey (ent, key);
|
||||
return atoi(k);
|
||||
}
|
||||
|
||||
void GetVectorForKey (entity_t *ent, const char *key, vec3_t vec)
|
||||
{
|
||||
const char *k;
|
||||
|
||||
k = ValueForKey (ent, key);
|
||||
sscanf (k, "%f %f %f", &vec[0], &vec[1], &vec[2]);
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Entity_FreeEpairs
|
||||
|
||||
Frees the entity epairs.
|
||||
===============
|
||||
*/
|
||||
void Entity_FreeEpairs(entity_t *e)
|
||||
{
|
||||
epair_t *ep, *next;
|
||||
|
||||
for (ep = e->epairs; ep; ep = next)
|
||||
{
|
||||
next = ep->next;
|
||||
free (ep->key);
|
||||
free (ep->value);
|
||||
free (ep);
|
||||
}
|
||||
e->epairs = NULL;
|
||||
}
|
||||
|
||||
void Entity_AddToList(entity_t *e, entity_t *elist)
|
||||
{
|
||||
if (e->next || e->prev)
|
||||
Error ("Entity_AddToList: already linked");
|
||||
//e->next = elist->next;
|
||||
//elist->next->prev = e;
|
||||
//elist->next = e;
|
||||
//e->prev = elist;
|
||||
e->next = elist;
|
||||
e->prev = elist->prev;
|
||||
elist->prev->next = e;
|
||||
elist->prev = e;
|
||||
}
|
||||
|
||||
void Entity_RemoveFromList (entity_t *e)
|
||||
{
|
||||
if (!e->next || !e->prev)
|
||||
Error ("Entity_RemoveFromList: not linked");
|
||||
e->next->prev = e->prev;
|
||||
e->prev->next = e->next;
|
||||
e->next = e->prev = NULL;
|
||||
}
|
||||
|
||||
void Entity_LinkBrush (entity_t *e, brush_t *b)
|
||||
{
|
||||
if (b->oprev || b->onext)
|
||||
Error ("Entity_LinkBrush: Already linked");
|
||||
b->owner = e;
|
||||
|
||||
// b->onext = e->brushes.onext;
|
||||
// b->oprev = &e->brushes;
|
||||
// e->brushes.onext->oprev = b;
|
||||
// e->brushes.onext = b;
|
||||
/*
|
||||
SPoG - changed to add brushes to end of list instead of start - so this can be used by map loader.
|
||||
This could concievably cause a problem if someone is traversing e->brushes while calling this function.
|
||||
So don't.
|
||||
*/
|
||||
b->onext = &e->brushes;
|
||||
b->oprev = e->brushes.oprev;
|
||||
e->brushes.oprev->onext = b;
|
||||
e->brushes.oprev = b;
|
||||
}
|
||||
|
||||
void Entity_UnlinkBrush (brush_t *b)
|
||||
{
|
||||
if (!b->onext || !b->oprev)
|
||||
Error ("Entity_UnlinkBrush: Not currently linked");
|
||||
b->onext->oprev = b->oprev;
|
||||
b->oprev->onext = b->onext;
|
||||
b->onext = b->oprev = NULL;
|
||||
b->owner = NULL;
|
||||
}
|
||||
|
||||
// for undo
|
||||
int Entity_MemorySize(entity_t *e)
|
||||
{
|
||||
epair_t *ep;
|
||||
int size = 0;
|
||||
|
||||
for (ep = e->epairs; ep; ep = ep->next)
|
||||
{
|
||||
size += strlen(ep->key);
|
||||
size += strlen(ep->value);
|
||||
size += sizeof(epair_t);
|
||||
}
|
||||
size += sizeof(entity_t);
|
||||
return size;
|
||||
}
|
||||
|
||||
epair_t* Entity_AllocateEpair(const char *key, const char *value)
|
||||
{
|
||||
epair_t *ep = (epair_t*)malloc (sizeof(*ep));
|
||||
ep->key = (char*)malloc(strlen(key)+1);
|
||||
strcpy (ep->key, key);
|
||||
ep->value = (char*)malloc(strlen(value)+1);
|
||||
strcpy (ep->value, value);
|
||||
ep->next = NULL;
|
||||
return ep;
|
||||
}
|
||||
|
||||
epair_t** Entity_GetKeyValList(entity_t *e)
|
||||
{
|
||||
return &e->epairs;
|
||||
}
|
||||
|
||||
void Entity_SetKeyValList(entity_t *e, epair_t* ep)
|
||||
{
|
||||
if( e->epairs )
|
||||
Sys_Printf( "Warning : pe->epairs != NULL in Entity_SetKeyValList, will not set\n" );
|
||||
else {
|
||||
e->epairs = ep;
|
||||
|
||||
for (epair_t *pe_ep = e->epairs; pe_ep; pe_ep = pe_ep->next)
|
||||
Entity_OnKeyValueChanged(e, pe_ep->key, pe_ep->value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\todo FIXME TTimo
|
||||
this is meant to raise messages instead of calling the IEdit directly
|
||||
*/
|
||||
static void Entity_OnKeyValueChanged(entity_t *e, const char *key, const char* value)
|
||||
{
|
||||
if(strcmp(key,"classname") == 0)
|
||||
{
|
||||
e->eclass = Eclass_ForName(value, false);
|
||||
Entity_UpdateClass(e, value);
|
||||
if(strcmp(value,"light") == 0)
|
||||
for(epair_t* ep = e->epairs; ep != NULL; ep=ep->next)
|
||||
Light_OnKeyValueChanged(e, ep->key, ep->value);
|
||||
if(e->model.pEdit)
|
||||
for(epair_t* ep = e->epairs; ep != NULL; ep=ep->next)
|
||||
e->model.pEdit->OnKeyValueChanged(e, ep->key, ep->value);
|
||||
}
|
||||
else if(Entity_IsLight(e))
|
||||
Light_OnKeyValueChanged(e, key, value);
|
||||
else if(e->model.pEdit)
|
||||
e->model.pEdit->OnKeyValueChanged(e, key, value);
|
||||
|
||||
// update brush mins/maxs for legacy culling system
|
||||
if(e->model.pRender && e->brushes.onext != &e->brushes)
|
||||
Brush_Build( e->brushes.onext, true, true, false, true );
|
||||
}
|
||||
|
||||
@@ -1,138 +1,138 @@
|
||||
/*
|
||||
Copyright (C) 1999-2007 id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "entity_entitymodel.h"
|
||||
|
||||
void Entity_UpdateClass(entity_t *e, const char* value)
|
||||
{
|
||||
if(strcmp(value, "misc_model") == 0
|
||||
|| (strcmp(value, "misc_gamemodel") == 0)
|
||||
|| (strcmp(value, "model_static") == 0))
|
||||
{
|
||||
if (e->model.pRender) e->model.pRender->DecRef();
|
||||
if (e->model.pSelect) e->model.pSelect->DecRef();
|
||||
if (e->model.pEdit) e->model.pEdit->DecRef();
|
||||
e->model.pRender = NULL;
|
||||
e->model.pSelect = NULL;
|
||||
e->model.pEdit = NULL;
|
||||
|
||||
CEntityMiscModel *model = new CEntityMiscModel(e);
|
||||
|
||||
e->model.pRender = (IRender*)model;
|
||||
e->model.pRender->IncRef();
|
||||
e->model.pSelect = (ISelect*)model;
|
||||
e->model.pSelect->IncRef();
|
||||
e->model.pEdit = (IEdit*)model;
|
||||
e->model.pEdit->IncRef();
|
||||
|
||||
model->DecRef();
|
||||
}
|
||||
else if(e->eclass && e->eclass->modelpath)
|
||||
{
|
||||
if (e->model.pRender) e->model.pRender->DecRef();
|
||||
if (e->model.pSelect) e->model.pSelect->DecRef();
|
||||
if (e->model.pEdit) e->model.pEdit->DecRef();
|
||||
e->model.pRender = NULL;
|
||||
e->model.pSelect = NULL;
|
||||
e->model.pEdit = NULL;
|
||||
|
||||
CEntityEclassModel *model = new CEntityEclassModel;
|
||||
|
||||
model->SetEclass(e->eclass);
|
||||
model->SetName(e->eclass->modelpath);
|
||||
|
||||
e->model.pRender = (IRender*)model;
|
||||
e->model.pRender->IncRef();
|
||||
e->model.pSelect = (ISelect*)model;
|
||||
e->model.pSelect->IncRef();
|
||||
e->model.pEdit = (IEdit*)model;
|
||||
e->model.pEdit->IncRef();
|
||||
|
||||
model->DecRef();
|
||||
}
|
||||
}
|
||||
|
||||
void pivot_draw(const vec3_t pivot)
|
||||
{
|
||||
vec3_t vCenter, vMin, vMax;
|
||||
VectorCopy(pivot, vCenter);
|
||||
|
||||
g_QglTable.m_pfn_qglPointSize(4);
|
||||
|
||||
g_QglTable.m_pfn_qglBegin(GL_POINTS);
|
||||
g_QglTable.m_pfn_qglVertex3fv(vCenter);
|
||||
g_QglTable.m_pfn_qglEnd();
|
||||
|
||||
g_QglTable.m_pfn_qglBegin(GL_LINES);
|
||||
vCenter[0] -= 8;
|
||||
g_QglTable.m_pfn_qglVertex3fv(vCenter);
|
||||
vCenter[0] += 16;
|
||||
g_QglTable.m_pfn_qglVertex3fv(vCenter);
|
||||
vCenter[0] -= 8;
|
||||
vCenter[1] -= 8;
|
||||
g_QglTable.m_pfn_qglVertex3fv(vCenter);
|
||||
vCenter[1] += 16;
|
||||
g_QglTable.m_pfn_qglVertex3fv(vCenter);
|
||||
vCenter[1] -= 8;
|
||||
vCenter[2] -= 8;
|
||||
g_QglTable.m_pfn_qglVertex3fv(vCenter);
|
||||
vCenter[2] += 16;
|
||||
g_QglTable.m_pfn_qglVertex3fv(vCenter);
|
||||
vCenter[2] -= 8;
|
||||
g_QglTable.m_pfn_qglEnd();
|
||||
|
||||
VectorCopy(vCenter, vMin);
|
||||
VectorCopy(vCenter, vMax);
|
||||
vMin[0] -= 4;
|
||||
vMin[1] -= 4;
|
||||
vMin[2] -= 4;
|
||||
vMax[0] += 4;
|
||||
vMax[1] += 4;
|
||||
vMax[2] += 4;
|
||||
|
||||
g_QglTable.m_pfn_qglBegin(GL_LINE_LOOP);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMin[0],vMin[1],vMin[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMax[0],vMin[1],vMin[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMax[0],vMax[1],vMin[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMin[0],vMax[1],vMin[2]);
|
||||
g_QglTable.m_pfn_qglEnd();
|
||||
|
||||
g_QglTable.m_pfn_qglBegin(GL_LINE_LOOP);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMin[0],vMin[1],vMax[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMax[0],vMin[1],vMax[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMax[0],vMax[1],vMax[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMin[0],vMax[1],vMax[2]);
|
||||
g_QglTable.m_pfn_qglEnd();
|
||||
|
||||
g_QglTable.m_pfn_qglBegin(GL_LINES);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMin[0],vMin[1],vMin[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMin[0],vMin[1],vMax[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMin[0],vMax[1],vMax[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMin[0],vMax[1],vMin[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMax[0],vMin[1],vMin[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMax[0],vMin[1],vMax[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMax[0],vMax[1],vMax[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMax[0],vMax[1],vMin[2]);
|
||||
g_QglTable.m_pfn_qglEnd();
|
||||
}
|
||||
|
||||
/*
|
||||
Copyright (C) 1999-2007 id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "entity_entitymodel.h"
|
||||
|
||||
void Entity_UpdateClass(entity_t *e, const char* value)
|
||||
{
|
||||
if(strcmp(value, "misc_model") == 0
|
||||
|| (strcmp(value, "misc_gamemodel") == 0)
|
||||
|| (strcmp(value, "model_static") == 0))
|
||||
{
|
||||
if (e->model.pRender) e->model.pRender->DecRef();
|
||||
if (e->model.pSelect) e->model.pSelect->DecRef();
|
||||
if (e->model.pEdit) e->model.pEdit->DecRef();
|
||||
e->model.pRender = NULL;
|
||||
e->model.pSelect = NULL;
|
||||
e->model.pEdit = NULL;
|
||||
|
||||
CEntityMiscModel *model = new CEntityMiscModel(e);
|
||||
|
||||
e->model.pRender = (IRender*)model;
|
||||
e->model.pRender->IncRef();
|
||||
e->model.pSelect = (ISelect*)model;
|
||||
e->model.pSelect->IncRef();
|
||||
e->model.pEdit = (IEdit*)model;
|
||||
e->model.pEdit->IncRef();
|
||||
|
||||
model->DecRef();
|
||||
}
|
||||
else if(e->eclass && e->eclass->modelpath)
|
||||
{
|
||||
if (e->model.pRender) e->model.pRender->DecRef();
|
||||
if (e->model.pSelect) e->model.pSelect->DecRef();
|
||||
if (e->model.pEdit) e->model.pEdit->DecRef();
|
||||
e->model.pRender = NULL;
|
||||
e->model.pSelect = NULL;
|
||||
e->model.pEdit = NULL;
|
||||
|
||||
CEntityEclassModel *model = new CEntityEclassModel;
|
||||
|
||||
model->SetEclass(e->eclass);
|
||||
model->SetName(e->eclass->modelpath);
|
||||
|
||||
e->model.pRender = (IRender*)model;
|
||||
e->model.pRender->IncRef();
|
||||
e->model.pSelect = (ISelect*)model;
|
||||
e->model.pSelect->IncRef();
|
||||
e->model.pEdit = (IEdit*)model;
|
||||
e->model.pEdit->IncRef();
|
||||
|
||||
model->DecRef();
|
||||
}
|
||||
}
|
||||
|
||||
void pivot_draw(const vec3_t pivot)
|
||||
{
|
||||
vec3_t vCenter, vMin, vMax;
|
||||
VectorCopy(pivot, vCenter);
|
||||
|
||||
g_QglTable.m_pfn_qglPointSize(4);
|
||||
|
||||
g_QglTable.m_pfn_qglBegin(GL_POINTS);
|
||||
g_QglTable.m_pfn_qglVertex3fv(vCenter);
|
||||
g_QglTable.m_pfn_qglEnd();
|
||||
|
||||
g_QglTable.m_pfn_qglBegin(GL_LINES);
|
||||
vCenter[0] -= 8;
|
||||
g_QglTable.m_pfn_qglVertex3fv(vCenter);
|
||||
vCenter[0] += 16;
|
||||
g_QglTable.m_pfn_qglVertex3fv(vCenter);
|
||||
vCenter[0] -= 8;
|
||||
vCenter[1] -= 8;
|
||||
g_QglTable.m_pfn_qglVertex3fv(vCenter);
|
||||
vCenter[1] += 16;
|
||||
g_QglTable.m_pfn_qglVertex3fv(vCenter);
|
||||
vCenter[1] -= 8;
|
||||
vCenter[2] -= 8;
|
||||
g_QglTable.m_pfn_qglVertex3fv(vCenter);
|
||||
vCenter[2] += 16;
|
||||
g_QglTable.m_pfn_qglVertex3fv(vCenter);
|
||||
vCenter[2] -= 8;
|
||||
g_QglTable.m_pfn_qglEnd();
|
||||
|
||||
VectorCopy(vCenter, vMin);
|
||||
VectorCopy(vCenter, vMax);
|
||||
vMin[0] -= 4;
|
||||
vMin[1] -= 4;
|
||||
vMin[2] -= 4;
|
||||
vMax[0] += 4;
|
||||
vMax[1] += 4;
|
||||
vMax[2] += 4;
|
||||
|
||||
g_QglTable.m_pfn_qglBegin(GL_LINE_LOOP);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMin[0],vMin[1],vMin[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMax[0],vMin[1],vMin[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMax[0],vMax[1],vMin[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMin[0],vMax[1],vMin[2]);
|
||||
g_QglTable.m_pfn_qglEnd();
|
||||
|
||||
g_QglTable.m_pfn_qglBegin(GL_LINE_LOOP);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMin[0],vMin[1],vMax[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMax[0],vMin[1],vMax[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMax[0],vMax[1],vMax[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMin[0],vMax[1],vMax[2]);
|
||||
g_QglTable.m_pfn_qglEnd();
|
||||
|
||||
g_QglTable.m_pfn_qglBegin(GL_LINES);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMin[0],vMin[1],vMin[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMin[0],vMin[1],vMax[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMin[0],vMax[1],vMax[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMin[0],vMax[1],vMin[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMax[0],vMin[1],vMin[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMax[0],vMin[1],vMax[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMax[0],vMax[1],vMax[2]);
|
||||
g_QglTable.m_pfn_qglVertex3f(vMax[0],vMax[1],vMin[2]);
|
||||
g_QglTable.m_pfn_qglEnd();
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,254 +1,254 @@
|
||||
/*
|
||||
Copyright (C) 1999-2007 id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "entity_entitymodel.h"
|
||||
#include "entity.h"
|
||||
|
||||
//
|
||||
// CEntityMiscModel implementation
|
||||
//
|
||||
|
||||
CEntityMiscModel::CEntityMiscModel (entity_t *e)
|
||||
{
|
||||
refCount = 1;
|
||||
m_entity = e;
|
||||
m_model = NULL;
|
||||
VectorSet(m_translate, 0,0,0);
|
||||
VectorSet(m_euler, 0,0,0);
|
||||
VectorSet(m_scale, 1,1,1);
|
||||
VectorSet(m_pivot, 0,0,0);
|
||||
m4x4_identity(m_transform);
|
||||
m4x4_identity(m_inverse_transform);
|
||||
}
|
||||
|
||||
CEntityMiscModel::~CEntityMiscModel ()
|
||||
{
|
||||
if(m_cachereq.GetBuffer()[0] != ':'
|
||||
&& m_version.c_str()[0] != '\0')
|
||||
GetModelCache()->DeleteByID(m_cachereq.GetBuffer(), m_version.c_str());
|
||||
}
|
||||
|
||||
|
||||
// IRender
|
||||
|
||||
void CEntityMiscModel::Draw(int state, int rflags) const
|
||||
{
|
||||
// push the current modelview matrix
|
||||
// FIXME: put in a check for stack recursion depth..
|
||||
// or avoid recursion of opengl matrix stack
|
||||
g_QglTable.m_pfn_qglPushMatrix();
|
||||
// apply the parent-to-local transform
|
||||
g_QglTable.m_pfn_qglMultMatrixf(m_transform);
|
||||
|
||||
pivot_draw(m_pivot);
|
||||
|
||||
// draw children
|
||||
if(m_model && m_model->pRender)
|
||||
{
|
||||
m_model->pRender->Draw(state, rflags);
|
||||
}
|
||||
|
||||
g_QglTable.m_pfn_qglPopMatrix();
|
||||
}
|
||||
|
||||
// ISelect
|
||||
|
||||
bool CEntityMiscModel::TestRay(const ray_t *ray, vec_t *dist) const
|
||||
{
|
||||
vec_t dist_start = *dist;
|
||||
vec_t dist_local = *dist;
|
||||
ray_t ray_local = *ray;
|
||||
|
||||
if (aabb_test_ray(&m_BBox, ray) == 0)
|
||||
return false;
|
||||
|
||||
ray_transform(&ray_local, m_inverse_transform);
|
||||
|
||||
if(m_model && m_model->pSelect)
|
||||
{
|
||||
if(m_model->pSelect->TestRay(&ray_local, &dist_local))
|
||||
*dist = dist_local;
|
||||
}
|
||||
else *dist = dist_local;
|
||||
|
||||
return *dist < dist_start;
|
||||
}
|
||||
|
||||
|
||||
//IEdit
|
||||
|
||||
void CEntityMiscModel::Translate(const vec3_t translation)
|
||||
{
|
||||
VectorIncrement(translation, m_translate);
|
||||
UpdateCachedData();
|
||||
}
|
||||
|
||||
void CEntityMiscModel::Rotate(const vec3_t pivot, const vec3_t rotation)
|
||||
{
|
||||
m4x4_t rotation_matrix;
|
||||
|
||||
m4x4_identity(rotation_matrix);
|
||||
m4x4_pivoted_rotate_by_vec3(rotation_matrix, rotation, eXYZ, pivot);
|
||||
m4x4_transform_point(rotation_matrix, m_translate);
|
||||
|
||||
VectorIncrement(rotation, m_euler);
|
||||
|
||||
UpdateCachedData();
|
||||
}
|
||||
|
||||
void CEntityMiscModel::OnKeyValueChanged(entity_t *e, const char *key, const char* value)
|
||||
{
|
||||
if(strcmp(key, "model") == 0)
|
||||
SetName(value);
|
||||
else if(strcmp(key, "_frame") == 0)
|
||||
{
|
||||
SetName(ValueForKey(e, "model"));
|
||||
}
|
||||
else if(strcmp(key, "angle") == 0)
|
||||
{
|
||||
VectorSet(m_euler, 0.f, 0.f, 0.f);
|
||||
m_euler[2] = atof(value);
|
||||
UpdateCachedData();
|
||||
}
|
||||
else if(strcmp(key, "angles") == 0)
|
||||
{
|
||||
VectorSet(m_euler, 0.f, 0.f, 0.f);
|
||||
if (value[0] != '\0')
|
||||
sscanf (value, "%f %f %f", &m_euler[1], &m_euler[2], &m_euler[0]);
|
||||
UpdateCachedData();
|
||||
}
|
||||
else if(strcmp(key, "modelscale") == 0 || strcmp(key,"modelscale_vec") == 0)
|
||||
{
|
||||
const char *s;
|
||||
VectorSet(m_scale, 1.f, 1.f, 1.f);
|
||||
s = ValueForKey(e,"modelscale");
|
||||
if (s[0] != '\0')
|
||||
{
|
||||
float f = atof(s);
|
||||
if( f != 0 )
|
||||
VectorSet(m_scale, f, f, f);
|
||||
else
|
||||
Sys_FPrintf(SYS_WRN, "WARNING: ignoring 0 modelscale key\n");
|
||||
}
|
||||
s = ValueForKey(e,"modelscale_vec");
|
||||
if (s[0] != '\0')
|
||||
{
|
||||
sscanf (s, "%f %f %f", &m_scale[0], &m_scale[1], &m_scale[2]);
|
||||
if (m_scale[0] == 0.0 && m_scale[1] == 0.0 && m_scale[2] == 0.0)
|
||||
{
|
||||
VectorSet(m_scale, 1,1,1);
|
||||
Sys_FPrintf(SYS_WRN, "WARNING: ignoring 0 0 0 modelscale_vec key\n");
|
||||
}
|
||||
}
|
||||
UpdateCachedData();
|
||||
}
|
||||
else if(strcmp(key, "origin") == 0)
|
||||
{
|
||||
sscanf(value, "%f %f %f", &m_translate[0], &m_translate[1], &m_translate[2]);
|
||||
UpdateCachedData();
|
||||
}
|
||||
else if(strncmp(key,"_remap",6) == 0)
|
||||
{
|
||||
SetName(ValueForKey(e, "model"));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// CEntityMiscModel
|
||||
//
|
||||
|
||||
// private:
|
||||
|
||||
void CEntityMiscModel::BuildCacheRequestString(const char *name)
|
||||
{
|
||||
bool hasRemaps = false;
|
||||
|
||||
m_cachereq.Format( "%s:%i", name, IntForKey(m_entity,"_frame") );
|
||||
|
||||
for (epair_t* ep = m_entity->epairs ; ep ; ep=ep->next)
|
||||
{
|
||||
if( strncmp(ep->key,"_remap",6) == 0 )
|
||||
{
|
||||
if( !hasRemaps )
|
||||
{
|
||||
hasRemaps = true;
|
||||
m_cachereq += "?";
|
||||
} else {
|
||||
m_cachereq += "&";
|
||||
}
|
||||
m_cachereq += ep->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CEntityMiscModel::SetName(const char *name)
|
||||
{
|
||||
Str m_oldcachereq = m_cachereq;
|
||||
|
||||
if( name[0] == '\0' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuildCacheRequestString(name);
|
||||
|
||||
if(strcmp(m_oldcachereq, m_cachereq) == 0)
|
||||
return;
|
||||
|
||||
if(m_cachereq.GetBuffer()[0] != ':'
|
||||
&& m_version.c_str()[0] != '\0')
|
||||
GetModelCache()->DeleteByID(m_cachereq.GetBuffer(), m_version.c_str());
|
||||
|
||||
m_model = NULL;
|
||||
|
||||
if(name[0] != '\0')
|
||||
{
|
||||
const char* dot = strrchr(name, '.');
|
||||
if(dot != NULL)
|
||||
{
|
||||
m_version = ++dot;
|
||||
m_model = GetModelCache()->GetByID(m_cachereq.GetBuffer(), m_version.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
UpdateCachedData();
|
||||
}
|
||||
|
||||
|
||||
void CEntityMiscModel::UpdateCachedData()
|
||||
{
|
||||
aabb_t aabb_temp;
|
||||
|
||||
m4x4_identity(m_transform);
|
||||
m4x4_pivoted_transform_by_vec3(m_transform, m_translate, m_euler, eXYZ, m_scale, m_pivot);
|
||||
memcpy(m_inverse_transform, m_transform, sizeof(m4x4_t));
|
||||
m4x4_invert(m_inverse_transform);
|
||||
|
||||
aabb_clear(&aabb_temp);
|
||||
|
||||
if(m_model && m_model->pRender)
|
||||
aabb_extend_by_aabb(&aabb_temp, m_model->pRender->GetAABB());
|
||||
else
|
||||
VectorSet(aabb_temp.extents, 8, 8, 8);
|
||||
|
||||
aabb_for_transformed_aabb(&m_BBox, &aabb_temp, m_transform);
|
||||
}
|
||||
/*
|
||||
Copyright (C) 1999-2007 id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "entity_entitymodel.h"
|
||||
#include "entity.h"
|
||||
|
||||
//
|
||||
// CEntityMiscModel implementation
|
||||
//
|
||||
|
||||
CEntityMiscModel::CEntityMiscModel (entity_t *e)
|
||||
{
|
||||
refCount = 1;
|
||||
m_entity = e;
|
||||
m_model = NULL;
|
||||
VectorSet(m_translate, 0,0,0);
|
||||
VectorSet(m_euler, 0,0,0);
|
||||
VectorSet(m_scale, 1,1,1);
|
||||
VectorSet(m_pivot, 0,0,0);
|
||||
m4x4_identity(m_transform);
|
||||
m4x4_identity(m_inverse_transform);
|
||||
}
|
||||
|
||||
CEntityMiscModel::~CEntityMiscModel ()
|
||||
{
|
||||
if(m_cachereq.GetBuffer()[0] != ':'
|
||||
&& m_version.c_str()[0] != '\0')
|
||||
GetModelCache()->DeleteByID(m_cachereq.GetBuffer(), m_version.c_str());
|
||||
}
|
||||
|
||||
|
||||
// IRender
|
||||
|
||||
void CEntityMiscModel::Draw(int state, int rflags) const
|
||||
{
|
||||
// push the current modelview matrix
|
||||
// FIXME: put in a check for stack recursion depth..
|
||||
// or avoid recursion of opengl matrix stack
|
||||
g_QglTable.m_pfn_qglPushMatrix();
|
||||
// apply the parent-to-local transform
|
||||
g_QglTable.m_pfn_qglMultMatrixf(m_transform);
|
||||
|
||||
pivot_draw(m_pivot);
|
||||
|
||||
// draw children
|
||||
if(m_model && m_model->pRender)
|
||||
{
|
||||
m_model->pRender->Draw(state, rflags);
|
||||
}
|
||||
|
||||
g_QglTable.m_pfn_qglPopMatrix();
|
||||
}
|
||||
|
||||
// ISelect
|
||||
|
||||
bool CEntityMiscModel::TestRay(const ray_t *ray, vec_t *dist) const
|
||||
{
|
||||
vec_t dist_start = *dist;
|
||||
vec_t dist_local = *dist;
|
||||
ray_t ray_local = *ray;
|
||||
|
||||
if (aabb_test_ray(&m_BBox, ray) == 0)
|
||||
return false;
|
||||
|
||||
ray_transform(&ray_local, m_inverse_transform);
|
||||
|
||||
if(m_model && m_model->pSelect)
|
||||
{
|
||||
if(m_model->pSelect->TestRay(&ray_local, &dist_local))
|
||||
*dist = dist_local;
|
||||
}
|
||||
else *dist = dist_local;
|
||||
|
||||
return *dist < dist_start;
|
||||
}
|
||||
|
||||
|
||||
//IEdit
|
||||
|
||||
void CEntityMiscModel::Translate(const vec3_t translation)
|
||||
{
|
||||
VectorIncrement(translation, m_translate);
|
||||
UpdateCachedData();
|
||||
}
|
||||
|
||||
void CEntityMiscModel::Rotate(const vec3_t pivot, const vec3_t rotation)
|
||||
{
|
||||
m4x4_t rotation_matrix;
|
||||
|
||||
m4x4_identity(rotation_matrix);
|
||||
m4x4_pivoted_rotate_by_vec3(rotation_matrix, rotation, eXYZ, pivot);
|
||||
m4x4_transform_point(rotation_matrix, m_translate);
|
||||
|
||||
VectorIncrement(rotation, m_euler);
|
||||
|
||||
UpdateCachedData();
|
||||
}
|
||||
|
||||
void CEntityMiscModel::OnKeyValueChanged(entity_t *e, const char *key, const char* value)
|
||||
{
|
||||
if(strcmp(key, "model") == 0)
|
||||
SetName(value);
|
||||
else if(strcmp(key, "_frame") == 0)
|
||||
{
|
||||
SetName(ValueForKey(e, "model"));
|
||||
}
|
||||
else if(strcmp(key, "angle") == 0)
|
||||
{
|
||||
VectorSet(m_euler, 0.f, 0.f, 0.f);
|
||||
m_euler[2] = atof(value);
|
||||
UpdateCachedData();
|
||||
}
|
||||
else if(strcmp(key, "angles") == 0)
|
||||
{
|
||||
VectorSet(m_euler, 0.f, 0.f, 0.f);
|
||||
if (value[0] != '\0')
|
||||
sscanf (value, "%f %f %f", &m_euler[1], &m_euler[2], &m_euler[0]);
|
||||
UpdateCachedData();
|
||||
}
|
||||
else if(strcmp(key, "modelscale") == 0 || strcmp(key,"modelscale_vec") == 0)
|
||||
{
|
||||
const char *s;
|
||||
VectorSet(m_scale, 1.f, 1.f, 1.f);
|
||||
s = ValueForKey(e,"modelscale");
|
||||
if (s[0] != '\0')
|
||||
{
|
||||
float f = atof(s);
|
||||
if( f != 0 )
|
||||
VectorSet(m_scale, f, f, f);
|
||||
else
|
||||
Sys_FPrintf(SYS_WRN, "WARNING: ignoring 0 modelscale key\n");
|
||||
}
|
||||
s = ValueForKey(e,"modelscale_vec");
|
||||
if (s[0] != '\0')
|
||||
{
|
||||
sscanf (s, "%f %f %f", &m_scale[0], &m_scale[1], &m_scale[2]);
|
||||
if (m_scale[0] == 0.0 && m_scale[1] == 0.0 && m_scale[2] == 0.0)
|
||||
{
|
||||
VectorSet(m_scale, 1,1,1);
|
||||
Sys_FPrintf(SYS_WRN, "WARNING: ignoring 0 0 0 modelscale_vec key\n");
|
||||
}
|
||||
}
|
||||
UpdateCachedData();
|
||||
}
|
||||
else if(strcmp(key, "origin") == 0)
|
||||
{
|
||||
sscanf(value, "%f %f %f", &m_translate[0], &m_translate[1], &m_translate[2]);
|
||||
UpdateCachedData();
|
||||
}
|
||||
else if(strncmp(key,"_remap",6) == 0)
|
||||
{
|
||||
SetName(ValueForKey(e, "model"));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// CEntityMiscModel
|
||||
//
|
||||
|
||||
// private:
|
||||
|
||||
void CEntityMiscModel::BuildCacheRequestString(const char *name)
|
||||
{
|
||||
bool hasRemaps = false;
|
||||
|
||||
m_cachereq.Format( "%s:%i", name, IntForKey(m_entity,"_frame") );
|
||||
|
||||
for (epair_t* ep = m_entity->epairs ; ep ; ep=ep->next)
|
||||
{
|
||||
if( strncmp(ep->key,"_remap",6) == 0 )
|
||||
{
|
||||
if( !hasRemaps )
|
||||
{
|
||||
hasRemaps = true;
|
||||
m_cachereq += "?";
|
||||
} else {
|
||||
m_cachereq += "&";
|
||||
}
|
||||
m_cachereq += ep->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CEntityMiscModel::SetName(const char *name)
|
||||
{
|
||||
Str m_oldcachereq = m_cachereq;
|
||||
|
||||
if( name[0] == '\0' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuildCacheRequestString(name);
|
||||
|
||||
if(strcmp(m_oldcachereq, m_cachereq) == 0)
|
||||
return;
|
||||
|
||||
if(m_cachereq.GetBuffer()[0] != ':'
|
||||
&& m_version.c_str()[0] != '\0')
|
||||
GetModelCache()->DeleteByID(m_cachereq.GetBuffer(), m_version.c_str());
|
||||
|
||||
m_model = NULL;
|
||||
|
||||
if(name[0] != '\0')
|
||||
{
|
||||
const char* dot = strrchr(name, '.');
|
||||
if(dot != NULL)
|
||||
{
|
||||
m_version = ++dot;
|
||||
m_model = GetModelCache()->GetByID(m_cachereq.GetBuffer(), m_version.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
UpdateCachedData();
|
||||
}
|
||||
|
||||
|
||||
void CEntityMiscModel::UpdateCachedData()
|
||||
{
|
||||
aabb_t aabb_temp;
|
||||
|
||||
m4x4_identity(m_transform);
|
||||
m4x4_pivoted_transform_by_vec3(m_transform, m_translate, m_euler, eXYZ, m_scale, m_pivot);
|
||||
memcpy(m_inverse_transform, m_transform, sizeof(m4x4_t));
|
||||
m4x4_invert(m_inverse_transform);
|
||||
|
||||
aabb_clear(&aabb_temp);
|
||||
|
||||
if(m_model && m_model->pRender)
|
||||
aabb_extend_by_aabb(&aabb_temp, m_model->pRender->GetAABB());
|
||||
else
|
||||
VectorSet(aabb_temp.extents, 8, 8, 8);
|
||||
|
||||
aabb_for_transformed_aabb(&m_BBox, &aabb_temp, m_transform);
|
||||
}
|
||||
|
||||
@@ -1,121 +1,121 @@
|
||||
/*
|
||||
Copyright (C) 1999-2007 id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
//
|
||||
// Model Plugin
|
||||
//
|
||||
|
||||
#include "plugin.h"
|
||||
#include "entity.h"
|
||||
#include "entity_entitymodel.h"
|
||||
#include "light.h"
|
||||
|
||||
// =============================================================================
|
||||
// Globals
|
||||
|
||||
// function tables
|
||||
_QERFuncTable_1 g_FuncTable;
|
||||
_QERQglTable g_QglTable;
|
||||
_QERBrushTable __BRUSHTABLENAME;
|
||||
_QERUndoTable __UNDOTABLENAME;
|
||||
_EClassManagerTable __ECLASSMANAGERTABLENAME;
|
||||
|
||||
// =============================================================================
|
||||
// SYNAPSE
|
||||
|
||||
class CSynapseClientEntity : public CSynapseClient
|
||||
{
|
||||
public:
|
||||
// CSynapseClient API
|
||||
bool RequestAPI(APIDescriptor_t *pAPI);
|
||||
const char* GetInfo();
|
||||
|
||||
CSynapseClientEntity() { }
|
||||
virtual ~CSynapseClientEntity() { }
|
||||
};
|
||||
|
||||
|
||||
CSynapseServer* g_pSynapseServer = NULL;
|
||||
CSynapseClientEntity g_SynapseClient;
|
||||
|
||||
#if __GNUC__ >= 4
|
||||
#pragma GCC visibility push(default)
|
||||
#endif
|
||||
extern "C" CSynapseClient* SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( const char *version, CSynapseServer *pServer ) {
|
||||
#if __GNUC__ >= 4
|
||||
#pragma GCC visibility pop
|
||||
#endif
|
||||
if (strcmp(version, SYNAPSE_VERSION))
|
||||
{
|
||||
Syn_Printf("ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version);
|
||||
return NULL;
|
||||
}
|
||||
g_pSynapseServer = pServer;
|
||||
g_pSynapseServer->IncRef();
|
||||
Set_Syn_Printf(g_pSynapseServer->Get_Syn_Printf());
|
||||
|
||||
g_SynapseClient.AddAPI(ENTITY_MAJOR, NULL, sizeof(_QEREntityTable));
|
||||
g_SynapseClient.AddAPI(RADIANT_MAJOR, NULL, sizeof(g_FuncTable), SYN_REQUIRE, &g_FuncTable);
|
||||
g_SynapseClient.AddAPI(QGL_MAJOR, NULL, sizeof(g_QglTable), SYN_REQUIRE, &g_QglTable);
|
||||
g_SynapseClient.AddAPI(BRUSH_MAJOR, NULL, sizeof(__BRUSHTABLENAME), SYN_REQUIRE, &__BRUSHTABLENAME);
|
||||
g_SynapseClient.AddAPI(UNDO_MAJOR, NULL, sizeof(__UNDOTABLENAME), SYN_REQUIRE, &__UNDOTABLENAME);
|
||||
g_SynapseClient.AddAPI(ECLASSMANAGER_MAJOR, NULL, sizeof(__ECLASSMANAGERTABLENAME), SYN_REQUIRE, &__ECLASSMANAGERTABLENAME);
|
||||
|
||||
return &g_SynapseClient;
|
||||
}
|
||||
|
||||
bool CSynapseClientEntity::RequestAPI(APIDescriptor_t *pAPI)
|
||||
{
|
||||
if (!strcmp(pAPI->major_name, ENTITY_MAJOR))
|
||||
{
|
||||
_QEREntityTable* pTable= static_cast<_QEREntityTable*>(pAPI->mpTable);
|
||||
pTable->m_pfnEntity_Alloc = &Entity_Alloc;
|
||||
pTable->m_pfnEntity_Free = &Entity_Free;
|
||||
pTable->m_pfnEntity_Clone = &Entity_Clone;
|
||||
pTable->m_pfnSetKeyValue = &SetKeyValue;
|
||||
pTable->m_pfnDeleteKey = &DeleteKey;
|
||||
pTable->m_pfnValueForKey = &ValueForKey;
|
||||
pTable->m_pfnFloatForKey = &FloatForKey;
|
||||
pTable->m_pfnIntForKey = &IntForKey;
|
||||
pTable->m_pfnGetVectorForKey = &GetVectorForKey;
|
||||
pTable->m_pfnEntity_AddToList = &Entity_AddToList;
|
||||
pTable->m_pfnEntity_RemoveFromList = &Entity_RemoveFromList;
|
||||
pTable->m_pfnEntity_LinkBrush = &Entity_LinkBrush;
|
||||
pTable->m_pfnEntity_UnlinkBrush = &Entity_UnlinkBrush;
|
||||
pTable->m_pfnDrawLight = &DrawLight;
|
||||
pTable->m_pfnEntity_MemorySize = &Entity_MemorySize;
|
||||
pTable->m_pfnAllocateEpair = &Entity_AllocateEpair;
|
||||
pTable->m_pfnGetEntityKeyValList = &Entity_GetKeyValList;
|
||||
pTable->m_pfnSetEntityKeyValList = &Entity_SetKeyValList;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo());
|
||||
return false;
|
||||
}
|
||||
|
||||
#include "version.h"
|
||||
|
||||
const char* CSynapseClientEntity::GetInfo()
|
||||
{
|
||||
return "Entity module built " __DATE__ " " RADIANT_VERSION;
|
||||
}
|
||||
/*
|
||||
Copyright (C) 1999-2007 id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
//
|
||||
// Model Plugin
|
||||
//
|
||||
|
||||
#include "plugin.h"
|
||||
#include "entity.h"
|
||||
#include "entity_entitymodel.h"
|
||||
#include "light.h"
|
||||
|
||||
// =============================================================================
|
||||
// Globals
|
||||
|
||||
// function tables
|
||||
_QERFuncTable_1 g_FuncTable;
|
||||
_QERQglTable g_QglTable;
|
||||
_QERBrushTable __BRUSHTABLENAME;
|
||||
_QERUndoTable __UNDOTABLENAME;
|
||||
_EClassManagerTable __ECLASSMANAGERTABLENAME;
|
||||
|
||||
// =============================================================================
|
||||
// SYNAPSE
|
||||
|
||||
class CSynapseClientEntity : public CSynapseClient
|
||||
{
|
||||
public:
|
||||
// CSynapseClient API
|
||||
bool RequestAPI(APIDescriptor_t *pAPI);
|
||||
const char* GetInfo();
|
||||
|
||||
CSynapseClientEntity() { }
|
||||
virtual ~CSynapseClientEntity() { }
|
||||
};
|
||||
|
||||
|
||||
CSynapseServer* g_pSynapseServer = NULL;
|
||||
CSynapseClientEntity g_SynapseClient;
|
||||
|
||||
#if __GNUC__ >= 4
|
||||
#pragma GCC visibility push(default)
|
||||
#endif
|
||||
extern "C" CSynapseClient* SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( const char *version, CSynapseServer *pServer ) {
|
||||
#if __GNUC__ >= 4
|
||||
#pragma GCC visibility pop
|
||||
#endif
|
||||
if (strcmp(version, SYNAPSE_VERSION))
|
||||
{
|
||||
Syn_Printf("ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version);
|
||||
return NULL;
|
||||
}
|
||||
g_pSynapseServer = pServer;
|
||||
g_pSynapseServer->IncRef();
|
||||
Set_Syn_Printf(g_pSynapseServer->Get_Syn_Printf());
|
||||
|
||||
g_SynapseClient.AddAPI(ENTITY_MAJOR, NULL, sizeof(_QEREntityTable));
|
||||
g_SynapseClient.AddAPI(RADIANT_MAJOR, NULL, sizeof(g_FuncTable), SYN_REQUIRE, &g_FuncTable);
|
||||
g_SynapseClient.AddAPI(QGL_MAJOR, NULL, sizeof(g_QglTable), SYN_REQUIRE, &g_QglTable);
|
||||
g_SynapseClient.AddAPI(BRUSH_MAJOR, NULL, sizeof(__BRUSHTABLENAME), SYN_REQUIRE, &__BRUSHTABLENAME);
|
||||
g_SynapseClient.AddAPI(UNDO_MAJOR, NULL, sizeof(__UNDOTABLENAME), SYN_REQUIRE, &__UNDOTABLENAME);
|
||||
g_SynapseClient.AddAPI(ECLASSMANAGER_MAJOR, NULL, sizeof(__ECLASSMANAGERTABLENAME), SYN_REQUIRE, &__ECLASSMANAGERTABLENAME);
|
||||
|
||||
return &g_SynapseClient;
|
||||
}
|
||||
|
||||
bool CSynapseClientEntity::RequestAPI(APIDescriptor_t *pAPI)
|
||||
{
|
||||
if (!strcmp(pAPI->major_name, ENTITY_MAJOR))
|
||||
{
|
||||
_QEREntityTable* pTable= static_cast<_QEREntityTable*>(pAPI->mpTable);
|
||||
pTable->m_pfnEntity_Alloc = &Entity_Alloc;
|
||||
pTable->m_pfnEntity_Free = &Entity_Free;
|
||||
pTable->m_pfnEntity_Clone = &Entity_Clone;
|
||||
pTable->m_pfnSetKeyValue = &SetKeyValue;
|
||||
pTable->m_pfnDeleteKey = &DeleteKey;
|
||||
pTable->m_pfnValueForKey = &ValueForKey;
|
||||
pTable->m_pfnFloatForKey = &FloatForKey;
|
||||
pTable->m_pfnIntForKey = &IntForKey;
|
||||
pTable->m_pfnGetVectorForKey = &GetVectorForKey;
|
||||
pTable->m_pfnEntity_AddToList = &Entity_AddToList;
|
||||
pTable->m_pfnEntity_RemoveFromList = &Entity_RemoveFromList;
|
||||
pTable->m_pfnEntity_LinkBrush = &Entity_LinkBrush;
|
||||
pTable->m_pfnEntity_UnlinkBrush = &Entity_UnlinkBrush;
|
||||
pTable->m_pfnDrawLight = &DrawLight;
|
||||
pTable->m_pfnEntity_MemorySize = &Entity_MemorySize;
|
||||
pTable->m_pfnAllocateEpair = &Entity_AllocateEpair;
|
||||
pTable->m_pfnGetEntityKeyValList = &Entity_GetKeyValList;
|
||||
pTable->m_pfnSetEntityKeyValList = &Entity_SetKeyValList;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo());
|
||||
return false;
|
||||
}
|
||||
|
||||
#include "version.h"
|
||||
|
||||
const char* CSynapseClientEntity::GetInfo()
|
||||
{
|
||||
return "Entity module built " __DATE__ " " RADIANT_VERSION;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user