more eol-style
[xonotic/netradiant.git] / plugins / entity / eclassmodel.cpp
1 /*
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 #include <stdlib.h>
23
24 #include "entity_entitymodel.h"
25
26 //
27 // CEntityEclassModel implementation
28 //
29
30 CEntityEclassModel::CEntityEclassModel ()
31 {
32   refCount = 1;
33   m_eclass = NULL;
34   m_model = NULL;
35   VectorSet(m_translate, 0,0,0);
36   VectorSet(m_euler, 0,0,0);
37   VectorSet(m_scale, 1,1,1);
38   VectorSet(m_pivot, 0,0,0);
39   m4x4_identity(m_transform);
40   m4x4_identity(m_inverse_transform);
41 }
42
43 CEntityEclassModel::~CEntityEclassModel ()
44 {
45   if(m_name.c_str()[0] != '\0'
46     && m_version.c_str()[0] != '\0')
47     GetModelCache()->DeleteByID(m_name.c_str(), m_version.c_str());
48 }
49
50
51 // IRender
52
53 void CEntityEclassModel::Draw(int state, int rflags) const
54 {
55   // push the current modelview matrix
56   // FIXME: put in a check for stack recursion depth..
57   // or avoid recursion of opengl matrix stack
58   g_QglTable.m_pfn_qglPushMatrix();
59   // apply the parent-to-local transform
60         g_QglTable.m_pfn_qglMultMatrixf(m_transform);
61
62   // draw children
63   if(m_model && m_model->pRender)
64   {
65     m_model->pRender->Draw(state, rflags);
66   }
67  
68   g_QglTable.m_pfn_qglPopMatrix();
69 }
70
71 // ISelect
72
73 bool CEntityEclassModel::TestRay(const ray_t *ray, vec_t *dist) const
74 {
75   vec_t dist_start = *dist;
76   vec_t dist_local = *dist;
77         ray_t ray_local = *ray;
78
79   if (aabb_intersect_ray(&m_BBox, &ray_local, &dist_local))
80     *dist = dist_local;
81   return *dist < dist_start;
82 }
83
84
85 //IEdit
86
87 void CEntityEclassModel::Translate(const vec3_t translation)
88 {
89   VectorIncrement(translation, m_translate);
90   UpdateCachedData();
91 }
92
93 void CEntityEclassModel::Rotate(const vec3_t pivot, const vec3_t rotation)
94 {
95   m4x4_t rotation_matrix;
96
97   m4x4_identity(rotation_matrix);
98   m4x4_pivoted_rotate_by_vec3(rotation_matrix, rotation, eXYZ, pivot);
99   m4x4_transform_point(rotation_matrix, m_translate);
100
101   VectorIncrement(rotation, m_euler);
102
103   UpdateCachedData();
104 }
105
106 void CEntityEclassModel::OnKeyValueChanged(entity_t *e, const char *key, const char* value)
107 {
108   if(strcmp(key,"origin") == 0)
109   {
110     sscanf(value, "%f %f %f", &m_translate[0], &m_translate[1], &m_translate[2]); 
111     UpdateCachedData();
112   } 
113   else if(strcmp(key,"angle") == 0)
114   {
115     VectorSet(m_euler, 0, 0, (float) atof(value));
116     UpdateCachedData();
117   }
118 }
119
120 void CEntityEclassModel::SetEclass(const eclass_t* eclass)
121 {
122   m_eclass = eclass;
123 }
124
125 void CEntityEclassModel::SetName(const char *name)
126 {
127   if(strcmp(m_name.c_str(), name) == 0)
128     return;
129
130   if(m_name.c_str()[0] != '\0'
131     && m_version.c_str()[0] != '\0')
132     GetModelCache()->DeleteByID(m_name.c_str(), m_version.c_str());
133
134   m_model = NULL;
135   m_name = name;
136
137   if(m_name.c_str()[0] != '\0')
138   {
139     const char* dot = strrchr(m_name.c_str(), '.');
140     if(dot != NULL)
141     {
142       m_version = ++dot;
143       m_model = GetModelCache()->GetByID(m_name.c_str(), m_version.c_str());
144     }
145   }
146
147   UpdateCachedData();
148 }
149
150 //
151 // CEntityEclassModel
152 //
153
154 // private:
155
156 void CEntityEclassModel::UpdateCachedData()
157 {
158   aabb_t aabb_temp;
159
160   aabb_clear(&aabb_temp);
161
162   m4x4_identity(m_transform);
163   m4x4_pivoted_transform_by_vec3(m_transform, m_translate, m_euler, eXYZ, m_scale, m_pivot);
164   memcpy(m_inverse_transform, m_transform, sizeof(m4x4_t));
165   if(m4x4_invert(m_inverse_transform) == 1) {
166     Sys_Printf("ERROR: Singular Matrix, cannot invert");
167   }
168
169   if(m_eclass)
170     aabb_construct_for_vec3(&aabb_temp, m_eclass->mins, m_eclass->maxs);
171   else
172     VectorSet(aabb_temp.extents, 8, 8, 8);
173
174   aabb_for_transformed_aabb(&m_BBox, &aabb_temp, m_transform);
175 }