From c5f2279f4a6e7ba9355afe2b0e05c9fe351daf3e Mon Sep 17 00:00:00 2001 From: Garux Date: Thu, 16 Aug 2018 20:00:58 +0300 Subject: [PATCH] * render direction arrow for group entities, having angle/angles key set or having angle/angles/direction attribute in .ent draw condition relies on entity.getKeyValue, which also provides default values; thus removed default "0" for all group entities in .def loader mind to add entity.getOnlySpecifiedKeyValue func or perform by visitor? --- libs/eclasslib.h | 2 ++ libs/entitylib.h | 17 ++++++++++ plugins/entity/angles.h | 11 +++++++ plugins/entity/generic.cpp | 16 --------- plugins/entity/group.cpp | 65 +++++++++++++++++++++++++++++++------ radiant/eclass_def.cpp | 2 +- radiant/eclass_xml.cpp | 5 ++- radiant/entityinspector.cpp | 1 + 8 files changed, 91 insertions(+), 28 deletions(-) diff --git a/libs/eclasslib.h b/libs/eclasslib.h index bc1b1222..79436d53 100644 --- a/libs/eclasslib.h +++ b/libs/eclasslib.h @@ -114,6 +114,7 @@ bool fixedsize; bool unknown; // wasn't found in source bool miscmodel_is; // also definable via model attribute presence in xml .ent definition CopiedString m_miscmodel_key; +bool has_angles; // definable via "angle"/"angles"/"direction" attribute presence in xml .ent definition, only affects rendering of group entities angles arrow now Vector3 mins; Vector3 maxs; @@ -258,6 +259,7 @@ inline EntityClass* Eclass_Alloc(){ e->unknown = false; e->miscmodel_is = false; e->m_miscmodel_key = "model"; + e->has_angles = false; memset( e->flagnames, 0, MAX_FLAGS * 32 ); e->maxs = Vector3( -1,-1,-1 ); diff --git a/libs/entitylib.h b/libs/entitylib.h index 6c9cc757..d12c7ed6 100644 --- a/libs/entitylib.h +++ b/libs/entitylib.h @@ -83,6 +83,23 @@ inline void arrow_draw( const Vector3& origin, const Vector3& direction_forward, glEnd(); } +class RenderableArrow : public OpenGLRenderable +{ +const Vector3& m_origin; +const Vector3& m_angles; + +public: +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 ) ) ); +} +}; + + class SelectionIntersection; inline void aabb_testselect( const AABB& aabb, SelectionTest& test, SelectionIntersection& best ){ diff --git a/plugins/entity/angles.h b/plugins/entity/angles.h index 3cfa4e25..655f6f82 100644 --- a/plugins/entity/angles.h +++ b/plugins/entity/angles.h @@ -147,6 +147,17 @@ void angleChanged( const char* value ){ } typedef MemberCaller1 AngleChangedCaller; +void groupAngleChanged( const char* value ){ + if( strlen( value ) == 2 && value[0] == '-' && value[1] == '1' ) + m_angles = Vector3( 0, -90, 0 ); + else if( strlen( value ) == 2 && value[0] == '-' && value[1] == '2' ) + m_angles = Vector3( 0, 90, 0 ); + else + read_angle( m_angles, value ); + m_anglesChanged(); +} +typedef MemberCaller1 GroupAngleChangedCaller; + void anglesChanged( const char* value ){ read_angles( m_angles, value ); m_anglesChanged(); diff --git a/plugins/entity/generic.cpp b/plugins/entity/generic.cpp index 4b1e4ee1..9e61b163 100644 --- a/plugins/entity/generic.cpp +++ b/plugins/entity/generic.cpp @@ -51,22 +51,6 @@ #include "entity.h" -class RenderableArrow : public OpenGLRenderable -{ -const Vector3& m_origin; -const Vector3& m_angles; - -public: -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 ) ) ); -} -}; - inline void read_aabb( AABB& aabb, const EntityClass& eclass ){ aabb = aabb_for_minmax( eclass.mins, eclass.maxs ); } diff --git a/plugins/entity/group.cpp b/plugins/entity/group.cpp index 707c6b19..7711df2a 100644 --- a/plugins/entity/group.cpp +++ b/plugins/entity/group.cpp @@ -68,6 +68,15 @@ Vector3 m_origin; mutable Vector3 m_name_origin; RenderableNamedEntity m_renderName; +AnglesKey m_anglesKey; +RenderableArrow m_arrow; +bool m_anglesDraw; +void updateAnglesDraw(){ + m_anglesDraw = m_entity.getEntityClass().has_angles || !string_empty( m_entity.getKeyValue( "angle" ) ) || !string_empty( m_entity.getKeyValue( "angles" ) ); + SceneChangeNotify(); +} +typedef MemberCaller UpdateAnglesDrawCaller; + Callback m_transformChanged; Callback m_evaluateTransform; @@ -75,6 +84,9 @@ void construct(){ m_keyObservers.insert( "classname", ClassnameFilter::ClassnameChangedCaller( m_filter ) ); m_keyObservers.insert( Static::instance().m_nameKey, NamedEntity::IdentifierChangedCaller( m_named ) ); m_keyObservers.insert( "origin", OriginKey::OriginChangedCaller( m_originKey ) ); + m_keyObservers.insert( "angle", AnglesKey::GroupAngleChangedCaller( m_anglesKey ) ); + m_keyObservers.insert( "angles", AnglesKey::AnglesChangedCaller( m_anglesKey ) ); + updateAnglesDraw(); } public: @@ -87,6 +99,8 @@ Group( EntityClass* eclass, scene::Node& node, const Callback& transformChanged, m_origin( ORIGINKEY_IDENTITY ), m_name_origin( g_vector3_identity ), m_renderName( m_named, m_name_origin, EXCLUDE_NAME ), + m_anglesKey( UpdateAnglesDrawCaller( *this ) ), + m_arrow( m_name_origin, m_anglesKey.m_angles ), m_transformChanged( transformChanged ), m_evaluateTransform( evaluateTransform ){ construct(); @@ -100,6 +114,8 @@ Group( const Group& other, scene::Node& node, const Callback& transformChanged, m_origin( ORIGINKEY_IDENTITY ), m_name_origin( g_vector3_identity ), m_renderName( m_named, m_name_origin, EXCLUDE_NAME ), + m_anglesKey( UpdateAnglesDrawCaller( *this ) ), + m_arrow( m_name_origin, m_anglesKey.m_angles ), m_transformChanged( transformChanged ), m_evaluateTransform( evaluateTransform ){ construct(); @@ -151,23 +167,52 @@ void detach( scene::Traversable::Observer* observer ){ } void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected, bool childSelected, const AABB& childBounds ) const { - renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly ); - if ( m_renderName.excluded_not() - && ( selected || childSelected || ( g_showNames && ( volume.fill() || aabb_fits_view( childBounds, volume.GetModelview(), volume.GetViewport(), g_showNamesRatio ) ) ) ) ) { - // don't draw the name for worldspawn -// if ( !strcmp( m_entity.getEntityClass().name(), "worldspawn" ) ) { -// return; -// } - + if ( m_renderName.excluded_not() ) { // place name in the middle of the "children cloud" m_name_origin = extents_valid( childBounds.extents.x() )? childBounds.origin : vector4_to_vector3( localToWorld.t() ); - m_renderName.render( renderer, volume, g_matrix4_identity, selected, childSelected ); + if ( selected || childSelected || g_showNames ) + m_renderName.render( renderer, volume, g_matrix4_identity, selected, childSelected ); + if ( m_anglesDraw && g_showAngles ) { + if( selected || childSelected ){ + renderer.PushState(); + renderer.Highlight( Renderer::ePrimitive ); + renderer.SetState( m_entity.getEntityClass().m_state_fill, Renderer::eFullMaterials ); + renderer.addRenderable( m_arrow, localToWorld ); + renderer.PopState(); + } + else{ + renderer.SetState( m_entity.getEntityClass().m_state_fill, Renderer::eFullMaterials ); + renderer.addRenderable( m_arrow, localToWorld ); + } + } } } void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected, bool childSelected, const AABB& childBounds ) const { - renderSolid( renderer, volume, localToWorld, selected, childSelected, childBounds ); + renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly ); + // don't draw the name for worldspawn +// if ( !strcmp( m_entity.getEntityClass().name(), "worldspawn" ) ) { +// return; +// } + if ( m_renderName.excluded_not() ) { + // place name in the middle of the "children cloud" + m_name_origin = extents_valid( childBounds.extents.x() )? childBounds.origin : vector4_to_vector3( localToWorld.t() ); + + if ( selected || childSelected || ( g_showNames && aabb_fits_view( childBounds, volume.GetModelview(), volume.GetViewport(), g_showNamesRatio ) ) ) + m_renderName.render( renderer, volume, g_matrix4_identity, selected, childSelected ); + if ( m_anglesDraw && g_showAngles ) { + if( selected || childSelected ){ + renderer.PushState(); + renderer.Highlight( Renderer::ePrimitive ); + renderer.addRenderable( m_arrow, localToWorld ); + renderer.PopState(); + } + else{ + renderer.addRenderable( m_arrow, localToWorld ); + } + } + } } void updateTransform(){ diff --git a/radiant/eclass_def.cpp b/radiant/eclass_def.cpp index 055757ed..7a7baf29 100644 --- a/radiant/eclass_def.cpp +++ b/radiant/eclass_def.cpp @@ -280,7 +280,7 @@ EntityClass *Eclass_InitFromText( const char *text ){ e->m_modelpath = buffer.c_str(); if ( !e->fixedsize ) { - EntityClass_insertAttribute( *e, "angle", EntityClassAttribute( "direction", "Direction", "0" ) ); + EntityClass_insertAttribute( *e, "angle", EntityClassAttribute( "direction", "Direction" ) ); } else { diff --git a/radiant/eclass_xml.cpp b/radiant/eclass_xml.cpp index db603be0..fdf81272 100644 --- a/radiant/eclass_xml.cpp +++ b/radiant/eclass_xml.cpp @@ -56,7 +56,7 @@ /// integer3 three integer values //not supported /// real floating-point value /// angle specialisation of real - Yaw angle -/// direction specialisation of real - Yaw angle, -1 = down, -2 = up +/// direction specialisation of real - Yaw angle, -1 = up, -2 = down /// real3 three floating-point values /// angles specialisation of real3 - Pitch Yaw Roll /// color specialisation of real3 - RGB floating-point colour @@ -213,6 +213,9 @@ AttributeImporter( StringOutputStream& comment, EntityClass* entityClass, const entityClass->miscmodel_is = true; entityClass->m_miscmodel_key = key; } + else if( string_equal( type, "angle" ) || string_equal( type, "angles" ) || string_equal( type, "direction" ) ){ + entityClass->has_angles = true; + } m_comment << key; m_comment << " : "; diff --git a/radiant/entityinspector.cpp b/radiant/entityinspector.cpp index 376a4dde..c479d8da 100644 --- a/radiant/entityinspector.cpp +++ b/radiant/entityinspector.cpp @@ -534,6 +534,7 @@ void update(){ } else { + radio_button_set_active_no_signal( m_radio.m_radio, 2 ); gtk_entry_set_text( m_entry, "0" ); } }