From: Garux <garux@mail.ru>
Date: Wed, 2 Aug 2017 06:19:22 +0000 (+0300)
Subject: Q3map2:
X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=0261afc6df181092b7d57751fec84e21d3ac593c;p=xonotic%2Fnetradiant.git

Q3map2:
	* -backsplash (float)scale (float)distance: scale area lights backsplash fraction + set distance globally
		(distance < -900 to omit distance setting); def = 1 23; real area lights have no backsplash (scale = 0)
		q3map_backsplash shader keyword overrides this setting

Radiant:

binds...
	* alt + m1 click/drag in component modes: select objects
misc...
	* fix: selected entity and brush numbers display in 'Find brush' dialog
	* prefer to display texture width and height in status bar over name (PANGO_ELLIPSIZE_START)
	* allow search shortcut (ctr+f in win) in entity inspector -> entity class list
	* fix: don't save empty group entities (but worldspawn)
---

diff --git a/plugins/mapq3/write.cpp b/plugins/mapq3/write.cpp
index 7a954586..f7becfee 100644
--- a/plugins/mapq3/write.cpp
+++ b/plugins/mapq3/write.cpp
@@ -70,6 +70,10 @@ bool pre( scene::Node& node ) const {
 
 	Entity* entity = Node_getEntity( node );
 	if ( entity != 0 ) {
+		if( entity->isContainer() && Node_getTraversable( node )->empty() && !string_equal( entity->getKeyValue( "classname" ), "worldspawn" ) ){
+			globalErrorStream() << "discarding empty group entity: # = " << g_count_entities << "; classname = " << entity->getKeyValue( "classname" ) << "\n";
+			return false;
+		}
 		m_writer.writeToken( "//" );
 		m_writer.writeToken( "entity" );
 		m_writer.writeUnsigned( g_count_entities++ );
diff --git a/radiant/brush.h b/radiant/brush.h
index d26547e8..c467af92 100644
--- a/radiant/brush.h
+++ b/radiant/brush.h
@@ -3428,6 +3428,39 @@ void testSelectComponents( Selector& selector, SelectionTest& test, SelectionSys
 	}
 }
 
+void invertComponentSelection( SelectionSystem::EComponentMode mode ){
+	switch ( mode )
+	{
+	case SelectionSystem::eVertex:
+	{
+		for ( VertexInstances::iterator i = m_vertexInstances.begin(); i != m_vertexInstances.end(); ++i )
+		{
+			( *i ).setSelected( !( *i ).isSelected() );
+		}
+	}
+	break;
+	case SelectionSystem::eEdge:
+	{
+		for ( EdgeInstances::iterator i = m_edgeInstances.begin(); i != m_edgeInstances.end(); ++i )
+		{
+			( *i ).setSelected( !( *i ).isSelected() );
+		}
+	}
+	break;
+	case SelectionSystem::eFace:
+	{
+		for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
+		{
+			if( !( *i ).getFace().isFiltered() )
+				( *i ).setSelected( mode, !( *i ).isSelected() );
+		}
+	}
+	break;
+	default:
+		break;
+	}
+}
+
 void selectPlanes( Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback ){
 	test.BeginMesh( localToWorld() );
 
diff --git a/radiant/entityinspector.cpp b/radiant/entityinspector.cpp
index f1096bf0..45232943 100644
--- a/radiant/entityinspector.cpp
+++ b/radiant/entityinspector.cpp
@@ -1233,7 +1233,7 @@ static gint EntityClassList_keypress( GtkWidget* widget, GdkEventKey* event, gpo
 	}
 
 	// select the entity that starts with the key pressed
-	if ( code <= 'Z' && code >= 'A' ) {
+	if ( code <= 'Z' && code >= 'A' && event->state == 0 ) {
 		GtkTreeView* view = g_entityClassList;
 		GtkTreeModel* model;
 		GtkTreeIter iter;
@@ -1339,7 +1339,7 @@ static gint EntityInspector_hideWindowKB( GtkWidget* widget, GdkEventKey* event,
 		return TRUE;
 	}
 	/* this doesn't work, if tab is bound (func is not called then) */
-	if ( event->keyval == GDK_Tab  ) {
+	if ( event->keyval == GDK_Tab ) {
 		gtk_window_set_focus( GTK_WINDOW( gtk_widget_get_toplevel( GTK_WIDGET( widget ) ) ), GTK_WIDGET( g_entityKeyEntry ) );
 		return TRUE;
 	}
diff --git a/radiant/mainframe.cpp b/radiant/mainframe.cpp
index 04e7b000..75662b23 100644
--- a/radiant/mainframe.cpp
+++ b/radiant/mainframe.cpp
@@ -2475,7 +2475,11 @@ GtkWidget* create_main_statusbar( GtkWidget *pStatusLabel[c_count_status] ){
 		gtk_frame_set_shadow_type( frame, GTK_SHADOW_IN );
 
 		GtkLabel* label = GTK_LABEL( gtk_label_new( "Label" ) );
-		gtk_label_set_ellipsize( label, PANGO_ELLIPSIZE_END );
+		if( i == c_texture_status )
+			gtk_label_set_ellipsize( label, PANGO_ELLIPSIZE_START );
+		else
+			gtk_label_set_ellipsize( label, PANGO_ELLIPSIZE_END );
+
 		gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
 		gtk_misc_set_padding( GTK_MISC( label ), 4, 2 );
 		gtk_widget_show( GTK_WIDGET( label ) );
diff --git a/radiant/map.cpp b/radiant/map.cpp
index e4c6e26a..73fceb5d 100644
--- a/radiant/map.cpp
+++ b/radiant/map.cpp
@@ -2099,7 +2099,7 @@ void SelectBrush( int entitynum, int brushnum ){
 }
 
 
-class BrushFindIndexWalker : public scene::Graph::Walker
+class BrushFindIndexWalker : public scene::Traversable::Walker
 {
 mutable const scene::Node* m_node;
 std::size_t& m_count;
@@ -2107,9 +2107,9 @@ public:
 BrushFindIndexWalker( const scene::Node& node, std::size_t& count )
 	: m_node( &node ), m_count( count ){
 }
-bool pre( const scene::Path& path, scene::Instance& instance ) const {
-	if ( Node_isPrimitive( path.top() ) ) {
-		if ( m_node == path.top().get_pointer() ) {
+bool pre( scene::Node& node ) const {
+	if ( Node_isPrimitive( node ) ) {
+		if ( m_node == &node ) {
 			m_node = 0;
 		}
 		if ( m_node ) {
@@ -2120,7 +2120,7 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
 }
 };
 
-class EntityFindIndexWalker : public scene::Graph::Walker
+class EntityFindIndexWalker : public scene::Traversable::Walker
 {
 mutable const scene::Node* m_node;
 std::size_t& m_count;
@@ -2128,9 +2128,9 @@ public:
 EntityFindIndexWalker( const scene::Node& node, std::size_t& count )
 	: m_node( &node ), m_count( count ){
 }
-bool pre( const scene::Path& path, scene::Instance& instance ) const {
-	if ( Node_isEntity( path.top() ) ) {
-		if ( m_node == path.top().get_pointer() ) {
+bool pre( scene::Node& node ) const {
+	if ( Node_isEntity( node ) ) {
+		if ( m_node == &node ) {
 			m_node = 0;
 		}
 		if ( m_node ) {
@@ -2147,8 +2147,24 @@ static void GetSelectionIndex( int *ent, int *brush ){
 	if ( GlobalSelectionSystem().countSelected() != 0 ) {
 		const scene::Path& path = GlobalSelectionSystem().ultimateSelected().path();
 
-		GlobalSceneGraph().traverse( BrushFindIndexWalker( path.top(), count_brush ) );
-		GlobalSceneGraph().traverse( EntityFindIndexWalker( path.parent(), count_entity ) );
+		{
+			scene::Traversable* traversable = Node_getTraversable( path.parent() );
+			if ( traversable != 0 && path.size() == 3 ) {
+				traversable->traverse( BrushFindIndexWalker( path.top(), count_brush ) );
+			}
+		}
+
+		{
+			scene::Traversable* traversable = Node_getTraversable( GlobalSceneGraph().root() );
+			if ( traversable != 0 ) {
+				if( path.size() == 3 ){
+					traversable->traverse( EntityFindIndexWalker( path.parent(), count_entity ) );
+				}
+				else if ( path.size() == 2 ){
+					traversable->traverse( EntityFindIndexWalker( path.top(), count_entity ) );
+				}
+			}
+		}
 	}
 	*brush = int(count_brush);
 	*ent = int(count_entity);
diff --git a/radiant/patch.h b/radiant/patch.h
index 66f53ef8..32f59165 100644
--- a/radiant/patch.h
+++ b/radiant/patch.h
@@ -1585,6 +1585,13 @@ void transformComponents( const Matrix4& matrix ){
 	}
 }
 
+void invertComponentSelection(){
+	for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i )
+	{
+		( *i ).m_selectable.setSelected( !( *i ).m_selectable.isSelected() );
+	}
+}
+
 
 void selectPlanes( Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback ){
 	test.BeginMesh( localToWorld() );
diff --git a/radiant/select.cpp b/radiant/select.cpp
index 240c05f4..67986fc6 100644
--- a/radiant/select.cpp
+++ b/radiant/select.cpp
@@ -39,6 +39,7 @@
 #include "gtkutil/widget.h"
 #include "brushmanip.h"
 #include "brush.h"
+#include "patch.h"
 #include "patchmanip.h"
 #include "patchdialog.h"
 #include "selection.h"
@@ -275,10 +276,11 @@ void Select_Delete( void ){
 class InvertSelectionWalker : public scene::Graph::Walker
 {
 SelectionSystem::EMode m_mode;
+SelectionSystem::EComponentMode m_compmode;
 mutable Selectable* m_selectable;
 public:
-InvertSelectionWalker( SelectionSystem::EMode mode )
-	: m_mode( mode ), m_selectable( 0 ){
+InvertSelectionWalker( SelectionSystem::EMode mode, SelectionSystem::EComponentMode compmode )
+	: m_mode( mode ), m_compmode( compmode ), m_selectable( 0 ){
 }
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
 	if( !path.top().get().visible() ){
@@ -298,6 +300,18 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
 			m_selectable = path.top().get().visible() ? selectable : 0;
 			break;
 		case SelectionSystem::eComponent:
+			BrushInstance* brushinstance = Instance_getBrush( instance );
+			if( brushinstance != 0 ){
+				if( brushinstance->isSelected() )
+					brushinstance->invertComponentSelection( m_compmode );
+			}
+			else{
+				PatchInstance* patchinstance = Instance_getPatch( instance );
+				if( patchinstance != 0 && m_compmode == SelectionSystem::eVertex ){
+					if( patchinstance->isSelected() )
+						patchinstance->invertComponentSelection();
+				}
+			}
 			break;
 		}
 	}
@@ -312,7 +326,7 @@ void post( const scene::Path& path, scene::Instance& instance ) const {
 };
 
 void Scene_Invert_Selection( scene::Graph& graph ){
-	graph.traverse( InvertSelectionWalker( GlobalSelectionSystem().Mode() ) );
+	graph.traverse( InvertSelectionWalker( GlobalSelectionSystem().Mode(), GlobalSelectionSystem().ComponentMode() ) );
 }
 
 void Select_Invert(){
diff --git a/radiant/selection.cpp b/radiant/selection.cpp
index 805b6ed7..a08659b4 100644
--- a/radiant/selection.cpp
+++ b/radiant/selection.cpp
@@ -2638,7 +2638,7 @@ std::list<Selectable*>& best(){
 }
 };
 
-bool g_bAltDragManipulatorResize = false;
+bool g_bAltDragManipulatorResize = false; //+select primitives in component modes
 bool g_bTmpComponentMode = false;
 
 class DragManipulator : public Manipulator
@@ -3157,7 +3157,7 @@ void SelectPoint( const View& view, const float device_point[2], const float dev
 				Scene_TestSelect_Component( selector, volume, scissored, eFace );
 			}
 			else{
-				Scene_TestSelect( selector, volume, scissored, Mode(), ComponentMode() );
+				Scene_TestSelect( selector, volume, scissored, g_bAltDragManipulatorResize ? ePrimitive : Mode(), ComponentMode() );
 			}
 
 			if ( !selector.failed() ) {
@@ -3306,7 +3306,7 @@ bool SelectPoint_InitPaint( const View& view, const float device_point[2], const
 				Scene_TestSelect_Component( selector, volume, scissored, eFace );
 			}
 			else{
-				Scene_TestSelect( selector, volume, scissored, Mode(), ComponentMode() );
+				Scene_TestSelect( selector, volume, scissored, g_bAltDragManipulatorResize ? ePrimitive : Mode(), ComponentMode() );
 			}
 			if ( !selector.failed() ){
 				SelectableSortedSet::iterator best = selector.begin();
@@ -4065,7 +4065,7 @@ const ModifierFlags c_modifier_copy_texture = c_modifierNone;
 class Selector_
 {
 RadiantSelectionSystem::EModifier modifier_for_state( ModifierFlags state ){
-	if ( ( state == c_modifier_toggle || state == c_modifier_toggle_face || state == c_modifier_face ) ) {
+	if ( ( state == c_modifier_toggle || state == c_modifier_toggle_face || state == c_modifier_face || state == c_modifierAlt ) ) {
 		if( m_mouse2 ){
 			return RadiantSelectionSystem::eReplace;
 		}
@@ -4287,7 +4287,7 @@ void onMouseDown( const WindowVector& position, ButtonIdentifier button, Modifie
 
 		DeviceVector devicePosition( window_to_normalised_device( position, m_width, m_height ) );
 		g_bAltDragManipulatorResize = ( modifiers == c_modifierAlt ) ? true : false;
-		if ( ( modifiers == c_modifier_manipulator || modifiers == c_modifierAlt ) && m_manipulator.mouseDown( devicePosition ) ) {
+		if ( ( modifiers == c_modifier_manipulator || ( modifiers == c_modifierAlt && getSelectionSystem().Mode() != SelectionSystem::eComponent ) ) && m_manipulator.mouseDown( devicePosition ) ) {
 			g_mouseMovedCallback.insert( MouseEventCallback( Manipulator_::MouseMovedCaller( m_manipulator ) ) );
 			g_mouseUpCallback.insert( MouseEventCallback( Manipulator_::MouseUpCaller( m_manipulator ) ) );
 		}
diff --git a/tools/quake3/common/aselib.c b/tools/quake3/common/aselib.c
index 76215232..b60758b8 100644
--- a/tools/quake3/common/aselib.c
+++ b/tools/quake3/common/aselib.c
@@ -411,9 +411,9 @@ static void ASE_SkipRestOfLine( void ){
 }
 
 static void ASE_KeyMAP_DIFFUSE( const char *token ){
-	char fullpath[1024], bitmap[1024], modeldir[1024];
+	char bitmap[1024];
 	char filename[1024];
-	int i = 0, count;
+	int i = 0;
 
 	strcpy( filename, gl_filename );
 
diff --git a/tools/quake3/q3map2/brush.c b/tools/quake3/q3map2/brush.c
index e15d5612..0f01063d 100644
--- a/tools/quake3/q3map2/brush.c
+++ b/tools/quake3/q3map2/brush.c
@@ -257,7 +257,7 @@ void SnapWeldVector( vec3_t a, vec3_t b, vec3_t out ){
 	{
 		/* round to integer */
 		ai = Q_rint( a[ i ] );
-		bi = Q_rint( a[ i ] );
+		bi = Q_rint( b[ i ] );
 
 		/* prefer exact integer */
 		if ( ai == a[ i ] ) {
@@ -268,7 +268,7 @@ void SnapWeldVector( vec3_t a, vec3_t b, vec3_t out ){
 		}
 
 		/* use nearest */
-		else if ( fabs( ai - a[ i ] ) < fabs( bi < b[ i ] ) ) {
+		else if ( fabs( ai - a[ i ] ) < fabs( bi - b[ i ] ) ) {
 			out[ i ] = a[ i ];
 		}
 		else{
diff --git a/tools/quake3/q3map2/bspfile_abstract.c b/tools/quake3/q3map2/bspfile_abstract.c
index 8aad9091..d94a6fa8 100644
--- a/tools/quake3/q3map2/bspfile_abstract.c
+++ b/tools/quake3/q3map2/bspfile_abstract.c
@@ -109,7 +109,7 @@ void SetDrawSurfacesBuffer(){
 
 	bspDrawSurfaces = safe_malloc_info( sizeof( bspDrawSurface_t ) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces" );
 
-	memset( bspDrawSurfaces, 0, MAX_MAP_DRAW_SURFS * sizeof( bspDrawVert_t ) );
+	memset( bspDrawSurfaces, 0, MAX_MAP_DRAW_SURFS * sizeof( bspDrawSurface_t ) );
 }
 
 void SetDrawSurfaces( int n ){
@@ -122,7 +122,7 @@ void SetDrawSurfaces( int n ){
 
 	bspDrawSurfaces = safe_malloc_info( sizeof( bspDrawSurface_t ) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces" );
 
-	memset( bspDrawSurfaces, 0, n * sizeof( bspDrawVert_t ) );
+	memset( bspDrawSurfaces, 0, n * sizeof( bspDrawSurface_t ) );
 }
 
 void BSPFilesCleanup(){
diff --git a/tools/quake3/q3map2/light.c b/tools/quake3/q3map2/light.c
index d6916367..f3f20ff3 100644
--- a/tools/quake3/q3map2/light.c
+++ b/tools/quake3/q3map2/light.c
@@ -2256,6 +2256,18 @@ int LightMain( int argc, char **argv ){
 			i++;
 		}
 
+		else if ( !strcmp( argv[ i ], "-backsplash" ) && i < ( argc - 3 ) ) {
+			f = atof( argv[ i + 1 ] );
+			g_backsplashFractionScale = f;
+			Sys_Printf( "Area lights backsplash fraction scaled by %f\n", f, g_backsplashFractionScale );
+			f = atof( argv[ i + 2 ] );
+			if ( f >= -900.0f ){
+				g_backsplashDistance = f;
+				Sys_Printf( "Area lights backsplash distance set globally to %f\n", f, g_backsplashDistance );
+			}
+			i+=2;
+		}
+
 		else if ( !strcmp( argv[ i ], "-nolm" ) ) {
 			nolm = qtrue;
 			Sys_Printf( "No lightmaps yo\n" );
diff --git a/tools/quake3/q3map2/light_ydnar.c b/tools/quake3/q3map2/light_ydnar.c
index 83595337..f655fb03 100644
--- a/tools/quake3/q3map2/light_ydnar.c
+++ b/tools/quake3/q3map2/light_ydnar.c
@@ -2235,7 +2235,7 @@ void IlluminateRawLightmap( int rawLightmapNum ){
 			}
 
 			/* set luxel filter radius */
-			luxelFilterRadius = superSample * filterRadius / lm->sampleSize;
+			luxelFilterRadius = lm->sampleSize != 0 ? superSample * filterRadius / lm->sampleSize : 0;
 			if ( luxelFilterRadius == 0 && ( filterRadius > 0.0f || filter ) ) {
 				luxelFilterRadius = 1;
 			}
diff --git a/tools/quake3/q3map2/lightmaps_ydnar.c b/tools/quake3/q3map2/lightmaps_ydnar.c
index c1c9ced0..f8b52105 100644
--- a/tools/quake3/q3map2/lightmaps_ydnar.c
+++ b/tools/quake3/q3map2/lightmaps_ydnar.c
@@ -525,7 +525,7 @@ qboolean AddPatchToRawLightmap( int num, rawLightmap_t *lm ){
 	length = 0;
 	for ( x = 0; x < ( mesh->width - 1 ); x++ )
 		length += widthTable[ x ];
-	lm->w = ceil( length / lm->sampleSize ) + 1;
+	lm->w = lm->sampleSize != 0 ? ceil( length / lm->sampleSize ) + 1 : 0;
 	if ( lm->w < ds->patchWidth ) {
 		lm->w = ds->patchWidth;
 	}
@@ -538,7 +538,7 @@ qboolean AddPatchToRawLightmap( int num, rawLightmap_t *lm ){
 	length = 0;
 	for ( y = 0; y < ( mesh->height - 1 ); y++ )
 		length += heightTable[ y ];
-	lm->h = ceil( length / lm->sampleSize ) + 1;
+	lm->h = lm->sampleSize != 0 ? ceil( length / lm->sampleSize ) + 1 : 0;
 	if ( lm->h < ds->patchHeight ) {
 		lm->h = ds->patchHeight;
 	}
diff --git a/tools/quake3/q3map2/q3map2.h b/tools/quake3/q3map2/q3map2.h
index 141ddcbd..ba10713e 100644
--- a/tools/quake3/q3map2/q3map2.h
+++ b/tools/quake3/q3map2/q3map2.h
@@ -2322,6 +2322,8 @@ Q_EXTERN float skyScale Q_ASSIGN( 1.0f );
 Q_EXTERN float bounceScale Q_ASSIGN( 0.25f );
 Q_EXTERN float bounceColorRatio Q_ASSIGN( 1.0f );
 Q_EXTERN float vertexglobalscale Q_ASSIGN( 1.0f );
+Q_EXTERN float g_backsplashFractionScale Q_ASSIGN( 1.0f );
+Q_EXTERN float g_backsplashDistance Q_ASSIGN( -999.0f );
 
 /* jal: alternative angle attenuation curve */
 Q_EXTERN qboolean lightAngleHL Q_ASSIGN( qfalse );
diff --git a/tools/quake3/q3map2/shaders.c b/tools/quake3/q3map2/shaders.c
index 3d5249ef..82be170a 100644
--- a/tools/quake3/q3map2/shaders.c
+++ b/tools/quake3/q3map2/shaders.c
@@ -645,8 +645,8 @@ static shaderInfo_t *AllocShaderInfo( void ){
 	/* set defaults */
 	ApplySurfaceParm( "default", &si->contentFlags, &si->surfaceFlags, &si->compileFlags );
 
-	si->backsplashFraction = DEF_BACKSPLASH_FRACTION;
-	si->backsplashDistance = DEF_BACKSPLASH_DISTANCE;
+	si->backsplashFraction = DEF_BACKSPLASH_FRACTION * g_backsplashFractionScale;
+	si->backsplashDistance = g_backsplashDistance < -900.0f ? DEF_BACKSPLASH_DISTANCE : g_backsplashDistance;
 
 	si->bounceScale = DEF_RADIOSITY_BOUNCE;