my own uncrustify run
This commit is contained in:
@@ -1,23 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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 "angle.h"
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_ANGLE_H)
|
||||
#if !defined( INCLUDED_ANGLE_H )
|
||||
#define INCLUDED_ANGLE_H
|
||||
|
||||
#include "ientity.h"
|
||||
@@ -30,72 +30,62 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
const float ANGLEKEY_IDENTITY = 0;
|
||||
|
||||
inline void default_angle(float& angle)
|
||||
{
|
||||
angle = ANGLEKEY_IDENTITY;
|
||||
inline void default_angle( float& angle ){
|
||||
angle = ANGLEKEY_IDENTITY;
|
||||
}
|
||||
inline void normalise_angle(float& angle)
|
||||
{
|
||||
angle = static_cast<float>(float_mod(angle, 360.0));
|
||||
inline void normalise_angle( float& angle ){
|
||||
angle = static_cast<float>( float_mod( angle, 360.0 ) );
|
||||
}
|
||||
inline void read_angle(float& angle, const char* value)
|
||||
{
|
||||
if(!string_parse_float(value, angle))
|
||||
{
|
||||
angle = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
normalise_angle(angle);
|
||||
}
|
||||
inline void read_angle( float& angle, const char* value ){
|
||||
if ( !string_parse_float( value, angle ) ) {
|
||||
angle = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
normalise_angle( angle );
|
||||
}
|
||||
}
|
||||
inline void write_angle(float angle, Entity* entity)
|
||||
{
|
||||
if(angle == 0)
|
||||
{
|
||||
entity->setKeyValue("angle", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
char value[64];
|
||||
sprintf(value, "%f", angle);
|
||||
entity->setKeyValue("angle", value);
|
||||
}
|
||||
inline void write_angle( float angle, Entity* entity ){
|
||||
if ( angle == 0 ) {
|
||||
entity->setKeyValue( "angle", "" );
|
||||
}
|
||||
else
|
||||
{
|
||||
char value[64];
|
||||
sprintf( value, "%f", angle );
|
||||
entity->setKeyValue( "angle", value );
|
||||
}
|
||||
}
|
||||
|
||||
class AngleKey
|
||||
{
|
||||
Callback m_angleChanged;
|
||||
Callback m_angleChanged;
|
||||
public:
|
||||
float m_angle;
|
||||
float m_angle;
|
||||
|
||||
|
||||
AngleKey(const Callback& angleChanged)
|
||||
: m_angleChanged(angleChanged), m_angle(ANGLEKEY_IDENTITY)
|
||||
{
|
||||
}
|
||||
AngleKey( const Callback& angleChanged )
|
||||
: m_angleChanged( angleChanged ), m_angle( ANGLEKEY_IDENTITY ){
|
||||
}
|
||||
|
||||
void angleChanged(const char* value)
|
||||
{
|
||||
read_angle(m_angle, value);
|
||||
m_angleChanged();
|
||||
}
|
||||
typedef MemberCaller1<AngleKey, const char*, &AngleKey::angleChanged> AngleChangedCaller;
|
||||
void angleChanged( const char* value ){
|
||||
read_angle( m_angle, value );
|
||||
m_angleChanged();
|
||||
}
|
||||
typedef MemberCaller1<AngleKey, const char*, &AngleKey::angleChanged> AngleChangedCaller;
|
||||
|
||||
void write(Entity* entity) const
|
||||
{
|
||||
write_angle(m_angle, entity);
|
||||
}
|
||||
void write( Entity* entity ) const {
|
||||
write_angle( m_angle, entity );
|
||||
}
|
||||
};
|
||||
|
||||
inline float angle_rotated(float angle, const Quaternion& rotation)
|
||||
{
|
||||
return matrix4_get_rotation_euler_xyz_degrees(
|
||||
matrix4_multiplied_by_matrix4(
|
||||
matrix4_rotation_for_z_degrees(angle),
|
||||
matrix4_rotation_for_quaternion_quantised(rotation)
|
||||
)
|
||||
).z();
|
||||
inline float angle_rotated( float angle, const Quaternion& rotation ){
|
||||
return matrix4_get_rotation_euler_xyz_degrees(
|
||||
matrix4_multiplied_by_matrix4(
|
||||
matrix4_rotation_for_z_degrees( angle ),
|
||||
matrix4_rotation_for_quaternion_quantised( rotation )
|
||||
)
|
||||
).z();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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 "angles.h"
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_ANGLES_H)
|
||||
#if !defined( INCLUDED_ANGLES_H )
|
||||
#define INCLUDED_ANGLES_H
|
||||
|
||||
#include "ientity.h"
|
||||
@@ -30,110 +30,96 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
#include "angle.h"
|
||||
|
||||
const Vector3 ANGLESKEY_IDENTITY = Vector3(0, 0, 0);
|
||||
const Vector3 ANGLESKEY_IDENTITY = Vector3( 0, 0, 0 );
|
||||
|
||||
inline void default_angles(Vector3& angles)
|
||||
{
|
||||
angles = ANGLESKEY_IDENTITY;
|
||||
inline void default_angles( Vector3& angles ){
|
||||
angles = ANGLESKEY_IDENTITY;
|
||||
}
|
||||
inline void normalise_angles(Vector3& angles)
|
||||
{
|
||||
angles[0] = static_cast<float>(float_mod(angles[0], 360));
|
||||
angles[1] = static_cast<float>(float_mod(angles[1], 360));
|
||||
angles[2] = static_cast<float>(float_mod(angles[2], 360));
|
||||
inline void normalise_angles( Vector3& angles ){
|
||||
angles[0] = static_cast<float>( float_mod( angles[0], 360 ) );
|
||||
angles[1] = static_cast<float>( float_mod( angles[1], 360 ) );
|
||||
angles[2] = static_cast<float>( float_mod( angles[2], 360 ) );
|
||||
}
|
||||
inline void read_angle(Vector3& angles, const char* value)
|
||||
{
|
||||
if(!string_parse_float(value, angles[2]))
|
||||
{
|
||||
default_angles(angles);
|
||||
}
|
||||
else
|
||||
{
|
||||
angles[0] = 0;
|
||||
angles[1] = 0;
|
||||
normalise_angles(angles);
|
||||
}
|
||||
inline void read_angle( Vector3& angles, const char* value ){
|
||||
if ( !string_parse_float( value, angles[2] ) ) {
|
||||
default_angles( angles );
|
||||
}
|
||||
else
|
||||
{
|
||||
angles[0] = 0;
|
||||
angles[1] = 0;
|
||||
normalise_angles( angles );
|
||||
}
|
||||
}
|
||||
inline void read_angles(Vector3& angles, const char* value)
|
||||
{
|
||||
if(!string_parse_vector3(value, angles))
|
||||
{
|
||||
default_angles(angles);
|
||||
}
|
||||
else
|
||||
{
|
||||
angles = Vector3(angles[2], angles[0], angles[1]);
|
||||
normalise_angles(angles);
|
||||
}
|
||||
inline void read_angles( Vector3& angles, const char* value ){
|
||||
if ( !string_parse_vector3( value, angles ) ) {
|
||||
default_angles( angles );
|
||||
}
|
||||
else
|
||||
{
|
||||
angles = Vector3( angles[2], angles[0], angles[1] );
|
||||
normalise_angles( angles );
|
||||
}
|
||||
}
|
||||
inline void write_angles(const Vector3& angles, Entity* entity)
|
||||
{
|
||||
if(angles[0] == 0
|
||||
&& angles[1] == 0
|
||||
&& angles[2] == 0)
|
||||
{
|
||||
entity->setKeyValue("angle", "");
|
||||
entity->setKeyValue("angles", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
char value[64];
|
||||
inline void write_angles( const Vector3& angles, Entity* entity ){
|
||||
if ( angles[0] == 0
|
||||
&& angles[1] == 0
|
||||
&& angles[2] == 0 ) {
|
||||
entity->setKeyValue( "angle", "" );
|
||||
entity->setKeyValue( "angles", "" );
|
||||
}
|
||||
else
|
||||
{
|
||||
char value[64];
|
||||
|
||||
if(angles[0] == 0 && angles[1] == 0)
|
||||
{
|
||||
entity->setKeyValue("angles", "");
|
||||
write_angle(angles[2], entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(value, "%f %f %f", angles[1], angles[2], angles[0]);
|
||||
entity->setKeyValue("angle", "");
|
||||
entity->setKeyValue("angles", value);
|
||||
}
|
||||
}
|
||||
if ( angles[0] == 0 && angles[1] == 0 ) {
|
||||
entity->setKeyValue( "angles", "" );
|
||||
write_angle( angles[2], entity );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( value, "%f %f %f", angles[1], angles[2], angles[0] );
|
||||
entity->setKeyValue( "angle", "" );
|
||||
entity->setKeyValue( "angles", value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline Vector3 angles_rotated(const Vector3& angles, const Quaternion& rotation)
|
||||
{
|
||||
return matrix4_get_rotation_euler_xyz_degrees(
|
||||
matrix4_multiplied_by_matrix4(
|
||||
matrix4_rotation_for_euler_xyz_degrees(angles),
|
||||
matrix4_rotation_for_quaternion_quantised(rotation)
|
||||
)
|
||||
);
|
||||
inline Vector3 angles_rotated( const Vector3& angles, const Quaternion& rotation ){
|
||||
return matrix4_get_rotation_euler_xyz_degrees(
|
||||
matrix4_multiplied_by_matrix4(
|
||||
matrix4_rotation_for_euler_xyz_degrees( angles ),
|
||||
matrix4_rotation_for_quaternion_quantised( rotation )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
class AnglesKey
|
||||
{
|
||||
Callback m_anglesChanged;
|
||||
Callback m_anglesChanged;
|
||||
public:
|
||||
Vector3 m_angles;
|
||||
Vector3 m_angles;
|
||||
|
||||
|
||||
AnglesKey(const Callback& anglesChanged)
|
||||
: m_anglesChanged(anglesChanged), m_angles(ANGLESKEY_IDENTITY)
|
||||
{
|
||||
}
|
||||
AnglesKey( const Callback& anglesChanged )
|
||||
: m_anglesChanged( anglesChanged ), m_angles( ANGLESKEY_IDENTITY ){
|
||||
}
|
||||
|
||||
void angleChanged(const char* value)
|
||||
{
|
||||
read_angle(m_angles, value);
|
||||
m_anglesChanged();
|
||||
}
|
||||
typedef MemberCaller1<AnglesKey, const char*, &AnglesKey::angleChanged> AngleChangedCaller;
|
||||
void angleChanged( const char* value ){
|
||||
read_angle( m_angles, value );
|
||||
m_anglesChanged();
|
||||
}
|
||||
typedef MemberCaller1<AnglesKey, const char*, &AnglesKey::angleChanged> AngleChangedCaller;
|
||||
|
||||
void anglesChanged(const char* value)
|
||||
{
|
||||
read_angles(m_angles, value);
|
||||
m_anglesChanged();
|
||||
}
|
||||
typedef MemberCaller1<AnglesKey, const char*, &AnglesKey::anglesChanged> AnglesChangedCaller;
|
||||
void anglesChanged( const char* value ){
|
||||
read_angles( m_angles, value );
|
||||
m_anglesChanged();
|
||||
}
|
||||
typedef MemberCaller1<AnglesKey, const char*, &AnglesKey::anglesChanged> AnglesChangedCaller;
|
||||
|
||||
void write(Entity* entity) const
|
||||
{
|
||||
write_angles(m_angles, entity);
|
||||
}
|
||||
void write( Entity* entity ) const {
|
||||
write_angles( m_angles, entity );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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 "colour.h"
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_COLOUR_H)
|
||||
#if !defined( INCLUDED_COLOUR_H )
|
||||
#define INCLUDED_COLOUR_H
|
||||
|
||||
#include "ientity.h"
|
||||
@@ -30,73 +30,62 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#include "generic/callback.h"
|
||||
#include "stringio.h"
|
||||
|
||||
inline void default_colour(Vector3& colour)
|
||||
{
|
||||
colour = Vector3(1, 1, 1);
|
||||
inline void default_colour( Vector3& colour ){
|
||||
colour = Vector3( 1, 1, 1 );
|
||||
}
|
||||
inline void read_colour(Vector3& colour, const char* value)
|
||||
{
|
||||
if(!string_parse_vector3(value, colour))
|
||||
{
|
||||
default_colour(colour);
|
||||
}
|
||||
inline void read_colour( Vector3& colour, const char* value ){
|
||||
if ( !string_parse_vector3( value, colour ) ) {
|
||||
default_colour( colour );
|
||||
}
|
||||
}
|
||||
inline void write_colour(const Vector3& colour, Entity* entity)
|
||||
{
|
||||
char value[64];
|
||||
inline void write_colour( const Vector3& colour, Entity* entity ){
|
||||
char value[64];
|
||||
|
||||
sprintf(value, "%f %f %f", colour[0], colour[1], colour[2]);
|
||||
entity->setKeyValue("_color", value);
|
||||
sprintf( value, "%f %f %f", colour[0], colour[1], colour[2] );
|
||||
entity->setKeyValue( "_color", value );
|
||||
}
|
||||
|
||||
class Colour
|
||||
{
|
||||
Callback m_colourChanged;
|
||||
Shader* m_state;
|
||||
Callback m_colourChanged;
|
||||
Shader* m_state;
|
||||
|
||||
void capture_state()
|
||||
{
|
||||
m_state = colour_capture_state_fill(m_colour);
|
||||
}
|
||||
void release_state()
|
||||
{
|
||||
colour_release_state_fill(m_colour);
|
||||
}
|
||||
void capture_state(){
|
||||
m_state = colour_capture_state_fill( m_colour );
|
||||
}
|
||||
void release_state(){
|
||||
colour_release_state_fill( m_colour );
|
||||
}
|
||||
|
||||
public:
|
||||
Vector3 m_colour;
|
||||
Vector3 m_colour;
|
||||
|
||||
Colour(const Callback& colourChanged)
|
||||
: m_colourChanged(colourChanged)
|
||||
{
|
||||
default_colour(m_colour);
|
||||
capture_state();
|
||||
}
|
||||
~Colour()
|
||||
{
|
||||
release_state();
|
||||
}
|
||||
Colour( const Callback& colourChanged )
|
||||
: m_colourChanged( colourChanged ){
|
||||
default_colour( m_colour );
|
||||
capture_state();
|
||||
}
|
||||
~Colour(){
|
||||
release_state();
|
||||
}
|
||||
|
||||
void colourChanged(const char* value)
|
||||
{
|
||||
release_state();
|
||||
read_colour(m_colour, value);
|
||||
capture_state();
|
||||
void colourChanged( const char* value ){
|
||||
release_state();
|
||||
read_colour( m_colour, value );
|
||||
capture_state();
|
||||
|
||||
m_colourChanged();
|
||||
}
|
||||
typedef MemberCaller1<Colour, const char*, &Colour::colourChanged> ColourChangedCaller;
|
||||
m_colourChanged();
|
||||
}
|
||||
typedef MemberCaller1<Colour, const char*, &Colour::colourChanged> ColourChangedCaller;
|
||||
|
||||
|
||||
void write(Entity* entity) const
|
||||
{
|
||||
write_colour(m_colour, entity);
|
||||
}
|
||||
void write( Entity* entity ) const {
|
||||
write_colour( m_colour, entity );
|
||||
}
|
||||
|
||||
Shader* state() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
Shader* state() const {
|
||||
return m_state;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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 "curve.h"
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_CURVE_H)
|
||||
#if !defined( INCLUDED_CURVE_H )
|
||||
#define INCLUDED_CURVE_H
|
||||
|
||||
#include "ientity.h"
|
||||
@@ -38,297 +38,258 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
class RenderableCurve : public OpenGLRenderable
|
||||
{
|
||||
public:
|
||||
std::vector<PointVertex> m_vertices;
|
||||
void render(RenderStateFlags state) const
|
||||
{
|
||||
pointvertex_gl_array(&m_vertices.front());
|
||||
glDrawArrays(GL_LINE_STRIP, 0, GLsizei(m_vertices.size()));
|
||||
}
|
||||
std::vector<PointVertex> m_vertices;
|
||||
void render( RenderStateFlags state ) const {
|
||||
pointvertex_gl_array( &m_vertices.front() );
|
||||
glDrawArrays( GL_LINE_STRIP, 0, GLsizei( m_vertices.size() ) );
|
||||
}
|
||||
};
|
||||
|
||||
inline void plotBasisFunction(std::size_t numSegments, int point, int degree)
|
||||
{
|
||||
Knots knots;
|
||||
KnotVector_openUniform(knots, 4, degree);
|
||||
inline void plotBasisFunction( std::size_t numSegments, int point, int degree ){
|
||||
Knots knots;
|
||||
KnotVector_openUniform( knots, 4, degree );
|
||||
|
||||
globalOutputStream() << "plotBasisFunction point " << point << " of 4, knot vector:";
|
||||
for(Knots::iterator i = knots.begin(); i != knots.end(); ++i)
|
||||
{
|
||||
globalOutputStream() << " " << *i;
|
||||
}
|
||||
globalOutputStream() << "\n";
|
||||
globalOutputStream() << "t=0 basis=" << BSpline_basis(knots, point, degree, 0.0) << "\n";
|
||||
for(std::size_t i = 1; i < numSegments; ++i)
|
||||
{
|
||||
double t = (1.0 / double(numSegments)) * double(i);
|
||||
globalOutputStream() << "t=" << t << " basis=" << BSpline_basis(knots, point, degree, t) << "\n";
|
||||
}
|
||||
globalOutputStream() << "t=1 basis=" << BSpline_basis(knots, point, degree, 1.0) << "\n";
|
||||
globalOutputStream() << "plotBasisFunction point " << point << " of 4, knot vector:";
|
||||
for ( Knots::iterator i = knots.begin(); i != knots.end(); ++i )
|
||||
{
|
||||
globalOutputStream() << " " << *i;
|
||||
}
|
||||
globalOutputStream() << "\n";
|
||||
globalOutputStream() << "t=0 basis=" << BSpline_basis( knots, point, degree, 0.0 ) << "\n";
|
||||
for ( std::size_t i = 1; i < numSegments; ++i )
|
||||
{
|
||||
double t = ( 1.0 / double(numSegments) ) * double(i);
|
||||
globalOutputStream() << "t=" << t << " basis=" << BSpline_basis( knots, point, degree, t ) << "\n";
|
||||
}
|
||||
globalOutputStream() << "t=1 basis=" << BSpline_basis( knots, point, degree, 1.0 ) << "\n";
|
||||
}
|
||||
|
||||
inline bool ControlPoints_parse(ControlPoints& controlPoints, const char* value)
|
||||
{
|
||||
StringTokeniser tokeniser(value, " ");
|
||||
inline bool ControlPoints_parse( ControlPoints& controlPoints, const char* value ){
|
||||
StringTokeniser tokeniser( value, " " );
|
||||
|
||||
std::size_t size;
|
||||
if(!string_parse_size(tokeniser.getToken(), size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
std::size_t size;
|
||||
if ( !string_parse_size( tokeniser.getToken(), size ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(size < 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
controlPoints.resize(size);
|
||||
if ( size < 3 ) {
|
||||
return false;
|
||||
}
|
||||
controlPoints.resize( size );
|
||||
|
||||
if(!string_equal(tokeniser.getToken(), "("))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for(ControlPoints::iterator i = controlPoints.begin(); i != controlPoints.end(); ++i)
|
||||
{
|
||||
if(!string_parse_float(tokeniser.getToken(), (*i).x())
|
||||
|| !string_parse_float(tokeniser.getToken(), (*i).y())
|
||||
|| !string_parse_float(tokeniser.getToken(), (*i).z()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!string_equal(tokeniser.getToken(), ")"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if ( !string_equal( tokeniser.getToken(), "(" ) ) {
|
||||
return false;
|
||||
}
|
||||
for ( ControlPoints::iterator i = controlPoints.begin(); i != controlPoints.end(); ++i )
|
||||
{
|
||||
if ( !string_parse_float( tokeniser.getToken(), ( *i ).x() )
|
||||
|| !string_parse_float( tokeniser.getToken(), ( *i ).y() )
|
||||
|| !string_parse_float( tokeniser.getToken(), ( *i ).z() ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ( !string_equal( tokeniser.getToken(), ")" ) ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void ControlPoints_write(const ControlPoints& controlPoints, StringOutputStream& value)
|
||||
{
|
||||
value << Unsigned(controlPoints.size()) << " (";
|
||||
for(ControlPoints::const_iterator i = controlPoints.begin(); i != controlPoints.end(); ++i)
|
||||
{
|
||||
value << " " << (*i).x() << " " << (*i).y() << " " << (*i).z() << " ";
|
||||
}
|
||||
value << ")";
|
||||
inline void ControlPoints_write( const ControlPoints& controlPoints, StringOutputStream& value ){
|
||||
value << Unsigned( controlPoints.size() ) << " (";
|
||||
for ( ControlPoints::const_iterator i = controlPoints.begin(); i != controlPoints.end(); ++i )
|
||||
{
|
||||
value << " " << ( *i ).x() << " " << ( *i ).y() << " " << ( *i ).z() << " ";
|
||||
}
|
||||
value << ")";
|
||||
}
|
||||
|
||||
inline void ControlPoint_testSelect(const Vector3& point, ObservedSelectable& selectable, Selector& selector, SelectionTest& test)
|
||||
{
|
||||
SelectionIntersection best;
|
||||
test.TestPoint(point, best);
|
||||
if(best.valid())
|
||||
{
|
||||
Selector_add(selector, selectable, best);
|
||||
}
|
||||
inline void ControlPoint_testSelect( const Vector3& point, ObservedSelectable& selectable, Selector& selector, SelectionTest& test ){
|
||||
SelectionIntersection best;
|
||||
test.TestPoint( point, best );
|
||||
if ( best.valid() ) {
|
||||
Selector_add( selector, selectable, best );
|
||||
}
|
||||
}
|
||||
|
||||
class ControlPointTransform
|
||||
{
|
||||
const Matrix4& m_matrix;
|
||||
const Matrix4& m_matrix;
|
||||
public:
|
||||
ControlPointTransform(const Matrix4& matrix) : m_matrix(matrix)
|
||||
{
|
||||
}
|
||||
void operator()(Vector3& point) const
|
||||
{
|
||||
matrix4_transform_point(m_matrix, point);
|
||||
}
|
||||
ControlPointTransform( const Matrix4& matrix ) : m_matrix( matrix ){
|
||||
}
|
||||
void operator()( Vector3& point ) const {
|
||||
matrix4_transform_point( m_matrix, point );
|
||||
}
|
||||
};
|
||||
|
||||
class ControlPointSnap
|
||||
{
|
||||
float m_snap;
|
||||
float m_snap;
|
||||
public:
|
||||
ControlPointSnap(float snap) : m_snap(snap)
|
||||
{
|
||||
}
|
||||
void operator()(Vector3& point) const
|
||||
{
|
||||
vector3_snap(point, m_snap);
|
||||
}
|
||||
ControlPointSnap( float snap ) : m_snap( snap ){
|
||||
}
|
||||
void operator()( Vector3& point ) const {
|
||||
vector3_snap( point, m_snap );
|
||||
}
|
||||
};
|
||||
|
||||
class ControlPointAdd
|
||||
{
|
||||
RenderablePointVector& m_points;
|
||||
RenderablePointVector& m_points;
|
||||
public:
|
||||
ControlPointAdd(RenderablePointVector& points) : m_points(points)
|
||||
{
|
||||
}
|
||||
void operator()(const Vector3& point) const
|
||||
{
|
||||
m_points.push_back(PointVertex(vertex3f_for_vector3(point), colour_vertex));
|
||||
}
|
||||
ControlPointAdd( RenderablePointVector& points ) : m_points( points ){
|
||||
}
|
||||
void operator()( const Vector3& point ) const {
|
||||
m_points.push_back( PointVertex( vertex3f_for_vector3( point ), colour_vertex ) );
|
||||
}
|
||||
};
|
||||
|
||||
class ControlPointAddSelected
|
||||
{
|
||||
RenderablePointVector& m_points;
|
||||
RenderablePointVector& m_points;
|
||||
public:
|
||||
ControlPointAddSelected(RenderablePointVector& points) : m_points(points)
|
||||
{
|
||||
}
|
||||
void operator()(const Vector3& point) const
|
||||
{
|
||||
m_points.push_back(PointVertex(vertex3f_for_vector3(point), colour_selected));
|
||||
}
|
||||
ControlPointAddSelected( RenderablePointVector& points ) : m_points( points ){
|
||||
}
|
||||
void operator()( const Vector3& point ) const {
|
||||
m_points.push_back( PointVertex( vertex3f_for_vector3( point ), colour_selected ) );
|
||||
}
|
||||
};
|
||||
|
||||
class CurveEditType
|
||||
{
|
||||
public:
|
||||
Shader* m_controlsShader;
|
||||
Shader* m_selectedShader;
|
||||
Shader* m_controlsShader;
|
||||
Shader* m_selectedShader;
|
||||
};
|
||||
|
||||
inline void ControlPoints_write(ControlPoints& controlPoints, const char* key, Entity& entity)
|
||||
{
|
||||
StringOutputStream value(256);
|
||||
if(!controlPoints.empty())
|
||||
{
|
||||
ControlPoints_write(controlPoints, value);
|
||||
}
|
||||
entity.setKeyValue(key, value.c_str());
|
||||
inline void ControlPoints_write( ControlPoints& controlPoints, const char* key, Entity& entity ){
|
||||
StringOutputStream value( 256 );
|
||||
if ( !controlPoints.empty() ) {
|
||||
ControlPoints_write( controlPoints, value );
|
||||
}
|
||||
entity.setKeyValue( key, value.c_str() );
|
||||
}
|
||||
|
||||
class CurveEdit
|
||||
{
|
||||
SelectionChangeCallback m_selectionChanged;
|
||||
ControlPoints& m_controlPoints;
|
||||
typedef Array<ObservedSelectable> Selectables;
|
||||
Selectables m_selectables;
|
||||
SelectionChangeCallback m_selectionChanged;
|
||||
ControlPoints& m_controlPoints;
|
||||
typedef Array<ObservedSelectable> Selectables;
|
||||
Selectables m_selectables;
|
||||
|
||||
RenderablePointVector m_controlsRender;
|
||||
mutable RenderablePointVector m_selectedRender;
|
||||
RenderablePointVector m_controlsRender;
|
||||
mutable RenderablePointVector m_selectedRender;
|
||||
|
||||
public:
|
||||
typedef Static<CurveEditType> Type;
|
||||
typedef Static<CurveEditType> Type;
|
||||
|
||||
CurveEdit(ControlPoints& controlPoints, const SelectionChangeCallback& selectionChanged) :
|
||||
m_selectionChanged(selectionChanged),
|
||||
m_controlPoints(controlPoints),
|
||||
m_controlsRender(GL_POINTS),
|
||||
m_selectedRender(GL_POINTS)
|
||||
{
|
||||
}
|
||||
CurveEdit( ControlPoints& controlPoints, const SelectionChangeCallback& selectionChanged ) :
|
||||
m_selectionChanged( selectionChanged ),
|
||||
m_controlPoints( controlPoints ),
|
||||
m_controlsRender( GL_POINTS ),
|
||||
m_selectedRender( GL_POINTS ){
|
||||
}
|
||||
|
||||
template<typename Functor>
|
||||
const Functor& forEachSelected(const Functor& functor)
|
||||
{
|
||||
ASSERT_MESSAGE(m_controlPoints.size() == m_selectables.size(), "curve instance mismatch");
|
||||
ControlPoints::iterator p = m_controlPoints.begin();
|
||||
for(Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p)
|
||||
{
|
||||
if((*i).isSelected())
|
||||
{
|
||||
functor(*p);
|
||||
}
|
||||
}
|
||||
return functor;
|
||||
}
|
||||
template<typename Functor>
|
||||
const Functor& forEachSelected(const Functor& functor) const
|
||||
{
|
||||
ASSERT_MESSAGE(m_controlPoints.size() == m_selectables.size(), "curve instance mismatch");
|
||||
ControlPoints::const_iterator p = m_controlPoints.begin();
|
||||
for(Selectables::const_iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p)
|
||||
{
|
||||
if((*i).isSelected())
|
||||
{
|
||||
functor(*p);
|
||||
}
|
||||
}
|
||||
return functor;
|
||||
}
|
||||
template<typename Functor>
|
||||
const Functor& forEach(const Functor& functor) const
|
||||
{
|
||||
for(ControlPoints::const_iterator i = m_controlPoints.begin(); i != m_controlPoints.end(); ++i)
|
||||
{
|
||||
functor(*i);
|
||||
}
|
||||
return functor;
|
||||
}
|
||||
template<typename Functor>
|
||||
const Functor& forEachSelected( const Functor& functor ){
|
||||
ASSERT_MESSAGE( m_controlPoints.size() == m_selectables.size(), "curve instance mismatch" );
|
||||
ControlPoints::iterator p = m_controlPoints.begin();
|
||||
for ( Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p )
|
||||
{
|
||||
if ( ( *i ).isSelected() ) {
|
||||
functor( *p );
|
||||
}
|
||||
}
|
||||
return functor;
|
||||
}
|
||||
template<typename Functor>
|
||||
const Functor& forEachSelected( const Functor& functor ) const {
|
||||
ASSERT_MESSAGE( m_controlPoints.size() == m_selectables.size(), "curve instance mismatch" );
|
||||
ControlPoints::const_iterator p = m_controlPoints.begin();
|
||||
for ( Selectables::const_iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p )
|
||||
{
|
||||
if ( ( *i ).isSelected() ) {
|
||||
functor( *p );
|
||||
}
|
||||
}
|
||||
return functor;
|
||||
}
|
||||
template<typename Functor>
|
||||
const Functor& forEach( const Functor& functor ) const {
|
||||
for ( ControlPoints::const_iterator i = m_controlPoints.begin(); i != m_controlPoints.end(); ++i )
|
||||
{
|
||||
functor( *i );
|
||||
}
|
||||
return functor;
|
||||
}
|
||||
|
||||
void testSelect(Selector& selector, SelectionTest& test)
|
||||
{
|
||||
ASSERT_MESSAGE(m_controlPoints.size() == m_selectables.size(), "curve instance mismatch");
|
||||
ControlPoints::const_iterator p = m_controlPoints.begin();
|
||||
for(Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p)
|
||||
{
|
||||
ControlPoint_testSelect(*p, *i, selector, test);
|
||||
}
|
||||
}
|
||||
void testSelect( Selector& selector, SelectionTest& test ){
|
||||
ASSERT_MESSAGE( m_controlPoints.size() == m_selectables.size(), "curve instance mismatch" );
|
||||
ControlPoints::const_iterator p = m_controlPoints.begin();
|
||||
for ( Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p )
|
||||
{
|
||||
ControlPoint_testSelect( *p, *i, selector, test );
|
||||
}
|
||||
}
|
||||
|
||||
bool isSelected() const
|
||||
{
|
||||
for(Selectables::const_iterator i = m_selectables.begin(); i != m_selectables.end(); ++i)
|
||||
{
|
||||
if((*i).isSelected())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void setSelected(bool selected)
|
||||
{
|
||||
for(Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i)
|
||||
{
|
||||
(*i).setSelected(selected);
|
||||
}
|
||||
}
|
||||
bool isSelected() const {
|
||||
for ( Selectables::const_iterator i = m_selectables.begin(); i != m_selectables.end(); ++i )
|
||||
{
|
||||
if ( ( *i ).isSelected() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void setSelected( bool selected ){
|
||||
for ( Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i )
|
||||
{
|
||||
( *i ).setSelected( selected );
|
||||
}
|
||||
}
|
||||
|
||||
void write(const char* key, Entity& entity)
|
||||
{
|
||||
ControlPoints_write(m_controlPoints, key, entity);
|
||||
}
|
||||
void write( const char* key, Entity& entity ){
|
||||
ControlPoints_write( m_controlPoints, key, entity );
|
||||
}
|
||||
|
||||
void transform(const Matrix4& matrix)
|
||||
{
|
||||
forEachSelected(ControlPointTransform(matrix));
|
||||
}
|
||||
void snapto(float snap)
|
||||
{
|
||||
forEachSelected(ControlPointSnap(snap));
|
||||
}
|
||||
void transform( const Matrix4& matrix ){
|
||||
forEachSelected( ControlPointTransform( matrix ) );
|
||||
}
|
||||
void snapto( float snap ){
|
||||
forEachSelected( ControlPointSnap( snap ) );
|
||||
}
|
||||
|
||||
void updateSelected() const
|
||||
{
|
||||
m_selectedRender.clear();
|
||||
forEachSelected(ControlPointAddSelected(m_selectedRender));
|
||||
}
|
||||
|
||||
void renderComponents(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
renderer.SetState(Type::instance().m_controlsShader, Renderer::eWireframeOnly);
|
||||
renderer.SetState(Type::instance().m_controlsShader, Renderer::eFullMaterials);
|
||||
renderer.addRenderable(m_controlsRender, localToWorld);
|
||||
}
|
||||
void updateSelected() const {
|
||||
m_selectedRender.clear();
|
||||
forEachSelected( ControlPointAddSelected( m_selectedRender ) );
|
||||
}
|
||||
|
||||
void renderComponentsSelected(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
updateSelected();
|
||||
if(!m_selectedRender.empty())
|
||||
{
|
||||
renderer.Highlight(Renderer::ePrimitive, false);
|
||||
renderer.SetState(Type::instance().m_selectedShader, Renderer::eWireframeOnly);
|
||||
renderer.SetState(Type::instance().m_selectedShader, Renderer::eFullMaterials);
|
||||
renderer.addRenderable(m_selectedRender, localToWorld);
|
||||
}
|
||||
}
|
||||
void renderComponents( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
|
||||
renderer.SetState( Type::instance().m_controlsShader, Renderer::eWireframeOnly );
|
||||
renderer.SetState( Type::instance().m_controlsShader, Renderer::eFullMaterials );
|
||||
renderer.addRenderable( m_controlsRender, localToWorld );
|
||||
}
|
||||
|
||||
void curveChanged()
|
||||
{
|
||||
m_selectables.resize(m_controlPoints.size(), m_selectionChanged);
|
||||
void renderComponentsSelected( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
|
||||
updateSelected();
|
||||
if ( !m_selectedRender.empty() ) {
|
||||
renderer.Highlight( Renderer::ePrimitive, false );
|
||||
renderer.SetState( Type::instance().m_selectedShader, Renderer::eWireframeOnly );
|
||||
renderer.SetState( Type::instance().m_selectedShader, Renderer::eFullMaterials );
|
||||
renderer.addRenderable( m_selectedRender, localToWorld );
|
||||
}
|
||||
}
|
||||
|
||||
m_controlsRender.clear();
|
||||
m_controlsRender.reserve(m_controlPoints.size());
|
||||
forEach(ControlPointAdd(m_controlsRender));
|
||||
void curveChanged(){
|
||||
m_selectables.resize( m_controlPoints.size(), m_selectionChanged );
|
||||
|
||||
m_selectedRender.reserve(m_controlPoints.size());
|
||||
}
|
||||
typedef MemberCaller<CurveEdit, &CurveEdit::curveChanged> CurveChangedCaller;
|
||||
m_controlsRender.clear();
|
||||
m_controlsRender.reserve( m_controlPoints.size() );
|
||||
forEach( ControlPointAdd( m_controlsRender ) );
|
||||
|
||||
m_selectedRender.reserve( m_controlPoints.size() );
|
||||
}
|
||||
typedef MemberCaller<CurveEdit, &CurveEdit::curveChanged> CurveChangedCaller;
|
||||
};
|
||||
|
||||
|
||||
@@ -337,177 +298,156 @@ const int NURBS_degree = 3;
|
||||
|
||||
class NURBSCurve
|
||||
{
|
||||
Signal0 m_curveChanged;
|
||||
Callback m_boundsChanged;
|
||||
Signal0 m_curveChanged;
|
||||
Callback m_boundsChanged;
|
||||
public:
|
||||
ControlPoints m_controlPoints;
|
||||
ControlPoints m_controlPointsTransformed;
|
||||
NURBSWeights m_weights;
|
||||
Knots m_knots;
|
||||
RenderableCurve m_renderCurve;
|
||||
AABB m_bounds;
|
||||
ControlPoints m_controlPoints;
|
||||
ControlPoints m_controlPointsTransformed;
|
||||
NURBSWeights m_weights;
|
||||
Knots m_knots;
|
||||
RenderableCurve m_renderCurve;
|
||||
AABB m_bounds;
|
||||
|
||||
NURBSCurve(const Callback& boundsChanged) : m_boundsChanged(boundsChanged)
|
||||
{
|
||||
}
|
||||
NURBSCurve( const Callback& boundsChanged ) : m_boundsChanged( boundsChanged ){
|
||||
}
|
||||
|
||||
SignalHandlerId connect(const SignalHandler& curveChanged)
|
||||
{
|
||||
curveChanged();
|
||||
return m_curveChanged.connectLast(curveChanged);
|
||||
}
|
||||
void disconnect(SignalHandlerId id)
|
||||
{
|
||||
m_curveChanged.disconnect(id);
|
||||
}
|
||||
void notify()
|
||||
{
|
||||
m_curveChanged();
|
||||
}
|
||||
SignalHandlerId connect( const SignalHandler& curveChanged ){
|
||||
curveChanged();
|
||||
return m_curveChanged.connectLast( curveChanged );
|
||||
}
|
||||
void disconnect( SignalHandlerId id ){
|
||||
m_curveChanged.disconnect( id );
|
||||
}
|
||||
void notify(){
|
||||
m_curveChanged();
|
||||
}
|
||||
|
||||
void tesselate()
|
||||
{
|
||||
if(!m_controlPointsTransformed.empty())
|
||||
{
|
||||
const std::size_t numSegments = (m_controlPointsTransformed.size() - 1) * 16;
|
||||
m_renderCurve.m_vertices.resize(numSegments + 1);
|
||||
m_renderCurve.m_vertices[0].vertex = vertex3f_for_vector3(m_controlPointsTransformed[0]);
|
||||
for(std::size_t i = 1; i < numSegments; ++i)
|
||||
{
|
||||
m_renderCurve.m_vertices[i].vertex = vertex3f_for_vector3(NURBS_evaluate(m_controlPointsTransformed, m_weights, m_knots, NURBS_degree, (1.0 / double(numSegments)) * double(i)));
|
||||
}
|
||||
m_renderCurve.m_vertices[numSegments].vertex = vertex3f_for_vector3(m_controlPointsTransformed[m_controlPointsTransformed.size() - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_renderCurve.m_vertices.clear();
|
||||
}
|
||||
}
|
||||
void tesselate(){
|
||||
if ( !m_controlPointsTransformed.empty() ) {
|
||||
const std::size_t numSegments = ( m_controlPointsTransformed.size() - 1 ) * 16;
|
||||
m_renderCurve.m_vertices.resize( numSegments + 1 );
|
||||
m_renderCurve.m_vertices[0].vertex = vertex3f_for_vector3( m_controlPointsTransformed[0] );
|
||||
for ( std::size_t i = 1; i < numSegments; ++i )
|
||||
{
|
||||
m_renderCurve.m_vertices[i].vertex = vertex3f_for_vector3( NURBS_evaluate( m_controlPointsTransformed, m_weights, m_knots, NURBS_degree, ( 1.0 / double(numSegments) ) * double(i) ) );
|
||||
}
|
||||
m_renderCurve.m_vertices[numSegments].vertex = vertex3f_for_vector3( m_controlPointsTransformed[m_controlPointsTransformed.size() - 1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_renderCurve.m_vertices.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void curveChanged()
|
||||
{
|
||||
tesselate();
|
||||
void curveChanged(){
|
||||
tesselate();
|
||||
|
||||
m_bounds = AABB();
|
||||
for(ControlPoints::iterator i = m_controlPointsTransformed.begin(); i != m_controlPointsTransformed.end(); ++i)
|
||||
{
|
||||
aabb_extend_by_point_safe(m_bounds, (*i));
|
||||
}
|
||||
m_bounds = AABB();
|
||||
for ( ControlPoints::iterator i = m_controlPointsTransformed.begin(); i != m_controlPointsTransformed.end(); ++i )
|
||||
{
|
||||
aabb_extend_by_point_safe( m_bounds, ( *i ) );
|
||||
}
|
||||
|
||||
m_boundsChanged();
|
||||
notify();
|
||||
}
|
||||
m_boundsChanged();
|
||||
notify();
|
||||
}
|
||||
|
||||
bool parseCurve(const char* value)
|
||||
{
|
||||
if(!ControlPoints_parse(m_controlPoints, value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool parseCurve( const char* value ){
|
||||
if ( !ControlPoints_parse( m_controlPoints, value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_weights.resize(m_controlPoints.size());
|
||||
for(NURBSWeights::iterator i = m_weights.begin(); i != m_weights.end(); ++i)
|
||||
{
|
||||
(*i) = 1;
|
||||
}
|
||||
m_weights.resize( m_controlPoints.size() );
|
||||
for ( NURBSWeights::iterator i = m_weights.begin(); i != m_weights.end(); ++i )
|
||||
{
|
||||
( *i ) = 1;
|
||||
}
|
||||
|
||||
KnotVector_openUniform(m_knots, m_controlPoints.size(), NURBS_degree);
|
||||
KnotVector_openUniform( m_knots, m_controlPoints.size(), NURBS_degree );
|
||||
|
||||
//plotBasisFunction(8, 0, NURBS_degree);
|
||||
//plotBasisFunction(8, 0, NURBS_degree);
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void curveChanged(const char* value)
|
||||
{
|
||||
if(string_empty(value) || !parseCurve(value))
|
||||
{
|
||||
m_controlPoints.resize(0);
|
||||
m_knots.resize(0);
|
||||
m_weights.resize(0);
|
||||
}
|
||||
m_controlPointsTransformed = m_controlPoints;
|
||||
curveChanged();
|
||||
}
|
||||
typedef MemberCaller1<NURBSCurve, const char*, &NURBSCurve::curveChanged> CurveChangedCaller;
|
||||
void curveChanged( const char* value ){
|
||||
if ( string_empty( value ) || !parseCurve( value ) ) {
|
||||
m_controlPoints.resize( 0 );
|
||||
m_knots.resize( 0 );
|
||||
m_weights.resize( 0 );
|
||||
}
|
||||
m_controlPointsTransformed = m_controlPoints;
|
||||
curveChanged();
|
||||
}
|
||||
typedef MemberCaller1<NURBSCurve, const char*, &NURBSCurve::curveChanged> CurveChangedCaller;
|
||||
};
|
||||
|
||||
class CatmullRomSpline
|
||||
{
|
||||
Signal0 m_curveChanged;
|
||||
Callback m_boundsChanged;
|
||||
Signal0 m_curveChanged;
|
||||
Callback m_boundsChanged;
|
||||
public:
|
||||
ControlPoints m_controlPoints;
|
||||
ControlPoints m_controlPointsTransformed;
|
||||
RenderableCurve m_renderCurve;
|
||||
AABB m_bounds;
|
||||
ControlPoints m_controlPoints;
|
||||
ControlPoints m_controlPointsTransformed;
|
||||
RenderableCurve m_renderCurve;
|
||||
AABB m_bounds;
|
||||
|
||||
CatmullRomSpline(const Callback& boundsChanged) : m_boundsChanged(boundsChanged)
|
||||
{
|
||||
}
|
||||
CatmullRomSpline( const Callback& boundsChanged ) : m_boundsChanged( boundsChanged ){
|
||||
}
|
||||
|
||||
SignalHandlerId connect(const SignalHandler& curveChanged)
|
||||
{
|
||||
curveChanged();
|
||||
return m_curveChanged.connectLast(curveChanged);
|
||||
}
|
||||
void disconnect(SignalHandlerId id)
|
||||
{
|
||||
m_curveChanged.disconnect(id);
|
||||
}
|
||||
void notify()
|
||||
{
|
||||
m_curveChanged();
|
||||
}
|
||||
SignalHandlerId connect( const SignalHandler& curveChanged ){
|
||||
curveChanged();
|
||||
return m_curveChanged.connectLast( curveChanged );
|
||||
}
|
||||
void disconnect( SignalHandlerId id ){
|
||||
m_curveChanged.disconnect( id );
|
||||
}
|
||||
void notify(){
|
||||
m_curveChanged();
|
||||
}
|
||||
|
||||
void tesselate()
|
||||
{
|
||||
if(!m_controlPointsTransformed.empty())
|
||||
{
|
||||
const std::size_t numSegments = (m_controlPointsTransformed.size() - 1) * 16;
|
||||
m_renderCurve.m_vertices.resize(numSegments + 1);
|
||||
m_renderCurve.m_vertices[0].vertex = vertex3f_for_vector3(m_controlPointsTransformed[0]);
|
||||
for(std::size_t i = 1; i < numSegments; ++i)
|
||||
{
|
||||
m_renderCurve.m_vertices[i].vertex = vertex3f_for_vector3(CatmullRom_evaluate(m_controlPointsTransformed, (1.0 / double(numSegments)) * double(i)));
|
||||
}
|
||||
m_renderCurve.m_vertices[numSegments].vertex = vertex3f_for_vector3(m_controlPointsTransformed[m_controlPointsTransformed.size() - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_renderCurve.m_vertices.clear();
|
||||
}
|
||||
}
|
||||
void tesselate(){
|
||||
if ( !m_controlPointsTransformed.empty() ) {
|
||||
const std::size_t numSegments = ( m_controlPointsTransformed.size() - 1 ) * 16;
|
||||
m_renderCurve.m_vertices.resize( numSegments + 1 );
|
||||
m_renderCurve.m_vertices[0].vertex = vertex3f_for_vector3( m_controlPointsTransformed[0] );
|
||||
for ( std::size_t i = 1; i < numSegments; ++i )
|
||||
{
|
||||
m_renderCurve.m_vertices[i].vertex = vertex3f_for_vector3( CatmullRom_evaluate( m_controlPointsTransformed, ( 1.0 / double(numSegments) ) * double(i) ) );
|
||||
}
|
||||
m_renderCurve.m_vertices[numSegments].vertex = vertex3f_for_vector3( m_controlPointsTransformed[m_controlPointsTransformed.size() - 1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_renderCurve.m_vertices.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool parseCurve(const char* value)
|
||||
{
|
||||
return ControlPoints_parse(m_controlPoints, value);
|
||||
}
|
||||
bool parseCurve( const char* value ){
|
||||
return ControlPoints_parse( m_controlPoints, value );
|
||||
}
|
||||
|
||||
void curveChanged()
|
||||
{
|
||||
tesselate();
|
||||
void curveChanged(){
|
||||
tesselate();
|
||||
|
||||
m_bounds = AABB();
|
||||
for(ControlPoints::iterator i = m_controlPointsTransformed.begin(); i != m_controlPointsTransformed.end(); ++i)
|
||||
{
|
||||
aabb_extend_by_point_safe(m_bounds, (*i));
|
||||
}
|
||||
m_bounds = AABB();
|
||||
for ( ControlPoints::iterator i = m_controlPointsTransformed.begin(); i != m_controlPointsTransformed.end(); ++i )
|
||||
{
|
||||
aabb_extend_by_point_safe( m_bounds, ( *i ) );
|
||||
}
|
||||
|
||||
m_boundsChanged();
|
||||
notify();
|
||||
}
|
||||
m_boundsChanged();
|
||||
notify();
|
||||
}
|
||||
|
||||
void curveChanged(const char* value)
|
||||
{
|
||||
if(string_empty(value) || !parseCurve(value))
|
||||
{
|
||||
m_controlPoints.resize(0);
|
||||
}
|
||||
m_controlPointsTransformed = m_controlPoints;
|
||||
curveChanged();
|
||||
}
|
||||
typedef MemberCaller1<CatmullRomSpline, const char*, &CatmullRomSpline::curveChanged> CurveChangedCaller;
|
||||
void curveChanged( const char* value ){
|
||||
if ( string_empty( value ) || !parseCurve( value ) ) {
|
||||
m_controlPoints.resize( 0 );
|
||||
}
|
||||
m_controlPointsTransformed = m_controlPoints;
|
||||
curveChanged();
|
||||
}
|
||||
typedef MemberCaller1<CatmullRomSpline, const char*, &CatmullRomSpline::curveChanged> CurveChangedCaller;
|
||||
};
|
||||
|
||||
const char* const curve_Nurbs = "curve_Nurbs";
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,35 +1,35 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_STATIC_H)
|
||||
#if !defined( INCLUDED_STATIC_H )
|
||||
#define INCLUDED_STATIC_H
|
||||
|
||||
namespace scene
|
||||
{
|
||||
class Node;
|
||||
class Node;
|
||||
}
|
||||
class EntityClass;
|
||||
|
||||
void Doom3Group_construct();
|
||||
void Doom3Group_destroy();
|
||||
scene::Node& New_Doom3Group(EntityClass* eclass);
|
||||
scene::Node& New_Doom3Group( EntityClass* eclass );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
///\file
|
||||
///\brief Represents any entity which has a fixed size specified in its entity-definition and displays a model (e.g. ammo_bfg).
|
||||
@@ -55,478 +55,406 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#include "entity.h"
|
||||
|
||||
class EclassModel :
|
||||
public Snappable
|
||||
public Snappable
|
||||
{
|
||||
MatrixTransform m_transform;
|
||||
EntityKeyValues m_entity;
|
||||
KeyObserverMap m_keyObservers;
|
||||
MatrixTransform m_transform;
|
||||
EntityKeyValues m_entity;
|
||||
KeyObserverMap m_keyObservers;
|
||||
|
||||
OriginKey m_originKey;
|
||||
Vector3 m_origin;
|
||||
AngleKey m_angleKey;
|
||||
float m_angle;
|
||||
RotationKey m_rotationKey;
|
||||
Float9 m_rotation;
|
||||
SingletonModel m_model;
|
||||
OriginKey m_originKey;
|
||||
Vector3 m_origin;
|
||||
AngleKey m_angleKey;
|
||||
float m_angle;
|
||||
RotationKey m_rotationKey;
|
||||
Float9 m_rotation;
|
||||
SingletonModel m_model;
|
||||
|
||||
ClassnameFilter m_filter;
|
||||
NamedEntity m_named;
|
||||
NameKeys m_nameKeys;
|
||||
RenderablePivot m_renderOrigin;
|
||||
RenderableNamedEntity m_renderName;
|
||||
ModelSkinKey m_skin;
|
||||
ClassnameFilter m_filter;
|
||||
NamedEntity m_named;
|
||||
NameKeys m_nameKeys;
|
||||
RenderablePivot m_renderOrigin;
|
||||
RenderableNamedEntity m_renderName;
|
||||
ModelSkinKey m_skin;
|
||||
|
||||
Callback m_transformChanged;
|
||||
Callback m_evaluateTransform;
|
||||
Callback m_transformChanged;
|
||||
Callback m_evaluateTransform;
|
||||
|
||||
void construct()
|
||||
{
|
||||
default_rotation(m_rotation);
|
||||
void construct(){
|
||||
default_rotation( m_rotation );
|
||||
|
||||
m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter));
|
||||
m_keyObservers.insert(Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named));
|
||||
if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
m_keyObservers.insert("angle", RotationKey::AngleChangedCaller(m_rotationKey));
|
||||
m_keyObservers.insert("rotation", RotationKey::RotationChangedCaller(m_rotationKey));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_keyObservers.insert("angle", AngleKey::AngleChangedCaller(m_angleKey));
|
||||
}
|
||||
m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey));
|
||||
}
|
||||
m_keyObservers.insert( "classname", ClassnameFilter::ClassnameChangedCaller( m_filter ) );
|
||||
m_keyObservers.insert( Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller( m_named ) );
|
||||
if ( g_gameType == eGameTypeDoom3 ) {
|
||||
m_keyObservers.insert( "angle", RotationKey::AngleChangedCaller( m_rotationKey ) );
|
||||
m_keyObservers.insert( "rotation", RotationKey::RotationChangedCaller( m_rotationKey ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_keyObservers.insert( "angle", AngleKey::AngleChangedCaller( m_angleKey ) );
|
||||
}
|
||||
m_keyObservers.insert( "origin", OriginKey::OriginChangedCaller( m_originKey ) );
|
||||
}
|
||||
|
||||
// vc 2k5 compiler fix
|
||||
#if _MSC_VER >= 1400
|
||||
public:
|
||||
public:
|
||||
#endif
|
||||
|
||||
void updateTransform()
|
||||
{
|
||||
m_transform.localToParent() = g_matrix4_identity;
|
||||
matrix4_translate_by_vec3(m_transform.localToParent(), m_origin);
|
||||
void updateTransform(){
|
||||
m_transform.localToParent() = g_matrix4_identity;
|
||||
matrix4_translate_by_vec3( m_transform.localToParent(), m_origin );
|
||||
|
||||
if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
matrix4_multiply_by_matrix4(m_transform.localToParent(), rotation_toMatrix(m_rotation));
|
||||
}
|
||||
else
|
||||
{
|
||||
matrix4_multiply_by_matrix4(m_transform.localToParent(), matrix4_rotation_for_z_degrees(m_angle));
|
||||
}
|
||||
if ( g_gameType == eGameTypeDoom3 ) {
|
||||
matrix4_multiply_by_matrix4( m_transform.localToParent(), rotation_toMatrix( m_rotation ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
matrix4_multiply_by_matrix4( m_transform.localToParent(), matrix4_rotation_for_z_degrees( m_angle ) );
|
||||
}
|
||||
|
||||
m_transformChanged();
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::updateTransform> UpdateTransformCaller;
|
||||
m_transformChanged();
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::updateTransform> UpdateTransformCaller;
|
||||
|
||||
void originChanged()
|
||||
{
|
||||
m_origin = m_originKey.m_origin;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::originChanged> OriginChangedCaller;
|
||||
void angleChanged()
|
||||
{
|
||||
m_angle = m_angleKey.m_angle;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::angleChanged> AngleChangedCaller;
|
||||
void rotationChanged()
|
||||
{
|
||||
rotation_assign(m_rotation, m_rotationKey.m_rotation);
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::rotationChanged> RotationChangedCaller;
|
||||
void originChanged(){
|
||||
m_origin = m_originKey.m_origin;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::originChanged> OriginChangedCaller;
|
||||
void angleChanged(){
|
||||
m_angle = m_angleKey.m_angle;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::angleChanged> AngleChangedCaller;
|
||||
void rotationChanged(){
|
||||
rotation_assign( m_rotation, m_rotationKey.m_rotation );
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::rotationChanged> RotationChangedCaller;
|
||||
|
||||
void skinChanged()
|
||||
{
|
||||
scene::Node* node = m_model.getNode();
|
||||
if(node != 0)
|
||||
{
|
||||
Node_modelSkinChanged(*node);
|
||||
}
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::skinChanged> SkinChangedCaller;
|
||||
void skinChanged(){
|
||||
scene::Node* node = m_model.getNode();
|
||||
if ( node != 0 ) {
|
||||
Node_modelSkinChanged( *node );
|
||||
}
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::skinChanged> SkinChangedCaller;
|
||||
|
||||
public:
|
||||
|
||||
EclassModel(EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
|
||||
m_entity(eclass),
|
||||
m_originKey(OriginChangedCaller(*this)),
|
||||
m_origin(ORIGINKEY_IDENTITY),
|
||||
m_angleKey(AngleChangedCaller(*this)),
|
||||
m_angle(ANGLEKEY_IDENTITY),
|
||||
m_rotationKey(RotationChangedCaller(*this)),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_skin(SkinChangedCaller(*this)),
|
||||
m_transformChanged(transformChanged),
|
||||
m_evaluateTransform(evaluateTransform)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
EclassModel(const EclassModel& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
|
||||
m_entity(other.m_entity),
|
||||
m_originKey(OriginChangedCaller(*this)),
|
||||
m_origin(ORIGINKEY_IDENTITY),
|
||||
m_angleKey(AngleChangedCaller(*this)),
|
||||
m_angle(ANGLEKEY_IDENTITY),
|
||||
m_rotationKey(RotationChangedCaller(*this)),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_skin(SkinChangedCaller(*this)),
|
||||
m_transformChanged(transformChanged),
|
||||
m_evaluateTransform(evaluateTransform)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
EclassModel( EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) :
|
||||
m_entity( eclass ),
|
||||
m_originKey( OriginChangedCaller( *this ) ),
|
||||
m_origin( ORIGINKEY_IDENTITY ),
|
||||
m_angleKey( AngleChangedCaller( *this ) ),
|
||||
m_angle( ANGLEKEY_IDENTITY ),
|
||||
m_rotationKey( RotationChangedCaller( *this ) ),
|
||||
m_filter( m_entity, node ),
|
||||
m_named( m_entity ),
|
||||
m_nameKeys( m_entity ),
|
||||
m_renderName( m_named, g_vector3_identity ),
|
||||
m_skin( SkinChangedCaller( *this ) ),
|
||||
m_transformChanged( transformChanged ),
|
||||
m_evaluateTransform( evaluateTransform ){
|
||||
construct();
|
||||
}
|
||||
EclassModel( const EclassModel& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) :
|
||||
m_entity( other.m_entity ),
|
||||
m_originKey( OriginChangedCaller( *this ) ),
|
||||
m_origin( ORIGINKEY_IDENTITY ),
|
||||
m_angleKey( AngleChangedCaller( *this ) ),
|
||||
m_angle( ANGLEKEY_IDENTITY ),
|
||||
m_rotationKey( RotationChangedCaller( *this ) ),
|
||||
m_filter( m_entity, node ),
|
||||
m_named( m_entity ),
|
||||
m_nameKeys( m_entity ),
|
||||
m_renderName( m_named, g_vector3_identity ),
|
||||
m_skin( SkinChangedCaller( *this ) ),
|
||||
m_transformChanged( transformChanged ),
|
||||
m_evaluateTransform( evaluateTransform ){
|
||||
construct();
|
||||
}
|
||||
|
||||
InstanceCounter m_instanceCounter;
|
||||
void instanceAttach(const scene::Path& path)
|
||||
{
|
||||
if(++m_instanceCounter.m_count == 1)
|
||||
{
|
||||
m_filter.instanceAttach();
|
||||
m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_entity.attach(m_keyObservers);
|
||||
m_model.modelChanged(m_entity.getEntityClass().modelpath());
|
||||
m_skin.skinChanged(m_entity.getEntityClass().skin());
|
||||
}
|
||||
}
|
||||
void instanceDetach(const scene::Path& path)
|
||||
{
|
||||
if(--m_instanceCounter.m_count == 0)
|
||||
{
|
||||
m_skin.skinChanged("");
|
||||
m_model.modelChanged("");
|
||||
m_entity.detach(m_keyObservers);
|
||||
m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_filter.instanceDetach();
|
||||
}
|
||||
}
|
||||
InstanceCounter m_instanceCounter;
|
||||
void instanceAttach( const scene::Path& path ){
|
||||
if ( ++m_instanceCounter.m_count == 1 ) {
|
||||
m_filter.instanceAttach();
|
||||
m_entity.instanceAttach( path_find_mapfile( path.begin(), path.end() ) );
|
||||
m_entity.attach( m_keyObservers );
|
||||
m_model.modelChanged( m_entity.getEntityClass().modelpath() );
|
||||
m_skin.skinChanged( m_entity.getEntityClass().skin() );
|
||||
}
|
||||
}
|
||||
void instanceDetach( const scene::Path& path ){
|
||||
if ( --m_instanceCounter.m_count == 0 ) {
|
||||
m_skin.skinChanged( "" );
|
||||
m_model.modelChanged( "" );
|
||||
m_entity.detach( m_keyObservers );
|
||||
m_entity.instanceDetach( path_find_mapfile( path.begin(), path.end() ) );
|
||||
m_filter.instanceDetach();
|
||||
}
|
||||
}
|
||||
|
||||
EntityKeyValues& getEntity()
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
const EntityKeyValues& getEntity() const
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
EntityKeyValues& getEntity(){
|
||||
return m_entity;
|
||||
}
|
||||
const EntityKeyValues& getEntity() const {
|
||||
return m_entity;
|
||||
}
|
||||
|
||||
scene::Traversable& getTraversable()
|
||||
{
|
||||
return m_model.getTraversable();
|
||||
}
|
||||
Namespaced& getNamespaced()
|
||||
{
|
||||
return m_nameKeys;
|
||||
}
|
||||
Nameable& getNameable()
|
||||
{
|
||||
return m_named;
|
||||
}
|
||||
TransformNode& getTransformNode()
|
||||
{
|
||||
return m_transform;
|
||||
}
|
||||
ModelSkin& getModelSkin()
|
||||
{
|
||||
return m_skin.get();
|
||||
}
|
||||
scene::Traversable& getTraversable(){
|
||||
return m_model.getTraversable();
|
||||
}
|
||||
Namespaced& getNamespaced(){
|
||||
return m_nameKeys;
|
||||
}
|
||||
Nameable& getNameable(){
|
||||
return m_named;
|
||||
}
|
||||
TransformNode& getTransformNode(){
|
||||
return m_transform;
|
||||
}
|
||||
ModelSkin& getModelSkin(){
|
||||
return m_skin.get();
|
||||
}
|
||||
|
||||
void attach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_model.attach(observer);
|
||||
}
|
||||
void detach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_model.detach(observer);
|
||||
}
|
||||
void attach( scene::Traversable::Observer* observer ){
|
||||
m_model.attach( observer );
|
||||
}
|
||||
void detach( scene::Traversable::Observer* observer ){
|
||||
m_model.detach( observer );
|
||||
}
|
||||
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected) const
|
||||
{
|
||||
if(selected)
|
||||
{
|
||||
m_renderOrigin.render(renderer, volume, localToWorld);
|
||||
}
|
||||
void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected ) const {
|
||||
if ( selected ) {
|
||||
m_renderOrigin.render( renderer, volume, localToWorld );
|
||||
}
|
||||
|
||||
renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected) const
|
||||
{
|
||||
renderSolid(renderer, volume, localToWorld, selected);
|
||||
if(g_showNames)
|
||||
{
|
||||
renderer.addRenderable(m_renderName, localToWorld);
|
||||
}
|
||||
}
|
||||
renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly );
|
||||
}
|
||||
void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected ) const {
|
||||
renderSolid( renderer, volume, localToWorld, selected );
|
||||
if ( g_showNames ) {
|
||||
renderer.addRenderable( m_renderName, localToWorld );
|
||||
}
|
||||
}
|
||||
|
||||
void translate(const Vector3& translation)
|
||||
{
|
||||
m_origin = origin_translated(m_origin, translation);
|
||||
}
|
||||
void rotate(const Quaternion& rotation)
|
||||
{
|
||||
if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
rotation_rotate(m_rotation, rotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_angle = angle_rotated(m_angle, rotation);
|
||||
}
|
||||
}
|
||||
void snapto(float snap)
|
||||
{
|
||||
m_originKey.m_origin = origin_snapped(m_originKey.m_origin, snap);
|
||||
m_originKey.write(&m_entity);
|
||||
}
|
||||
void revertTransform()
|
||||
{
|
||||
m_origin = m_originKey.m_origin;
|
||||
if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
rotation_assign(m_rotation, m_rotationKey.m_rotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_angle = m_angleKey.m_angle;
|
||||
}
|
||||
}
|
||||
void freezeTransform()
|
||||
{
|
||||
m_originKey.m_origin = m_origin;
|
||||
m_originKey.write(&m_entity);
|
||||
if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
rotation_assign(m_rotationKey.m_rotation, m_rotation);
|
||||
m_rotationKey.write(&m_entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_angleKey.m_angle = m_angle;
|
||||
m_angleKey.write(&m_entity);
|
||||
}
|
||||
}
|
||||
void transformChanged()
|
||||
{
|
||||
revertTransform();
|
||||
m_evaluateTransform();
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::transformChanged> TransformChangedCaller;
|
||||
void translate( const Vector3& translation ){
|
||||
m_origin = origin_translated( m_origin, translation );
|
||||
}
|
||||
void rotate( const Quaternion& rotation ){
|
||||
if ( g_gameType == eGameTypeDoom3 ) {
|
||||
rotation_rotate( m_rotation, rotation );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_angle = angle_rotated( m_angle, rotation );
|
||||
}
|
||||
}
|
||||
void snapto( float snap ){
|
||||
m_originKey.m_origin = origin_snapped( m_originKey.m_origin, snap );
|
||||
m_originKey.write( &m_entity );
|
||||
}
|
||||
void revertTransform(){
|
||||
m_origin = m_originKey.m_origin;
|
||||
if ( g_gameType == eGameTypeDoom3 ) {
|
||||
rotation_assign( m_rotation, m_rotationKey.m_rotation );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_angle = m_angleKey.m_angle;
|
||||
}
|
||||
}
|
||||
void freezeTransform(){
|
||||
m_originKey.m_origin = m_origin;
|
||||
m_originKey.write( &m_entity );
|
||||
if ( g_gameType == eGameTypeDoom3 ) {
|
||||
rotation_assign( m_rotationKey.m_rotation, m_rotation );
|
||||
m_rotationKey.write( &m_entity );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_angleKey.m_angle = m_angle;
|
||||
m_angleKey.write( &m_entity );
|
||||
}
|
||||
}
|
||||
void transformChanged(){
|
||||
revertTransform();
|
||||
m_evaluateTransform();
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::transformChanged> TransformChangedCaller;
|
||||
};
|
||||
|
||||
class EclassModelInstance : public TargetableInstance, public TransformModifier, public Renderable
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
InstanceTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
m_casts = TargetableInstance::StaticTypeCasts::instance().get();
|
||||
InstanceStaticCast<EclassModelInstance, Renderable>::install(m_casts);
|
||||
InstanceStaticCast<EclassModelInstance, Transformable>::install(m_casts);
|
||||
InstanceIdentityCast<EclassModelInstance>::install(m_casts);
|
||||
}
|
||||
InstanceTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
EclassModel& m_contained;
|
||||
class TypeCasts
|
||||
{
|
||||
InstanceTypeCastTable m_casts;
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
TypeCasts(){
|
||||
m_casts = TargetableInstance::StaticTypeCasts::instance().get();
|
||||
InstanceStaticCast<EclassModelInstance, Renderable>::install( m_casts );
|
||||
InstanceStaticCast<EclassModelInstance, Transformable>::install( m_casts );
|
||||
InstanceIdentityCast<EclassModelInstance>::install( m_casts );
|
||||
}
|
||||
InstanceTypeCastTable& get(){
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
STRING_CONSTANT(Name, "EclassModelInstance");
|
||||
EclassModel& m_contained;
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
EclassModelInstance(const scene::Path& path, scene::Instance* parent, EclassModel& contained) :
|
||||
TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this),
|
||||
TransformModifier(EclassModel::TransformChangedCaller(contained), ApplyTransformCaller(*this)),
|
||||
m_contained(contained)
|
||||
{
|
||||
m_contained.instanceAttach(Instance::path());
|
||||
STRING_CONSTANT( Name, "EclassModelInstance" );
|
||||
|
||||
StaticRenderableConnectionLines::instance().attach(*this);
|
||||
}
|
||||
~EclassModelInstance()
|
||||
{
|
||||
StaticRenderableConnectionLines::instance().detach(*this);
|
||||
EclassModelInstance( const scene::Path& path, scene::Instance* parent, EclassModel& contained ) :
|
||||
TargetableInstance( path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this ),
|
||||
TransformModifier( EclassModel::TransformChangedCaller( contained ), ApplyTransformCaller( *this ) ),
|
||||
m_contained( contained ){
|
||||
m_contained.instanceAttach( Instance::path() );
|
||||
|
||||
m_contained.instanceDetach(Instance::path());
|
||||
}
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderSolid(renderer, volume, Instance::localToWorld(), getSelectable().isSelected());
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderWireframe(renderer, volume, Instance::localToWorld(), getSelectable().isSelected());
|
||||
}
|
||||
StaticRenderableConnectionLines::instance().attach( *this );
|
||||
}
|
||||
~EclassModelInstance(){
|
||||
StaticRenderableConnectionLines::instance().detach( *this );
|
||||
|
||||
void evaluateTransform()
|
||||
{
|
||||
if(getType() == TRANSFORM_PRIMITIVE)
|
||||
{
|
||||
m_contained.translate(getTranslation());
|
||||
m_contained.rotate(getRotation());
|
||||
}
|
||||
}
|
||||
void applyTransform()
|
||||
{
|
||||
m_contained.revertTransform();
|
||||
evaluateTransform();
|
||||
m_contained.freezeTransform();
|
||||
}
|
||||
typedef MemberCaller<EclassModelInstance, &EclassModelInstance::applyTransform> ApplyTransformCaller;
|
||||
m_contained.instanceDetach( Instance::path() );
|
||||
}
|
||||
void renderSolid( Renderer& renderer, const VolumeTest& volume ) const {
|
||||
m_contained.renderSolid( renderer, volume, Instance::localToWorld(), getSelectable().isSelected() );
|
||||
}
|
||||
void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const {
|
||||
m_contained.renderWireframe( renderer, volume, Instance::localToWorld(), getSelectable().isSelected() );
|
||||
}
|
||||
|
||||
void evaluateTransform(){
|
||||
if ( getType() == TRANSFORM_PRIMITIVE ) {
|
||||
m_contained.translate( getTranslation() );
|
||||
m_contained.rotate( getRotation() );
|
||||
}
|
||||
}
|
||||
void applyTransform(){
|
||||
m_contained.revertTransform();
|
||||
evaluateTransform();
|
||||
m_contained.freezeTransform();
|
||||
}
|
||||
typedef MemberCaller<EclassModelInstance, &EclassModelInstance::applyTransform> ApplyTransformCaller;
|
||||
};
|
||||
|
||||
class EclassModelNode :
|
||||
public scene::Node::Symbiot,
|
||||
public scene::Instantiable,
|
||||
public scene::Cloneable,
|
||||
public scene::Traversable::Observer
|
||||
public scene::Node::Symbiot,
|
||||
public scene::Instantiable,
|
||||
public scene::Cloneable,
|
||||
public scene::Traversable::Observer
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
NodeTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
NodeStaticCast<EclassModelNode, scene::Instantiable>::install(m_casts);
|
||||
NodeStaticCast<EclassModelNode, scene::Cloneable>::install(m_casts);
|
||||
NodeContainedCast<EclassModelNode, scene::Traversable>::install(m_casts);
|
||||
NodeContainedCast<EclassModelNode, Snappable>::install(m_casts);
|
||||
NodeContainedCast<EclassModelNode, TransformNode>::install(m_casts);
|
||||
NodeContainedCast<EclassModelNode, Entity>::install(m_casts);
|
||||
NodeContainedCast<EclassModelNode, Nameable>::install(m_casts);
|
||||
NodeContainedCast<EclassModelNode, Namespaced>::install(m_casts);
|
||||
NodeContainedCast<EclassModelNode, ModelSkin>::install(m_casts);
|
||||
}
|
||||
NodeTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
scene::Node m_node;
|
||||
InstanceSet m_instances;
|
||||
EclassModel m_contained;
|
||||
|
||||
void construct()
|
||||
{
|
||||
m_contained.attach(this);
|
||||
}
|
||||
void destroy()
|
||||
{
|
||||
m_contained.detach(this);
|
||||
}
|
||||
|
||||
class TypeCasts
|
||||
{
|
||||
NodeTypeCastTable m_casts;
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
scene::Traversable& get(NullType<scene::Traversable>)
|
||||
{
|
||||
return m_contained.getTraversable();
|
||||
}
|
||||
Snappable& get(NullType<Snappable>)
|
||||
{
|
||||
return m_contained;
|
||||
}
|
||||
TransformNode& get(NullType<TransformNode>)
|
||||
{
|
||||
return m_contained.getTransformNode();
|
||||
}
|
||||
Entity& get(NullType<Entity>)
|
||||
{
|
||||
return m_contained.getEntity();
|
||||
}
|
||||
Nameable& get(NullType<Nameable>)
|
||||
{
|
||||
return m_contained.getNameable();
|
||||
}
|
||||
Namespaced& get(NullType<Namespaced>)
|
||||
{
|
||||
return m_contained.getNamespaced();
|
||||
}
|
||||
ModelSkin& get(NullType<ModelSkin>)
|
||||
{
|
||||
return m_contained.getModelSkin();
|
||||
}
|
||||
|
||||
EclassModelNode(EntityClass* eclass) :
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSetEvaluateTransform<EclassModelInstance>::Caller(m_instances))
|
||||
{
|
||||
construct();
|
||||
}
|
||||
EclassModelNode(const EclassModelNode& other) :
|
||||
scene::Node::Symbiot(other),
|
||||
scene::Instantiable(other),
|
||||
scene::Cloneable(other),
|
||||
scene::Traversable::Observer(other),
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSetEvaluateTransform<EclassModelInstance>::Caller(m_instances))
|
||||
{
|
||||
construct();
|
||||
}
|
||||
~EclassModelNode()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
scene::Node& node()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
void insert(scene::Node& child)
|
||||
{
|
||||
m_instances.insert(child);
|
||||
}
|
||||
void erase(scene::Node& child)
|
||||
{
|
||||
m_instances.erase(child);
|
||||
}
|
||||
|
||||
scene::Node& clone() const
|
||||
{
|
||||
return (new EclassModelNode(*this))->node();
|
||||
}
|
||||
|
||||
scene::Instance* create(const scene::Path& path, scene::Instance* parent)
|
||||
{
|
||||
return new EclassModelInstance(path, parent, m_contained);
|
||||
}
|
||||
void forEachInstance(const scene::Instantiable::Visitor& visitor)
|
||||
{
|
||||
m_instances.forEachInstance(visitor);
|
||||
}
|
||||
void insert(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
|
||||
{
|
||||
m_instances.insert(observer, path, instance);
|
||||
}
|
||||
scene::Instance* erase(scene::Instantiable::Observer* observer, const scene::Path& path)
|
||||
{
|
||||
return m_instances.erase(observer, path);
|
||||
}
|
||||
TypeCasts(){
|
||||
NodeStaticCast<EclassModelNode, scene::Instantiable>::install( m_casts );
|
||||
NodeStaticCast<EclassModelNode, scene::Cloneable>::install( m_casts );
|
||||
NodeContainedCast<EclassModelNode, scene::Traversable>::install( m_casts );
|
||||
NodeContainedCast<EclassModelNode, Snappable>::install( m_casts );
|
||||
NodeContainedCast<EclassModelNode, TransformNode>::install( m_casts );
|
||||
NodeContainedCast<EclassModelNode, Entity>::install( m_casts );
|
||||
NodeContainedCast<EclassModelNode, Nameable>::install( m_casts );
|
||||
NodeContainedCast<EclassModelNode, Namespaced>::install( m_casts );
|
||||
NodeContainedCast<EclassModelNode, ModelSkin>::install( m_casts );
|
||||
}
|
||||
NodeTypeCastTable& get(){
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
scene::Node& New_EclassModel(EntityClass* eclass)
|
||||
{
|
||||
return (new EclassModelNode(eclass))->node();
|
||||
|
||||
scene::Node m_node;
|
||||
InstanceSet m_instances;
|
||||
EclassModel m_contained;
|
||||
|
||||
void construct(){
|
||||
m_contained.attach( this );
|
||||
}
|
||||
void destroy(){
|
||||
m_contained.detach( this );
|
||||
}
|
||||
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
scene::Traversable& get( NullType<scene::Traversable>){
|
||||
return m_contained.getTraversable();
|
||||
}
|
||||
Snappable& get( NullType<Snappable>){
|
||||
return m_contained;
|
||||
}
|
||||
TransformNode& get( NullType<TransformNode>){
|
||||
return m_contained.getTransformNode();
|
||||
}
|
||||
Entity& get( NullType<Entity>){
|
||||
return m_contained.getEntity();
|
||||
}
|
||||
Nameable& get( NullType<Nameable>){
|
||||
return m_contained.getNameable();
|
||||
}
|
||||
Namespaced& get( NullType<Namespaced>){
|
||||
return m_contained.getNamespaced();
|
||||
}
|
||||
ModelSkin& get( NullType<ModelSkin>){
|
||||
return m_contained.getModelSkin();
|
||||
}
|
||||
|
||||
EclassModelNode( EntityClass* eclass ) :
|
||||
m_node( this, this, StaticTypeCasts::instance().get() ),
|
||||
m_contained( eclass, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform<EclassModelInstance>::Caller( m_instances ) ){
|
||||
construct();
|
||||
}
|
||||
EclassModelNode( const EclassModelNode& other ) :
|
||||
scene::Node::Symbiot( other ),
|
||||
scene::Instantiable( other ),
|
||||
scene::Cloneable( other ),
|
||||
scene::Traversable::Observer( other ),
|
||||
m_node( this, this, StaticTypeCasts::instance().get() ),
|
||||
m_contained( other.m_contained, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform<EclassModelInstance>::Caller( m_instances ) ){
|
||||
construct();
|
||||
}
|
||||
~EclassModelNode(){
|
||||
destroy();
|
||||
}
|
||||
void release(){
|
||||
delete this;
|
||||
}
|
||||
scene::Node& node(){
|
||||
return m_node;
|
||||
}
|
||||
|
||||
void insert( scene::Node& child ){
|
||||
m_instances.insert( child );
|
||||
}
|
||||
void erase( scene::Node& child ){
|
||||
m_instances.erase( child );
|
||||
}
|
||||
|
||||
scene::Node& clone() const {
|
||||
return ( new EclassModelNode( *this ) )->node();
|
||||
}
|
||||
|
||||
scene::Instance* create( const scene::Path& path, scene::Instance* parent ){
|
||||
return new EclassModelInstance( path, parent, m_contained );
|
||||
}
|
||||
void forEachInstance( const scene::Instantiable::Visitor& visitor ){
|
||||
m_instances.forEachInstance( visitor );
|
||||
}
|
||||
void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){
|
||||
m_instances.insert( observer, path, instance );
|
||||
}
|
||||
scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){
|
||||
return m_instances.erase( observer, path );
|
||||
}
|
||||
};
|
||||
|
||||
scene::Node& New_EclassModel( EntityClass* eclass ){
|
||||
return ( new EclassModelNode( eclass ) )->node();
|
||||
}
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_ECLASSMODEL_H)
|
||||
#if !defined( INCLUDED_ECLASSMODEL_H )
|
||||
#define INCLUDED_ECLASSMODEL_H
|
||||
|
||||
namespace scene
|
||||
{
|
||||
class Node;
|
||||
class Node;
|
||||
};
|
||||
class EntityClass;
|
||||
|
||||
scene::Node& New_EclassModel(EntityClass* eclass);
|
||||
scene::Node& New_EclassModel( EntityClass* eclass );
|
||||
|
||||
#include "entity.h"
|
||||
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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 "entity.h"
|
||||
|
||||
@@ -48,73 +48,62 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
EGameType g_gameType;
|
||||
|
||||
inline scene::Node& entity_for_eclass(EntityClass* eclass)
|
||||
{
|
||||
if((string_compare_nocase_n(eclass->name(), "misc_", 5) == 0 && string_equal_nocase(eclass->name() + string_length(eclass->name()) - 5, "model")) // misc_*model (also misc_model) // TODO make classname_* wrapper functions for this
|
||||
|| classname_equal(eclass->name(), "model_static"))
|
||||
{
|
||||
return New_MiscModel(eclass);
|
||||
}
|
||||
else if(classname_equal(eclass->name(), "light")
|
||||
|| classname_equal(eclass->name(), "lightJunior"))
|
||||
{
|
||||
return New_Light(eclass);
|
||||
}
|
||||
if(!eclass->fixedsize)
|
||||
{
|
||||
if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
return New_Doom3Group(eclass);
|
||||
}
|
||||
else
|
||||
{
|
||||
return New_Group(eclass);
|
||||
}
|
||||
}
|
||||
else if(!string_empty(eclass->modelpath()))
|
||||
{
|
||||
return New_EclassModel(eclass);
|
||||
}
|
||||
else
|
||||
{
|
||||
return New_GenericEntity(eclass);
|
||||
}
|
||||
inline scene::Node& entity_for_eclass( EntityClass* eclass ){
|
||||
if ( ( string_compare_nocase_n( eclass->name(), "misc_", 5 ) == 0 && string_equal_nocase( eclass->name() + string_length( eclass->name() ) - 5, "model" ) ) // misc_*model (also misc_model) // TODO make classname_* wrapper functions for this
|
||||
|| classname_equal( eclass->name(), "model_static" ) ) {
|
||||
return New_MiscModel( eclass );
|
||||
}
|
||||
else if ( classname_equal( eclass->name(), "light" )
|
||||
|| classname_equal( eclass->name(), "lightJunior" ) ) {
|
||||
return New_Light( eclass );
|
||||
}
|
||||
if ( !eclass->fixedsize ) {
|
||||
if ( g_gameType == eGameTypeDoom3 ) {
|
||||
return New_Doom3Group( eclass );
|
||||
}
|
||||
else
|
||||
{
|
||||
return New_Group( eclass );
|
||||
}
|
||||
}
|
||||
else if ( !string_empty( eclass->modelpath() ) ) {
|
||||
return New_EclassModel( eclass );
|
||||
}
|
||||
else
|
||||
{
|
||||
return New_GenericEntity( eclass );
|
||||
}
|
||||
}
|
||||
|
||||
void Entity_setName(Entity& entity, const char* name)
|
||||
{
|
||||
entity.setKeyValue("name", name);
|
||||
void Entity_setName( Entity& entity, const char* name ){
|
||||
entity.setKeyValue( "name", name );
|
||||
}
|
||||
typedef ReferenceCaller1<Entity, const char*, Entity_setName> EntitySetNameCaller;
|
||||
|
||||
inline Namespaced* Node_getNamespaced(scene::Node& node)
|
||||
{
|
||||
return NodeTypeCast<Namespaced>::cast(node);
|
||||
inline Namespaced* Node_getNamespaced( scene::Node& node ){
|
||||
return NodeTypeCast<Namespaced>::cast( node );
|
||||
}
|
||||
|
||||
inline scene::Node& node_for_eclass(EntityClass* eclass)
|
||||
{
|
||||
scene::Node& node = entity_for_eclass(eclass);
|
||||
Node_getEntity(node)->setKeyValue("classname", eclass->name());
|
||||
inline scene::Node& node_for_eclass( EntityClass* eclass ){
|
||||
scene::Node& node = entity_for_eclass( eclass );
|
||||
Node_getEntity( node )->setKeyValue( "classname", eclass->name() );
|
||||
|
||||
if(g_gameType == eGameTypeDoom3
|
||||
&& string_not_empty(eclass->name())
|
||||
&& !string_equal(eclass->name(), "worldspawn")
|
||||
&& !string_equal(eclass->name(), "UNKNOWN_CLASS"))
|
||||
{
|
||||
char buffer[1024];
|
||||
strcpy(buffer, eclass->name());
|
||||
strcat(buffer, "_1");
|
||||
GlobalNamespace().makeUnique(buffer, EntitySetNameCaller(*Node_getEntity(node)));
|
||||
}
|
||||
if ( g_gameType == eGameTypeDoom3
|
||||
&& string_not_empty( eclass->name() )
|
||||
&& !string_equal( eclass->name(), "worldspawn" )
|
||||
&& !string_equal( eclass->name(), "UNKNOWN_CLASS" ) ) {
|
||||
char buffer[1024];
|
||||
strcpy( buffer, eclass->name() );
|
||||
strcat( buffer, "_1" );
|
||||
GlobalNamespace().makeUnique( buffer, EntitySetNameCaller( *Node_getEntity( node ) ) );
|
||||
}
|
||||
|
||||
Namespaced* namespaced = Node_getNamespaced(node);
|
||||
if(namespaced != 0)
|
||||
{
|
||||
namespaced->setNamespace(GlobalNamespace());
|
||||
}
|
||||
Namespaced* namespaced = Node_getNamespaced( node );
|
||||
if ( namespaced != 0 ) {
|
||||
namespaced->setNamespace( GlobalNamespace() );
|
||||
}
|
||||
|
||||
return node;
|
||||
return node;
|
||||
}
|
||||
|
||||
EntityCreator::KeyValueChangedFunc EntityKeyValues::m_entityKeyValueChanged = 0;
|
||||
@@ -129,281 +118,246 @@ bool g_lightRadii = false;
|
||||
class ConnectEntities
|
||||
{
|
||||
public:
|
||||
Entity* m_e1;
|
||||
Entity* m_e2;
|
||||
int m_index;
|
||||
ConnectEntities(Entity* e1, Entity* e2, int index) : m_e1(e1), m_e2(e2), m_index(index)
|
||||
{
|
||||
}
|
||||
const char *keyname()
|
||||
{
|
||||
StringOutputStream key(16);
|
||||
if(m_index <= 0)
|
||||
return "target";
|
||||
if(m_index == 1)
|
||||
return "killtarget";
|
||||
key << "target" << m_index;
|
||||
return key.c_str();
|
||||
}
|
||||
void connect(const char* name)
|
||||
{
|
||||
m_e1->setKeyValue(keyname(), name);
|
||||
m_e2->setKeyValue("targetname", name);
|
||||
}
|
||||
typedef MemberCaller1<ConnectEntities, const char*, &ConnectEntities::connect> ConnectCaller;
|
||||
Entity* m_e1;
|
||||
Entity* m_e2;
|
||||
int m_index;
|
||||
ConnectEntities( Entity* e1, Entity* e2, int index ) : m_e1( e1 ), m_e2( e2 ), m_index( index ){
|
||||
}
|
||||
const char *keyname(){
|
||||
StringOutputStream key( 16 );
|
||||
if ( m_index <= 0 ) {
|
||||
return "target";
|
||||
}
|
||||
if ( m_index == 1 ) {
|
||||
return "killtarget";
|
||||
}
|
||||
key << "target" << m_index;
|
||||
return key.c_str();
|
||||
}
|
||||
void connect( const char* name ){
|
||||
m_e1->setKeyValue( keyname(), name );
|
||||
m_e2->setKeyValue( "targetname", name );
|
||||
}
|
||||
typedef MemberCaller1<ConnectEntities, const char*, &ConnectEntities::connect> ConnectCaller;
|
||||
};
|
||||
|
||||
inline Entity* ScenePath_getEntity(const scene::Path& path)
|
||||
{
|
||||
Entity* entity = Node_getEntity(path.top());
|
||||
if(entity == 0)
|
||||
{
|
||||
entity = Node_getEntity(path.parent());
|
||||
}
|
||||
return entity;
|
||||
inline Entity* ScenePath_getEntity( const scene::Path& path ){
|
||||
Entity* entity = Node_getEntity( path.top() );
|
||||
if ( entity == 0 ) {
|
||||
entity = Node_getEntity( path.parent() );
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
class Quake3EntityCreator : public EntityCreator
|
||||
{
|
||||
public:
|
||||
scene::Node& createEntity(EntityClass* eclass)
|
||||
{
|
||||
return node_for_eclass(eclass);
|
||||
}
|
||||
void setKeyValueChangedFunc(KeyValueChangedFunc func)
|
||||
{
|
||||
EntityKeyValues::setKeyValueChangedFunc(func);
|
||||
}
|
||||
void setCounter(Counter* counter)
|
||||
{
|
||||
EntityKeyValues::setCounter(counter);
|
||||
}
|
||||
void connectEntities(const scene::Path& path, const scene::Path& targetPath, int index)
|
||||
{
|
||||
Entity* e1 = ScenePath_getEntity(path);
|
||||
Entity* e2 = ScenePath_getEntity(targetPath);
|
||||
scene::Node& createEntity( EntityClass* eclass ){
|
||||
return node_for_eclass( eclass );
|
||||
}
|
||||
void setKeyValueChangedFunc( KeyValueChangedFunc func ){
|
||||
EntityKeyValues::setKeyValueChangedFunc( func );
|
||||
}
|
||||
void setCounter( Counter* counter ){
|
||||
EntityKeyValues::setCounter( counter );
|
||||
}
|
||||
void connectEntities( const scene::Path& path, const scene::Path& targetPath, int index ){
|
||||
Entity* e1 = ScenePath_getEntity( path );
|
||||
Entity* e2 = ScenePath_getEntity( targetPath );
|
||||
|
||||
if(e1 == 0 || e2 == 0)
|
||||
{
|
||||
globalErrorStream() << "entityConnectSelected: both of the selected instances must be an entity\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if(e1 == e2)
|
||||
{
|
||||
globalErrorStream() << "entityConnectSelected: the selected instances must not both be from the same entity\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
UndoableCommand undo("entityConnectSelected");
|
||||
|
||||
if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
StringOutputStream key(16);
|
||||
if(index >= 0)
|
||||
{
|
||||
key << "target";
|
||||
if(index != 0)
|
||||
{
|
||||
key << index;
|
||||
}
|
||||
e1->setKeyValue(key.c_str(), e2->getKeyValue("name"));
|
||||
key.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
for(unsigned int i = 0; ; ++i)
|
||||
{
|
||||
key << "target";
|
||||
if(i != 0)
|
||||
{
|
||||
key << i;
|
||||
}
|
||||
const char* value = e1->getKeyValue(key.c_str());
|
||||
if(string_empty(value))
|
||||
{
|
||||
e1->setKeyValue(key.c_str(), e2->getKeyValue("name"));
|
||||
break;
|
||||
}
|
||||
key.clear();
|
||||
if ( e1 == 0 || e2 == 0 ) {
|
||||
globalErrorStream() << "entityConnectSelected: both of the selected instances must be an entity\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ConnectEntities connector(e1, e2, index);
|
||||
const char* value = e2->getKeyValue("targetname");
|
||||
if(!string_empty(value))
|
||||
{
|
||||
connector.connect(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* type = e2->getKeyValue("classname");
|
||||
if(string_empty(type))
|
||||
{
|
||||
type = "t";
|
||||
}
|
||||
StringOutputStream key(64);
|
||||
key << type << "1";
|
||||
GlobalNamespace().makeUnique(key.c_str(), ConnectEntities::ConnectCaller(connector));
|
||||
}
|
||||
}
|
||||
|
||||
SceneChangeNotify();
|
||||
}
|
||||
void setLightRadii(bool lightRadii)
|
||||
{
|
||||
g_lightRadii = lightRadii;
|
||||
}
|
||||
bool getLightRadii()
|
||||
{
|
||||
return g_lightRadii;
|
||||
}
|
||||
void setShowNames(bool showNames)
|
||||
{
|
||||
g_showNames = showNames;
|
||||
}
|
||||
bool getShowNames()
|
||||
{
|
||||
return g_showNames;
|
||||
}
|
||||
void setShowAngles(bool showAngles)
|
||||
{
|
||||
g_showAngles = showAngles;
|
||||
}
|
||||
bool getShowAngles()
|
||||
{
|
||||
return g_showAngles;
|
||||
}
|
||||
if ( e1 == e2 ) {
|
||||
globalErrorStream() << "entityConnectSelected: the selected instances must not both be from the same entity\n";
|
||||
return;
|
||||
}
|
||||
|
||||
void printStatistics() const
|
||||
{
|
||||
StringPool_analyse(EntityKeyValues::getPool());
|
||||
}
|
||||
|
||||
UndoableCommand undo( "entityConnectSelected" );
|
||||
|
||||
if ( g_gameType == eGameTypeDoom3 ) {
|
||||
StringOutputStream key( 16 );
|
||||
if ( index >= 0 ) {
|
||||
key << "target";
|
||||
if ( index != 0 ) {
|
||||
key << index;
|
||||
}
|
||||
e1->setKeyValue( key.c_str(), e2->getKeyValue( "name" ) );
|
||||
key.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( unsigned int i = 0; ; ++i )
|
||||
{
|
||||
key << "target";
|
||||
if ( i != 0 ) {
|
||||
key << i;
|
||||
}
|
||||
const char* value = e1->getKeyValue( key.c_str() );
|
||||
if ( string_empty( value ) ) {
|
||||
e1->setKeyValue( key.c_str(), e2->getKeyValue( "name" ) );
|
||||
break;
|
||||
}
|
||||
key.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ConnectEntities connector( e1, e2, index );
|
||||
const char* value = e2->getKeyValue( "targetname" );
|
||||
if ( !string_empty( value ) ) {
|
||||
connector.connect( value );
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* type = e2->getKeyValue( "classname" );
|
||||
if ( string_empty( type ) ) {
|
||||
type = "t";
|
||||
}
|
||||
StringOutputStream key( 64 );
|
||||
key << type << "1";
|
||||
GlobalNamespace().makeUnique( key.c_str(), ConnectEntities::ConnectCaller( connector ) );
|
||||
}
|
||||
}
|
||||
|
||||
SceneChangeNotify();
|
||||
}
|
||||
void setLightRadii( bool lightRadii ){
|
||||
g_lightRadii = lightRadii;
|
||||
}
|
||||
bool getLightRadii(){
|
||||
return g_lightRadii;
|
||||
}
|
||||
void setShowNames( bool showNames ){
|
||||
g_showNames = showNames;
|
||||
}
|
||||
bool getShowNames(){
|
||||
return g_showNames;
|
||||
}
|
||||
void setShowAngles( bool showAngles ){
|
||||
g_showAngles = showAngles;
|
||||
}
|
||||
bool getShowAngles(){
|
||||
return g_showAngles;
|
||||
}
|
||||
|
||||
void printStatistics() const {
|
||||
StringPool_analyse( EntityKeyValues::getPool() );
|
||||
}
|
||||
};
|
||||
|
||||
Quake3EntityCreator g_Quake3EntityCreator;
|
||||
|
||||
EntityCreator& GetEntityCreator()
|
||||
{
|
||||
return g_Quake3EntityCreator;
|
||||
EntityCreator& GetEntityCreator(){
|
||||
return g_Quake3EntityCreator;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class filter_entity_classname : public EntityFilter
|
||||
{
|
||||
const char* m_classname;
|
||||
const char* m_classname;
|
||||
public:
|
||||
filter_entity_classname(const char* classname) : m_classname(classname)
|
||||
{
|
||||
}
|
||||
bool filter(const Entity& entity) const
|
||||
{
|
||||
return string_equal(entity.getKeyValue("classname"), m_classname);
|
||||
}
|
||||
filter_entity_classname( const char* classname ) : m_classname( classname ){
|
||||
}
|
||||
bool filter( const Entity& entity ) const {
|
||||
return string_equal( entity.getKeyValue( "classname" ), m_classname );
|
||||
}
|
||||
};
|
||||
|
||||
class filter_entity_classgroup : public EntityFilter
|
||||
{
|
||||
const char* m_classgroup;
|
||||
std::size_t m_length;
|
||||
const char* m_classgroup;
|
||||
std::size_t m_length;
|
||||
public:
|
||||
filter_entity_classgroup(const char* classgroup) : m_classgroup(classgroup), m_length(string_length(m_classgroup))
|
||||
{
|
||||
}
|
||||
bool filter(const Entity& entity) const
|
||||
{
|
||||
return string_equal_n(entity.getKeyValue("classname"), m_classgroup, m_length);
|
||||
}
|
||||
filter_entity_classgroup( const char* classgroup ) : m_classgroup( classgroup ), m_length( string_length( m_classgroup ) ){
|
||||
}
|
||||
bool filter( const Entity& entity ) const {
|
||||
return string_equal_n( entity.getKeyValue( "classname" ), m_classgroup, m_length );
|
||||
}
|
||||
};
|
||||
|
||||
filter_entity_classname g_filter_entity_world("worldspawn");
|
||||
filter_entity_classname g_filter_entity_func_group("func_group");
|
||||
filter_entity_classname g_filter_entity_light("light");
|
||||
filter_entity_classname g_filter_entity_misc_model("misc_model");
|
||||
filter_entity_classname g_filter_entity_misc_gamemodel("misc_gamemodel");
|
||||
filter_entity_classgroup g_filter_entity_trigger("trigger_");
|
||||
filter_entity_classgroup g_filter_entity_path("path_");
|
||||
filter_entity_classname g_filter_entity_world( "worldspawn" );
|
||||
filter_entity_classname g_filter_entity_func_group( "func_group" );
|
||||
filter_entity_classname g_filter_entity_light( "light" );
|
||||
filter_entity_classname g_filter_entity_misc_model( "misc_model" );
|
||||
filter_entity_classname g_filter_entity_misc_gamemodel( "misc_gamemodel" );
|
||||
filter_entity_classgroup g_filter_entity_trigger( "trigger_" );
|
||||
filter_entity_classgroup g_filter_entity_path( "path_" );
|
||||
|
||||
class filter_entity_doom3model : public EntityFilter
|
||||
{
|
||||
public:
|
||||
bool filter(const Entity& entity) const
|
||||
{
|
||||
return string_equal(entity.getKeyValue("classname"), "func_static")
|
||||
&& !string_equal(entity.getKeyValue("model"), entity.getKeyValue("name"));
|
||||
}
|
||||
bool filter( const Entity& entity ) const {
|
||||
return string_equal( entity.getKeyValue( "classname" ), "func_static" )
|
||||
&& !string_equal( entity.getKeyValue( "model" ), entity.getKeyValue( "name" ) );
|
||||
}
|
||||
};
|
||||
|
||||
filter_entity_doom3model g_filter_entity_doom3model;
|
||||
|
||||
|
||||
void Entity_InitFilters()
|
||||
{
|
||||
add_entity_filter(g_filter_entity_world, EXCLUDE_WORLD);
|
||||
add_entity_filter(g_filter_entity_func_group, EXCLUDE_WORLD);
|
||||
add_entity_filter(g_filter_entity_world, EXCLUDE_ENT, true);
|
||||
add_entity_filter(g_filter_entity_trigger, EXCLUDE_TRIGGERS);
|
||||
add_entity_filter(g_filter_entity_misc_model, EXCLUDE_MODELS);
|
||||
add_entity_filter(g_filter_entity_misc_gamemodel, EXCLUDE_MODELS);
|
||||
add_entity_filter(g_filter_entity_doom3model, EXCLUDE_MODELS);
|
||||
add_entity_filter(g_filter_entity_light, EXCLUDE_LIGHTS);
|
||||
add_entity_filter(g_filter_entity_path, EXCLUDE_PATHS);
|
||||
void Entity_InitFilters(){
|
||||
add_entity_filter( g_filter_entity_world, EXCLUDE_WORLD );
|
||||
add_entity_filter( g_filter_entity_func_group, EXCLUDE_WORLD );
|
||||
add_entity_filter( g_filter_entity_world, EXCLUDE_ENT, true );
|
||||
add_entity_filter( g_filter_entity_trigger, EXCLUDE_TRIGGERS );
|
||||
add_entity_filter( g_filter_entity_misc_model, EXCLUDE_MODELS );
|
||||
add_entity_filter( g_filter_entity_misc_gamemodel, EXCLUDE_MODELS );
|
||||
add_entity_filter( g_filter_entity_doom3model, EXCLUDE_MODELS );
|
||||
add_entity_filter( g_filter_entity_light, EXCLUDE_LIGHTS );
|
||||
add_entity_filter( g_filter_entity_path, EXCLUDE_PATHS );
|
||||
}
|
||||
|
||||
|
||||
#include "preferencesystem.h"
|
||||
|
||||
void Entity_Construct(EGameType gameType)
|
||||
{
|
||||
g_gameType = gameType;
|
||||
if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
g_targetable_nameKey = "name";
|
||||
void Entity_Construct( EGameType gameType ){
|
||||
g_gameType = gameType;
|
||||
if ( g_gameType == eGameTypeDoom3 ) {
|
||||
g_targetable_nameKey = "name";
|
||||
|
||||
Static<KeyIsName>::instance().m_keyIsName = keyIsNameDoom3;
|
||||
Static<KeyIsName>::instance().m_nameKey = "name";
|
||||
}
|
||||
else
|
||||
{
|
||||
Static<KeyIsName>::instance().m_keyIsName = keyIsNameQuake3;
|
||||
Static<KeyIsName>::instance().m_nameKey = "targetname";
|
||||
}
|
||||
Static<KeyIsName>::instance().m_keyIsName = keyIsNameDoom3;
|
||||
Static<KeyIsName>::instance().m_nameKey = "name";
|
||||
}
|
||||
else
|
||||
{
|
||||
Static<KeyIsName>::instance().m_keyIsName = keyIsNameQuake3;
|
||||
Static<KeyIsName>::instance().m_nameKey = "targetname";
|
||||
}
|
||||
|
||||
GlobalPreferenceSystem().registerPreference("SI_ShowNames", BoolImportStringCaller(g_showNames), BoolExportStringCaller(g_showNames));
|
||||
GlobalPreferenceSystem().registerPreference("SI_ShowAngles", BoolImportStringCaller(g_showAngles), BoolExportStringCaller(g_showAngles));
|
||||
GlobalPreferenceSystem().registerPreference("NewLightStyle", BoolImportStringCaller(g_newLightDraw), BoolExportStringCaller(g_newLightDraw));
|
||||
GlobalPreferenceSystem().registerPreference("LightRadiuses", BoolImportStringCaller(g_lightRadii), BoolExportStringCaller(g_lightRadii));
|
||||
GlobalPreferenceSystem().registerPreference( "SI_ShowNames", BoolImportStringCaller( g_showNames ), BoolExportStringCaller( g_showNames ) );
|
||||
GlobalPreferenceSystem().registerPreference( "SI_ShowAngles", BoolImportStringCaller( g_showAngles ), BoolExportStringCaller( g_showAngles ) );
|
||||
GlobalPreferenceSystem().registerPreference( "NewLightStyle", BoolImportStringCaller( g_newLightDraw ), BoolExportStringCaller( g_newLightDraw ) );
|
||||
GlobalPreferenceSystem().registerPreference( "LightRadiuses", BoolImportStringCaller( g_lightRadii ), BoolExportStringCaller( g_lightRadii ) );
|
||||
|
||||
Entity_InitFilters();
|
||||
LightType lightType = LIGHTTYPE_DEFAULT;
|
||||
if(g_gameType == eGameTypeRTCW)
|
||||
{
|
||||
lightType = LIGHTTYPE_RTCW;
|
||||
}
|
||||
else if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
lightType = LIGHTTYPE_DOOM3;
|
||||
}
|
||||
Light_Construct(lightType);
|
||||
MiscModel_construct();
|
||||
Doom3Group_construct();
|
||||
Entity_InitFilters();
|
||||
LightType lightType = LIGHTTYPE_DEFAULT;
|
||||
if ( g_gameType == eGameTypeRTCW ) {
|
||||
lightType = LIGHTTYPE_RTCW;
|
||||
}
|
||||
else if ( g_gameType == eGameTypeDoom3 ) {
|
||||
lightType = LIGHTTYPE_DOOM3;
|
||||
}
|
||||
Light_Construct( lightType );
|
||||
MiscModel_construct();
|
||||
Doom3Group_construct();
|
||||
|
||||
RenderablePivot::StaticShader::instance() = GlobalShaderCache().capture("$PIVOT");
|
||||
RenderablePivot::StaticShader::instance() = GlobalShaderCache().capture( "$PIVOT" );
|
||||
|
||||
GlobalShaderCache().attachRenderable(StaticRenderableConnectionLines::instance());
|
||||
GlobalShaderCache().attachRenderable( StaticRenderableConnectionLines::instance() );
|
||||
}
|
||||
|
||||
void Entity_Destroy()
|
||||
{
|
||||
GlobalShaderCache().detachRenderable(StaticRenderableConnectionLines::instance());
|
||||
void Entity_Destroy(){
|
||||
GlobalShaderCache().detachRenderable( StaticRenderableConnectionLines::instance() );
|
||||
|
||||
GlobalShaderCache().release("$PIVOT");
|
||||
GlobalShaderCache().release( "$PIVOT" );
|
||||
|
||||
Doom3Group_destroy();
|
||||
MiscModel_destroy();
|
||||
Light_Destroy();
|
||||
Doom3Group_destroy();
|
||||
MiscModel_destroy();
|
||||
Light_Destroy();
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_ENTITY_H)
|
||||
#if !defined( INCLUDED_ENTITY_H )
|
||||
#define INCLUDED_ENTITY_H
|
||||
|
||||
class EntityCreator;
|
||||
@@ -27,15 +27,15 @@ EntityCreator& GetEntityCreator();
|
||||
|
||||
enum EGameType
|
||||
{
|
||||
eGameTypeQuake3,
|
||||
eGameTypeRTCW,
|
||||
eGameTypeDoom3,
|
||||
eGameTypeQuake3,
|
||||
eGameTypeRTCW,
|
||||
eGameTypeDoom3,
|
||||
};
|
||||
|
||||
extern EGameType g_gameType;
|
||||
|
||||
class FilterSystem;
|
||||
void Entity_Construct(EGameType gameType = eGameTypeQuake3);
|
||||
void Entity_Construct( EGameType gameType = eGameTypeQuake3 );
|
||||
void Entity_Destroy();
|
||||
|
||||
extern bool g_showNames;
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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 "filters.h"
|
||||
|
||||
@@ -27,46 +27,38 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
class EntityFilterWrapper : public Filter
|
||||
{
|
||||
bool m_active;
|
||||
bool m_invert;
|
||||
EntityFilter& m_filter;
|
||||
bool m_active;
|
||||
bool m_invert;
|
||||
EntityFilter& m_filter;
|
||||
public:
|
||||
EntityFilterWrapper(EntityFilter& filter, bool invert) : m_invert(invert), m_filter(filter)
|
||||
{
|
||||
}
|
||||
void setActive(bool active)
|
||||
{
|
||||
m_active = active;
|
||||
}
|
||||
bool active()
|
||||
{
|
||||
return m_active;
|
||||
}
|
||||
bool filter(const Entity& entity)
|
||||
{
|
||||
return m_invert ^ m_filter.filter(entity);
|
||||
}
|
||||
EntityFilterWrapper( EntityFilter& filter, bool invert ) : m_invert( invert ), m_filter( filter ){
|
||||
}
|
||||
void setActive( bool active ){
|
||||
m_active = active;
|
||||
}
|
||||
bool active(){
|
||||
return m_active;
|
||||
}
|
||||
bool filter( const Entity& entity ){
|
||||
return m_invert ^ m_filter.filter( entity );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef std::list<EntityFilterWrapper> EntityFilters;
|
||||
EntityFilters g_entityFilters;
|
||||
|
||||
void add_entity_filter(EntityFilter& filter, int mask, bool invert)
|
||||
{
|
||||
g_entityFilters.push_back(EntityFilterWrapper(filter, invert));
|
||||
GlobalFilterSystem().addFilter(g_entityFilters.back(), mask);
|
||||
void add_entity_filter( EntityFilter& filter, int mask, bool invert ){
|
||||
g_entityFilters.push_back( EntityFilterWrapper( filter, invert ) );
|
||||
GlobalFilterSystem().addFilter( g_entityFilters.back(), mask );
|
||||
}
|
||||
|
||||
bool entity_filtered(Entity& entity)
|
||||
{
|
||||
for(EntityFilters::iterator i = g_entityFilters.begin(); i != g_entityFilters.end(); ++i)
|
||||
{
|
||||
if((*i).active() && (*i).filter(entity))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
bool entity_filtered( Entity& entity ){
|
||||
for ( EntityFilters::iterator i = g_entityFilters.begin(); i != g_entityFilters.end(); ++i )
|
||||
{
|
||||
if ( ( *i ).active() && ( *i ).filter( entity ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_FILTERS_H)
|
||||
#if !defined( INCLUDED_FILTERS_H )
|
||||
#define INCLUDED_FILTERS_H
|
||||
|
||||
#include "ifilter.h"
|
||||
@@ -32,51 +32,44 @@ class Entity;
|
||||
class EntityFilter
|
||||
{
|
||||
public:
|
||||
virtual bool filter(const Entity& entity) const = 0;
|
||||
virtual bool filter( const Entity& entity ) const = 0;
|
||||
};
|
||||
|
||||
bool entity_filtered(Entity& entity);
|
||||
void add_entity_filter(EntityFilter& filter, int mask, bool invert = false);
|
||||
bool entity_filtered( Entity& entity );
|
||||
void add_entity_filter( EntityFilter& filter, int mask, bool invert = false );
|
||||
|
||||
class ClassnameFilter : public Filterable
|
||||
{
|
||||
scene::Node& m_node;
|
||||
scene::Node& m_node;
|
||||
public:
|
||||
Entity& m_entity;
|
||||
Entity& m_entity;
|
||||
|
||||
ClassnameFilter(Entity& entity, scene::Node& node) : m_node(node), m_entity(entity)
|
||||
{
|
||||
}
|
||||
~ClassnameFilter()
|
||||
{
|
||||
}
|
||||
ClassnameFilter( Entity& entity, scene::Node& node ) : m_node( node ), m_entity( entity ){
|
||||
}
|
||||
~ClassnameFilter(){
|
||||
}
|
||||
|
||||
void instanceAttach()
|
||||
{
|
||||
GlobalFilterSystem().registerFilterable(*this);
|
||||
}
|
||||
void instanceDetach()
|
||||
{
|
||||
GlobalFilterSystem().unregisterFilterable(*this);
|
||||
}
|
||||
void instanceAttach(){
|
||||
GlobalFilterSystem().registerFilterable( *this );
|
||||
}
|
||||
void instanceDetach(){
|
||||
GlobalFilterSystem().unregisterFilterable( *this );
|
||||
}
|
||||
|
||||
void updateFiltered()
|
||||
{
|
||||
if(entity_filtered(m_entity))
|
||||
{
|
||||
m_node.enable(scene::Node::eFiltered);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_node.disable(scene::Node::eFiltered);
|
||||
}
|
||||
}
|
||||
void updateFiltered(){
|
||||
if ( entity_filtered( m_entity ) ) {
|
||||
m_node.enable( scene::Node::eFiltered );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_node.disable( scene::Node::eFiltered );
|
||||
}
|
||||
}
|
||||
|
||||
void classnameChanged(const char* value)
|
||||
{
|
||||
updateFiltered();
|
||||
}
|
||||
typedef MemberCaller1<ClassnameFilter, const char*, &ClassnameFilter::classnameChanged> ClassnameChangedCaller;
|
||||
void classnameChanged( const char* value ){
|
||||
updateFiltered();
|
||||
}
|
||||
typedef MemberCaller1<ClassnameFilter, const char*, &ClassnameFilter::classnameChanged> ClassnameChangedCaller;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
///\file
|
||||
///\brief Represents any entity which has a fixed size specified in its entity-definition and does not display a model (e.g. info_player_start).
|
||||
@@ -53,444 +53,382 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
class RenderableArrow : public OpenGLRenderable
|
||||
{
|
||||
const Vector3& m_origin;
|
||||
const Vector3& m_angles;
|
||||
const Vector3& m_origin;
|
||||
const Vector3& m_angles;
|
||||
|
||||
public:
|
||||
RenderableArrow(const Vector3& origin, const Vector3& angles)
|
||||
: m_origin(origin), m_angles(angles)
|
||||
{
|
||||
}
|
||||
RenderableArrow( const Vector3& origin, const Vector3& angles )
|
||||
: m_origin( origin ), m_angles( angles ){
|
||||
}
|
||||
|
||||
void render(RenderStateFlags state) const
|
||||
{
|
||||
Matrix4 mat = matrix4_rotation_for_euler_xyz_degrees(m_angles);
|
||||
arrow_draw(m_origin, matrix4_transformed_direction(mat, Vector3(1, 0, 0)), matrix4_transformed_direction(mat, Vector3(0, 1, 0)), matrix4_transformed_direction(mat, Vector3(0, 0, 1)));
|
||||
}
|
||||
void render( RenderStateFlags state ) const {
|
||||
Matrix4 mat = matrix4_rotation_for_euler_xyz_degrees( m_angles );
|
||||
arrow_draw( m_origin, matrix4_transformed_direction( mat, Vector3( 1, 0, 0 ) ), matrix4_transformed_direction( mat, Vector3( 0, 1, 0 ) ), matrix4_transformed_direction( mat, Vector3( 0, 0, 1 ) ) );
|
||||
}
|
||||
};
|
||||
|
||||
inline void read_aabb(AABB& aabb, const EntityClass& eclass)
|
||||
{
|
||||
aabb = aabb_for_minmax(eclass.mins, eclass.maxs);
|
||||
inline void read_aabb( AABB& aabb, const EntityClass& eclass ){
|
||||
aabb = aabb_for_minmax( eclass.mins, eclass.maxs );
|
||||
}
|
||||
|
||||
|
||||
class GenericEntity :
|
||||
public Cullable,
|
||||
public Bounded,
|
||||
public Snappable
|
||||
public Cullable,
|
||||
public Bounded,
|
||||
public Snappable
|
||||
{
|
||||
EntityKeyValues m_entity;
|
||||
KeyObserverMap m_keyObservers;
|
||||
MatrixTransform m_transform;
|
||||
EntityKeyValues m_entity;
|
||||
KeyObserverMap m_keyObservers;
|
||||
MatrixTransform m_transform;
|
||||
|
||||
OriginKey m_originKey;
|
||||
Vector3 m_origin;
|
||||
AnglesKey m_anglesKey;
|
||||
Vector3 m_angles;
|
||||
OriginKey m_originKey;
|
||||
Vector3 m_origin;
|
||||
AnglesKey m_anglesKey;
|
||||
Vector3 m_angles;
|
||||
|
||||
ClassnameFilter m_filter;
|
||||
NamedEntity m_named;
|
||||
NameKeys m_nameKeys;
|
||||
ClassnameFilter m_filter;
|
||||
NamedEntity m_named;
|
||||
NameKeys m_nameKeys;
|
||||
|
||||
AABB m_aabb_local;
|
||||
AABB m_aabb_local;
|
||||
|
||||
RenderableArrow m_arrow;
|
||||
RenderableSolidAABB m_aabb_solid;
|
||||
RenderableWireframeAABB m_aabb_wire;
|
||||
RenderableNamedEntity m_renderName;
|
||||
RenderableArrow m_arrow;
|
||||
RenderableSolidAABB m_aabb_solid;
|
||||
RenderableWireframeAABB m_aabb_wire;
|
||||
RenderableNamedEntity m_renderName;
|
||||
|
||||
Callback m_transformChanged;
|
||||
Callback m_evaluateTransform;
|
||||
Callback m_transformChanged;
|
||||
Callback m_evaluateTransform;
|
||||
|
||||
void construct()
|
||||
{
|
||||
read_aabb(m_aabb_local, m_entity.getEntityClass());
|
||||
void construct(){
|
||||
read_aabb( m_aabb_local, m_entity.getEntityClass() );
|
||||
|
||||
m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter));
|
||||
m_keyObservers.insert(Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named));
|
||||
m_keyObservers.insert("angle", AnglesKey::AngleChangedCaller(m_anglesKey));
|
||||
m_keyObservers.insert("angles", AnglesKey::AnglesChangedCaller(m_anglesKey));
|
||||
m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey));
|
||||
}
|
||||
m_keyObservers.insert( "classname", ClassnameFilter::ClassnameChangedCaller( m_filter ) );
|
||||
m_keyObservers.insert( Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller( m_named ) );
|
||||
m_keyObservers.insert( "angle", AnglesKey::AngleChangedCaller( m_anglesKey ) );
|
||||
m_keyObservers.insert( "angles", AnglesKey::AnglesChangedCaller( m_anglesKey ) );
|
||||
m_keyObservers.insert( "origin", OriginKey::OriginChangedCaller( m_originKey ) );
|
||||
}
|
||||
|
||||
// vc 2k5 compiler fix
|
||||
// vc 2k5 compiler fix
|
||||
#if _MSC_VER >= 1400
|
||||
public:
|
||||
public:
|
||||
#endif
|
||||
|
||||
void updateTransform()
|
||||
{
|
||||
m_transform.localToParent() = g_matrix4_identity;
|
||||
matrix4_translate_by_vec3(m_transform.localToParent(), m_origin);
|
||||
m_transformChanged();
|
||||
}
|
||||
typedef MemberCaller<GenericEntity, &GenericEntity::updateTransform> UpdateTransformCaller;
|
||||
void originChanged()
|
||||
{
|
||||
m_origin = m_originKey.m_origin;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<GenericEntity, &GenericEntity::originChanged> OriginChangedCaller;
|
||||
void anglesChanged()
|
||||
{
|
||||
m_angles = m_anglesKey.m_angles;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<GenericEntity, &GenericEntity::anglesChanged> AnglesChangedCaller;
|
||||
void updateTransform(){
|
||||
m_transform.localToParent() = g_matrix4_identity;
|
||||
matrix4_translate_by_vec3( m_transform.localToParent(), m_origin );
|
||||
m_transformChanged();
|
||||
}
|
||||
typedef MemberCaller<GenericEntity, &GenericEntity::updateTransform> UpdateTransformCaller;
|
||||
void originChanged(){
|
||||
m_origin = m_originKey.m_origin;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<GenericEntity, &GenericEntity::originChanged> OriginChangedCaller;
|
||||
void anglesChanged(){
|
||||
m_angles = m_anglesKey.m_angles;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<GenericEntity, &GenericEntity::anglesChanged> AnglesChangedCaller;
|
||||
public:
|
||||
|
||||
GenericEntity(EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
|
||||
m_entity(eclass),
|
||||
m_originKey(OriginChangedCaller(*this)),
|
||||
m_origin(ORIGINKEY_IDENTITY),
|
||||
m_anglesKey(AnglesChangedCaller(*this)),
|
||||
m_angles(ANGLESKEY_IDENTITY),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_arrow(m_aabb_local.origin, m_angles),
|
||||
m_aabb_solid(m_aabb_local),
|
||||
m_aabb_wire(m_aabb_local),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_transformChanged(transformChanged),
|
||||
m_evaluateTransform(evaluateTransform)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
GenericEntity(const GenericEntity& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
|
||||
m_entity(other.m_entity),
|
||||
m_originKey(OriginChangedCaller(*this)),
|
||||
m_origin(ORIGINKEY_IDENTITY),
|
||||
m_anglesKey(AnglesChangedCaller(*this)),
|
||||
m_angles(ANGLESKEY_IDENTITY),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_arrow(m_aabb_local.origin, m_angles),
|
||||
m_aabb_solid(m_aabb_local),
|
||||
m_aabb_wire(m_aabb_local),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_transformChanged(transformChanged),
|
||||
m_evaluateTransform(evaluateTransform)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
GenericEntity( EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) :
|
||||
m_entity( eclass ),
|
||||
m_originKey( OriginChangedCaller( *this ) ),
|
||||
m_origin( ORIGINKEY_IDENTITY ),
|
||||
m_anglesKey( AnglesChangedCaller( *this ) ),
|
||||
m_angles( ANGLESKEY_IDENTITY ),
|
||||
m_filter( m_entity, node ),
|
||||
m_named( m_entity ),
|
||||
m_nameKeys( m_entity ),
|
||||
m_arrow( m_aabb_local.origin, m_angles ),
|
||||
m_aabb_solid( m_aabb_local ),
|
||||
m_aabb_wire( m_aabb_local ),
|
||||
m_renderName( m_named, g_vector3_identity ),
|
||||
m_transformChanged( transformChanged ),
|
||||
m_evaluateTransform( evaluateTransform ){
|
||||
construct();
|
||||
}
|
||||
GenericEntity( const GenericEntity& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) :
|
||||
m_entity( other.m_entity ),
|
||||
m_originKey( OriginChangedCaller( *this ) ),
|
||||
m_origin( ORIGINKEY_IDENTITY ),
|
||||
m_anglesKey( AnglesChangedCaller( *this ) ),
|
||||
m_angles( ANGLESKEY_IDENTITY ),
|
||||
m_filter( m_entity, node ),
|
||||
m_named( m_entity ),
|
||||
m_nameKeys( m_entity ),
|
||||
m_arrow( m_aabb_local.origin, m_angles ),
|
||||
m_aabb_solid( m_aabb_local ),
|
||||
m_aabb_wire( m_aabb_local ),
|
||||
m_renderName( m_named, g_vector3_identity ),
|
||||
m_transformChanged( transformChanged ),
|
||||
m_evaluateTransform( evaluateTransform ){
|
||||
construct();
|
||||
}
|
||||
|
||||
InstanceCounter m_instanceCounter;
|
||||
void instanceAttach(const scene::Path& path)
|
||||
{
|
||||
if(++m_instanceCounter.m_count == 1)
|
||||
{
|
||||
m_filter.instanceAttach();
|
||||
m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_entity.attach(m_keyObservers);
|
||||
}
|
||||
}
|
||||
void instanceDetach(const scene::Path& path)
|
||||
{
|
||||
if(--m_instanceCounter.m_count == 0)
|
||||
{
|
||||
m_entity.detach(m_keyObservers);
|
||||
m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_filter.instanceDetach();
|
||||
}
|
||||
}
|
||||
InstanceCounter m_instanceCounter;
|
||||
void instanceAttach( const scene::Path& path ){
|
||||
if ( ++m_instanceCounter.m_count == 1 ) {
|
||||
m_filter.instanceAttach();
|
||||
m_entity.instanceAttach( path_find_mapfile( path.begin(), path.end() ) );
|
||||
m_entity.attach( m_keyObservers );
|
||||
}
|
||||
}
|
||||
void instanceDetach( const scene::Path& path ){
|
||||
if ( --m_instanceCounter.m_count == 0 ) {
|
||||
m_entity.detach( m_keyObservers );
|
||||
m_entity.instanceDetach( path_find_mapfile( path.begin(), path.end() ) );
|
||||
m_filter.instanceDetach();
|
||||
}
|
||||
}
|
||||
|
||||
EntityKeyValues& getEntity()
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
const EntityKeyValues& getEntity() const
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
EntityKeyValues& getEntity(){
|
||||
return m_entity;
|
||||
}
|
||||
const EntityKeyValues& getEntity() const {
|
||||
return m_entity;
|
||||
}
|
||||
|
||||
Namespaced& getNamespaced()
|
||||
{
|
||||
return m_nameKeys;
|
||||
}
|
||||
Nameable& getNameable()
|
||||
{
|
||||
return m_named;
|
||||
}
|
||||
TransformNode& getTransformNode()
|
||||
{
|
||||
return m_transform;
|
||||
}
|
||||
Namespaced& getNamespaced(){
|
||||
return m_nameKeys;
|
||||
}
|
||||
Nameable& getNameable(){
|
||||
return m_named;
|
||||
}
|
||||
TransformNode& getTransformNode(){
|
||||
return m_transform;
|
||||
}
|
||||
|
||||
const AABB& localAABB() const
|
||||
{
|
||||
return m_aabb_local;
|
||||
}
|
||||
const AABB& localAABB() const {
|
||||
return m_aabb_local;
|
||||
}
|
||||
|
||||
VolumeIntersectionValue intersectVolume(const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
return volume.TestAABB(localAABB(), localToWorld);
|
||||
}
|
||||
VolumeIntersectionValue intersectVolume( const VolumeTest& volume, const Matrix4& localToWorld ) const {
|
||||
return volume.TestAABB( localAABB(), localToWorld );
|
||||
}
|
||||
|
||||
void renderArrow(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
if(g_showAngles)
|
||||
{
|
||||
renderer.addRenderable(m_arrow, localToWorld);
|
||||
}
|
||||
}
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
renderer.SetState(m_entity.getEntityClass().m_state_fill, Renderer::eFullMaterials);
|
||||
renderer.addRenderable(m_aabb_solid, localToWorld);
|
||||
renderArrow(renderer, volume, localToWorld);
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
|
||||
renderer.addRenderable(m_aabb_wire, localToWorld);
|
||||
renderArrow(renderer, volume, localToWorld);
|
||||
if(g_showNames)
|
||||
{
|
||||
renderer.addRenderable(m_renderName, localToWorld);
|
||||
}
|
||||
}
|
||||
void renderArrow( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
|
||||
if ( g_showAngles ) {
|
||||
renderer.addRenderable( m_arrow, localToWorld );
|
||||
}
|
||||
}
|
||||
void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
|
||||
renderer.SetState( m_entity.getEntityClass().m_state_fill, Renderer::eFullMaterials );
|
||||
renderer.addRenderable( m_aabb_solid, localToWorld );
|
||||
renderArrow( renderer, volume, localToWorld );
|
||||
}
|
||||
void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
|
||||
renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly );
|
||||
renderer.addRenderable( m_aabb_wire, localToWorld );
|
||||
renderArrow( renderer, volume, localToWorld );
|
||||
if ( g_showNames ) {
|
||||
renderer.addRenderable( m_renderName, localToWorld );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void testSelect(Selector& selector, SelectionTest& test, const Matrix4& localToWorld)
|
||||
{
|
||||
test.BeginMesh(localToWorld);
|
||||
void testSelect( Selector& selector, SelectionTest& test, const Matrix4& localToWorld ){
|
||||
test.BeginMesh( localToWorld );
|
||||
|
||||
SelectionIntersection best;
|
||||
aabb_testselect(m_aabb_local, test, best);
|
||||
if(best.valid())
|
||||
{
|
||||
selector.addIntersection(best);
|
||||
}
|
||||
}
|
||||
SelectionIntersection best;
|
||||
aabb_testselect( m_aabb_local, test, best );
|
||||
if ( best.valid() ) {
|
||||
selector.addIntersection( best );
|
||||
}
|
||||
}
|
||||
|
||||
void translate(const Vector3& translation)
|
||||
{
|
||||
m_origin = origin_translated(m_origin, translation);
|
||||
}
|
||||
void rotate(const Quaternion& rotation)
|
||||
{
|
||||
m_angles = angles_rotated(m_angles, rotation);
|
||||
}
|
||||
void snapto(float snap)
|
||||
{
|
||||
m_originKey.m_origin = origin_snapped(m_originKey.m_origin, snap);
|
||||
m_originKey.write(&m_entity);
|
||||
}
|
||||
void revertTransform()
|
||||
{
|
||||
m_origin = m_originKey.m_origin;
|
||||
m_angles = m_anglesKey.m_angles;
|
||||
}
|
||||
void freezeTransform()
|
||||
{
|
||||
m_originKey.m_origin = m_origin;
|
||||
m_originKey.write(&m_entity);
|
||||
m_anglesKey.m_angles = m_angles;
|
||||
m_anglesKey.write(&m_entity);
|
||||
}
|
||||
void transformChanged()
|
||||
{
|
||||
revertTransform();
|
||||
m_evaluateTransform();
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<GenericEntity, &GenericEntity::transformChanged> TransformChangedCaller;
|
||||
void translate( const Vector3& translation ){
|
||||
m_origin = origin_translated( m_origin, translation );
|
||||
}
|
||||
void rotate( const Quaternion& rotation ){
|
||||
m_angles = angles_rotated( m_angles, rotation );
|
||||
}
|
||||
void snapto( float snap ){
|
||||
m_originKey.m_origin = origin_snapped( m_originKey.m_origin, snap );
|
||||
m_originKey.write( &m_entity );
|
||||
}
|
||||
void revertTransform(){
|
||||
m_origin = m_originKey.m_origin;
|
||||
m_angles = m_anglesKey.m_angles;
|
||||
}
|
||||
void freezeTransform(){
|
||||
m_originKey.m_origin = m_origin;
|
||||
m_originKey.write( &m_entity );
|
||||
m_anglesKey.m_angles = m_angles;
|
||||
m_anglesKey.write( &m_entity );
|
||||
}
|
||||
void transformChanged(){
|
||||
revertTransform();
|
||||
m_evaluateTransform();
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<GenericEntity, &GenericEntity::transformChanged> TransformChangedCaller;
|
||||
};
|
||||
|
||||
class GenericEntityInstance :
|
||||
public TargetableInstance,
|
||||
public TransformModifier,
|
||||
public Renderable,
|
||||
public SelectionTestable
|
||||
public TargetableInstance,
|
||||
public TransformModifier,
|
||||
public Renderable,
|
||||
public SelectionTestable
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
InstanceTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
m_casts = TargetableInstance::StaticTypeCasts::instance().get();
|
||||
InstanceContainedCast<GenericEntityInstance, Bounded>::install(m_casts);
|
||||
InstanceContainedCast<GenericEntityInstance, Cullable>::install(m_casts);
|
||||
InstanceStaticCast<GenericEntityInstance, Renderable>::install(m_casts);
|
||||
InstanceStaticCast<GenericEntityInstance, SelectionTestable>::install(m_casts);
|
||||
InstanceStaticCast<GenericEntityInstance, Transformable>::install(m_casts);
|
||||
InstanceIdentityCast<GenericEntityInstance>::install(m_casts);
|
||||
}
|
||||
InstanceTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
class TypeCasts
|
||||
{
|
||||
InstanceTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts(){
|
||||
m_casts = TargetableInstance::StaticTypeCasts::instance().get();
|
||||
InstanceContainedCast<GenericEntityInstance, Bounded>::install( m_casts );
|
||||
InstanceContainedCast<GenericEntityInstance, Cullable>::install( m_casts );
|
||||
InstanceStaticCast<GenericEntityInstance, Renderable>::install( m_casts );
|
||||
InstanceStaticCast<GenericEntityInstance, SelectionTestable>::install( m_casts );
|
||||
InstanceStaticCast<GenericEntityInstance, Transformable>::install( m_casts );
|
||||
InstanceIdentityCast<GenericEntityInstance>::install( m_casts );
|
||||
}
|
||||
InstanceTypeCastTable& get(){
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
GenericEntity& m_contained;
|
||||
mutable AABB m_bounds;
|
||||
GenericEntity& m_contained;
|
||||
mutable AABB m_bounds;
|
||||
public:
|
||||
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
Bounded& get(NullType<Bounded>)
|
||||
{
|
||||
return m_contained;
|
||||
}
|
||||
Cullable& get(NullType<Cullable>)
|
||||
{
|
||||
return m_contained;
|
||||
}
|
||||
Bounded& get( NullType<Bounded>){
|
||||
return m_contained;
|
||||
}
|
||||
Cullable& get( NullType<Cullable>){
|
||||
return m_contained;
|
||||
}
|
||||
|
||||
STRING_CONSTANT(Name, "GenericEntityInstance");
|
||||
STRING_CONSTANT( Name, "GenericEntityInstance" );
|
||||
|
||||
GenericEntityInstance(const scene::Path& path, scene::Instance* parent, GenericEntity& contained) :
|
||||
TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this),
|
||||
TransformModifier(GenericEntity::TransformChangedCaller(contained), ApplyTransformCaller(*this)),
|
||||
m_contained(contained)
|
||||
{
|
||||
m_contained.instanceAttach(Instance::path());
|
||||
GenericEntityInstance( const scene::Path& path, scene::Instance* parent, GenericEntity& contained ) :
|
||||
TargetableInstance( path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this ),
|
||||
TransformModifier( GenericEntity::TransformChangedCaller( contained ), ApplyTransformCaller( *this ) ),
|
||||
m_contained( contained ){
|
||||
m_contained.instanceAttach( Instance::path() );
|
||||
|
||||
StaticRenderableConnectionLines::instance().attach(*this);
|
||||
}
|
||||
~GenericEntityInstance()
|
||||
{
|
||||
StaticRenderableConnectionLines::instance().detach(*this);
|
||||
StaticRenderableConnectionLines::instance().attach( *this );
|
||||
}
|
||||
~GenericEntityInstance(){
|
||||
StaticRenderableConnectionLines::instance().detach( *this );
|
||||
|
||||
m_contained.instanceDetach(Instance::path());
|
||||
}
|
||||
m_contained.instanceDetach( Instance::path() );
|
||||
}
|
||||
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderSolid(renderer, volume, Instance::localToWorld());
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderWireframe(renderer, volume, Instance::localToWorld());
|
||||
}
|
||||
void renderSolid( Renderer& renderer, const VolumeTest& volume ) const {
|
||||
m_contained.renderSolid( renderer, volume, Instance::localToWorld() );
|
||||
}
|
||||
void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const {
|
||||
m_contained.renderWireframe( renderer, volume, Instance::localToWorld() );
|
||||
}
|
||||
|
||||
void testSelect(Selector& selector, SelectionTest& test)
|
||||
{
|
||||
m_contained.testSelect(selector, test, Instance::localToWorld());
|
||||
}
|
||||
void testSelect( Selector& selector, SelectionTest& test ){
|
||||
m_contained.testSelect( selector, test, Instance::localToWorld() );
|
||||
}
|
||||
|
||||
void evaluateTransform()
|
||||
{
|
||||
if(getType() == TRANSFORM_PRIMITIVE)
|
||||
{
|
||||
m_contained.translate(getTranslation());
|
||||
m_contained.rotate(getRotation());
|
||||
}
|
||||
}
|
||||
void applyTransform()
|
||||
{
|
||||
m_contained.revertTransform();
|
||||
evaluateTransform();
|
||||
m_contained.freezeTransform();
|
||||
}
|
||||
typedef MemberCaller<GenericEntityInstance, &GenericEntityInstance::applyTransform> ApplyTransformCaller;
|
||||
void evaluateTransform(){
|
||||
if ( getType() == TRANSFORM_PRIMITIVE ) {
|
||||
m_contained.translate( getTranslation() );
|
||||
m_contained.rotate( getRotation() );
|
||||
}
|
||||
}
|
||||
void applyTransform(){
|
||||
m_contained.revertTransform();
|
||||
evaluateTransform();
|
||||
m_contained.freezeTransform();
|
||||
}
|
||||
typedef MemberCaller<GenericEntityInstance, &GenericEntityInstance::applyTransform> ApplyTransformCaller;
|
||||
};
|
||||
|
||||
class GenericEntityNode :
|
||||
public scene::Node::Symbiot,
|
||||
public scene::Instantiable,
|
||||
public scene::Cloneable
|
||||
public scene::Node::Symbiot,
|
||||
public scene::Instantiable,
|
||||
public scene::Cloneable
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
NodeTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
NodeStaticCast<GenericEntityNode, scene::Instantiable>::install(m_casts);
|
||||
NodeStaticCast<GenericEntityNode, scene::Cloneable>::install(m_casts);
|
||||
NodeContainedCast<GenericEntityNode, Snappable>::install(m_casts);
|
||||
NodeContainedCast<GenericEntityNode, TransformNode>::install(m_casts);
|
||||
NodeContainedCast<GenericEntityNode, Entity>::install(m_casts);
|
||||
NodeContainedCast<GenericEntityNode, Nameable>::install(m_casts);
|
||||
NodeContainedCast<GenericEntityNode, Namespaced>::install(m_casts);
|
||||
}
|
||||
NodeTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
InstanceSet m_instances;
|
||||
|
||||
scene::Node m_node;
|
||||
GenericEntity m_contained;
|
||||
|
||||
class TypeCasts
|
||||
{
|
||||
NodeTypeCastTable m_casts;
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
Snappable& get(NullType<Snappable>)
|
||||
{
|
||||
return m_contained;
|
||||
}
|
||||
TransformNode& get(NullType<TransformNode>)
|
||||
{
|
||||
return m_contained.getTransformNode();
|
||||
}
|
||||
Entity& get(NullType<Entity>)
|
||||
{
|
||||
return m_contained.getEntity();
|
||||
}
|
||||
Nameable& get(NullType<Nameable>)
|
||||
{
|
||||
return m_contained.getNameable();
|
||||
}
|
||||
Namespaced& get(NullType<Namespaced>)
|
||||
{
|
||||
return m_contained.getNamespaced();
|
||||
}
|
||||
|
||||
GenericEntityNode(EntityClass* eclass) :
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSetEvaluateTransform<GenericEntityInstance>::Caller(m_instances))
|
||||
{
|
||||
}
|
||||
GenericEntityNode(const GenericEntityNode& other) :
|
||||
scene::Node::Symbiot(other),
|
||||
scene::Instantiable(other),
|
||||
scene::Cloneable(other),
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSetEvaluateTransform<GenericEntityInstance>::Caller(m_instances))
|
||||
{
|
||||
}
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
scene::Node& node()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
scene::Node& clone() const
|
||||
{
|
||||
return (new GenericEntityNode(*this))->node();
|
||||
}
|
||||
|
||||
scene::Instance* create(const scene::Path& path, scene::Instance* parent)
|
||||
{
|
||||
return new GenericEntityInstance(path, parent, m_contained);
|
||||
}
|
||||
void forEachInstance(const scene::Instantiable::Visitor& visitor)
|
||||
{
|
||||
m_instances.forEachInstance(visitor);
|
||||
}
|
||||
void insert(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
|
||||
{
|
||||
m_instances.insert(observer, path, instance);
|
||||
}
|
||||
scene::Instance* erase(scene::Instantiable::Observer* observer, const scene::Path& path)
|
||||
{
|
||||
return m_instances.erase(observer, path);
|
||||
}
|
||||
TypeCasts(){
|
||||
NodeStaticCast<GenericEntityNode, scene::Instantiable>::install( m_casts );
|
||||
NodeStaticCast<GenericEntityNode, scene::Cloneable>::install( m_casts );
|
||||
NodeContainedCast<GenericEntityNode, Snappable>::install( m_casts );
|
||||
NodeContainedCast<GenericEntityNode, TransformNode>::install( m_casts );
|
||||
NodeContainedCast<GenericEntityNode, Entity>::install( m_casts );
|
||||
NodeContainedCast<GenericEntityNode, Nameable>::install( m_casts );
|
||||
NodeContainedCast<GenericEntityNode, Namespaced>::install( m_casts );
|
||||
}
|
||||
NodeTypeCastTable& get(){
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
scene::Node& New_GenericEntity(EntityClass* eclass)
|
||||
{
|
||||
return (new GenericEntityNode(eclass))->node();
|
||||
|
||||
InstanceSet m_instances;
|
||||
|
||||
scene::Node m_node;
|
||||
GenericEntity m_contained;
|
||||
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
Snappable& get( NullType<Snappable>){
|
||||
return m_contained;
|
||||
}
|
||||
TransformNode& get( NullType<TransformNode>){
|
||||
return m_contained.getTransformNode();
|
||||
}
|
||||
Entity& get( NullType<Entity>){
|
||||
return m_contained.getEntity();
|
||||
}
|
||||
Nameable& get( NullType<Nameable>){
|
||||
return m_contained.getNameable();
|
||||
}
|
||||
Namespaced& get( NullType<Namespaced>){
|
||||
return m_contained.getNamespaced();
|
||||
}
|
||||
|
||||
GenericEntityNode( EntityClass* eclass ) :
|
||||
m_node( this, this, StaticTypeCasts::instance().get() ),
|
||||
m_contained( eclass, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform<GenericEntityInstance>::Caller( m_instances ) ){
|
||||
}
|
||||
GenericEntityNode( const GenericEntityNode& other ) :
|
||||
scene::Node::Symbiot( other ),
|
||||
scene::Instantiable( other ),
|
||||
scene::Cloneable( other ),
|
||||
m_node( this, this, StaticTypeCasts::instance().get() ),
|
||||
m_contained( other.m_contained, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform<GenericEntityInstance>::Caller( m_instances ) ){
|
||||
}
|
||||
void release(){
|
||||
delete this;
|
||||
}
|
||||
scene::Node& node(){
|
||||
return m_node;
|
||||
}
|
||||
|
||||
scene::Node& clone() const {
|
||||
return ( new GenericEntityNode( *this ) )->node();
|
||||
}
|
||||
|
||||
scene::Instance* create( const scene::Path& path, scene::Instance* parent ){
|
||||
return new GenericEntityInstance( path, parent, m_contained );
|
||||
}
|
||||
void forEachInstance( const scene::Instantiable::Visitor& visitor ){
|
||||
m_instances.forEachInstance( visitor );
|
||||
}
|
||||
void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){
|
||||
m_instances.insert( observer, path, instance );
|
||||
}
|
||||
scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){
|
||||
return m_instances.erase( observer, path );
|
||||
}
|
||||
};
|
||||
|
||||
scene::Node& New_GenericEntity( EntityClass* eclass ){
|
||||
return ( new GenericEntityNode( eclass ) )->node();
|
||||
}
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GENERIC_H)
|
||||
#if !defined( INCLUDED_GENERIC_H )
|
||||
#define INCLUDED_GENERIC_H
|
||||
|
||||
scene::Node& New_GenericEntity(EntityClass* eclass);
|
||||
scene::Node& New_GenericEntity( EntityClass* eclass );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
///\file
|
||||
///\brief Represents any entity which does not have a fixed size specified in its entity-definition (except misc_model).
|
||||
@@ -51,471 +51,401 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
class Group
|
||||
{
|
||||
EntityKeyValues m_entity;
|
||||
KeyObserverMap m_keyObservers;
|
||||
MatrixTransform m_transform;
|
||||
TraversableNodeSet m_traverse;
|
||||
EntityKeyValues m_entity;
|
||||
KeyObserverMap m_keyObservers;
|
||||
MatrixTransform m_transform;
|
||||
TraversableNodeSet m_traverse;
|
||||
|
||||
ClassnameFilter m_filter;
|
||||
NamedEntity m_named;
|
||||
NameKeys m_nameKeys;
|
||||
ClassnameFilter m_filter;
|
||||
NamedEntity m_named;
|
||||
NameKeys m_nameKeys;
|
||||
|
||||
OriginKey m_originKey;
|
||||
Vector3 m_origin;
|
||||
OriginKey m_originKey;
|
||||
Vector3 m_origin;
|
||||
|
||||
RenderableNamedEntity m_renderName;
|
||||
mutable Vector3 m_name_origin;
|
||||
RenderableNamedEntity m_renderName;
|
||||
mutable Vector3 m_name_origin;
|
||||
|
||||
Callback m_transformChanged;
|
||||
Callback m_evaluateTransform;
|
||||
Callback m_transformChanged;
|
||||
Callback m_evaluateTransform;
|
||||
|
||||
void construct(){
|
||||
m_keyObservers.insert( "classname", ClassnameFilter::ClassnameChangedCaller( m_filter ) );
|
||||
m_keyObservers.insert( Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller( m_named ) );
|
||||
m_keyObservers.insert( "origin", OriginKey::OriginChangedCaller( m_originKey ) );
|
||||
}
|
||||
|
||||
void construct()
|
||||
{
|
||||
m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter));
|
||||
m_keyObservers.insert(Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named));
|
||||
m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey));
|
||||
}
|
||||
|
||||
public:
|
||||
Group(EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
|
||||
m_entity(eclass),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_originKey(OriginChangedCaller(*this)),
|
||||
m_origin(ORIGINKEY_IDENTITY),
|
||||
m_renderName(m_named, m_name_origin),
|
||||
m_name_origin(g_vector3_identity),
|
||||
m_transformChanged(transformChanged),
|
||||
m_evaluateTransform(evaluateTransform)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
Group(const Group& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
|
||||
m_entity(other.m_entity),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_originKey(OriginChangedCaller(*this)),
|
||||
m_origin(ORIGINKEY_IDENTITY),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_transformChanged(transformChanged),
|
||||
m_evaluateTransform(evaluateTransform)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
Group( EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) :
|
||||
m_entity( eclass ),
|
||||
m_filter( m_entity, node ),
|
||||
m_named( m_entity ),
|
||||
m_nameKeys( m_entity ),
|
||||
m_originKey( OriginChangedCaller( *this ) ),
|
||||
m_origin( ORIGINKEY_IDENTITY ),
|
||||
m_renderName( m_named, m_name_origin ),
|
||||
m_name_origin( g_vector3_identity ),
|
||||
m_transformChanged( transformChanged ),
|
||||
m_evaluateTransform( evaluateTransform ){
|
||||
construct();
|
||||
}
|
||||
Group( const Group& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) :
|
||||
m_entity( other.m_entity ),
|
||||
m_filter( m_entity, node ),
|
||||
m_named( m_entity ),
|
||||
m_nameKeys( m_entity ),
|
||||
m_originKey( OriginChangedCaller( *this ) ),
|
||||
m_origin( ORIGINKEY_IDENTITY ),
|
||||
m_renderName( m_named, g_vector3_identity ),
|
||||
m_transformChanged( transformChanged ),
|
||||
m_evaluateTransform( evaluateTransform ){
|
||||
construct();
|
||||
}
|
||||
|
||||
InstanceCounter m_instanceCounter;
|
||||
void instanceAttach(const scene::Path& path)
|
||||
{
|
||||
if(++m_instanceCounter.m_count == 1)
|
||||
{
|
||||
m_filter.instanceAttach();
|
||||
m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_traverse.instanceAttach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_entity.attach(m_keyObservers);
|
||||
}
|
||||
}
|
||||
void instanceDetach(const scene::Path& path)
|
||||
{
|
||||
if(--m_instanceCounter.m_count == 0)
|
||||
{
|
||||
m_entity.detach(m_keyObservers);
|
||||
m_traverse.instanceDetach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_filter.instanceDetach();
|
||||
}
|
||||
}
|
||||
InstanceCounter m_instanceCounter;
|
||||
void instanceAttach( const scene::Path& path ){
|
||||
if ( ++m_instanceCounter.m_count == 1 ) {
|
||||
m_filter.instanceAttach();
|
||||
m_entity.instanceAttach( path_find_mapfile( path.begin(), path.end() ) );
|
||||
m_traverse.instanceAttach( path_find_mapfile( path.begin(), path.end() ) );
|
||||
m_entity.attach( m_keyObservers );
|
||||
}
|
||||
}
|
||||
void instanceDetach( const scene::Path& path ){
|
||||
if ( --m_instanceCounter.m_count == 0 ) {
|
||||
m_entity.detach( m_keyObservers );
|
||||
m_traverse.instanceDetach( path_find_mapfile( path.begin(), path.end() ) );
|
||||
m_entity.instanceDetach( path_find_mapfile( path.begin(), path.end() ) );
|
||||
m_filter.instanceDetach();
|
||||
}
|
||||
}
|
||||
|
||||
EntityKeyValues& getEntity()
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
const EntityKeyValues& getEntity() const
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
EntityKeyValues& getEntity(){
|
||||
return m_entity;
|
||||
}
|
||||
const EntityKeyValues& getEntity() const {
|
||||
return m_entity;
|
||||
}
|
||||
|
||||
scene::Traversable& getTraversable()
|
||||
{
|
||||
return m_traverse;
|
||||
}
|
||||
Namespaced& getNamespaced()
|
||||
{
|
||||
return m_nameKeys;
|
||||
}
|
||||
Nameable& getNameable()
|
||||
{
|
||||
return m_named;
|
||||
}
|
||||
TransformNode& getTransformNode()
|
||||
{
|
||||
return m_transform;
|
||||
}
|
||||
scene::Traversable& getTraversable(){
|
||||
return m_traverse;
|
||||
}
|
||||
Namespaced& getNamespaced(){
|
||||
return m_nameKeys;
|
||||
}
|
||||
Nameable& getNameable(){
|
||||
return m_named;
|
||||
}
|
||||
TransformNode& getTransformNode(){
|
||||
return m_transform;
|
||||
}
|
||||
|
||||
void attach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_traverse.attach(observer);
|
||||
}
|
||||
void detach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_traverse.detach(observer);
|
||||
}
|
||||
void attach( scene::Traversable::Observer* observer ){
|
||||
m_traverse.attach( observer );
|
||||
}
|
||||
void detach( scene::Traversable::Observer* observer ){
|
||||
m_traverse.detach( observer );
|
||||
}
|
||||
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
|
||||
}
|
||||
void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
|
||||
renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly );
|
||||
}
|
||||
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, const AABB& childBounds) const
|
||||
{
|
||||
renderSolid(renderer, volume, localToWorld);
|
||||
void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, const AABB& childBounds ) const {
|
||||
renderSolid( renderer, volume, localToWorld );
|
||||
|
||||
if(g_showNames)
|
||||
{
|
||||
// don't draw the name for worldspawn
|
||||
if(!strcmp(m_entity.getEntityClass().name(), "worldspawn"))
|
||||
return;
|
||||
if ( g_showNames ) {
|
||||
// don't draw the name for worldspawn
|
||||
if ( !strcmp( m_entity.getEntityClass().name(), "worldspawn" ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// place name in the middle of the "children cloud"
|
||||
m_name_origin = childBounds.origin;
|
||||
// place name in the middle of the "children cloud"
|
||||
m_name_origin = childBounds.origin;
|
||||
|
||||
renderer.addRenderable(m_renderName, localToWorld);
|
||||
}
|
||||
}
|
||||
renderer.addRenderable( m_renderName, localToWorld );
|
||||
}
|
||||
}
|
||||
|
||||
void updateTransform()
|
||||
{
|
||||
m_transform.localToParent() = g_matrix4_identity;
|
||||
matrix4_translate_by_vec3(m_transform.localToParent(), m_origin);
|
||||
m_transformChanged();
|
||||
}
|
||||
typedef MemberCaller<Group, &Group::updateTransform> UpdateTransformCaller;
|
||||
void originChanged()
|
||||
{
|
||||
m_origin = m_originKey.m_origin;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<Group, &Group::originChanged> OriginChangedCaller;
|
||||
void updateTransform(){
|
||||
m_transform.localToParent() = g_matrix4_identity;
|
||||
matrix4_translate_by_vec3( m_transform.localToParent(), m_origin );
|
||||
m_transformChanged();
|
||||
}
|
||||
typedef MemberCaller<Group, &Group::updateTransform> UpdateTransformCaller;
|
||||
void originChanged(){
|
||||
m_origin = m_originKey.m_origin;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<Group, &Group::originChanged> OriginChangedCaller;
|
||||
|
||||
void translate(const Vector3& translation)
|
||||
{
|
||||
m_origin = origin_translated(m_origin, translation);
|
||||
}
|
||||
void translate( const Vector3& translation ){
|
||||
m_origin = origin_translated( m_origin, translation );
|
||||
}
|
||||
|
||||
void revertTransform()
|
||||
{
|
||||
m_origin = m_originKey.m_origin;
|
||||
}
|
||||
void freezeTransform()
|
||||
{
|
||||
m_originKey.m_origin = m_origin;
|
||||
m_originKey.write(&m_entity);
|
||||
}
|
||||
void transformChanged()
|
||||
{
|
||||
revertTransform();
|
||||
m_evaluateTransform();
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<Group, &Group::transformChanged> TransformChangedCaller;
|
||||
void revertTransform(){
|
||||
m_origin = m_originKey.m_origin;
|
||||
}
|
||||
void freezeTransform(){
|
||||
m_originKey.m_origin = m_origin;
|
||||
m_originKey.write( &m_entity );
|
||||
}
|
||||
void transformChanged(){
|
||||
revertTransform();
|
||||
m_evaluateTransform();
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<Group, &Group::transformChanged> TransformChangedCaller;
|
||||
};
|
||||
|
||||
#if 0
|
||||
class TransformableSetTranslation
|
||||
{
|
||||
Translation m_value;
|
||||
Translation m_value;
|
||||
public:
|
||||
TransformableSetTranslation(const Translation& value) : m_value(value)
|
||||
{
|
||||
}
|
||||
void operator()(Transformable& transformable) const
|
||||
{
|
||||
transformable.setTranslation(m_value);
|
||||
}
|
||||
TransformableSetTranslation( const Translation& value ) : m_value( value ){
|
||||
}
|
||||
void operator()( Transformable& transformable ) const {
|
||||
transformable.setTranslation( m_value );
|
||||
}
|
||||
};
|
||||
|
||||
class TransformableSetRotation
|
||||
{
|
||||
Rotation m_value;
|
||||
Rotation m_value;
|
||||
public:
|
||||
TransformableSetRotation(const Rotation& value) : m_value(value)
|
||||
{
|
||||
}
|
||||
void operator()(Transformable& transformable) const
|
||||
{
|
||||
transformable.setRotation(m_value);
|
||||
}
|
||||
TransformableSetRotation( const Rotation& value ) : m_value( value ){
|
||||
}
|
||||
void operator()( Transformable& transformable ) const {
|
||||
transformable.setRotation( m_value );
|
||||
}
|
||||
};
|
||||
|
||||
class TransformableSetScale
|
||||
{
|
||||
Scale m_value;
|
||||
Scale m_value;
|
||||
public:
|
||||
TransformableSetScale(const Scale& value) : m_value(value)
|
||||
{
|
||||
}
|
||||
void operator()(Transformable& transformable) const
|
||||
{
|
||||
transformable.setScale(m_value);
|
||||
}
|
||||
TransformableSetScale( const Scale& value ) : m_value( value ){
|
||||
}
|
||||
void operator()( Transformable& transformable ) const {
|
||||
transformable.setScale( m_value );
|
||||
}
|
||||
};
|
||||
|
||||
class TransformableSetType
|
||||
{
|
||||
TransformModifierType m_value;
|
||||
TransformModifierType m_value;
|
||||
public:
|
||||
TransformableSetType(const TransformModifierType& value) : m_value(value)
|
||||
{
|
||||
}
|
||||
void operator()(Transformable& transformable) const
|
||||
{
|
||||
transformable.setType(m_value);
|
||||
}
|
||||
TransformableSetType( const TransformModifierType& value ) : m_value( value ){
|
||||
}
|
||||
void operator()( Transformable& transformable ) const {
|
||||
transformable.setType( m_value );
|
||||
}
|
||||
};
|
||||
|
||||
class TransformableFreezeTransform
|
||||
{
|
||||
TransformModifierType m_value;
|
||||
TransformModifierType m_value;
|
||||
public:
|
||||
void operator()(Transformable& transformable) const
|
||||
{
|
||||
transformable.freezeTransform();
|
||||
}
|
||||
void operator()( Transformable& transformable ) const {
|
||||
transformable.freezeTransform();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Functor>
|
||||
inline void Scene_forEachChildTransformable(const Functor& functor, const scene::Path& path)
|
||||
{
|
||||
GlobalSceneGraph().traverse_subgraph(ChildInstanceWalker< InstanceApply<Transformable, Functor> >(functor), path);
|
||||
inline void Scene_forEachChildTransformable( const Functor& functor, const scene::Path& path ){
|
||||
GlobalSceneGraph().traverse_subgraph( ChildInstanceWalker< InstanceApply<Transformable, Functor> >( functor ), path );
|
||||
}
|
||||
#endif
|
||||
|
||||
class GroupInstance :
|
||||
public TargetableInstance,
|
||||
public TransformModifier,
|
||||
public TargetableInstance,
|
||||
public TransformModifier,
|
||||
#if 0
|
||||
public Transformable,
|
||||
public Transformable,
|
||||
#endif
|
||||
public Renderable
|
||||
public Renderable
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
InstanceTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
m_casts = TargetableInstance::StaticTypeCasts::instance().get();
|
||||
InstanceStaticCast<GroupInstance, Renderable>::install(m_casts);
|
||||
#if 0
|
||||
InstanceStaticCast<GroupInstance, Transformable>::install(m_casts);
|
||||
#endif
|
||||
}
|
||||
InstanceTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
Group& m_contained;
|
||||
class TypeCasts
|
||||
{
|
||||
InstanceTypeCastTable m_casts;
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
TypeCasts(){
|
||||
m_casts = TargetableInstance::StaticTypeCasts::instance().get();
|
||||
InstanceStaticCast<GroupInstance, Renderable>::install( m_casts );
|
||||
#if 0
|
||||
InstanceStaticCast<GroupInstance, Transformable>::install( m_casts );
|
||||
#endif
|
||||
}
|
||||
InstanceTypeCastTable& get(){
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
GroupInstance(const scene::Path& path, scene::Instance* parent, Group& group) :
|
||||
TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), group.getEntity(), *this),
|
||||
TransformModifier(Group::TransformChangedCaller(group), ApplyTransformCaller(*this)),
|
||||
m_contained(group)
|
||||
{
|
||||
m_contained.instanceAttach(Instance::path());
|
||||
StaticRenderableConnectionLines::instance().attach(*this);
|
||||
}
|
||||
~GroupInstance()
|
||||
{
|
||||
StaticRenderableConnectionLines::instance().detach(*this);
|
||||
m_contained.instanceDetach(Instance::path());
|
||||
}
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderSolid(renderer, volume, Instance::localToWorld());
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderWireframe(renderer, volume, Instance::localToWorld(), Instance::childBounds());
|
||||
}
|
||||
Group& m_contained;
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
STRING_CONSTANT(Name, "GroupInstance");
|
||||
GroupInstance( const scene::Path& path, scene::Instance* parent, Group& group ) :
|
||||
TargetableInstance( path, parent, this, StaticTypeCasts::instance().get(), group.getEntity(), *this ),
|
||||
TransformModifier( Group::TransformChangedCaller( group ), ApplyTransformCaller( *this ) ),
|
||||
m_contained( group ){
|
||||
m_contained.instanceAttach( Instance::path() );
|
||||
StaticRenderableConnectionLines::instance().attach( *this );
|
||||
}
|
||||
~GroupInstance(){
|
||||
StaticRenderableConnectionLines::instance().detach( *this );
|
||||
m_contained.instanceDetach( Instance::path() );
|
||||
}
|
||||
void renderSolid( Renderer& renderer, const VolumeTest& volume ) const {
|
||||
m_contained.renderSolid( renderer, volume, Instance::localToWorld() );
|
||||
}
|
||||
void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const {
|
||||
m_contained.renderWireframe( renderer, volume, Instance::localToWorld(), Instance::childBounds() );
|
||||
}
|
||||
|
||||
STRING_CONSTANT( Name, "GroupInstance" );
|
||||
|
||||
#if 0
|
||||
void setType(TransformModifierType type)
|
||||
{
|
||||
Scene_forEachChildTransformable(TransformableSetType(type), Instance::path());
|
||||
}
|
||||
void setTranslation(const Translation& value)
|
||||
{
|
||||
Scene_forEachChildTransformable(TransformableSetTranslation(value), Instance::path());
|
||||
}
|
||||
void setRotation(const Rotation& value)
|
||||
{
|
||||
Scene_forEachChildTransformable(TransformableSetRotation(value), Instance::path());
|
||||
}
|
||||
void setScale(const Scale& value)
|
||||
{
|
||||
Scene_forEachChildTransformable(TransformableSetScale(value), Instance::path());
|
||||
}
|
||||
void freezeTransform()
|
||||
{
|
||||
Scene_forEachChildTransformable(TransformableFreezeTransform(), Instance::path());
|
||||
}
|
||||
void setType( TransformModifierType type ){
|
||||
Scene_forEachChildTransformable( TransformableSetType( type ), Instance::path() );
|
||||
}
|
||||
void setTranslation( const Translation& value ){
|
||||
Scene_forEachChildTransformable( TransformableSetTranslation( value ), Instance::path() );
|
||||
}
|
||||
void setRotation( const Rotation& value ){
|
||||
Scene_forEachChildTransformable( TransformableSetRotation( value ), Instance::path() );
|
||||
}
|
||||
void setScale( const Scale& value ){
|
||||
Scene_forEachChildTransformable( TransformableSetScale( value ), Instance::path() );
|
||||
}
|
||||
void freezeTransform(){
|
||||
Scene_forEachChildTransformable( TransformableFreezeTransform(), Instance::path() );
|
||||
}
|
||||
|
||||
void evaluateTransform()
|
||||
{
|
||||
}
|
||||
void evaluateTransform(){
|
||||
}
|
||||
#endif
|
||||
|
||||
void evaluateTransform()
|
||||
{
|
||||
if(getType() == TRANSFORM_PRIMITIVE)
|
||||
{
|
||||
m_contained.translate(getTranslation());
|
||||
}
|
||||
}
|
||||
void applyTransform()
|
||||
{
|
||||
m_contained.revertTransform();
|
||||
evaluateTransform();
|
||||
m_contained.freezeTransform();
|
||||
}
|
||||
typedef MemberCaller<GroupInstance, &GroupInstance::applyTransform> ApplyTransformCaller;
|
||||
void evaluateTransform(){
|
||||
if ( getType() == TRANSFORM_PRIMITIVE ) {
|
||||
m_contained.translate( getTranslation() );
|
||||
}
|
||||
}
|
||||
void applyTransform(){
|
||||
m_contained.revertTransform();
|
||||
evaluateTransform();
|
||||
m_contained.freezeTransform();
|
||||
}
|
||||
typedef MemberCaller<GroupInstance, &GroupInstance::applyTransform> ApplyTransformCaller;
|
||||
};
|
||||
|
||||
class GroupNode :
|
||||
public scene::Node::Symbiot,
|
||||
public scene::Instantiable,
|
||||
public scene::Cloneable,
|
||||
public scene::Traversable::Observer
|
||||
public scene::Node::Symbiot,
|
||||
public scene::Instantiable,
|
||||
public scene::Cloneable,
|
||||
public scene::Traversable::Observer
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
NodeTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
NodeStaticCast<GroupNode, scene::Instantiable>::install(m_casts);
|
||||
NodeStaticCast<GroupNode, scene::Cloneable>::install(m_casts);
|
||||
NodeContainedCast<GroupNode, scene::Traversable>::install(m_casts);
|
||||
NodeContainedCast<GroupNode, TransformNode>::install(m_casts);
|
||||
NodeContainedCast<GroupNode, Entity>::install(m_casts);
|
||||
NodeContainedCast<GroupNode, Nameable>::install(m_casts);
|
||||
NodeContainedCast<GroupNode, Namespaced>::install(m_casts);
|
||||
}
|
||||
NodeTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
class TypeCasts
|
||||
{
|
||||
NodeTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts(){
|
||||
NodeStaticCast<GroupNode, scene::Instantiable>::install( m_casts );
|
||||
NodeStaticCast<GroupNode, scene::Cloneable>::install( m_casts );
|
||||
NodeContainedCast<GroupNode, scene::Traversable>::install( m_casts );
|
||||
NodeContainedCast<GroupNode, TransformNode>::install( m_casts );
|
||||
NodeContainedCast<GroupNode, Entity>::install( m_casts );
|
||||
NodeContainedCast<GroupNode, Nameable>::install( m_casts );
|
||||
NodeContainedCast<GroupNode, Namespaced>::install( m_casts );
|
||||
}
|
||||
NodeTypeCastTable& get(){
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
scene::Node m_node;
|
||||
InstanceSet m_instances;
|
||||
Group m_contained;
|
||||
scene::Node m_node;
|
||||
InstanceSet m_instances;
|
||||
Group m_contained;
|
||||
|
||||
void construct()
|
||||
{
|
||||
m_contained.attach(this);
|
||||
}
|
||||
void destroy()
|
||||
{
|
||||
m_contained.detach(this);
|
||||
}
|
||||
void construct(){
|
||||
m_contained.attach( this );
|
||||
}
|
||||
void destroy(){
|
||||
m_contained.detach( this );
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
scene::Traversable& get(NullType<scene::Traversable>)
|
||||
{
|
||||
return m_contained.getTraversable();
|
||||
}
|
||||
TransformNode& get(NullType<TransformNode>)
|
||||
{
|
||||
return m_contained.getTransformNode();
|
||||
}
|
||||
Entity& get(NullType<Entity>)
|
||||
{
|
||||
return m_contained.getEntity();
|
||||
}
|
||||
Nameable& get(NullType<Nameable>)
|
||||
{
|
||||
return m_contained.getNameable();
|
||||
}
|
||||
Namespaced& get(NullType<Namespaced>)
|
||||
{
|
||||
return m_contained.getNamespaced();
|
||||
}
|
||||
scene::Traversable& get( NullType<scene::Traversable>){
|
||||
return m_contained.getTraversable();
|
||||
}
|
||||
TransformNode& get( NullType<TransformNode>){
|
||||
return m_contained.getTransformNode();
|
||||
}
|
||||
Entity& get( NullType<Entity>){
|
||||
return m_contained.getEntity();
|
||||
}
|
||||
Nameable& get( NullType<Nameable>){
|
||||
return m_contained.getNameable();
|
||||
}
|
||||
Namespaced& get( NullType<Namespaced>){
|
||||
return m_contained.getNamespaced();
|
||||
}
|
||||
|
||||
GroupNode(EntityClass* eclass) :
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSetEvaluateTransform<GroupInstance>::Caller(m_instances))
|
||||
{
|
||||
construct();
|
||||
}
|
||||
GroupNode(const GroupNode& other) :
|
||||
scene::Node::Symbiot(other),
|
||||
scene::Instantiable(other),
|
||||
scene::Cloneable(other),
|
||||
scene::Traversable::Observer(other),
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSetEvaluateTransform<GroupInstance>::Caller(m_instances))
|
||||
{
|
||||
construct();
|
||||
}
|
||||
~GroupNode()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
GroupNode( EntityClass* eclass ) :
|
||||
m_node( this, this, StaticTypeCasts::instance().get() ),
|
||||
m_contained( eclass, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform<GroupInstance>::Caller( m_instances ) ){
|
||||
construct();
|
||||
}
|
||||
GroupNode( const GroupNode& other ) :
|
||||
scene::Node::Symbiot( other ),
|
||||
scene::Instantiable( other ),
|
||||
scene::Cloneable( other ),
|
||||
scene::Traversable::Observer( other ),
|
||||
m_node( this, this, StaticTypeCasts::instance().get() ),
|
||||
m_contained( other.m_contained, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform<GroupInstance>::Caller( m_instances ) ){
|
||||
construct();
|
||||
}
|
||||
~GroupNode(){
|
||||
destroy();
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
scene::Node& node()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
void release(){
|
||||
delete this;
|
||||
}
|
||||
scene::Node& node(){
|
||||
return m_node;
|
||||
}
|
||||
|
||||
scene::Node& clone() const
|
||||
{
|
||||
return (new GroupNode(*this))->node();
|
||||
}
|
||||
scene::Node& clone() const {
|
||||
return ( new GroupNode( *this ) )->node();
|
||||
}
|
||||
|
||||
void insert(scene::Node& child)
|
||||
{
|
||||
m_instances.insert(child);
|
||||
}
|
||||
void erase(scene::Node& child)
|
||||
{
|
||||
m_instances.erase(child);
|
||||
}
|
||||
void insert( scene::Node& child ){
|
||||
m_instances.insert( child );
|
||||
}
|
||||
void erase( scene::Node& child ){
|
||||
m_instances.erase( child );
|
||||
}
|
||||
|
||||
scene::Instance* create(const scene::Path& path, scene::Instance* parent)
|
||||
{
|
||||
return new GroupInstance(path, parent, m_contained);
|
||||
}
|
||||
void forEachInstance(const scene::Instantiable::Visitor& visitor)
|
||||
{
|
||||
m_instances.forEachInstance(visitor);
|
||||
}
|
||||
void insert(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
|
||||
{
|
||||
m_instances.insert(observer, path, instance);
|
||||
}
|
||||
scene::Instance* erase(scene::Instantiable::Observer* observer, const scene::Path& path)
|
||||
{
|
||||
return m_instances.erase(observer, path);
|
||||
}
|
||||
scene::Instance* create( const scene::Path& path, scene::Instance* parent ){
|
||||
return new GroupInstance( path, parent, m_contained );
|
||||
}
|
||||
void forEachInstance( const scene::Instantiable::Visitor& visitor ){
|
||||
m_instances.forEachInstance( visitor );
|
||||
}
|
||||
void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){
|
||||
m_instances.insert( observer, path, instance );
|
||||
}
|
||||
scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){
|
||||
return m_instances.erase( observer, path );
|
||||
}
|
||||
};
|
||||
|
||||
scene::Node& New_Group(EntityClass* eclass)
|
||||
{
|
||||
return (new GroupNode(eclass))->node();
|
||||
scene::Node& New_Group( EntityClass* eclass ){
|
||||
return ( new GroupNode( eclass ) )->node();
|
||||
}
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GROUP_H)
|
||||
#if !defined( INCLUDED_GROUP_H )
|
||||
#define INCLUDED_GROUP_H
|
||||
|
||||
scene::Node& New_Group(EntityClass* eclass);
|
||||
scene::Node& New_Group( EntityClass* eclass );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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 "keyobservers.h"
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_KEYOBSERVERS_H)
|
||||
#if !defined( INCLUDED_KEYOBSERVERS_H )
|
||||
#define INCLUDED_KEYOBSERVERS_H
|
||||
|
||||
#include "entitylib.h"
|
||||
@@ -27,27 +27,24 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
class KeyObserverMap : public Entity::Observer
|
||||
{
|
||||
typedef std::multimap<const char*, KeyObserver, RawStringLess> KeyObservers;
|
||||
KeyObservers m_keyObservers;
|
||||
typedef std::multimap<const char*, KeyObserver, RawStringLess> KeyObservers;
|
||||
KeyObservers m_keyObservers;
|
||||
public:
|
||||
void insert(const char* key, const KeyObserver& observer)
|
||||
{
|
||||
m_keyObservers.insert(KeyObservers::value_type(key, observer));
|
||||
}
|
||||
void insert(const char* key, EntityKeyValue& value)
|
||||
{
|
||||
for(KeyObservers::const_iterator i = m_keyObservers.find(key); i != m_keyObservers.end() && string_equal((*i).first, key); ++i)
|
||||
{
|
||||
value.attach((*i).second);
|
||||
}
|
||||
}
|
||||
void erase(const char* key, EntityKeyValue& value)
|
||||
{
|
||||
for(KeyObservers::const_iterator i = m_keyObservers.find(key); i != m_keyObservers.end() && string_equal((*i).first, key); ++i)
|
||||
{
|
||||
value.detach((*i).second);
|
||||
}
|
||||
}
|
||||
void insert( const char* key, const KeyObserver& observer ){
|
||||
m_keyObservers.insert( KeyObservers::value_type( key, observer ) );
|
||||
}
|
||||
void insert( const char* key, EntityKeyValue& value ){
|
||||
for ( KeyObservers::const_iterator i = m_keyObservers.find( key ); i != m_keyObservers.end() && string_equal( ( *i ).first, key ); ++i )
|
||||
{
|
||||
value.attach( ( *i ).second );
|
||||
}
|
||||
}
|
||||
void erase( const char* key, EntityKeyValue& value ){
|
||||
for ( KeyObservers::const_iterator i = m_keyObservers.find( key ); i != m_keyObservers.end() && string_equal( ( *i ).first, key ); ++i )
|
||||
{
|
||||
value.detach( ( *i ).second );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,41 +1,41 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_LIGHT_H)
|
||||
#if !defined( INCLUDED_LIGHT_H )
|
||||
#define INCLUDED_LIGHT_H
|
||||
|
||||
namespace scene
|
||||
{
|
||||
class Node;
|
||||
class Node;
|
||||
};
|
||||
class EntityClass;
|
||||
|
||||
scene::Node& New_Light(EntityClass* eclass);
|
||||
scene::Node& New_Light( EntityClass* eclass );
|
||||
enum LightType
|
||||
{
|
||||
LIGHTTYPE_DEFAULT,
|
||||
LIGHTTYPE_RTCW,
|
||||
LIGHTTYPE_DOOM3
|
||||
LIGHTTYPE_DEFAULT,
|
||||
LIGHTTYPE_RTCW,
|
||||
LIGHTTYPE_DOOM3
|
||||
};
|
||||
void Light_Construct(LightType lightType);
|
||||
void Light_Construct( LightType lightType );
|
||||
void Light_Destroy();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
///\file
|
||||
///\brief Represents the Quake3 misc_model entity.
|
||||
@@ -51,426 +51,362 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#include "entity.h"
|
||||
|
||||
class MiscModel :
|
||||
public Snappable
|
||||
public Snappable
|
||||
{
|
||||
EntityKeyValues m_entity;
|
||||
KeyObserverMap m_keyObservers;
|
||||
MatrixTransform m_transform;
|
||||
EntityKeyValues m_entity;
|
||||
KeyObserverMap m_keyObservers;
|
||||
MatrixTransform m_transform;
|
||||
|
||||
OriginKey m_originKey;
|
||||
Vector3 m_origin;
|
||||
AnglesKey m_anglesKey;
|
||||
Vector3 m_angles;
|
||||
ScaleKey m_scaleKey;
|
||||
Vector3 m_scale;
|
||||
OriginKey m_originKey;
|
||||
Vector3 m_origin;
|
||||
AnglesKey m_anglesKey;
|
||||
Vector3 m_angles;
|
||||
ScaleKey m_scaleKey;
|
||||
Vector3 m_scale;
|
||||
|
||||
SingletonModel m_model;
|
||||
SingletonModel m_model;
|
||||
|
||||
ClassnameFilter m_filter;
|
||||
NamedEntity m_named;
|
||||
NameKeys m_nameKeys;
|
||||
RenderablePivot m_renderOrigin;
|
||||
RenderableNamedEntity m_renderName;
|
||||
ClassnameFilter m_filter;
|
||||
NamedEntity m_named;
|
||||
NameKeys m_nameKeys;
|
||||
RenderablePivot m_renderOrigin;
|
||||
RenderableNamedEntity m_renderName;
|
||||
|
||||
Callback m_transformChanged;
|
||||
Callback m_evaluateTransform;
|
||||
Callback m_transformChanged;
|
||||
Callback m_evaluateTransform;
|
||||
|
||||
void construct()
|
||||
{
|
||||
m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter));
|
||||
m_keyObservers.insert(Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named));
|
||||
m_keyObservers.insert("model", SingletonModel::ModelChangedCaller(m_model));
|
||||
m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey));
|
||||
m_keyObservers.insert("angle", AnglesKey::AngleChangedCaller(m_anglesKey));
|
||||
m_keyObservers.insert("angles", AnglesKey::AnglesChangedCaller(m_anglesKey));
|
||||
m_keyObservers.insert("modelscale", ScaleKey::UniformScaleChangedCaller(m_scaleKey));
|
||||
m_keyObservers.insert("modelscale_vec", ScaleKey::ScaleChangedCaller(m_scaleKey));
|
||||
}
|
||||
void construct(){
|
||||
m_keyObservers.insert( "classname", ClassnameFilter::ClassnameChangedCaller( m_filter ) );
|
||||
m_keyObservers.insert( Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller( m_named ) );
|
||||
m_keyObservers.insert( "model", SingletonModel::ModelChangedCaller( m_model ) );
|
||||
m_keyObservers.insert( "origin", OriginKey::OriginChangedCaller( m_originKey ) );
|
||||
m_keyObservers.insert( "angle", AnglesKey::AngleChangedCaller( m_anglesKey ) );
|
||||
m_keyObservers.insert( "angles", AnglesKey::AnglesChangedCaller( m_anglesKey ) );
|
||||
m_keyObservers.insert( "modelscale", ScaleKey::UniformScaleChangedCaller( m_scaleKey ) );
|
||||
m_keyObservers.insert( "modelscale_vec", ScaleKey::ScaleChangedCaller( m_scaleKey ) );
|
||||
}
|
||||
|
||||
void updateTransform()
|
||||
{
|
||||
m_transform.localToParent() = g_matrix4_identity;
|
||||
matrix4_transform_by_euler_xyz_degrees(m_transform.localToParent(), m_origin, m_angles, m_scale);
|
||||
m_transformChanged();
|
||||
}
|
||||
void updateTransform(){
|
||||
m_transform.localToParent() = g_matrix4_identity;
|
||||
matrix4_transform_by_euler_xyz_degrees( m_transform.localToParent(), m_origin, m_angles, m_scale );
|
||||
m_transformChanged();
|
||||
}
|
||||
|
||||
// vc 2k5 compiler fix
|
||||
// vc 2k5 compiler fix
|
||||
#if _MSC_VER >= 1400
|
||||
public:
|
||||
#endif
|
||||
|
||||
void originChanged()
|
||||
{
|
||||
m_origin = m_originKey.m_origin;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<MiscModel, &MiscModel::originChanged> OriginChangedCaller;
|
||||
void anglesChanged()
|
||||
{
|
||||
m_angles = m_anglesKey.m_angles;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<MiscModel, &MiscModel::anglesChanged> AnglesChangedCaller;
|
||||
void scaleChanged()
|
||||
{
|
||||
m_scale = m_scaleKey.m_scale;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<MiscModel, &MiscModel::scaleChanged> ScaleChangedCaller;
|
||||
public:
|
||||
#endif
|
||||
|
||||
void originChanged(){
|
||||
m_origin = m_originKey.m_origin;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<MiscModel, &MiscModel::originChanged> OriginChangedCaller;
|
||||
void anglesChanged(){
|
||||
m_angles = m_anglesKey.m_angles;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<MiscModel, &MiscModel::anglesChanged> AnglesChangedCaller;
|
||||
void scaleChanged(){
|
||||
m_scale = m_scaleKey.m_scale;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<MiscModel, &MiscModel::scaleChanged> ScaleChangedCaller;
|
||||
public:
|
||||
|
||||
MiscModel(EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
|
||||
m_entity(eclass),
|
||||
m_originKey(OriginChangedCaller(*this)),
|
||||
m_origin(ORIGINKEY_IDENTITY),
|
||||
m_anglesKey(AnglesChangedCaller(*this)),
|
||||
m_angles(ANGLESKEY_IDENTITY),
|
||||
m_scaleKey(ScaleChangedCaller(*this)),
|
||||
m_scale(SCALEKEY_IDENTITY),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_transformChanged(transformChanged),
|
||||
m_evaluateTransform(evaluateTransform)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
MiscModel(const MiscModel& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
|
||||
m_entity(other.m_entity),
|
||||
m_originKey(OriginChangedCaller(*this)),
|
||||
m_origin(ORIGINKEY_IDENTITY),
|
||||
m_anglesKey(AnglesChangedCaller(*this)),
|
||||
m_angles(ANGLESKEY_IDENTITY),
|
||||
m_scaleKey(ScaleChangedCaller(*this)),
|
||||
m_scale(SCALEKEY_IDENTITY),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_transformChanged(transformChanged),
|
||||
m_evaluateTransform(evaluateTransform)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
MiscModel( EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) :
|
||||
m_entity( eclass ),
|
||||
m_originKey( OriginChangedCaller( *this ) ),
|
||||
m_origin( ORIGINKEY_IDENTITY ),
|
||||
m_anglesKey( AnglesChangedCaller( *this ) ),
|
||||
m_angles( ANGLESKEY_IDENTITY ),
|
||||
m_scaleKey( ScaleChangedCaller( *this ) ),
|
||||
m_scale( SCALEKEY_IDENTITY ),
|
||||
m_filter( m_entity, node ),
|
||||
m_named( m_entity ),
|
||||
m_nameKeys( m_entity ),
|
||||
m_renderName( m_named, g_vector3_identity ),
|
||||
m_transformChanged( transformChanged ),
|
||||
m_evaluateTransform( evaluateTransform ){
|
||||
construct();
|
||||
}
|
||||
MiscModel( const MiscModel& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) :
|
||||
m_entity( other.m_entity ),
|
||||
m_originKey( OriginChangedCaller( *this ) ),
|
||||
m_origin( ORIGINKEY_IDENTITY ),
|
||||
m_anglesKey( AnglesChangedCaller( *this ) ),
|
||||
m_angles( ANGLESKEY_IDENTITY ),
|
||||
m_scaleKey( ScaleChangedCaller( *this ) ),
|
||||
m_scale( SCALEKEY_IDENTITY ),
|
||||
m_filter( m_entity, node ),
|
||||
m_named( m_entity ),
|
||||
m_nameKeys( m_entity ),
|
||||
m_renderName( m_named, g_vector3_identity ),
|
||||
m_transformChanged( transformChanged ),
|
||||
m_evaluateTransform( evaluateTransform ){
|
||||
construct();
|
||||
}
|
||||
|
||||
InstanceCounter m_instanceCounter;
|
||||
void instanceAttach(const scene::Path& path)
|
||||
{
|
||||
if(++m_instanceCounter.m_count == 1)
|
||||
{
|
||||
m_filter.instanceAttach();
|
||||
m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_entity.attach(m_keyObservers);
|
||||
}
|
||||
}
|
||||
void instanceDetach(const scene::Path& path)
|
||||
{
|
||||
if(--m_instanceCounter.m_count == 0)
|
||||
{
|
||||
m_entity.detach(m_keyObservers);
|
||||
m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_filter.instanceDetach();
|
||||
}
|
||||
}
|
||||
InstanceCounter m_instanceCounter;
|
||||
void instanceAttach( const scene::Path& path ){
|
||||
if ( ++m_instanceCounter.m_count == 1 ) {
|
||||
m_filter.instanceAttach();
|
||||
m_entity.instanceAttach( path_find_mapfile( path.begin(), path.end() ) );
|
||||
m_entity.attach( m_keyObservers );
|
||||
}
|
||||
}
|
||||
void instanceDetach( const scene::Path& path ){
|
||||
if ( --m_instanceCounter.m_count == 0 ) {
|
||||
m_entity.detach( m_keyObservers );
|
||||
m_entity.instanceDetach( path_find_mapfile( path.begin(), path.end() ) );
|
||||
m_filter.instanceDetach();
|
||||
}
|
||||
}
|
||||
|
||||
EntityKeyValues& getEntity()
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
const EntityKeyValues& getEntity() const
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
EntityKeyValues& getEntity(){
|
||||
return m_entity;
|
||||
}
|
||||
const EntityKeyValues& getEntity() const {
|
||||
return m_entity;
|
||||
}
|
||||
|
||||
scene::Traversable& getTraversable()
|
||||
{
|
||||
return m_model.getTraversable();
|
||||
}
|
||||
Namespaced& getNamespaced()
|
||||
{
|
||||
return m_nameKeys;
|
||||
}
|
||||
Nameable& getNameable()
|
||||
{
|
||||
return m_named;
|
||||
}
|
||||
TransformNode& getTransformNode()
|
||||
{
|
||||
return m_transform;
|
||||
}
|
||||
scene::Traversable& getTraversable(){
|
||||
return m_model.getTraversable();
|
||||
}
|
||||
Namespaced& getNamespaced(){
|
||||
return m_nameKeys;
|
||||
}
|
||||
Nameable& getNameable(){
|
||||
return m_named;
|
||||
}
|
||||
TransformNode& getTransformNode(){
|
||||
return m_transform;
|
||||
}
|
||||
|
||||
void attach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_model.attach(observer);
|
||||
}
|
||||
void detach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_model.detach(observer);
|
||||
}
|
||||
void attach( scene::Traversable::Observer* observer ){
|
||||
m_model.attach( observer );
|
||||
}
|
||||
void detach( scene::Traversable::Observer* observer ){
|
||||
m_model.detach( observer );
|
||||
}
|
||||
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected) const
|
||||
{
|
||||
if(selected)
|
||||
{
|
||||
m_renderOrigin.render(renderer, volume, localToWorld);
|
||||
}
|
||||
void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected ) const {
|
||||
if ( selected ) {
|
||||
m_renderOrigin.render( renderer, volume, localToWorld );
|
||||
}
|
||||
|
||||
renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected) const
|
||||
{
|
||||
renderSolid(renderer, volume, localToWorld, selected);
|
||||
if(g_showNames)
|
||||
{
|
||||
renderer.addRenderable(m_renderName, localToWorld);
|
||||
}
|
||||
}
|
||||
renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly );
|
||||
}
|
||||
void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected ) const {
|
||||
renderSolid( renderer, volume, localToWorld, selected );
|
||||
if ( g_showNames ) {
|
||||
renderer.addRenderable( m_renderName, localToWorld );
|
||||
}
|
||||
}
|
||||
|
||||
void translate(const Vector3& translation)
|
||||
{
|
||||
m_origin = origin_translated(m_origin, translation);
|
||||
}
|
||||
void rotate(const Quaternion& rotation)
|
||||
{
|
||||
m_angles = angles_rotated(m_angles, rotation);
|
||||
}
|
||||
void scale(const Vector3& scaling)
|
||||
{
|
||||
m_scale = scale_scaled(m_scale, scaling);
|
||||
}
|
||||
void snapto(float snap)
|
||||
{
|
||||
m_originKey.m_origin = origin_snapped(m_originKey.m_origin, snap);
|
||||
m_originKey.write(&m_entity);
|
||||
}
|
||||
void revertTransform()
|
||||
{
|
||||
m_origin = m_originKey.m_origin;
|
||||
m_angles = m_anglesKey.m_angles;
|
||||
m_scale = m_scaleKey.m_scale;
|
||||
}
|
||||
void freezeTransform()
|
||||
{
|
||||
m_originKey.m_origin = m_origin;
|
||||
m_originKey.write(&m_entity);
|
||||
m_anglesKey.m_angles = m_angles;
|
||||
m_anglesKey.write(&m_entity);
|
||||
m_scaleKey.m_scale = m_scale;
|
||||
m_scaleKey.write(&m_entity);
|
||||
}
|
||||
void transformChanged()
|
||||
{
|
||||
revertTransform();
|
||||
m_evaluateTransform();
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<MiscModel, &MiscModel::transformChanged> TransformChangedCaller;
|
||||
void translate( const Vector3& translation ){
|
||||
m_origin = origin_translated( m_origin, translation );
|
||||
}
|
||||
void rotate( const Quaternion& rotation ){
|
||||
m_angles = angles_rotated( m_angles, rotation );
|
||||
}
|
||||
void scale( const Vector3& scaling ){
|
||||
m_scale = scale_scaled( m_scale, scaling );
|
||||
}
|
||||
void snapto( float snap ){
|
||||
m_originKey.m_origin = origin_snapped( m_originKey.m_origin, snap );
|
||||
m_originKey.write( &m_entity );
|
||||
}
|
||||
void revertTransform(){
|
||||
m_origin = m_originKey.m_origin;
|
||||
m_angles = m_anglesKey.m_angles;
|
||||
m_scale = m_scaleKey.m_scale;
|
||||
}
|
||||
void freezeTransform(){
|
||||
m_originKey.m_origin = m_origin;
|
||||
m_originKey.write( &m_entity );
|
||||
m_anglesKey.m_angles = m_angles;
|
||||
m_anglesKey.write( &m_entity );
|
||||
m_scaleKey.m_scale = m_scale;
|
||||
m_scaleKey.write( &m_entity );
|
||||
}
|
||||
void transformChanged(){
|
||||
revertTransform();
|
||||
m_evaluateTransform();
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<MiscModel, &MiscModel::transformChanged> TransformChangedCaller;
|
||||
};
|
||||
|
||||
class MiscModelInstance : public TargetableInstance, public TransformModifier, public Renderable
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
InstanceTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
m_casts = TargetableInstance::StaticTypeCasts::instance().get();
|
||||
InstanceStaticCast<MiscModelInstance, Renderable>::install(m_casts);
|
||||
InstanceStaticCast<MiscModelInstance, Transformable>::install(m_casts);
|
||||
InstanceIdentityCast<MiscModelInstance>::install(m_casts);
|
||||
}
|
||||
InstanceTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
MiscModel& m_contained;
|
||||
class TypeCasts
|
||||
{
|
||||
InstanceTypeCastTable m_casts;
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
TypeCasts(){
|
||||
m_casts = TargetableInstance::StaticTypeCasts::instance().get();
|
||||
InstanceStaticCast<MiscModelInstance, Renderable>::install( m_casts );
|
||||
InstanceStaticCast<MiscModelInstance, Transformable>::install( m_casts );
|
||||
InstanceIdentityCast<MiscModelInstance>::install( m_casts );
|
||||
}
|
||||
InstanceTypeCastTable& get(){
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
STRING_CONSTANT(Name, "MiscModelInstance");
|
||||
MiscModel& m_contained;
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
MiscModelInstance(const scene::Path& path, scene::Instance* parent, MiscModel& miscmodel) :
|
||||
TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), miscmodel.getEntity(), *this),
|
||||
TransformModifier(MiscModel::TransformChangedCaller(miscmodel), ApplyTransformCaller(*this)),
|
||||
m_contained(miscmodel)
|
||||
{
|
||||
m_contained.instanceAttach(Instance::path());
|
||||
StaticRenderableConnectionLines::instance().attach(*this);
|
||||
}
|
||||
~MiscModelInstance()
|
||||
{
|
||||
StaticRenderableConnectionLines::instance().detach(*this);
|
||||
m_contained.instanceDetach(Instance::path());
|
||||
}
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderSolid(renderer, volume, Instance::localToWorld(), getSelectable().isSelected());
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderWireframe(renderer, volume, Instance::localToWorld(), getSelectable().isSelected());
|
||||
}
|
||||
void evaluateTransform()
|
||||
{
|
||||
if(getType() == TRANSFORM_PRIMITIVE)
|
||||
{
|
||||
m_contained.translate(getTranslation());
|
||||
m_contained.rotate(getRotation());
|
||||
m_contained.scale(getScale());
|
||||
}
|
||||
}
|
||||
void applyTransform()
|
||||
{
|
||||
m_contained.revertTransform();
|
||||
evaluateTransform();
|
||||
m_contained.freezeTransform();
|
||||
}
|
||||
typedef MemberCaller<MiscModelInstance, &MiscModelInstance::applyTransform> ApplyTransformCaller;
|
||||
STRING_CONSTANT( Name, "MiscModelInstance" );
|
||||
|
||||
MiscModelInstance( const scene::Path& path, scene::Instance* parent, MiscModel& miscmodel ) :
|
||||
TargetableInstance( path, parent, this, StaticTypeCasts::instance().get(), miscmodel.getEntity(), *this ),
|
||||
TransformModifier( MiscModel::TransformChangedCaller( miscmodel ), ApplyTransformCaller( *this ) ),
|
||||
m_contained( miscmodel ){
|
||||
m_contained.instanceAttach( Instance::path() );
|
||||
StaticRenderableConnectionLines::instance().attach( *this );
|
||||
}
|
||||
~MiscModelInstance(){
|
||||
StaticRenderableConnectionLines::instance().detach( *this );
|
||||
m_contained.instanceDetach( Instance::path() );
|
||||
}
|
||||
void renderSolid( Renderer& renderer, const VolumeTest& volume ) const {
|
||||
m_contained.renderSolid( renderer, volume, Instance::localToWorld(), getSelectable().isSelected() );
|
||||
}
|
||||
void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const {
|
||||
m_contained.renderWireframe( renderer, volume, Instance::localToWorld(), getSelectable().isSelected() );
|
||||
}
|
||||
void evaluateTransform(){
|
||||
if ( getType() == TRANSFORM_PRIMITIVE ) {
|
||||
m_contained.translate( getTranslation() );
|
||||
m_contained.rotate( getRotation() );
|
||||
m_contained.scale( getScale() );
|
||||
}
|
||||
}
|
||||
void applyTransform(){
|
||||
m_contained.revertTransform();
|
||||
evaluateTransform();
|
||||
m_contained.freezeTransform();
|
||||
}
|
||||
typedef MemberCaller<MiscModelInstance, &MiscModelInstance::applyTransform> ApplyTransformCaller;
|
||||
};
|
||||
|
||||
class MiscModelNode :
|
||||
public scene::Node::Symbiot,
|
||||
public scene::Instantiable,
|
||||
public scene::Cloneable,
|
||||
public scene::Traversable::Observer
|
||||
public scene::Node::Symbiot,
|
||||
public scene::Instantiable,
|
||||
public scene::Cloneable,
|
||||
public scene::Traversable::Observer
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
NodeTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
NodeStaticCast<MiscModelNode, scene::Instantiable>::install(m_casts);
|
||||
NodeStaticCast<MiscModelNode, scene::Cloneable>::install(m_casts);
|
||||
NodeContainedCast<MiscModelNode, scene::Traversable>::install(m_casts);
|
||||
NodeContainedCast<MiscModelNode, Snappable>::install(m_casts);
|
||||
NodeContainedCast<MiscModelNode, TransformNode>::install(m_casts);
|
||||
NodeContainedCast<MiscModelNode, Entity>::install(m_casts);
|
||||
NodeContainedCast<MiscModelNode, Nameable>::install(m_casts);
|
||||
NodeContainedCast<MiscModelNode, Namespaced>::install(m_casts);
|
||||
}
|
||||
NodeTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
scene::Node m_node;
|
||||
InstanceSet m_instances;
|
||||
MiscModel m_contained;
|
||||
|
||||
void construct()
|
||||
{
|
||||
m_contained.attach(this);
|
||||
}
|
||||
void destroy()
|
||||
{
|
||||
m_contained.detach(this);
|
||||
}
|
||||
|
||||
class TypeCasts
|
||||
{
|
||||
NodeTypeCastTable m_casts;
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
scene::Traversable& get(NullType<scene::Traversable>)
|
||||
{
|
||||
return m_contained.getTraversable();
|
||||
}
|
||||
Snappable& get(NullType<Snappable>)
|
||||
{
|
||||
return m_contained;
|
||||
}
|
||||
TransformNode& get(NullType<TransformNode>)
|
||||
{
|
||||
return m_contained.getTransformNode();
|
||||
}
|
||||
Entity& get(NullType<Entity>)
|
||||
{
|
||||
return m_contained.getEntity();
|
||||
}
|
||||
Nameable& get(NullType<Nameable>)
|
||||
{
|
||||
return m_contained.getNameable();
|
||||
}
|
||||
Namespaced& get(NullType<Namespaced>)
|
||||
{
|
||||
return m_contained.getNamespaced();
|
||||
}
|
||||
|
||||
MiscModelNode(EntityClass* eclass) :
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSetEvaluateTransform<MiscModelInstance>::Caller(m_instances))
|
||||
{
|
||||
construct();
|
||||
}
|
||||
MiscModelNode(const MiscModelNode& other) :
|
||||
scene::Node::Symbiot(other),
|
||||
scene::Instantiable(other),
|
||||
scene::Cloneable(other),
|
||||
scene::Traversable::Observer(other),
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSetEvaluateTransform<MiscModelInstance>::Caller(m_instances))
|
||||
{
|
||||
construct();
|
||||
}
|
||||
~MiscModelNode()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
scene::Node& node()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
scene::Node& clone() const
|
||||
{
|
||||
return (new MiscModelNode(*this))->node();
|
||||
}
|
||||
|
||||
void insert(scene::Node& child)
|
||||
{
|
||||
m_instances.insert(child);
|
||||
}
|
||||
void erase(scene::Node& child)
|
||||
{
|
||||
m_instances.erase(child);
|
||||
}
|
||||
|
||||
scene::Instance* create(const scene::Path& path, scene::Instance* parent)
|
||||
{
|
||||
return new MiscModelInstance(path, parent, m_contained);
|
||||
}
|
||||
void forEachInstance(const scene::Instantiable::Visitor& visitor)
|
||||
{
|
||||
m_instances.forEachInstance(visitor);
|
||||
}
|
||||
void insert(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
|
||||
{
|
||||
m_instances.insert(observer, path, instance);
|
||||
}
|
||||
scene::Instance* erase(scene::Instantiable::Observer* observer, const scene::Path& path)
|
||||
{
|
||||
return m_instances.erase(observer, path);
|
||||
}
|
||||
TypeCasts(){
|
||||
NodeStaticCast<MiscModelNode, scene::Instantiable>::install( m_casts );
|
||||
NodeStaticCast<MiscModelNode, scene::Cloneable>::install( m_casts );
|
||||
NodeContainedCast<MiscModelNode, scene::Traversable>::install( m_casts );
|
||||
NodeContainedCast<MiscModelNode, Snappable>::install( m_casts );
|
||||
NodeContainedCast<MiscModelNode, TransformNode>::install( m_casts );
|
||||
NodeContainedCast<MiscModelNode, Entity>::install( m_casts );
|
||||
NodeContainedCast<MiscModelNode, Nameable>::install( m_casts );
|
||||
NodeContainedCast<MiscModelNode, Namespaced>::install( m_casts );
|
||||
}
|
||||
NodeTypeCastTable& get(){
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
scene::Node& New_MiscModel(EntityClass* eclass)
|
||||
{
|
||||
return (new MiscModelNode(eclass))->node();
|
||||
|
||||
scene::Node m_node;
|
||||
InstanceSet m_instances;
|
||||
MiscModel m_contained;
|
||||
|
||||
void construct(){
|
||||
m_contained.attach( this );
|
||||
}
|
||||
void destroy(){
|
||||
m_contained.detach( this );
|
||||
}
|
||||
|
||||
void MiscModel_construct()
|
||||
{
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
scene::Traversable& get( NullType<scene::Traversable>){
|
||||
return m_contained.getTraversable();
|
||||
}
|
||||
void MiscModel_destroy()
|
||||
{
|
||||
Snappable& get( NullType<Snappable>){
|
||||
return m_contained;
|
||||
}
|
||||
TransformNode& get( NullType<TransformNode>){
|
||||
return m_contained.getTransformNode();
|
||||
}
|
||||
Entity& get( NullType<Entity>){
|
||||
return m_contained.getEntity();
|
||||
}
|
||||
Nameable& get( NullType<Nameable>){
|
||||
return m_contained.getNameable();
|
||||
}
|
||||
Namespaced& get( NullType<Namespaced>){
|
||||
return m_contained.getNamespaced();
|
||||
}
|
||||
|
||||
MiscModelNode( EntityClass* eclass ) :
|
||||
m_node( this, this, StaticTypeCasts::instance().get() ),
|
||||
m_contained( eclass, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform<MiscModelInstance>::Caller( m_instances ) ){
|
||||
construct();
|
||||
}
|
||||
MiscModelNode( const MiscModelNode& other ) :
|
||||
scene::Node::Symbiot( other ),
|
||||
scene::Instantiable( other ),
|
||||
scene::Cloneable( other ),
|
||||
scene::Traversable::Observer( other ),
|
||||
m_node( this, this, StaticTypeCasts::instance().get() ),
|
||||
m_contained( other.m_contained, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform<MiscModelInstance>::Caller( m_instances ) ){
|
||||
construct();
|
||||
}
|
||||
~MiscModelNode(){
|
||||
destroy();
|
||||
}
|
||||
|
||||
void release(){
|
||||
delete this;
|
||||
}
|
||||
scene::Node& node(){
|
||||
return m_node;
|
||||
}
|
||||
|
||||
scene::Node& clone() const {
|
||||
return ( new MiscModelNode( *this ) )->node();
|
||||
}
|
||||
|
||||
void insert( scene::Node& child ){
|
||||
m_instances.insert( child );
|
||||
}
|
||||
void erase( scene::Node& child ){
|
||||
m_instances.erase( child );
|
||||
}
|
||||
|
||||
scene::Instance* create( const scene::Path& path, scene::Instance* parent ){
|
||||
return new MiscModelInstance( path, parent, m_contained );
|
||||
}
|
||||
void forEachInstance( const scene::Instantiable::Visitor& visitor ){
|
||||
m_instances.forEachInstance( visitor );
|
||||
}
|
||||
void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){
|
||||
m_instances.insert( observer, path, instance );
|
||||
}
|
||||
scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){
|
||||
return m_instances.erase( observer, path );
|
||||
}
|
||||
};
|
||||
|
||||
scene::Node& New_MiscModel( EntityClass* eclass ){
|
||||
return ( new MiscModelNode( eclass ) )->node();
|
||||
}
|
||||
|
||||
void MiscModel_construct(){
|
||||
}
|
||||
void MiscModel_destroy(){
|
||||
}
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_MISCMODEL_H)
|
||||
#if !defined( INCLUDED_MISCMODEL_H )
|
||||
#define INCLUDED_MISCMODEL_H
|
||||
|
||||
scene::Node& New_MiscModel(EntityClass* eclass);
|
||||
scene::Node& New_MiscModel( EntityClass* eclass );
|
||||
void MiscModel_construct();
|
||||
void MiscModel_destroy();
|
||||
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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 "model.h"
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_MODEL_H)
|
||||
#if !defined( INCLUDED_MODEL_H )
|
||||
#define INCLUDED_MODEL_H
|
||||
|
||||
#include "entitylib.h"
|
||||
@@ -31,94 +31,79 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
class EModel : public ModuleObserver
|
||||
{
|
||||
ResourceReference m_resource;
|
||||
scene::Traversable& m_traverse;
|
||||
scene::Node* m_node;
|
||||
Callback m_modelChanged;
|
||||
ResourceReference m_resource;
|
||||
scene::Traversable& m_traverse;
|
||||
scene::Node* m_node;
|
||||
Callback m_modelChanged;
|
||||
|
||||
public:
|
||||
EModel(scene::Traversable& traversable, const Callback& modelChanged)
|
||||
: m_resource(""), m_traverse(traversable), m_node(0), m_modelChanged(modelChanged)
|
||||
{
|
||||
m_resource.attach(*this);
|
||||
}
|
||||
~EModel()
|
||||
{
|
||||
m_resource.detach(*this);
|
||||
}
|
||||
EModel( scene::Traversable& traversable, const Callback& modelChanged )
|
||||
: m_resource( "" ), m_traverse( traversable ), m_node( 0 ), m_modelChanged( modelChanged ){
|
||||
m_resource.attach( *this );
|
||||
}
|
||||
~EModel(){
|
||||
m_resource.detach( *this );
|
||||
}
|
||||
|
||||
void realise()
|
||||
{
|
||||
m_resource.get()->load();
|
||||
m_node = m_resource.get()->getNode();
|
||||
if(m_node != 0)
|
||||
{
|
||||
m_traverse.insert(*m_node);
|
||||
}
|
||||
}
|
||||
void unrealise()
|
||||
{
|
||||
if(m_node != 0)
|
||||
{
|
||||
m_traverse.erase(*m_node);
|
||||
}
|
||||
}
|
||||
|
||||
void modelChanged(const char* value)
|
||||
{
|
||||
StringOutputStream cleaned(string_length(value));
|
||||
cleaned << PathCleaned(value);
|
||||
m_resource.detach(*this);
|
||||
m_resource.setName(cleaned.c_str());
|
||||
m_resource.attach(*this);
|
||||
m_modelChanged();
|
||||
}
|
||||
typedef MemberCaller1<EModel, const char*, &EModel::modelChanged> ModelChangedCaller;
|
||||
void realise(){
|
||||
m_resource.get()->load();
|
||||
m_node = m_resource.get()->getNode();
|
||||
if ( m_node != 0 ) {
|
||||
m_traverse.insert( *m_node );
|
||||
}
|
||||
}
|
||||
void unrealise(){
|
||||
if ( m_node != 0 ) {
|
||||
m_traverse.erase( *m_node );
|
||||
}
|
||||
}
|
||||
|
||||
const char* getName() const
|
||||
{
|
||||
return m_resource.getName();
|
||||
}
|
||||
scene::Node* getNode() const
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
void modelChanged( const char* value ){
|
||||
StringOutputStream cleaned( string_length( value ) );
|
||||
cleaned << PathCleaned( value );
|
||||
m_resource.detach( *this );
|
||||
m_resource.setName( cleaned.c_str() );
|
||||
m_resource.attach( *this );
|
||||
m_modelChanged();
|
||||
}
|
||||
typedef MemberCaller1<EModel, const char*, &EModel::modelChanged> ModelChangedCaller;
|
||||
|
||||
const char* getName() const {
|
||||
return m_resource.getName();
|
||||
}
|
||||
scene::Node* getNode() const {
|
||||
return m_node;
|
||||
}
|
||||
};
|
||||
|
||||
class SingletonModel
|
||||
{
|
||||
TraversableNode m_traverse;
|
||||
EModel m_model;
|
||||
TraversableNode m_traverse;
|
||||
EModel m_model;
|
||||
public:
|
||||
SingletonModel()
|
||||
: m_model(m_traverse, Callback())
|
||||
{
|
||||
}
|
||||
SingletonModel()
|
||||
: m_model( m_traverse, Callback() ){
|
||||
}
|
||||
|
||||
void attach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_traverse.attach(observer);
|
||||
}
|
||||
void detach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_traverse.detach(observer);
|
||||
}
|
||||
void attach( scene::Traversable::Observer* observer ){
|
||||
m_traverse.attach( observer );
|
||||
}
|
||||
void detach( scene::Traversable::Observer* observer ){
|
||||
m_traverse.detach( observer );
|
||||
}
|
||||
|
||||
scene::Traversable& getTraversable()
|
||||
{
|
||||
return m_traverse;
|
||||
}
|
||||
scene::Traversable& getTraversable(){
|
||||
return m_traverse;
|
||||
}
|
||||
|
||||
void modelChanged(const char* value)
|
||||
{
|
||||
m_model.modelChanged(value);
|
||||
}
|
||||
typedef MemberCaller1<SingletonModel, const char*, &SingletonModel::modelChanged> ModelChangedCaller;
|
||||
void modelChanged( const char* value ){
|
||||
m_model.modelChanged( value );
|
||||
}
|
||||
typedef MemberCaller1<SingletonModel, const char*, &SingletonModel::modelChanged> ModelChangedCaller;
|
||||
|
||||
scene::Node* getNode() const
|
||||
{
|
||||
return m_model.getNode();
|
||||
}
|
||||
scene::Node* getNode() const {
|
||||
return m_model.getNode();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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 "modelskinkey.h"
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_MODELSKINKEY_H)
|
||||
#if !defined( INCLUDED_MODELSKINKEY_H )
|
||||
#define INCLUDED_MODELSKINKEY_H
|
||||
|
||||
#include "modelskin.h"
|
||||
@@ -30,82 +30,70 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#include "entitylib.h"
|
||||
#include "traverselib.h"
|
||||
|
||||
inline void parseTextureName(CopiedString& name, const char* token)
|
||||
{
|
||||
StringOutputStream cleaned(256);
|
||||
cleaned << PathCleaned(token);
|
||||
name = StringRange(cleaned.c_str(), path_get_filename_base_end(cleaned.c_str())); // remove extension
|
||||
inline void parseTextureName( CopiedString& name, const char* token ){
|
||||
StringOutputStream cleaned( 256 );
|
||||
cleaned << PathCleaned( token );
|
||||
name = StringRange( cleaned.c_str(), path_get_filename_base_end( cleaned.c_str() ) ); // remove extension
|
||||
}
|
||||
|
||||
class ModelSkinKey : public ModuleObserver
|
||||
{
|
||||
CopiedString m_name;
|
||||
ModelSkin* m_skin;
|
||||
Callback m_skinChangedCallback;
|
||||
CopiedString m_name;
|
||||
ModelSkin* m_skin;
|
||||
Callback m_skinChangedCallback;
|
||||
|
||||
ModelSkinKey(const ModelSkinKey&);
|
||||
ModelSkinKey operator=(const ModelSkinKey&);
|
||||
ModelSkinKey( const ModelSkinKey& );
|
||||
ModelSkinKey operator=( const ModelSkinKey& );
|
||||
|
||||
void construct()
|
||||
{
|
||||
m_skin = &GlobalModelSkinCache().capture(m_name.c_str());
|
||||
m_skin->attach(*this);
|
||||
}
|
||||
void destroy()
|
||||
{
|
||||
m_skin->detach(*this);
|
||||
GlobalModelSkinCache().release(m_name.c_str());
|
||||
}
|
||||
void construct(){
|
||||
m_skin = &GlobalModelSkinCache().capture( m_name.c_str() );
|
||||
m_skin->attach( *this );
|
||||
}
|
||||
void destroy(){
|
||||
m_skin->detach( *this );
|
||||
GlobalModelSkinCache().release( m_name.c_str() );
|
||||
}
|
||||
|
||||
public:
|
||||
ModelSkinKey(const Callback& skinChangedCallback) : m_skinChangedCallback(skinChangedCallback)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
~ModelSkinKey()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
ModelSkin& get() const
|
||||
{
|
||||
return *m_skin;
|
||||
}
|
||||
void skinChanged(const char* value)
|
||||
{
|
||||
destroy();
|
||||
parseTextureName(m_name, value);
|
||||
construct();
|
||||
}
|
||||
typedef MemberCaller1<ModelSkinKey, const char*, &ModelSkinKey::skinChanged> SkinChangedCaller;
|
||||
ModelSkinKey( const Callback& skinChangedCallback ) : m_skinChangedCallback( skinChangedCallback ){
|
||||
construct();
|
||||
}
|
||||
~ModelSkinKey(){
|
||||
destroy();
|
||||
}
|
||||
ModelSkin& get() const {
|
||||
return *m_skin;
|
||||
}
|
||||
void skinChanged( const char* value ){
|
||||
destroy();
|
||||
parseTextureName( m_name, value );
|
||||
construct();
|
||||
}
|
||||
typedef MemberCaller1<ModelSkinKey, const char*, &ModelSkinKey::skinChanged> SkinChangedCaller;
|
||||
|
||||
void realise()
|
||||
{
|
||||
m_skinChangedCallback();
|
||||
}
|
||||
void unrealise()
|
||||
{
|
||||
}
|
||||
void realise(){
|
||||
m_skinChangedCallback();
|
||||
}
|
||||
void unrealise(){
|
||||
}
|
||||
};
|
||||
|
||||
class InstanceSkinChanged : public scene::Instantiable::Visitor
|
||||
{
|
||||
public:
|
||||
void visit(scene::Instance& instance) const
|
||||
{
|
||||
//\todo don't do this for instances that are not children of the entity setting the skin
|
||||
SkinnedModel* skinned = InstanceTypeCast<SkinnedModel>::cast(instance);
|
||||
if(skinned != 0)
|
||||
{
|
||||
skinned->skinChanged();
|
||||
}
|
||||
}
|
||||
void visit( scene::Instance& instance ) const {
|
||||
//\todo don't do this for instances that are not children of the entity setting the skin
|
||||
SkinnedModel* skinned = InstanceTypeCast<SkinnedModel>::cast( instance );
|
||||
if ( skinned != 0 ) {
|
||||
skinned->skinChanged();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline void Node_modelSkinChanged(scene::Node& node)
|
||||
{
|
||||
scene::Instantiable* instantiable = Node_getInstantiable(node);
|
||||
ASSERT_NOTNULL(instantiable);
|
||||
instantiable->forEachInstance(InstanceSkinChanged());
|
||||
inline void Node_modelSkinChanged( scene::Node& node ){
|
||||
scene::Instantiable* instantiable = Node_getInstantiable( node );
|
||||
ASSERT_NOTNULL( instantiable );
|
||||
instantiable->forEachInstance( InstanceSkinChanged() );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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 "namedentity.h"
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_NAMEDENTITY_H)
|
||||
#if !defined( INCLUDED_NAMEDENTITY_H )
|
||||
#define INCLUDED_NAMEDENTITY_H
|
||||
|
||||
#include "entitylib.h"
|
||||
@@ -31,81 +31,69 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
class NameCallbackSet
|
||||
{
|
||||
typedef std::set<NameCallback> NameCallbacks;
|
||||
NameCallbacks m_callbacks;
|
||||
typedef std::set<NameCallback> NameCallbacks;
|
||||
NameCallbacks m_callbacks;
|
||||
public:
|
||||
void insert(const NameCallback& callback)
|
||||
{
|
||||
m_callbacks.insert(callback);
|
||||
}
|
||||
void erase(const NameCallback& callback)
|
||||
{
|
||||
m_callbacks.erase(callback);
|
||||
}
|
||||
void changed(const char* name) const
|
||||
{
|
||||
for(NameCallbacks::const_iterator i = m_callbacks.begin(); i != m_callbacks.end(); ++i)
|
||||
{
|
||||
(*i)(name);
|
||||
}
|
||||
}
|
||||
void insert( const NameCallback& callback ){
|
||||
m_callbacks.insert( callback );
|
||||
}
|
||||
void erase( const NameCallback& callback ){
|
||||
m_callbacks.erase( callback );
|
||||
}
|
||||
void changed( const char* name ) const {
|
||||
for ( NameCallbacks::const_iterator i = m_callbacks.begin(); i != m_callbacks.end(); ++i )
|
||||
{
|
||||
( *i )( name );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class NamedEntity : public Nameable
|
||||
{
|
||||
EntityKeyValues& m_entity;
|
||||
NameCallbackSet m_changed;
|
||||
CopiedString m_name;
|
||||
EntityKeyValues& m_entity;
|
||||
NameCallbackSet m_changed;
|
||||
CopiedString m_name;
|
||||
public:
|
||||
NamedEntity(EntityKeyValues& entity) : m_entity(entity)
|
||||
{
|
||||
}
|
||||
const char* name() const
|
||||
{
|
||||
if(string_empty(m_name.c_str()))
|
||||
{
|
||||
return m_entity.getEntityClass().name();
|
||||
}
|
||||
return m_name.c_str();
|
||||
}
|
||||
void attach(const NameCallback& callback)
|
||||
{
|
||||
m_changed.insert(callback);
|
||||
}
|
||||
void detach(const NameCallback& callback)
|
||||
{
|
||||
m_changed.erase(callback);
|
||||
}
|
||||
NamedEntity( EntityKeyValues& entity ) : m_entity( entity ){
|
||||
}
|
||||
const char* name() const {
|
||||
if ( string_empty( m_name.c_str() ) ) {
|
||||
return m_entity.getEntityClass().name();
|
||||
}
|
||||
return m_name.c_str();
|
||||
}
|
||||
void attach( const NameCallback& callback ){
|
||||
m_changed.insert( callback );
|
||||
}
|
||||
void detach( const NameCallback& callback ){
|
||||
m_changed.erase( callback );
|
||||
}
|
||||
|
||||
void identifierChanged(const char* value)
|
||||
{
|
||||
if(string_empty(value))
|
||||
{
|
||||
m_changed.changed(m_entity.getEntityClass().name());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_changed.changed(value);
|
||||
}
|
||||
m_name = value;
|
||||
}
|
||||
typedef MemberCaller1<NamedEntity, const char*, &NamedEntity::identifierChanged> IdentifierChangedCaller;
|
||||
void identifierChanged( const char* value ){
|
||||
if ( string_empty( value ) ) {
|
||||
m_changed.changed( m_entity.getEntityClass().name() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_changed.changed( value );
|
||||
}
|
||||
m_name = value;
|
||||
}
|
||||
typedef MemberCaller1<NamedEntity, const char*, &NamedEntity::identifierChanged> IdentifierChangedCaller;
|
||||
};
|
||||
|
||||
class RenderableNamedEntity : public OpenGLRenderable
|
||||
{
|
||||
const NamedEntity& m_named;
|
||||
const Vector3& m_position;
|
||||
const NamedEntity& m_named;
|
||||
const Vector3& m_position;
|
||||
public:
|
||||
RenderableNamedEntity(const NamedEntity& named, const Vector3& position)
|
||||
: m_named(named), m_position(position)
|
||||
{
|
||||
}
|
||||
void render(RenderStateFlags state) const
|
||||
{
|
||||
glRasterPos3fv(vector3_to_array(m_position));
|
||||
GlobalOpenGL().drawString(m_named.name());
|
||||
}
|
||||
RenderableNamedEntity( const NamedEntity& named, const Vector3& position )
|
||||
: m_named( named ), m_position( position ){
|
||||
}
|
||||
void render( RenderStateFlags state ) const {
|
||||
glRasterPos3fv( vector3_to_array( m_position ) );
|
||||
GlobalOpenGL().drawString( m_named.name() );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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 "namekeys.h"
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_NAMEKEYS_H)
|
||||
#if !defined( INCLUDED_NAMEKEYS_H )
|
||||
#define INCLUDED_NAMEKEYS_H
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -28,23 +28,21 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#include "entitylib.h"
|
||||
#include "namespace.h"
|
||||
|
||||
inline bool string_is_integer(const char* string)
|
||||
{
|
||||
strtol(string, const_cast<char**>(&string), 10);
|
||||
return *string == '\0';
|
||||
inline bool string_is_integer( const char* string ){
|
||||
strtol( string, const_cast<char**>( &string ), 10 );
|
||||
return *string == '\0';
|
||||
}
|
||||
|
||||
typedef bool (*KeyIsNameFunc)(const char* key);
|
||||
typedef bool ( *KeyIsNameFunc )( const char* key );
|
||||
|
||||
class KeyIsName
|
||||
{
|
||||
public:
|
||||
KeyIsNameFunc m_keyIsName;
|
||||
const char* m_nameKey;
|
||||
KeyIsNameFunc m_keyIsName;
|
||||
const char* m_nameKey;
|
||||
|
||||
KeyIsName()
|
||||
{
|
||||
}
|
||||
KeyIsName(){
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -54,97 +52,82 @@ typedef MemberCaller1<EntityKeyValue, const KeyObserver&, &EntityKeyValue::detac
|
||||
|
||||
class NameKeys : public Entity::Observer, public Namespaced
|
||||
{
|
||||
Namespace* m_namespace;
|
||||
EntityKeyValues& m_entity;
|
||||
KeyIsNameFunc m_keyIsName;
|
||||
NameKeys(const NameKeys& other);
|
||||
NameKeys& operator=(const NameKeys& other);
|
||||
Namespace* m_namespace;
|
||||
EntityKeyValues& m_entity;
|
||||
KeyIsNameFunc m_keyIsName;
|
||||
NameKeys( const NameKeys& other );
|
||||
NameKeys& operator=( const NameKeys& other );
|
||||
|
||||
typedef std::map<CopiedString, EntityKeyValue*> KeyValues;
|
||||
KeyValues m_keyValues;
|
||||
typedef std::map<CopiedString, EntityKeyValue*> KeyValues;
|
||||
KeyValues m_keyValues;
|
||||
|
||||
void insertName(const char* key, EntityKeyValue& value)
|
||||
{
|
||||
if(m_namespace != 0 && m_keyIsName(key))
|
||||
{
|
||||
//globalOutputStream() << "insert " << key << "\n";
|
||||
m_namespace->attach(KeyValueAssignCaller(value), KeyValueAttachCaller(value));
|
||||
}
|
||||
}
|
||||
void eraseName(const char* key, EntityKeyValue& value)
|
||||
{
|
||||
if(m_namespace != 0 && m_keyIsName(key))
|
||||
{
|
||||
//globalOutputStream() << "erase " << key << "\n";
|
||||
m_namespace->detach(KeyValueAssignCaller(value), KeyValueDetachCaller(value));
|
||||
}
|
||||
}
|
||||
void insertAll()
|
||||
{
|
||||
for(KeyValues::iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
|
||||
{
|
||||
insertName((*i).first.c_str(), *(*i).second);
|
||||
}
|
||||
}
|
||||
void eraseAll()
|
||||
{
|
||||
for(KeyValues::iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
|
||||
{
|
||||
eraseName((*i).first.c_str(), *(*i).second);
|
||||
}
|
||||
}
|
||||
void insertName( const char* key, EntityKeyValue& value ){
|
||||
if ( m_namespace != 0 && m_keyIsName( key ) ) {
|
||||
//globalOutputStream() << "insert " << key << "\n";
|
||||
m_namespace->attach( KeyValueAssignCaller( value ), KeyValueAttachCaller( value ) );
|
||||
}
|
||||
}
|
||||
void eraseName( const char* key, EntityKeyValue& value ){
|
||||
if ( m_namespace != 0 && m_keyIsName( key ) ) {
|
||||
//globalOutputStream() << "erase " << key << "\n";
|
||||
m_namespace->detach( KeyValueAssignCaller( value ), KeyValueDetachCaller( value ) );
|
||||
}
|
||||
}
|
||||
void insertAll(){
|
||||
for ( KeyValues::iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i )
|
||||
{
|
||||
insertName( ( *i ).first.c_str(), *( *i ).second );
|
||||
}
|
||||
}
|
||||
void eraseAll(){
|
||||
for ( KeyValues::iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i )
|
||||
{
|
||||
eraseName( ( *i ).first.c_str(), *( *i ).second );
|
||||
}
|
||||
}
|
||||
public:
|
||||
NameKeys(EntityKeyValues& entity) : m_namespace(0), m_entity(entity), m_keyIsName(Static<KeyIsName>::instance().m_keyIsName)
|
||||
{
|
||||
m_entity.attach(*this);
|
||||
}
|
||||
~NameKeys()
|
||||
{
|
||||
m_entity.detach(*this);
|
||||
}
|
||||
void setNamespace(Namespace& space)
|
||||
{
|
||||
eraseAll();
|
||||
m_namespace = &space;
|
||||
insertAll();
|
||||
}
|
||||
void setKeyIsName(KeyIsNameFunc keyIsName)
|
||||
{
|
||||
eraseAll();
|
||||
m_keyIsName = keyIsName;
|
||||
insertAll();
|
||||
}
|
||||
void insert(const char* key, EntityKeyValue& value)
|
||||
{
|
||||
m_keyValues.insert(KeyValues::value_type(key, &value));
|
||||
insertName(key, value);
|
||||
}
|
||||
void erase(const char* key, EntityKeyValue& value)
|
||||
{
|
||||
eraseName(key, value);
|
||||
m_keyValues.erase(key);
|
||||
}
|
||||
NameKeys( EntityKeyValues& entity ) : m_namespace( 0 ), m_entity( entity ), m_keyIsName( Static<KeyIsName>::instance().m_keyIsName ){
|
||||
m_entity.attach( *this );
|
||||
}
|
||||
~NameKeys(){
|
||||
m_entity.detach( *this );
|
||||
}
|
||||
void setNamespace( Namespace& space ){
|
||||
eraseAll();
|
||||
m_namespace = &space;
|
||||
insertAll();
|
||||
}
|
||||
void setKeyIsName( KeyIsNameFunc keyIsName ){
|
||||
eraseAll();
|
||||
m_keyIsName = keyIsName;
|
||||
insertAll();
|
||||
}
|
||||
void insert( const char* key, EntityKeyValue& value ){
|
||||
m_keyValues.insert( KeyValues::value_type( key, &value ) );
|
||||
insertName( key, value );
|
||||
}
|
||||
void erase( const char* key, EntityKeyValue& value ){
|
||||
eraseName( key, value );
|
||||
m_keyValues.erase( key );
|
||||
}
|
||||
};
|
||||
|
||||
inline bool keyIsNameDoom3(const char* key)
|
||||
{
|
||||
return string_equal(key, "target")
|
||||
|| (string_equal_n(key, "target", 6) && string_is_integer(key + 6))
|
||||
|| string_equal(key, "name");
|
||||
inline bool keyIsNameDoom3( const char* key ){
|
||||
return string_equal( key, "target" )
|
||||
|| ( string_equal_n( key, "target", 6 ) && string_is_integer( key + 6 ) )
|
||||
|| string_equal( key, "name" );
|
||||
}
|
||||
|
||||
inline bool keyIsNameDoom3Doom3Group(const char* key)
|
||||
{
|
||||
return keyIsNameDoom3(key)
|
||||
|| string_equal(key, "model");
|
||||
inline bool keyIsNameDoom3Doom3Group( const char* key ){
|
||||
return keyIsNameDoom3( key )
|
||||
|| string_equal( key, "model" );
|
||||
}
|
||||
|
||||
inline bool keyIsNameQuake3(const char* key)
|
||||
{
|
||||
return string_equal(key, "target")
|
||||
|| string_equal(key, "targetname")
|
||||
|| string_equal(key, "killtarget")
|
||||
|| (string_equal_n(key, "target", 6) && string_is_integer(key + 6)); // Nexuiz
|
||||
inline bool keyIsNameQuake3( const char* key ){
|
||||
return string_equal( key, "target" )
|
||||
|| string_equal( key, "targetname" )
|
||||
|| string_equal( key, "killtarget" )
|
||||
|| ( string_equal_n( key, "target", 6 ) && string_is_integer( key + 6 ) ); // Nexuiz
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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 "origin.h"
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_ORIGIN_H)
|
||||
#if !defined( INCLUDED_ORIGIN_H )
|
||||
#define INCLUDED_ORIGIN_H
|
||||
|
||||
#include "ientity.h"
|
||||
@@ -28,141 +28,118 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#include "generic/callback.h"
|
||||
#include "stringio.h"
|
||||
|
||||
const Vector3 ORIGINKEY_IDENTITY = Vector3(0, 0, 0);
|
||||
const Vector3 ORIGINKEY_IDENTITY = Vector3( 0, 0, 0 );
|
||||
|
||||
inline void default_origin(Vector3& origin)
|
||||
{
|
||||
origin = ORIGINKEY_IDENTITY;
|
||||
inline void default_origin( Vector3& origin ){
|
||||
origin = ORIGINKEY_IDENTITY;
|
||||
}
|
||||
inline void read_origin(Vector3& origin, const char* value)
|
||||
{
|
||||
if(!string_parse_vector3(value, origin))
|
||||
{
|
||||
default_origin(origin);
|
||||
}
|
||||
inline void read_origin( Vector3& origin, const char* value ){
|
||||
if ( !string_parse_vector3( value, origin ) ) {
|
||||
default_origin( origin );
|
||||
}
|
||||
}
|
||||
inline void write_origin(const Vector3& origin, Entity* entity, const char* key)
|
||||
{
|
||||
char value[64];
|
||||
sprintf(value, "%f %f %f", origin[0], origin[1], origin[2]);
|
||||
entity->setKeyValue(key, value);
|
||||
inline void write_origin( const Vector3& origin, Entity* entity, const char* key ){
|
||||
char value[64];
|
||||
sprintf( value, "%f %f %f", origin[0], origin[1], origin[2] );
|
||||
entity->setKeyValue( key, value );
|
||||
}
|
||||
|
||||
inline Vector3 origin_translated(const Vector3& origin, const Vector3& translation)
|
||||
{
|
||||
return matrix4_get_translation_vec3(
|
||||
matrix4_multiplied_by_matrix4(
|
||||
matrix4_translation_for_vec3(origin),
|
||||
matrix4_translation_for_vec3(translation)
|
||||
)
|
||||
);
|
||||
inline Vector3 origin_translated( const Vector3& origin, const Vector3& translation ){
|
||||
return matrix4_get_translation_vec3(
|
||||
matrix4_multiplied_by_matrix4(
|
||||
matrix4_translation_for_vec3( origin ),
|
||||
matrix4_translation_for_vec3( translation )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
inline Vector3 origin_snapped(const Vector3& origin, float snap)
|
||||
{
|
||||
return vector3_snapped(origin, snap);
|
||||
inline Vector3 origin_snapped( const Vector3& origin, float snap ){
|
||||
return vector3_snapped( origin, snap );
|
||||
}
|
||||
|
||||
class OriginKey
|
||||
{
|
||||
Callback m_originChanged;
|
||||
Callback m_originChanged;
|
||||
public:
|
||||
Vector3 m_origin;
|
||||
Vector3 m_origin;
|
||||
|
||||
|
||||
OriginKey(const Callback& originChanged)
|
||||
: m_originChanged(originChanged), m_origin(ORIGINKEY_IDENTITY)
|
||||
{
|
||||
}
|
||||
OriginKey( const Callback& originChanged )
|
||||
: m_originChanged( originChanged ), m_origin( ORIGINKEY_IDENTITY ){
|
||||
}
|
||||
|
||||
void originChanged(const char* value)
|
||||
{
|
||||
read_origin(m_origin, value);
|
||||
m_originChanged();
|
||||
}
|
||||
typedef MemberCaller1<OriginKey, const char*, &OriginKey::originChanged> OriginChangedCaller;
|
||||
void originChanged( const char* value ){
|
||||
read_origin( m_origin, value );
|
||||
m_originChanged();
|
||||
}
|
||||
typedef MemberCaller1<OriginKey, const char*, &OriginKey::originChanged> OriginChangedCaller;
|
||||
|
||||
|
||||
void write(Entity* entity) const
|
||||
{
|
||||
write_origin(m_origin, entity, "origin");
|
||||
}
|
||||
void write( Entity* entity ) const {
|
||||
write_origin( m_origin, entity, "origin" );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#include "scenelib.h"
|
||||
|
||||
inline BrushDoom3* Node_getBrushDoom3(scene::Node& node)
|
||||
{
|
||||
return NodeTypeCast<BrushDoom3>::cast(node);
|
||||
inline BrushDoom3* Node_getBrushDoom3( scene::Node& node ){
|
||||
return NodeTypeCast<BrushDoom3>::cast( node );
|
||||
}
|
||||
|
||||
inline void BrushDoom3_setDoom3GroupOrigin(scene::Node& node, const Vector3& origin)
|
||||
{
|
||||
BrushDoom3* brush = Node_getBrushDoom3(node);
|
||||
if(brush != 0)
|
||||
{
|
||||
brush->setDoom3GroupOrigin(origin);
|
||||
}
|
||||
inline void BrushDoom3_setDoom3GroupOrigin( scene::Node& node, const Vector3& origin ){
|
||||
BrushDoom3* brush = Node_getBrushDoom3( node );
|
||||
if ( brush != 0 ) {
|
||||
brush->setDoom3GroupOrigin( origin );
|
||||
}
|
||||
}
|
||||
|
||||
class SetDoom3GroupOriginWalker : public scene::Traversable::Walker
|
||||
{
|
||||
const Vector3& m_origin;
|
||||
const Vector3& m_origin;
|
||||
public:
|
||||
SetDoom3GroupOriginWalker(const Vector3& origin) : m_origin(origin)
|
||||
{
|
||||
}
|
||||
bool pre(scene::Node& node) const
|
||||
{
|
||||
BrushDoom3_setDoom3GroupOrigin(node, m_origin);
|
||||
return true;
|
||||
}
|
||||
SetDoom3GroupOriginWalker( const Vector3& origin ) : m_origin( origin ){
|
||||
}
|
||||
bool pre( scene::Node& node ) const {
|
||||
BrushDoom3_setDoom3GroupOrigin( node, m_origin );
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class Doom3GroupOrigin : public scene::Traversable::Observer
|
||||
{
|
||||
scene::Traversable& m_set;
|
||||
const Vector3& m_origin;
|
||||
bool m_enabled;
|
||||
scene::Traversable& m_set;
|
||||
const Vector3& m_origin;
|
||||
bool m_enabled;
|
||||
|
||||
public:
|
||||
Doom3GroupOrigin(scene::Traversable& set, const Vector3& origin) : m_set(set), m_origin(origin), m_enabled(false)
|
||||
{
|
||||
}
|
||||
Doom3GroupOrigin( scene::Traversable& set, const Vector3& origin ) : m_set( set ), m_origin( origin ), m_enabled( false ){
|
||||
}
|
||||
|
||||
void enable()
|
||||
{
|
||||
m_enabled = true;
|
||||
originChanged();
|
||||
}
|
||||
void disable()
|
||||
{
|
||||
m_enabled = false;
|
||||
}
|
||||
void enable(){
|
||||
m_enabled = true;
|
||||
originChanged();
|
||||
}
|
||||
void disable(){
|
||||
m_enabled = false;
|
||||
}
|
||||
|
||||
void originChanged()
|
||||
{
|
||||
if(m_enabled)
|
||||
{
|
||||
m_set.traverse(SetDoom3GroupOriginWalker(m_origin));
|
||||
}
|
||||
}
|
||||
void originChanged(){
|
||||
if ( m_enabled ) {
|
||||
m_set.traverse( SetDoom3GroupOriginWalker( m_origin ) );
|
||||
}
|
||||
}
|
||||
|
||||
void insert(scene::Node& node)
|
||||
{
|
||||
if(m_enabled)
|
||||
{
|
||||
BrushDoom3_setDoom3GroupOrigin(node, m_origin);
|
||||
}
|
||||
}
|
||||
void erase(scene::Node& node)
|
||||
{
|
||||
if(m_enabled)
|
||||
{
|
||||
BrushDoom3_setDoom3GroupOrigin(node, Vector3(0, 0, 0));
|
||||
}
|
||||
}
|
||||
void insert( scene::Node& node ){
|
||||
if ( m_enabled ) {
|
||||
BrushDoom3_setDoom3GroupOrigin( node, m_origin );
|
||||
}
|
||||
}
|
||||
void erase( scene::Node& node ){
|
||||
if ( m_enabled ) {
|
||||
BrushDoom3_setDoom3GroupOrigin( node, Vector3( 0, 0, 0 ) );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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"
|
||||
|
||||
@@ -45,43 +45,40 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
|
||||
class EntityDependencies :
|
||||
public GlobalRadiantModuleRef,
|
||||
public GlobalOpenGLModuleRef,
|
||||
public GlobalUndoModuleRef,
|
||||
public GlobalSceneGraphModuleRef,
|
||||
public GlobalShaderCacheModuleRef,
|
||||
public GlobalSelectionModuleRef,
|
||||
public GlobalReferenceModuleRef,
|
||||
public GlobalFilterModuleRef,
|
||||
public GlobalPreferenceSystemModuleRef,
|
||||
public GlobalNamespaceModuleRef,
|
||||
public GlobalModelSkinCacheModuleRef
|
||||
public GlobalRadiantModuleRef,
|
||||
public GlobalOpenGLModuleRef,
|
||||
public GlobalUndoModuleRef,
|
||||
public GlobalSceneGraphModuleRef,
|
||||
public GlobalShaderCacheModuleRef,
|
||||
public GlobalSelectionModuleRef,
|
||||
public GlobalReferenceModuleRef,
|
||||
public GlobalFilterModuleRef,
|
||||
public GlobalPreferenceSystemModuleRef,
|
||||
public GlobalNamespaceModuleRef,
|
||||
public GlobalModelSkinCacheModuleRef
|
||||
{
|
||||
};
|
||||
|
||||
class EntityQ3API : public TypeSystemRef
|
||||
{
|
||||
EntityCreator* m_entityq3;
|
||||
EntityCreator* m_entityq3;
|
||||
public:
|
||||
typedef EntityCreator Type;
|
||||
STRING_CONSTANT(Name, "quake3");
|
||||
typedef EntityCreator Type;
|
||||
STRING_CONSTANT( Name, "quake3" );
|
||||
|
||||
EntityQ3API()
|
||||
{
|
||||
Entity_Construct();
|
||||
EntityQ3API(){
|
||||
Entity_Construct();
|
||||
|
||||
m_entityq3 = &GetEntityCreator();
|
||||
m_entityq3 = &GetEntityCreator();
|
||||
|
||||
GlobalReferenceCache().setEntityCreator(*m_entityq3);
|
||||
}
|
||||
~EntityQ3API()
|
||||
{
|
||||
Entity_Destroy();
|
||||
}
|
||||
EntityCreator* getTable()
|
||||
{
|
||||
return m_entityq3;
|
||||
}
|
||||
GlobalReferenceCache().setEntityCreator( *m_entityq3 );
|
||||
}
|
||||
~EntityQ3API(){
|
||||
Entity_Destroy();
|
||||
}
|
||||
EntityCreator* getTable(){
|
||||
return m_entityq3;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<EntityQ3API, EntityDependencies> EntityQ3Module;
|
||||
@@ -91,27 +88,24 @@ EntityQ3Module g_EntityQ3Module;
|
||||
|
||||
class EntityWolfAPI : public TypeSystemRef
|
||||
{
|
||||
EntityCreator* m_entitywolf;
|
||||
EntityCreator* m_entitywolf;
|
||||
public:
|
||||
typedef EntityCreator Type;
|
||||
STRING_CONSTANT(Name, "wolf");
|
||||
typedef EntityCreator Type;
|
||||
STRING_CONSTANT( Name, "wolf" );
|
||||
|
||||
EntityWolfAPI()
|
||||
{
|
||||
Entity_Construct(eGameTypeRTCW);
|
||||
EntityWolfAPI(){
|
||||
Entity_Construct( eGameTypeRTCW );
|
||||
|
||||
m_entitywolf = &GetEntityCreator();
|
||||
m_entitywolf = &GetEntityCreator();
|
||||
|
||||
GlobalReferenceCache().setEntityCreator(*m_entitywolf);
|
||||
}
|
||||
~EntityWolfAPI()
|
||||
{
|
||||
Entity_Destroy();
|
||||
}
|
||||
EntityCreator* getTable()
|
||||
{
|
||||
return m_entitywolf;
|
||||
}
|
||||
GlobalReferenceCache().setEntityCreator( *m_entitywolf );
|
||||
}
|
||||
~EntityWolfAPI(){
|
||||
Entity_Destroy();
|
||||
}
|
||||
EntityCreator* getTable(){
|
||||
return m_entitywolf;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<EntityWolfAPI, EntityDependencies> EntityWolfModule;
|
||||
@@ -121,27 +115,24 @@ EntityWolfModule g_EntityWolfModule;
|
||||
|
||||
class EntityDoom3API : public TypeSystemRef
|
||||
{
|
||||
EntityCreator* m_entitydoom3;
|
||||
EntityCreator* m_entitydoom3;
|
||||
public:
|
||||
typedef EntityCreator Type;
|
||||
STRING_CONSTANT(Name, "doom3");
|
||||
typedef EntityCreator Type;
|
||||
STRING_CONSTANT( Name, "doom3" );
|
||||
|
||||
EntityDoom3API()
|
||||
{
|
||||
Entity_Construct(eGameTypeDoom3);
|
||||
EntityDoom3API(){
|
||||
Entity_Construct( eGameTypeDoom3 );
|
||||
|
||||
m_entitydoom3 = &GetEntityCreator();
|
||||
m_entitydoom3 = &GetEntityCreator();
|
||||
|
||||
GlobalReferenceCache().setEntityCreator(*m_entitydoom3);
|
||||
}
|
||||
~EntityDoom3API()
|
||||
{
|
||||
Entity_Destroy();
|
||||
}
|
||||
EntityCreator* getTable()
|
||||
{
|
||||
return m_entitydoom3;
|
||||
}
|
||||
GlobalReferenceCache().setEntityCreator( *m_entitydoom3 );
|
||||
}
|
||||
~EntityDoom3API(){
|
||||
Entity_Destroy();
|
||||
}
|
||||
EntityCreator* getTable(){
|
||||
return m_entitydoom3;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<EntityDoom3API, EntityDependencies> EntityDoom3Module;
|
||||
@@ -149,12 +140,11 @@ typedef SingletonModule<EntityDoom3API, EntityDependencies> EntityDoom3Module;
|
||||
EntityDoom3Module g_EntityDoom3Module;
|
||||
|
||||
|
||||
extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer& server)
|
||||
{
|
||||
initialiseModule(server);
|
||||
extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){
|
||||
initialiseModule( server );
|
||||
|
||||
g_EntityQ3Module.selfRegister();
|
||||
g_EntityWolfModule.selfRegister();
|
||||
g_EntityDoom3Module.selfRegister();
|
||||
Doom3ModelSkinCacheModule_selfRegister(server);
|
||||
g_EntityQ3Module.selfRegister();
|
||||
g_EntityWolfModule.selfRegister();
|
||||
g_EntityDoom3Module.selfRegister();
|
||||
Doom3ModelSkinCacheModule_selfRegister( server );
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_PLUGIN_H)
|
||||
#if !defined( INCLUDED_PLUGIN_H )
|
||||
#define INCLUDED_PLUGIN_H
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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 "rotation.h"
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_ROTATION_H)
|
||||
#if !defined( INCLUDED_ROTATION_H )
|
||||
#define INCLUDED_ROTATION_H
|
||||
|
||||
#include "ientity.h"
|
||||
@@ -33,167 +33,151 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
typedef float Float9[9];
|
||||
|
||||
inline void default_rotation(Float9 rotation)
|
||||
{
|
||||
rotation[0] = 1;
|
||||
rotation[1] = 0;
|
||||
rotation[2] = 0;
|
||||
rotation[3] = 0;
|
||||
rotation[4] = 1;
|
||||
rotation[5] = 0;
|
||||
rotation[6] = 0;
|
||||
rotation[7] = 0;
|
||||
rotation[8] = 1;
|
||||
inline void default_rotation( Float9 rotation ){
|
||||
rotation[0] = 1;
|
||||
rotation[1] = 0;
|
||||
rotation[2] = 0;
|
||||
rotation[3] = 0;
|
||||
rotation[4] = 1;
|
||||
rotation[5] = 0;
|
||||
rotation[6] = 0;
|
||||
rotation[7] = 0;
|
||||
rotation[8] = 1;
|
||||
}
|
||||
inline void write_rotation(const Float9 rotation, Entity* entity, const char* key = "rotation")
|
||||
{
|
||||
if(rotation[0] == 1
|
||||
&& rotation[1] == 0
|
||||
&& rotation[2] == 0
|
||||
&& rotation[3] == 0
|
||||
&& rotation[4] == 1
|
||||
&& rotation[5] == 0
|
||||
&& rotation[6] == 0
|
||||
&& rotation[7] == 0
|
||||
&& rotation[8] == 1)
|
||||
{
|
||||
entity->setKeyValue(key, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
StringOutputStream value(256);
|
||||
value << rotation[0] << ' '
|
||||
<< rotation[1] << ' '
|
||||
<< rotation[2] << ' '
|
||||
<< rotation[3] << ' '
|
||||
<< rotation[4] << ' '
|
||||
<< rotation[5] << ' '
|
||||
<< rotation[6] << ' '
|
||||
<< rotation[7] << ' '
|
||||
<< rotation[8];
|
||||
entity->setKeyValue(key, value.c_str());
|
||||
}
|
||||
inline void write_rotation( const Float9 rotation, Entity* entity, const char* key = "rotation" ){
|
||||
if ( rotation[0] == 1
|
||||
&& rotation[1] == 0
|
||||
&& rotation[2] == 0
|
||||
&& rotation[3] == 0
|
||||
&& rotation[4] == 1
|
||||
&& rotation[5] == 0
|
||||
&& rotation[6] == 0
|
||||
&& rotation[7] == 0
|
||||
&& rotation[8] == 1 ) {
|
||||
entity->setKeyValue( key, "" );
|
||||
}
|
||||
else
|
||||
{
|
||||
StringOutputStream value( 256 );
|
||||
value << rotation[0] << ' '
|
||||
<< rotation[1] << ' '
|
||||
<< rotation[2] << ' '
|
||||
<< rotation[3] << ' '
|
||||
<< rotation[4] << ' '
|
||||
<< rotation[5] << ' '
|
||||
<< rotation[6] << ' '
|
||||
<< rotation[7] << ' '
|
||||
<< rotation[8];
|
||||
entity->setKeyValue( key, value.c_str() );
|
||||
}
|
||||
}
|
||||
inline void read_rotation(Float9 rotation, const char* value)
|
||||
{
|
||||
if(!string_parse_vector(value, rotation, rotation + 9))
|
||||
{
|
||||
default_rotation(rotation);
|
||||
}
|
||||
inline void read_rotation( Float9 rotation, const char* value ){
|
||||
if ( !string_parse_vector( value, rotation, rotation + 9 ) ) {
|
||||
default_rotation( rotation );
|
||||
}
|
||||
}
|
||||
|
||||
inline Matrix4 rotation_toMatrix(const Float9 rotation)
|
||||
{
|
||||
return Matrix4(
|
||||
rotation[0],
|
||||
rotation[1],
|
||||
rotation[2],
|
||||
0,
|
||||
rotation[3],
|
||||
rotation[4],
|
||||
rotation[5],
|
||||
0,
|
||||
rotation[6],
|
||||
rotation[7],
|
||||
rotation[8],
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
);
|
||||
inline Matrix4 rotation_toMatrix( const Float9 rotation ){
|
||||
return Matrix4(
|
||||
rotation[0],
|
||||
rotation[1],
|
||||
rotation[2],
|
||||
0,
|
||||
rotation[3],
|
||||
rotation[4],
|
||||
rotation[5],
|
||||
0,
|
||||
rotation[6],
|
||||
rotation[7],
|
||||
rotation[8],
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
inline void rotation_fromMatrix(Float9 rotation, const Matrix4& matrix)
|
||||
{
|
||||
rotation[0] = matrix.xx();
|
||||
rotation[1] = matrix.xy();
|
||||
rotation[2] = matrix.xz();
|
||||
rotation[3] = matrix.yx();
|
||||
rotation[4] = matrix.yy();
|
||||
rotation[5] = matrix.yz();
|
||||
rotation[6] = matrix.zx();
|
||||
rotation[7] = matrix.zy();
|
||||
rotation[8] = matrix.zz();
|
||||
inline void rotation_fromMatrix( Float9 rotation, const Matrix4& matrix ){
|
||||
rotation[0] = matrix.xx();
|
||||
rotation[1] = matrix.xy();
|
||||
rotation[2] = matrix.xz();
|
||||
rotation[3] = matrix.yx();
|
||||
rotation[4] = matrix.yy();
|
||||
rotation[5] = matrix.yz();
|
||||
rotation[6] = matrix.zx();
|
||||
rotation[7] = matrix.zy();
|
||||
rotation[8] = matrix.zz();
|
||||
}
|
||||
|
||||
inline void rotation_assign(Float9 rotation, const Float9 other)
|
||||
{
|
||||
rotation[0] = other[0];
|
||||
rotation[1] = other[1];
|
||||
rotation[2] = other[2];
|
||||
rotation[3] = other[3];
|
||||
rotation[4] = other[4];
|
||||
rotation[5] = other[5];
|
||||
rotation[6] = other[6];
|
||||
rotation[7] = other[7];
|
||||
rotation[8] = other[8];
|
||||
inline void rotation_assign( Float9 rotation, const Float9 other ){
|
||||
rotation[0] = other[0];
|
||||
rotation[1] = other[1];
|
||||
rotation[2] = other[2];
|
||||
rotation[3] = other[3];
|
||||
rotation[4] = other[4];
|
||||
rotation[5] = other[5];
|
||||
rotation[6] = other[6];
|
||||
rotation[7] = other[7];
|
||||
rotation[8] = other[8];
|
||||
}
|
||||
|
||||
inline void rotation_rotate(Float9 rotation, const Quaternion& rotate)
|
||||
{
|
||||
rotation_fromMatrix(rotation,
|
||||
matrix4_multiplied_by_matrix4(
|
||||
rotation_toMatrix(rotation),
|
||||
matrix4_rotation_for_quaternion_quantised(rotate)
|
||||
)
|
||||
);
|
||||
inline void rotation_rotate( Float9 rotation, const Quaternion& rotate ){
|
||||
rotation_fromMatrix( rotation,
|
||||
matrix4_multiplied_by_matrix4(
|
||||
rotation_toMatrix( rotation ),
|
||||
matrix4_rotation_for_quaternion_quantised( rotate )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
inline void read_angle(Float9 rotation, const char* value)
|
||||
{
|
||||
float angle;
|
||||
if(!string_parse_float(value, angle))
|
||||
{
|
||||
default_rotation(rotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
rotation_fromMatrix(rotation, matrix4_rotation_for_z_degrees(angle));
|
||||
}
|
||||
inline void read_angle( Float9 rotation, const char* value ){
|
||||
float angle;
|
||||
if ( !string_parse_float( value, angle ) ) {
|
||||
default_rotation( rotation );
|
||||
}
|
||||
else
|
||||
{
|
||||
rotation_fromMatrix( rotation, matrix4_rotation_for_z_degrees( angle ) );
|
||||
}
|
||||
}
|
||||
|
||||
class RotationKey
|
||||
{
|
||||
Callback m_rotationChanged;
|
||||
Callback m_rotationChanged;
|
||||
public:
|
||||
Float9 m_rotation;
|
||||
Float9 m_rotation;
|
||||
|
||||
|
||||
RotationKey(const Callback& rotationChanged)
|
||||
: m_rotationChanged(rotationChanged)
|
||||
{
|
||||
default_rotation(m_rotation);
|
||||
}
|
||||
RotationKey( const Callback& rotationChanged )
|
||||
: m_rotationChanged( rotationChanged ){
|
||||
default_rotation( m_rotation );
|
||||
}
|
||||
|
||||
void angleChanged(const char* value)
|
||||
{
|
||||
read_angle(m_rotation, value);
|
||||
m_rotationChanged();
|
||||
}
|
||||
typedef MemberCaller1<RotationKey, const char*, &RotationKey::angleChanged> AngleChangedCaller;
|
||||
void angleChanged( const char* value ){
|
||||
read_angle( m_rotation, value );
|
||||
m_rotationChanged();
|
||||
}
|
||||
typedef MemberCaller1<RotationKey, const char*, &RotationKey::angleChanged> AngleChangedCaller;
|
||||
|
||||
void rotationChanged(const char* value)
|
||||
{
|
||||
read_rotation(m_rotation, value);
|
||||
m_rotationChanged();
|
||||
}
|
||||
typedef MemberCaller1<RotationKey, const char*, &RotationKey::rotationChanged> RotationChangedCaller;
|
||||
void rotationChanged( const char* value ){
|
||||
read_rotation( m_rotation, value );
|
||||
m_rotationChanged();
|
||||
}
|
||||
typedef MemberCaller1<RotationKey, const char*, &RotationKey::rotationChanged> RotationChangedCaller;
|
||||
|
||||
void write(Entity* entity) const
|
||||
{
|
||||
Vector3 euler = matrix4_get_rotation_euler_xyz_degrees(rotation_toMatrix(m_rotation));
|
||||
if(euler[0] == 0 && euler[1] == 0)
|
||||
{
|
||||
entity->setKeyValue("rotation", "");
|
||||
write_angle(euler[2], entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
entity->setKeyValue("angle", "");
|
||||
write_rotation(m_rotation, entity);
|
||||
}
|
||||
}
|
||||
void write( Entity* entity ) const {
|
||||
Vector3 euler = matrix4_get_rotation_euler_xyz_degrees( rotation_toMatrix( m_rotation ) );
|
||||
if ( euler[0] == 0 && euler[1] == 0 ) {
|
||||
entity->setKeyValue( "rotation", "" );
|
||||
write_angle( euler[2], entity );
|
||||
}
|
||||
else
|
||||
{
|
||||
entity->setKeyValue( "angle", "" );
|
||||
write_rotation( m_rotation, entity );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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 "scale.h"
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_SCALE_H)
|
||||
#if !defined( INCLUDED_SCALE_H )
|
||||
#define INCLUDED_SCALE_H
|
||||
|
||||
#include "ientity.h"
|
||||
@@ -28,100 +28,89 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#include "generic/callback.h"
|
||||
#include "stringio.h"
|
||||
|
||||
const Vector3 SCALEKEY_IDENTITY = Vector3(1, 1, 1);
|
||||
const Vector3 SCALEKEY_IDENTITY = Vector3( 1, 1, 1 );
|
||||
|
||||
inline void default_scale(Vector3& scale)
|
||||
{
|
||||
scale = SCALEKEY_IDENTITY;
|
||||
inline void default_scale( Vector3& scale ){
|
||||
scale = SCALEKEY_IDENTITY;
|
||||
}
|
||||
inline void read_scale(Vector3& scalevec, const char* value)
|
||||
{
|
||||
float scale;
|
||||
if(!string_parse_float(value, scale)
|
||||
|| scale == 0)
|
||||
{
|
||||
default_scale(scalevec);
|
||||
}
|
||||
else
|
||||
{
|
||||
scalevec = Vector3(scale, scale, scale);
|
||||
}
|
||||
inline void read_scale( Vector3& scalevec, const char* value ){
|
||||
float scale;
|
||||
if ( !string_parse_float( value, scale )
|
||||
|| scale == 0 ) {
|
||||
default_scale( scalevec );
|
||||
}
|
||||
else
|
||||
{
|
||||
scalevec = Vector3( scale, scale, scale );
|
||||
}
|
||||
}
|
||||
inline void read_scalevec(Vector3& scale, const char* value)
|
||||
{
|
||||
if(!string_parse_vector3(value, scale)
|
||||
|| scale[0] == 0
|
||||
|| scale[1] == 0
|
||||
|| scale[2] == 0)
|
||||
default_scale(scale);
|
||||
inline void read_scalevec( Vector3& scale, const char* value ){
|
||||
if ( !string_parse_vector3( value, scale )
|
||||
|| scale[0] == 0
|
||||
|| scale[1] == 0
|
||||
|| scale[2] == 0 ) {
|
||||
default_scale( scale );
|
||||
}
|
||||
}
|
||||
inline void write_scale(const Vector3& scale, Entity* entity)
|
||||
{
|
||||
if(scale[0] == 1 && scale[1] == 1 && scale[2] == 1)
|
||||
{
|
||||
entity->setKeyValue("modelscale", "");
|
||||
entity->setKeyValue("modelscale_vec", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
char value[64];
|
||||
inline void write_scale( const Vector3& scale, Entity* entity ){
|
||||
if ( scale[0] == 1 && scale[1] == 1 && scale[2] == 1 ) {
|
||||
entity->setKeyValue( "modelscale", "" );
|
||||
entity->setKeyValue( "modelscale_vec", "" );
|
||||
}
|
||||
else
|
||||
{
|
||||
char value[64];
|
||||
|
||||
if(scale[0] == scale[1] && scale[0] == scale[2])
|
||||
{
|
||||
sprintf(value, "%f", scale[0]);
|
||||
entity->setKeyValue("modelscale_vec", "");
|
||||
entity->setKeyValue("modelscale", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(value, "%f %f %f", scale[0], scale[1], scale[2]);
|
||||
entity->setKeyValue("modelscale", "");
|
||||
entity->setKeyValue("modelscale_vec", value);
|
||||
}
|
||||
}
|
||||
if ( scale[0] == scale[1] && scale[0] == scale[2] ) {
|
||||
sprintf( value, "%f", scale[0] );
|
||||
entity->setKeyValue( "modelscale_vec", "" );
|
||||
entity->setKeyValue( "modelscale", value );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( value, "%f %f %f", scale[0], scale[1], scale[2] );
|
||||
entity->setKeyValue( "modelscale", "" );
|
||||
entity->setKeyValue( "modelscale_vec", value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline Vector3 scale_scaled(const Vector3& scale, const Vector3& scaling)
|
||||
{
|
||||
return matrix4_get_scale_vec3(
|
||||
matrix4_multiplied_by_matrix4(
|
||||
matrix4_scale_for_vec3(scale),
|
||||
matrix4_scale_for_vec3(scaling)
|
||||
)
|
||||
);
|
||||
inline Vector3 scale_scaled( const Vector3& scale, const Vector3& scaling ){
|
||||
return matrix4_get_scale_vec3(
|
||||
matrix4_multiplied_by_matrix4(
|
||||
matrix4_scale_for_vec3( scale ),
|
||||
matrix4_scale_for_vec3( scaling )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
class ScaleKey
|
||||
{
|
||||
Callback m_scaleChanged;
|
||||
Callback m_scaleChanged;
|
||||
public:
|
||||
Vector3 m_scale;
|
||||
Vector3 m_scale;
|
||||
|
||||
|
||||
ScaleKey(const Callback& scaleChanged)
|
||||
: m_scaleChanged(scaleChanged), m_scale(SCALEKEY_IDENTITY)
|
||||
{
|
||||
}
|
||||
ScaleKey( const Callback& scaleChanged )
|
||||
: m_scaleChanged( scaleChanged ), m_scale( SCALEKEY_IDENTITY ){
|
||||
}
|
||||
|
||||
void uniformScaleChanged(const char* value)
|
||||
{
|
||||
read_scale(m_scale, value);
|
||||
m_scaleChanged();
|
||||
}
|
||||
typedef MemberCaller1<ScaleKey, const char*, &ScaleKey::uniformScaleChanged> UniformScaleChangedCaller;
|
||||
void uniformScaleChanged( const char* value ){
|
||||
read_scale( m_scale, value );
|
||||
m_scaleChanged();
|
||||
}
|
||||
typedef MemberCaller1<ScaleKey, const char*, &ScaleKey::uniformScaleChanged> UniformScaleChangedCaller;
|
||||
|
||||
void scaleChanged(const char* value)
|
||||
{
|
||||
read_scalevec(m_scale, value);
|
||||
m_scaleChanged();
|
||||
}
|
||||
typedef MemberCaller1<ScaleKey, const char*, &ScaleKey::scaleChanged> ScaleChangedCaller;
|
||||
void scaleChanged( const char* value ){
|
||||
read_scalevec( m_scale, value );
|
||||
m_scaleChanged();
|
||||
}
|
||||
typedef MemberCaller1<ScaleKey, const char*, &ScaleKey::scaleChanged> ScaleChangedCaller;
|
||||
|
||||
void write(Entity* entity) const
|
||||
{
|
||||
write_scale(m_scale, entity);
|
||||
}
|
||||
void write( Entity* entity ) const {
|
||||
write_scale( m_scale, entity );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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 "skincache.h"
|
||||
|
||||
@@ -37,162 +37,141 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
#include "stringio.h"
|
||||
|
||||
void parseShaderName(CopiedString& name, const char* token)
|
||||
{
|
||||
StringOutputStream cleaned(256);
|
||||
cleaned << PathCleaned(token);
|
||||
name = cleaned.c_str();
|
||||
void parseShaderName( CopiedString& name, const char* token ){
|
||||
StringOutputStream cleaned( 256 );
|
||||
cleaned << PathCleaned( token );
|
||||
name = cleaned.c_str();
|
||||
}
|
||||
|
||||
class Doom3ModelSkin
|
||||
{
|
||||
typedef std::map<CopiedString, CopiedString> Remaps;
|
||||
Remaps m_remaps;
|
||||
typedef std::map<CopiedString, CopiedString> Remaps;
|
||||
Remaps m_remaps;
|
||||
public:
|
||||
bool parseTokens(Tokeniser& tokeniser)
|
||||
{
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "{"));
|
||||
tokeniser.nextLine();
|
||||
for(;;)
|
||||
{
|
||||
const char* token = tokeniser.getToken();
|
||||
if(token == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(string_equal(token, "}"))
|
||||
{
|
||||
tokeniser.nextLine();
|
||||
return true;
|
||||
}
|
||||
else if(string_equal(token, "model"))
|
||||
{
|
||||
//const char* model =
|
||||
tokeniser.getToken();
|
||||
}
|
||||
else
|
||||
{
|
||||
CopiedString from, to;
|
||||
parseShaderName(from, token);
|
||||
bool parseTokens( Tokeniser& tokeniser ){
|
||||
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "{" ) );
|
||||
tokeniser.nextLine();
|
||||
for (;; )
|
||||
{
|
||||
const char* token = tokeniser.getToken();
|
||||
if ( token == 0 ) {
|
||||
return false;
|
||||
}
|
||||
if ( string_equal( token, "}" ) ) {
|
||||
tokeniser.nextLine();
|
||||
return true;
|
||||
}
|
||||
else if ( string_equal( token, "model" ) ) {
|
||||
//const char* model =
|
||||
tokeniser.getToken();
|
||||
}
|
||||
else
|
||||
{
|
||||
CopiedString from, to;
|
||||
parseShaderName( from, token );
|
||||
|
||||
tokeniser.nextLine(); // hack to handle badly formed skins
|
||||
tokeniser.nextLine(); // hack to handle badly formed skins
|
||||
|
||||
parseShaderName(to, tokeniser.getToken());
|
||||
parseShaderName( to, tokeniser.getToken() );
|
||||
|
||||
if(!string_equal(from.c_str(), to.c_str()))
|
||||
{
|
||||
m_remaps.insert(Remaps::value_type(from, to));
|
||||
}
|
||||
}
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
}
|
||||
const char* getRemap(const char* name) const
|
||||
{
|
||||
Remaps::const_iterator i = m_remaps.find(name);
|
||||
if(i != m_remaps.end())
|
||||
{
|
||||
return (*i).second.c_str();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
void forEachRemap(const SkinRemapCallback& callback) const
|
||||
{
|
||||
for(Remaps::const_iterator i = m_remaps.begin(); i != m_remaps.end(); ++i)
|
||||
{
|
||||
callback(SkinRemap((*i).first.c_str(), (*i).second.c_str()));
|
||||
}
|
||||
}
|
||||
if ( !string_equal( from.c_str(), to.c_str() ) ) {
|
||||
m_remaps.insert( Remaps::value_type( from, to ) );
|
||||
}
|
||||
}
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
}
|
||||
const char* getRemap( const char* name ) const {
|
||||
Remaps::const_iterator i = m_remaps.find( name );
|
||||
if ( i != m_remaps.end() ) {
|
||||
return ( *i ).second.c_str();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
void forEachRemap( const SkinRemapCallback& callback ) const {
|
||||
for ( Remaps::const_iterator i = m_remaps.begin(); i != m_remaps.end(); ++i )
|
||||
{
|
||||
callback( SkinRemap( ( *i ).first.c_str(), ( *i ).second.c_str() ) );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class GlobalSkins
|
||||
{
|
||||
public:
|
||||
typedef std::map<CopiedString, Doom3ModelSkin> SkinMap;
|
||||
SkinMap m_skins;
|
||||
Doom3ModelSkin g_nullSkin;
|
||||
typedef std::map<CopiedString, Doom3ModelSkin> SkinMap;
|
||||
SkinMap m_skins;
|
||||
Doom3ModelSkin g_nullSkin;
|
||||
|
||||
Doom3ModelSkin& getSkin(const char* name)
|
||||
{
|
||||
SkinMap::iterator i = m_skins.find(name);
|
||||
if(i != m_skins.end())
|
||||
{
|
||||
return (*i).second;
|
||||
}
|
||||
|
||||
return g_nullSkin;
|
||||
}
|
||||
Doom3ModelSkin& getSkin( const char* name ){
|
||||
SkinMap::iterator i = m_skins.find( name );
|
||||
if ( i != m_skins.end() ) {
|
||||
return ( *i ).second;
|
||||
}
|
||||
|
||||
bool parseTokens(Tokeniser& tokeniser)
|
||||
{
|
||||
tokeniser.nextLine();
|
||||
for(;;)
|
||||
{
|
||||
const char* token = tokeniser.getToken();
|
||||
if(token == 0)
|
||||
{
|
||||
// end of token stream
|
||||
return true;
|
||||
}
|
||||
if(!string_equal(token, "skin"))
|
||||
{
|
||||
Tokeniser_unexpectedError(tokeniser, token, "skin");
|
||||
return false;
|
||||
}
|
||||
const char* other = tokeniser.getToken();
|
||||
if(other == 0)
|
||||
{
|
||||
Tokeniser_unexpectedError(tokeniser, token, "#string");
|
||||
return false;
|
||||
}
|
||||
CopiedString name;
|
||||
parseShaderName(name, other);
|
||||
Doom3ModelSkin& skin = m_skins[name];
|
||||
RETURN_FALSE_IF_FAIL(skin.parseTokens(tokeniser));
|
||||
}
|
||||
}
|
||||
return g_nullSkin;
|
||||
}
|
||||
|
||||
void parseFile(const char* name)
|
||||
{
|
||||
StringOutputStream relativeName(64);
|
||||
relativeName << "skins/" << name;
|
||||
ArchiveTextFile* file = GlobalFileSystem().openTextFile(relativeName.c_str());
|
||||
if(file != 0)
|
||||
{
|
||||
globalOutputStream() << "parsing skins from " << makeQuoted(name) << "\n";
|
||||
{
|
||||
Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser(file->getInputStream());
|
||||
parseTokens(tokeniser);
|
||||
tokeniser.release();
|
||||
}
|
||||
file->release();
|
||||
}
|
||||
else
|
||||
{
|
||||
globalErrorStream() << "failed to open " << makeQuoted(name) << "\n";
|
||||
}
|
||||
}
|
||||
bool parseTokens( Tokeniser& tokeniser ){
|
||||
tokeniser.nextLine();
|
||||
for (;; )
|
||||
{
|
||||
const char* token = tokeniser.getToken();
|
||||
if ( token == 0 ) {
|
||||
// end of token stream
|
||||
return true;
|
||||
}
|
||||
if ( !string_equal( token, "skin" ) ) {
|
||||
Tokeniser_unexpectedError( tokeniser, token, "skin" );
|
||||
return false;
|
||||
}
|
||||
const char* other = tokeniser.getToken();
|
||||
if ( other == 0 ) {
|
||||
Tokeniser_unexpectedError( tokeniser, token, "#string" );
|
||||
return false;
|
||||
}
|
||||
CopiedString name;
|
||||
parseShaderName( name, other );
|
||||
Doom3ModelSkin& skin = m_skins[name];
|
||||
RETURN_FALSE_IF_FAIL( skin.parseTokens( tokeniser ) );
|
||||
}
|
||||
}
|
||||
|
||||
typedef MemberCaller1<GlobalSkins, const char*, &GlobalSkins::parseFile> ParseFileCaller;
|
||||
void parseFile( const char* name ){
|
||||
StringOutputStream relativeName( 64 );
|
||||
relativeName << "skins/" << name;
|
||||
ArchiveTextFile* file = GlobalFileSystem().openTextFile( relativeName.c_str() );
|
||||
if ( file != 0 ) {
|
||||
globalOutputStream() << "parsing skins from " << makeQuoted( name ) << "\n";
|
||||
{
|
||||
Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser( file->getInputStream() );
|
||||
parseTokens( tokeniser );
|
||||
tokeniser.release();
|
||||
}
|
||||
file->release();
|
||||
}
|
||||
else
|
||||
{
|
||||
globalErrorStream() << "failed to open " << makeQuoted( name ) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void construct()
|
||||
{
|
||||
GlobalFileSystem().forEachFile("skins/", "skin", ParseFileCaller(*this));
|
||||
}
|
||||
typedef MemberCaller1<GlobalSkins, const char*, &GlobalSkins::parseFile> ParseFileCaller;
|
||||
|
||||
void destroy()
|
||||
{
|
||||
m_skins.clear();
|
||||
}
|
||||
void construct(){
|
||||
GlobalFileSystem().forEachFile( "skins/", "skin", ParseFileCaller( *this ) );
|
||||
}
|
||||
|
||||
void realise()
|
||||
{
|
||||
construct();
|
||||
}
|
||||
void unrealise()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
void destroy(){
|
||||
m_skins.clear();
|
||||
}
|
||||
|
||||
void realise(){
|
||||
construct();
|
||||
}
|
||||
void unrealise(){
|
||||
destroy();
|
||||
}
|
||||
};
|
||||
|
||||
GlobalSkins g_skins;
|
||||
@@ -200,137 +179,114 @@ GlobalSkins g_skins;
|
||||
|
||||
class Doom3ModelSkinCacheElement : public ModelSkin
|
||||
{
|
||||
ModuleObservers m_observers;
|
||||
Doom3ModelSkin* m_skin;
|
||||
ModuleObservers m_observers;
|
||||
Doom3ModelSkin* m_skin;
|
||||
public:
|
||||
Doom3ModelSkinCacheElement() : m_skin(0)
|
||||
{
|
||||
}
|
||||
void attach(ModuleObserver& observer)
|
||||
{
|
||||
m_observers.attach(observer);
|
||||
if(realised())
|
||||
{
|
||||
observer.realise();
|
||||
}
|
||||
}
|
||||
void detach(ModuleObserver& observer)
|
||||
{
|
||||
if(realised())
|
||||
{
|
||||
observer.unrealise();
|
||||
}
|
||||
m_observers.detach(observer);
|
||||
}
|
||||
bool realised() const
|
||||
{
|
||||
return m_skin != 0;
|
||||
}
|
||||
void realise(const char* name)
|
||||
{
|
||||
ASSERT_MESSAGE(!realised(), "Doom3ModelSkinCacheElement::realise: already realised");
|
||||
m_skin = &g_skins.getSkin(name);
|
||||
m_observers.realise();
|
||||
}
|
||||
void unrealise()
|
||||
{
|
||||
ASSERT_MESSAGE(realised(), "Doom3ModelSkinCacheElement::unrealise: not realised");
|
||||
m_observers.unrealise();
|
||||
m_skin = 0;
|
||||
}
|
||||
const char* getRemap(const char* name) const
|
||||
{
|
||||
ASSERT_MESSAGE(realised(), "Doom3ModelSkinCacheElement::getRemap: not realised");
|
||||
return m_skin->getRemap(name);
|
||||
}
|
||||
void forEachRemap(const SkinRemapCallback& callback) const
|
||||
{
|
||||
ASSERT_MESSAGE(realised(), "Doom3ModelSkinCacheElement::forEachRemap: not realised");
|
||||
m_skin->forEachRemap(callback);
|
||||
}
|
||||
Doom3ModelSkinCacheElement() : m_skin( 0 ){
|
||||
}
|
||||
void attach( ModuleObserver& observer ){
|
||||
m_observers.attach( observer );
|
||||
if ( realised() ) {
|
||||
observer.realise();
|
||||
}
|
||||
}
|
||||
void detach( ModuleObserver& observer ){
|
||||
if ( realised() ) {
|
||||
observer.unrealise();
|
||||
}
|
||||
m_observers.detach( observer );
|
||||
}
|
||||
bool realised() const {
|
||||
return m_skin != 0;
|
||||
}
|
||||
void realise( const char* name ){
|
||||
ASSERT_MESSAGE( !realised(), "Doom3ModelSkinCacheElement::realise: already realised" );
|
||||
m_skin = &g_skins.getSkin( name );
|
||||
m_observers.realise();
|
||||
}
|
||||
void unrealise(){
|
||||
ASSERT_MESSAGE( realised(), "Doom3ModelSkinCacheElement::unrealise: not realised" );
|
||||
m_observers.unrealise();
|
||||
m_skin = 0;
|
||||
}
|
||||
const char* getRemap( const char* name ) const {
|
||||
ASSERT_MESSAGE( realised(), "Doom3ModelSkinCacheElement::getRemap: not realised" );
|
||||
return m_skin->getRemap( name );
|
||||
}
|
||||
void forEachRemap( const SkinRemapCallback& callback ) const {
|
||||
ASSERT_MESSAGE( realised(), "Doom3ModelSkinCacheElement::forEachRemap: not realised" );
|
||||
m_skin->forEachRemap( callback );
|
||||
}
|
||||
};
|
||||
|
||||
class Doom3ModelSkinCache : public ModelSkinCache, public ModuleObserver
|
||||
{
|
||||
class CreateDoom3ModelSkin
|
||||
{
|
||||
Doom3ModelSkinCache& m_cache;
|
||||
public:
|
||||
explicit CreateDoom3ModelSkin(Doom3ModelSkinCache& cache)
|
||||
: m_cache(cache)
|
||||
{
|
||||
}
|
||||
Doom3ModelSkinCacheElement* construct(const CopiedString& name)
|
||||
{
|
||||
Doom3ModelSkinCacheElement* skin = new Doom3ModelSkinCacheElement;
|
||||
if(m_cache.realised())
|
||||
{
|
||||
skin->realise(name.c_str());
|
||||
}
|
||||
return skin;
|
||||
}
|
||||
void destroy(Doom3ModelSkinCacheElement* skin)
|
||||
{
|
||||
if(m_cache.realised())
|
||||
{
|
||||
skin->unrealise();
|
||||
}
|
||||
delete skin;
|
||||
}
|
||||
};
|
||||
class CreateDoom3ModelSkin
|
||||
{
|
||||
Doom3ModelSkinCache& m_cache;
|
||||
public:
|
||||
explicit CreateDoom3ModelSkin( Doom3ModelSkinCache& cache )
|
||||
: m_cache( cache ){
|
||||
}
|
||||
Doom3ModelSkinCacheElement* construct( const CopiedString& name ){
|
||||
Doom3ModelSkinCacheElement* skin = new Doom3ModelSkinCacheElement;
|
||||
if ( m_cache.realised() ) {
|
||||
skin->realise( name.c_str() );
|
||||
}
|
||||
return skin;
|
||||
}
|
||||
void destroy( Doom3ModelSkinCacheElement* skin ){
|
||||
if ( m_cache.realised() ) {
|
||||
skin->unrealise();
|
||||
}
|
||||
delete skin;
|
||||
}
|
||||
};
|
||||
|
||||
typedef HashedCache<CopiedString, Doom3ModelSkinCacheElement, HashString, std::equal_to<CopiedString>, CreateDoom3ModelSkin> Cache;
|
||||
Cache m_cache;
|
||||
bool m_realised;
|
||||
typedef HashedCache<CopiedString, Doom3ModelSkinCacheElement, HashString, std::equal_to<CopiedString>, CreateDoom3ModelSkin> Cache;
|
||||
Cache m_cache;
|
||||
bool m_realised;
|
||||
|
||||
public:
|
||||
typedef ModelSkinCache Type;
|
||||
STRING_CONSTANT(Name, "*");
|
||||
ModelSkinCache* getTable()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
typedef ModelSkinCache Type;
|
||||
STRING_CONSTANT( Name, "*" );
|
||||
ModelSkinCache* getTable(){
|
||||
return this;
|
||||
}
|
||||
|
||||
Doom3ModelSkinCache() : m_cache(CreateDoom3ModelSkin(*this)), m_realised(false)
|
||||
{
|
||||
GlobalFileSystem().attach(*this);
|
||||
}
|
||||
~Doom3ModelSkinCache()
|
||||
{
|
||||
GlobalFileSystem().detach(*this);
|
||||
}
|
||||
Doom3ModelSkinCache() : m_cache( CreateDoom3ModelSkin( *this ) ), m_realised( false ){
|
||||
GlobalFileSystem().attach( *this );
|
||||
}
|
||||
~Doom3ModelSkinCache(){
|
||||
GlobalFileSystem().detach( *this );
|
||||
}
|
||||
|
||||
ModelSkin& capture(const char* name)
|
||||
{
|
||||
return *m_cache.capture(name);
|
||||
}
|
||||
void release(const char* name)
|
||||
{
|
||||
m_cache.release(name);
|
||||
}
|
||||
ModelSkin& capture( const char* name ){
|
||||
return *m_cache.capture( name );
|
||||
}
|
||||
void release( const char* name ){
|
||||
m_cache.release( name );
|
||||
}
|
||||
|
||||
bool realised() const
|
||||
{
|
||||
return m_realised;
|
||||
}
|
||||
void realise()
|
||||
{
|
||||
g_skins.realise();
|
||||
m_realised = true;
|
||||
for(Cache::iterator i = m_cache.begin(); i != m_cache.end(); ++i)
|
||||
{
|
||||
(*i).value->realise((*i).key.c_str());
|
||||
}
|
||||
}
|
||||
void unrealise()
|
||||
{
|
||||
m_realised = false;
|
||||
for(Cache::iterator i = m_cache.begin(); i != m_cache.end(); ++i)
|
||||
{
|
||||
(*i).value->unrealise();
|
||||
}
|
||||
g_skins.unrealise();
|
||||
}
|
||||
bool realised() const {
|
||||
return m_realised;
|
||||
}
|
||||
void realise(){
|
||||
g_skins.realise();
|
||||
m_realised = true;
|
||||
for ( Cache::iterator i = m_cache.begin(); i != m_cache.end(); ++i )
|
||||
{
|
||||
( *i ).value->realise( ( *i ).key.c_str() );
|
||||
}
|
||||
}
|
||||
void unrealise(){
|
||||
m_realised = false;
|
||||
for ( Cache::iterator i = m_cache.begin(); i != m_cache.end(); ++i )
|
||||
{
|
||||
( *i ).value->unrealise();
|
||||
}
|
||||
g_skins.unrealise();
|
||||
}
|
||||
};
|
||||
|
||||
class Doom3ModelSkinCacheDependencies : public GlobalFileSystemModuleRef, public GlobalScripLibModuleRef
|
||||
@@ -341,8 +297,6 @@ typedef SingletonModule<Doom3ModelSkinCache, Doom3ModelSkinCacheDependencies> Do
|
||||
|
||||
Doom3ModelSkinCacheModule g_Doom3ModelSkinCacheModule;
|
||||
|
||||
void Doom3ModelSkinCacheModule_selfRegister(ModuleServer& server)
|
||||
{
|
||||
g_Doom3ModelSkinCacheModule.selfRegister();
|
||||
void Doom3ModelSkinCacheModule_selfRegister( ModuleServer& server ){
|
||||
g_Doom3ModelSkinCacheModule.selfRegister();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_SKINCACHE_H)
|
||||
#if !defined( INCLUDED_SKINCACHE_H )
|
||||
#define INCLUDED_SKINCACHE_H
|
||||
|
||||
class ModuleServer;
|
||||
void Doom3ModelSkinCacheModule_selfRegister(ModuleServer& server);
|
||||
void Doom3ModelSkinCacheModule_selfRegister( ModuleServer& server );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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 "targetable.h"
|
||||
|
||||
@@ -27,11 +27,11 @@ const char* g_targetable_nameKey = "targetname";
|
||||
|
||||
targetnames_t g_targetnames;
|
||||
|
||||
targetables_t* getTargetables(const char* targetname)
|
||||
{
|
||||
if(targetname[0] == '\0')
|
||||
return 0;
|
||||
return &g_targetnames[targetname];
|
||||
targetables_t* getTargetables( const char* targetname ){
|
||||
if ( targetname[0] == '\0' ) {
|
||||
return 0;
|
||||
}
|
||||
return &g_targetnames[targetname];
|
||||
}
|
||||
|
||||
Shader* RenderableTargetingEntity::m_state;
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_TARGETABLE_H)
|
||||
#if !defined( INCLUDED_TARGETABLE_H )
|
||||
#define INCLUDED_TARGETABLE_H
|
||||
|
||||
#include <set>
|
||||
@@ -39,417 +39,360 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
class Targetable
|
||||
{
|
||||
public:
|
||||
virtual const Vector3& world_position() const = 0;
|
||||
virtual const Vector3& world_position() const = 0;
|
||||
};
|
||||
|
||||
typedef std::set<Targetable*> targetables_t;
|
||||
|
||||
extern const char* g_targetable_nameKey;
|
||||
|
||||
targetables_t* getTargetables(const char* targetname);
|
||||
targetables_t* getTargetables( const char* targetname );
|
||||
|
||||
class EntityConnectionLine : public OpenGLRenderable
|
||||
{
|
||||
public:
|
||||
Vector3 start;
|
||||
Vector3 end;
|
||||
Vector3 start;
|
||||
Vector3 end;
|
||||
|
||||
void render(RenderStateFlags state) const
|
||||
{
|
||||
float s1[2], s2[2];
|
||||
Vector3 dir(vector3_subtracted(end, start));
|
||||
double len = vector3_length(dir);
|
||||
vector3_scale(dir, 8.0 * (1.0 / len));
|
||||
s1[0] = dir[0] - dir[1];
|
||||
s1[1] = dir[0] + dir[1];
|
||||
s2[0] = dir[0] + dir[1];
|
||||
s2[1] = -dir[0] + dir[1];
|
||||
|
||||
glBegin(GL_LINES);
|
||||
void render( RenderStateFlags state ) const {
|
||||
float s1[2], s2[2];
|
||||
Vector3 dir( vector3_subtracted( end, start ) );
|
||||
double len = vector3_length( dir );
|
||||
vector3_scale( dir, 8.0 * ( 1.0 / len ) );
|
||||
s1[0] = dir[0] - dir[1];
|
||||
s1[1] = dir[0] + dir[1];
|
||||
s2[0] = dir[0] + dir[1];
|
||||
s2[1] = -dir[0] + dir[1];
|
||||
|
||||
glVertex3fv(vector3_to_array(start));
|
||||
glVertex3fv(vector3_to_array(end));
|
||||
glBegin( GL_LINES );
|
||||
|
||||
len*=0.0625; // half / 8
|
||||
glVertex3fv( vector3_to_array( start ) );
|
||||
glVertex3fv( vector3_to_array( end ) );
|
||||
|
||||
Vector3 arrow(start);
|
||||
for (unsigned int i = 0, count = (len<32)? 1 : static_cast<unsigned int>(len*0.0625); i < count; i++)
|
||||
{
|
||||
vector3_add(arrow, vector3_scaled(dir, (len<32)?len:32));
|
||||
glVertex3fv(vector3_to_array(arrow));
|
||||
glVertex3f(arrow[0]+s1[0], arrow[1]+s1[1], arrow[2]+dir[2]);
|
||||
glVertex3fv(vector3_to_array(arrow));
|
||||
glVertex3f(arrow[0]+s2[0], arrow[1]+s2[1], arrow[2]+dir[2]);
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
len *= 0.0625; // half / 8
|
||||
|
||||
Vector3 arrow( start );
|
||||
for ( unsigned int i = 0, count = ( len < 32 ) ? 1 : static_cast<unsigned int>( len * 0.0625 ); i < count; i++ )
|
||||
{
|
||||
vector3_add( arrow, vector3_scaled( dir, ( len < 32 ) ? len : 32 ) );
|
||||
glVertex3fv( vector3_to_array( arrow ) );
|
||||
glVertex3f( arrow[0] + s1[0], arrow[1] + s1[1], arrow[2] + dir[2] );
|
||||
glVertex3fv( vector3_to_array( arrow ) );
|
||||
glVertex3f( arrow[0] + s2[0], arrow[1] + s2[1], arrow[2] + dir[2] );
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
};
|
||||
|
||||
class TargetedEntity
|
||||
{
|
||||
Targetable& m_targetable;
|
||||
targetables_t* m_targets;
|
||||
Targetable& m_targetable;
|
||||
targetables_t* m_targets;
|
||||
|
||||
void construct()
|
||||
{
|
||||
if(m_targets != 0)
|
||||
m_targets->insert(&m_targetable);
|
||||
}
|
||||
void destroy()
|
||||
{
|
||||
if(m_targets != 0)
|
||||
m_targets->erase(&m_targetable);
|
||||
}
|
||||
void construct(){
|
||||
if ( m_targets != 0 ) {
|
||||
m_targets->insert( &m_targetable );
|
||||
}
|
||||
}
|
||||
void destroy(){
|
||||
if ( m_targets != 0 ) {
|
||||
m_targets->erase( &m_targetable );
|
||||
}
|
||||
}
|
||||
public:
|
||||
TargetedEntity(Targetable& targetable)
|
||||
: m_targetable(targetable), m_targets(getTargetables(""))
|
||||
{
|
||||
construct();
|
||||
}
|
||||
~TargetedEntity()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
void targetnameChanged(const char* name)
|
||||
{
|
||||
destroy();
|
||||
m_targets = getTargetables(name);
|
||||
construct();
|
||||
}
|
||||
typedef MemberCaller1<TargetedEntity, const char*, &TargetedEntity::targetnameChanged> TargetnameChangedCaller;
|
||||
TargetedEntity( Targetable& targetable )
|
||||
: m_targetable( targetable ), m_targets( getTargetables( "" ) ){
|
||||
construct();
|
||||
}
|
||||
~TargetedEntity(){
|
||||
destroy();
|
||||
}
|
||||
void targetnameChanged( const char* name ){
|
||||
destroy();
|
||||
m_targets = getTargetables( name );
|
||||
construct();
|
||||
}
|
||||
typedef MemberCaller1<TargetedEntity, const char*, &TargetedEntity::targetnameChanged> TargetnameChangedCaller;
|
||||
};
|
||||
|
||||
|
||||
class TargetingEntity
|
||||
{
|
||||
targetables_t* m_targets;
|
||||
targetables_t* m_targets;
|
||||
public:
|
||||
TargetingEntity() :
|
||||
m_targets(getTargetables(""))
|
||||
{
|
||||
}
|
||||
void targetChanged(const char* target)
|
||||
{
|
||||
m_targets = getTargetables(target);
|
||||
}
|
||||
typedef MemberCaller1<TargetingEntity, const char*, &TargetingEntity::targetChanged> TargetChangedCaller;
|
||||
TargetingEntity() :
|
||||
m_targets( getTargetables( "" ) ){
|
||||
}
|
||||
void targetChanged( const char* target ){
|
||||
m_targets = getTargetables( target );
|
||||
}
|
||||
typedef MemberCaller1<TargetingEntity, const char*, &TargetingEntity::targetChanged> TargetChangedCaller;
|
||||
|
||||
typedef targetables_t::iterator iterator;
|
||||
typedef targetables_t::iterator iterator;
|
||||
|
||||
iterator begin() const
|
||||
{
|
||||
if(m_targets == 0)
|
||||
{
|
||||
return iterator();
|
||||
}
|
||||
return m_targets->begin();
|
||||
}
|
||||
iterator end() const
|
||||
{
|
||||
if(m_targets == 0)
|
||||
{
|
||||
return iterator();
|
||||
}
|
||||
return m_targets->end();
|
||||
}
|
||||
size_t size() const
|
||||
{
|
||||
if(m_targets == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return m_targets->size();
|
||||
}
|
||||
bool empty() const
|
||||
{
|
||||
return m_targets == 0 || m_targets->empty();
|
||||
}
|
||||
iterator begin() const {
|
||||
if ( m_targets == 0 ) {
|
||||
return iterator();
|
||||
}
|
||||
return m_targets->begin();
|
||||
}
|
||||
iterator end() const {
|
||||
if ( m_targets == 0 ) {
|
||||
return iterator();
|
||||
}
|
||||
return m_targets->end();
|
||||
}
|
||||
size_t size() const {
|
||||
if ( m_targets == 0 ) {
|
||||
return 0;
|
||||
}
|
||||
return m_targets->size();
|
||||
}
|
||||
bool empty() const {
|
||||
return m_targets == 0 || m_targets->empty();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename Functor>
|
||||
void TargetingEntity_forEach(const TargetingEntity& targets, const Functor& functor)
|
||||
{
|
||||
for(TargetingEntity::iterator i = targets.begin(); i != targets.end(); ++i)
|
||||
{
|
||||
functor((*i)->world_position());
|
||||
}
|
||||
void TargetingEntity_forEach( const TargetingEntity& targets, const Functor& functor ){
|
||||
for ( TargetingEntity::iterator i = targets.begin(); i != targets.end(); ++i )
|
||||
{
|
||||
functor( ( *i )->world_position() );
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::map<std::size_t, TargetingEntity> TargetingEntities;
|
||||
|
||||
template<typename Functor>
|
||||
void TargetingEntities_forEach(const TargetingEntities& targetingEntities, const Functor& functor)
|
||||
{
|
||||
for(TargetingEntities::const_iterator i = targetingEntities.begin(); i != targetingEntities.end(); ++i)
|
||||
{
|
||||
TargetingEntity_forEach((*i).second, functor);
|
||||
}
|
||||
void TargetingEntities_forEach( const TargetingEntities& targetingEntities, const Functor& functor ){
|
||||
for ( TargetingEntities::const_iterator i = targetingEntities.begin(); i != targetingEntities.end(); ++i )
|
||||
{
|
||||
TargetingEntity_forEach( ( *i ).second, functor );
|
||||
}
|
||||
}
|
||||
|
||||
class TargetLinesPushBack
|
||||
{
|
||||
RenderablePointVector& m_targetLines;
|
||||
const Vector3& m_worldPosition;
|
||||
const VolumeTest& m_volume;
|
||||
RenderablePointVector& m_targetLines;
|
||||
const Vector3& m_worldPosition;
|
||||
const VolumeTest& m_volume;
|
||||
public:
|
||||
TargetLinesPushBack(RenderablePointVector& targetLines, const Vector3& worldPosition, const VolumeTest& volume) :
|
||||
m_targetLines(targetLines), m_worldPosition(worldPosition), m_volume(volume)
|
||||
{
|
||||
}
|
||||
void operator()(const Vector3& worldPosition) const
|
||||
{
|
||||
if(m_volume.TestLine(segment_for_startend(m_worldPosition, worldPosition)))
|
||||
{
|
||||
m_targetLines.push_back(PointVertex(reinterpret_cast<const Vertex3f&>(m_worldPosition)));
|
||||
m_targetLines.push_back(PointVertex(reinterpret_cast<const Vertex3f&>(worldPosition)));
|
||||
}
|
||||
}
|
||||
TargetLinesPushBack( RenderablePointVector& targetLines, const Vector3& worldPosition, const VolumeTest& volume ) :
|
||||
m_targetLines( targetLines ), m_worldPosition( worldPosition ), m_volume( volume ){
|
||||
}
|
||||
void operator()( const Vector3& worldPosition ) const {
|
||||
if ( m_volume.TestLine( segment_for_startend( m_worldPosition, worldPosition ) ) ) {
|
||||
m_targetLines.push_back( PointVertex( reinterpret_cast<const Vertex3f&>( m_worldPosition ) ) );
|
||||
m_targetLines.push_back( PointVertex( reinterpret_cast<const Vertex3f&>( worldPosition ) ) );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class TargetKeys : public Entity::Observer
|
||||
{
|
||||
TargetingEntities m_targetingEntities;
|
||||
Callback m_targetsChanged;
|
||||
TargetingEntities m_targetingEntities;
|
||||
Callback m_targetsChanged;
|
||||
|
||||
bool readTargetKey(const char* key, std::size_t& index)
|
||||
{
|
||||
if(string_equal_n(key, "target", 6))
|
||||
{
|
||||
index = 0;
|
||||
if(string_empty(key + 6) || string_parse_size(key + 6, index))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(string_equal(key, "killtarget"))
|
||||
{
|
||||
index = -1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool readTargetKey( const char* key, std::size_t& index ){
|
||||
if ( string_equal_n( key, "target", 6 ) ) {
|
||||
index = 0;
|
||||
if ( string_empty( key + 6 ) || string_parse_size( key + 6, index ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ( string_equal( key, "killtarget" ) ) {
|
||||
index = -1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public:
|
||||
void setTargetsChanged(const Callback& targetsChanged)
|
||||
{
|
||||
m_targetsChanged = targetsChanged;
|
||||
}
|
||||
void targetsChanged()
|
||||
{
|
||||
m_targetsChanged();
|
||||
}
|
||||
void setTargetsChanged( const Callback& targetsChanged ){
|
||||
m_targetsChanged = targetsChanged;
|
||||
}
|
||||
void targetsChanged(){
|
||||
m_targetsChanged();
|
||||
}
|
||||
|
||||
void insert(const char* key, EntityKeyValue& value)
|
||||
{
|
||||
std::size_t index;
|
||||
if(readTargetKey(key, index))
|
||||
{
|
||||
TargetingEntities::iterator i = m_targetingEntities.insert(TargetingEntities::value_type(index, TargetingEntity())).first;
|
||||
value.attach(TargetingEntity::TargetChangedCaller((*i).second));
|
||||
targetsChanged();
|
||||
}
|
||||
}
|
||||
void erase(const char* key, EntityKeyValue& value)
|
||||
{
|
||||
std::size_t index;
|
||||
if(readTargetKey(key, index))
|
||||
{
|
||||
TargetingEntities::iterator i = m_targetingEntities.find(index);
|
||||
value.detach(TargetingEntity::TargetChangedCaller((*i).second));
|
||||
m_targetingEntities.erase(i);
|
||||
targetsChanged();
|
||||
}
|
||||
}
|
||||
const TargetingEntities& get() const
|
||||
{
|
||||
return m_targetingEntities;
|
||||
}
|
||||
void insert( const char* key, EntityKeyValue& value ){
|
||||
std::size_t index;
|
||||
if ( readTargetKey( key, index ) ) {
|
||||
TargetingEntities::iterator i = m_targetingEntities.insert( TargetingEntities::value_type( index, TargetingEntity() ) ).first;
|
||||
value.attach( TargetingEntity::TargetChangedCaller( ( *i ).second ) );
|
||||
targetsChanged();
|
||||
}
|
||||
}
|
||||
void erase( const char* key, EntityKeyValue& value ){
|
||||
std::size_t index;
|
||||
if ( readTargetKey( key, index ) ) {
|
||||
TargetingEntities::iterator i = m_targetingEntities.find( index );
|
||||
value.detach( TargetingEntity::TargetChangedCaller( ( *i ).second ) );
|
||||
m_targetingEntities.erase( i );
|
||||
targetsChanged();
|
||||
}
|
||||
}
|
||||
const TargetingEntities& get() const {
|
||||
return m_targetingEntities;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class RenderableTargetingEntity
|
||||
{
|
||||
TargetingEntity& m_targets;
|
||||
mutable RenderablePointVector m_target_lines;
|
||||
TargetingEntity& m_targets;
|
||||
mutable RenderablePointVector m_target_lines;
|
||||
public:
|
||||
static Shader* m_state;
|
||||
static Shader* m_state;
|
||||
|
||||
RenderableTargetingEntity(TargetingEntity& targets)
|
||||
: m_targets(targets), m_target_lines(GL_LINES)
|
||||
{
|
||||
}
|
||||
void compile(const VolumeTest& volume, const Vector3& world_position) const
|
||||
{
|
||||
m_target_lines.clear();
|
||||
m_target_lines.reserve(m_targets.size() * 2);
|
||||
TargetingEntity_forEach(m_targets, TargetLinesPushBack(m_target_lines, world_position, volume));
|
||||
}
|
||||
void render(Renderer& renderer, const VolumeTest& volume, const Vector3& world_position) const
|
||||
{
|
||||
if(!m_targets.empty())
|
||||
{
|
||||
compile(volume, world_position);
|
||||
if(!m_target_lines.empty())
|
||||
{
|
||||
renderer.addRenderable(m_target_lines, g_matrix4_identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
RenderableTargetingEntity( TargetingEntity& targets )
|
||||
: m_targets( targets ), m_target_lines( GL_LINES ){
|
||||
}
|
||||
void compile( const VolumeTest& volume, const Vector3& world_position ) const {
|
||||
m_target_lines.clear();
|
||||
m_target_lines.reserve( m_targets.size() * 2 );
|
||||
TargetingEntity_forEach( m_targets, TargetLinesPushBack( m_target_lines, world_position, volume ) );
|
||||
}
|
||||
void render( Renderer& renderer, const VolumeTest& volume, const Vector3& world_position ) const {
|
||||
if ( !m_targets.empty() ) {
|
||||
compile( volume, world_position );
|
||||
if ( !m_target_lines.empty() ) {
|
||||
renderer.addRenderable( m_target_lines, g_matrix4_identity );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class RenderableTargetingEntities
|
||||
{
|
||||
const TargetingEntities& m_targets;
|
||||
mutable RenderablePointVector m_target_lines;
|
||||
const TargetingEntities& m_targets;
|
||||
mutable RenderablePointVector m_target_lines;
|
||||
public:
|
||||
static Shader* m_state;
|
||||
static Shader* m_state;
|
||||
|
||||
RenderableTargetingEntities(const TargetingEntities& targets)
|
||||
: m_targets(targets), m_target_lines(GL_LINES)
|
||||
{
|
||||
}
|
||||
void compile(const VolumeTest& volume, const Vector3& world_position) const
|
||||
{
|
||||
m_target_lines.clear();
|
||||
TargetingEntities_forEach(m_targets, TargetLinesPushBack(m_target_lines, world_position, volume));
|
||||
}
|
||||
void render(Renderer& renderer, const VolumeTest& volume, const Vector3& world_position) const
|
||||
{
|
||||
if(!m_targets.empty())
|
||||
{
|
||||
compile(volume, world_position);
|
||||
if(!m_target_lines.empty())
|
||||
{
|
||||
renderer.addRenderable(m_target_lines, g_matrix4_identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
RenderableTargetingEntities( const TargetingEntities& targets )
|
||||
: m_targets( targets ), m_target_lines( GL_LINES ){
|
||||
}
|
||||
void compile( const VolumeTest& volume, const Vector3& world_position ) const {
|
||||
m_target_lines.clear();
|
||||
TargetingEntities_forEach( m_targets, TargetLinesPushBack( m_target_lines, world_position, volume ) );
|
||||
}
|
||||
void render( Renderer& renderer, const VolumeTest& volume, const Vector3& world_position ) const {
|
||||
if ( !m_targets.empty() ) {
|
||||
compile( volume, world_position );
|
||||
if ( !m_target_lines.empty() ) {
|
||||
renderer.addRenderable( m_target_lines, g_matrix4_identity );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class TargetableInstance :
|
||||
public SelectableInstance,
|
||||
public Targetable,
|
||||
public Entity::Observer
|
||||
public SelectableInstance,
|
||||
public Targetable,
|
||||
public Entity::Observer
|
||||
{
|
||||
mutable Vertex3f m_position;
|
||||
EntityKeyValues& m_entity;
|
||||
TargetKeys m_targeting;
|
||||
TargetedEntity m_targeted;
|
||||
RenderableTargetingEntities m_renderable;
|
||||
mutable Vertex3f m_position;
|
||||
EntityKeyValues& m_entity;
|
||||
TargetKeys m_targeting;
|
||||
TargetedEntity m_targeted;
|
||||
RenderableTargetingEntities m_renderable;
|
||||
public:
|
||||
|
||||
TargetableInstance(
|
||||
const scene::Path& path,
|
||||
scene::Instance* parent,
|
||||
void* instance,
|
||||
InstanceTypeCastTable& casts,
|
||||
EntityKeyValues& entity,
|
||||
Targetable& targetable
|
||||
) :
|
||||
SelectableInstance(path, parent, instance, casts),
|
||||
m_entity(entity),
|
||||
m_targeted(targetable),
|
||||
m_renderable(m_targeting.get())
|
||||
{
|
||||
m_entity.attach(*this);
|
||||
m_entity.attach(m_targeting);
|
||||
}
|
||||
~TargetableInstance()
|
||||
{
|
||||
m_entity.detach(m_targeting);
|
||||
m_entity.detach(*this);
|
||||
}
|
||||
TargetableInstance(
|
||||
const scene::Path& path,
|
||||
scene::Instance* parent,
|
||||
void* instance,
|
||||
InstanceTypeCastTable& casts,
|
||||
EntityKeyValues& entity,
|
||||
Targetable& targetable
|
||||
) :
|
||||
SelectableInstance( path, parent, instance, casts ),
|
||||
m_entity( entity ),
|
||||
m_targeted( targetable ),
|
||||
m_renderable( m_targeting.get() ){
|
||||
m_entity.attach( *this );
|
||||
m_entity.attach( m_targeting );
|
||||
}
|
||||
~TargetableInstance(){
|
||||
m_entity.detach( m_targeting );
|
||||
m_entity.detach( *this );
|
||||
}
|
||||
|
||||
void setTargetsChanged(const Callback& targetsChanged)
|
||||
{
|
||||
m_targeting.setTargetsChanged(targetsChanged);
|
||||
}
|
||||
void targetsChanged()
|
||||
{
|
||||
m_targeting.targetsChanged();
|
||||
}
|
||||
void setTargetsChanged( const Callback& targetsChanged ){
|
||||
m_targeting.setTargetsChanged( targetsChanged );
|
||||
}
|
||||
void targetsChanged(){
|
||||
m_targeting.targetsChanged();
|
||||
}
|
||||
|
||||
void insert(const char* key, EntityKeyValue& value)
|
||||
{
|
||||
if(string_equal(key, g_targetable_nameKey))
|
||||
{
|
||||
value.attach(TargetedEntity::TargetnameChangedCaller(m_targeted));
|
||||
}
|
||||
}
|
||||
void erase(const char* key, EntityKeyValue& value)
|
||||
{
|
||||
if(string_equal(key, g_targetable_nameKey))
|
||||
{
|
||||
value.detach(TargetedEntity::TargetnameChangedCaller(m_targeted));
|
||||
}
|
||||
}
|
||||
void insert( const char* key, EntityKeyValue& value ){
|
||||
if ( string_equal( key, g_targetable_nameKey ) ) {
|
||||
value.attach( TargetedEntity::TargetnameChangedCaller( m_targeted ) );
|
||||
}
|
||||
}
|
||||
void erase( const char* key, EntityKeyValue& value ){
|
||||
if ( string_equal( key, g_targetable_nameKey ) ) {
|
||||
value.detach( TargetedEntity::TargetnameChangedCaller( m_targeted ) );
|
||||
}
|
||||
}
|
||||
|
||||
const Vector3& world_position() const
|
||||
{
|
||||
const Vector3& world_position() const {
|
||||
#if 1
|
||||
const AABB& bounds = Instance::worldAABB();
|
||||
if(aabb_valid(bounds))
|
||||
{
|
||||
return bounds.origin;
|
||||
}
|
||||
const AABB& bounds = Instance::worldAABB();
|
||||
if ( aabb_valid( bounds ) ) {
|
||||
return bounds.origin;
|
||||
}
|
||||
#else
|
||||
const AABB& childBounds = Instance::childBounds();
|
||||
if(aabb_valid(childBounds))
|
||||
{
|
||||
return childBounds.origin;
|
||||
}
|
||||
const AABB& childBounds = Instance::childBounds();
|
||||
if ( aabb_valid( childBounds ) ) {
|
||||
return childBounds.origin;
|
||||
}
|
||||
#endif
|
||||
return vector4_to_vector3(localToWorld().t());
|
||||
}
|
||||
return vector4_to_vector3( localToWorld().t() );
|
||||
}
|
||||
|
||||
void render(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
|
||||
renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eFullMaterials);
|
||||
m_renderable.render(renderer, volume, world_position());
|
||||
}
|
||||
void render( Renderer& renderer, const VolumeTest& volume ) const {
|
||||
renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly );
|
||||
renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eFullMaterials );
|
||||
m_renderable.render( renderer, volume, world_position() );
|
||||
}
|
||||
|
||||
const TargetingEntities& getTargeting() const
|
||||
{
|
||||
return m_targeting.get();
|
||||
}
|
||||
const TargetingEntities& getTargeting() const {
|
||||
return m_targeting.get();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class RenderableConnectionLines : public Renderable
|
||||
{
|
||||
typedef std::set<TargetableInstance*> TargetableInstances;
|
||||
TargetableInstances m_instances;
|
||||
typedef std::set<TargetableInstance*> TargetableInstances;
|
||||
TargetableInstances m_instances;
|
||||
public:
|
||||
void attach(TargetableInstance& instance)
|
||||
{
|
||||
ASSERT_MESSAGE(m_instances.find(&instance) == m_instances.end(), "cannot attach instance");
|
||||
m_instances.insert(&instance);
|
||||
}
|
||||
void detach(TargetableInstance& instance)
|
||||
{
|
||||
ASSERT_MESSAGE(m_instances.find(&instance) != m_instances.end(), "cannot detach instance");
|
||||
m_instances.erase(&instance);
|
||||
}
|
||||
void attach( TargetableInstance& instance ){
|
||||
ASSERT_MESSAGE( m_instances.find( &instance ) == m_instances.end(), "cannot attach instance" );
|
||||
m_instances.insert( &instance );
|
||||
}
|
||||
void detach( TargetableInstance& instance ){
|
||||
ASSERT_MESSAGE( m_instances.find( &instance ) != m_instances.end(), "cannot detach instance" );
|
||||
m_instances.erase( &instance );
|
||||
}
|
||||
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
for(TargetableInstances::const_iterator i = m_instances.begin(); i != m_instances.end(); ++i)
|
||||
{
|
||||
if((*i)->path().top().get().visible())
|
||||
{
|
||||
(*i)->render(renderer, volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
renderSolid(renderer, volume);
|
||||
}
|
||||
void renderSolid( Renderer& renderer, const VolumeTest& volume ) const {
|
||||
for ( TargetableInstances::const_iterator i = m_instances.begin(); i != m_instances.end(); ++i )
|
||||
{
|
||||
if ( ( *i )->path().top().get().visible() ) {
|
||||
( *i )->render( renderer, volume );
|
||||
}
|
||||
}
|
||||
}
|
||||
void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const {
|
||||
renderSolid( renderer, volume );
|
||||
}
|
||||
};
|
||||
|
||||
typedef Static<RenderableConnectionLines> StaticRenderableConnectionLines;
|
||||
|
||||
Reference in New Issue
Block a user