From 461d008daa6328113ea4ccda37e5604d3df14ba3 Mon Sep 17 00:00:00 2001 From: Garux Date: Wed, 2 Aug 2017 09:20:56 +0300 Subject: [PATCH] Q3map2: * fix: parsing of /* */ comments, having * or / inside Radiant: misc... encapsulate RETURN_FALSE_IF_FAIL macros with do while 0: minus warnings * button to call color selector from ents inspector color entry * explanatory text on initial engine path configuration * don't show Global preferences by default, except first start * activate {xyview, camera, texbro glwidget} on mouse button press and scroll, so {texbro treeview and console} hotkeys do not override global ones * activate windows, containing xyview, camera, texbro on mouse scroll * fix: autoapplying trigger texture on entity creation is undoable * fix: texbro m1/2 x2 work, when some tag is loaded * bold key and spawnflags names in entity inspector entity description * fix: +CameraFreeMove* command, +shift, -CameraFreeMove*, -shift = still moving (reason: caps letter) --- libs/gtkutil/accelerator.cpp | 4 +- libs/picomodel/pm_mdc.c | 2 +- libs/stringio.h | 3 +- plugins/md3model/md5.cpp | 3 +- radiant/camwindow.cpp | 6 +++ radiant/eclass_doom3.cpp | 3 +- radiant/entity.cpp | 25 ++++++----- radiant/entity.h | 1 + radiant/entityinspector.cpp | 81 +++++++++++++++++++++++++++++++++- radiant/gtkdlgs.cpp | 4 +- radiant/gtkdlgs.h | 4 +- radiant/mainframe.cpp | 20 ++++++++- radiant/preferences.cpp | 2 +- radiant/preferences.h | 2 +- radiant/texwindow.cpp | 12 +++-- radiant/xywindow.cpp | 7 +++ tools/quake3/common/scriplib.c | 2 +- tools/quake3/q3map2/portals.c | 2 +- 18 files changed, 150 insertions(+), 33 deletions(-) diff --git a/libs/gtkutil/accelerator.cpp b/libs/gtkutil/accelerator.cpp index c49c2c70..5e01456c 100644 --- a/libs/gtkutil/accelerator.cpp +++ b/libs/gtkutil/accelerator.cpp @@ -342,14 +342,14 @@ AcceleratorMap g_keydown_accelerators; AcceleratorMap g_keyup_accelerators; bool Keys_press( PressedKeys::Keys& keys, guint keyval ){ - if ( keys.insert( keyval ).second ) { + if ( keys.insert( gdk_keyval_to_upper( keyval ) ).second ) { return AcceleratorMap_activate( g_keydown_accelerators, accelerator_for_event_key( keyval, 0 ) ); } return g_keydown_accelerators.find( accelerator_for_event_key( keyval, 0 ) ) != g_keydown_accelerators.end(); } bool Keys_release( PressedKeys::Keys& keys, guint keyval ){ - if ( keys.erase( keyval ) != 0 ) { + if ( keys.erase( gdk_keyval_to_upper( keyval ) ) != 0 ) { return AcceleratorMap_activate( g_keyup_accelerators, accelerator_for_event_key( keyval, 0 ) ); } return g_keyup_accelerators.find( accelerator_for_event_key( keyval, 0 ) ) != g_keyup_accelerators.end(); diff --git a/libs/picomodel/pm_mdc.c b/libs/picomodel/pm_mdc.c index 7e898ff1..aac525b8 100644 --- a/libs/picomodel/pm_mdc.c +++ b/libs/picomodel/pm_mdc.c @@ -52,7 +52,7 @@ #define MDC_DIST_SCALE 0.05f /* mdc decoding normal table */ -double mdcNormals[ 256 ][ 3 ] = +const double mdcNormals[ 256 ][ 3 ] = { { 1.000000, 0.000000, 0.000000 }, { 0.980785, 0.195090, 0.000000 }, diff --git a/libs/stringio.h b/libs/stringio.h index 658e0ace..83572e2f 100644 --- a/libs/stringio.h +++ b/libs/stringio.h @@ -219,7 +219,8 @@ inline bool string_parse_size( const char* string, std::size_t& i ){ } -#define RETURN_FALSE_IF_FAIL( expression ) if ( !expression ) {return false; }else +//#define RETURN_FALSE_IF_FAIL( expression ) if ( !expression ) {return false; }else +#define RETURN_FALSE_IF_FAIL( expression ) do{ if ( !expression ) {return false; } }while( 0 ) inline void Tokeniser_unexpectedError( Tokeniser& tokeniser, const char* token, const char* expected ){ globalErrorStream() << Unsigned( tokeniser.getLine() ) << ":" << Unsigned( tokeniser.getColumn() ) << ": parse error at '" << ( token != 0 ? token : "#EOF" ) << "': expected '" << expected << "'\n"; diff --git a/plugins/md3model/md5.cpp b/plugins/md3model/md5.cpp index 69719051..6da4b720 100644 --- a/plugins/md3model/md5.cpp +++ b/plugins/md3model/md5.cpp @@ -29,7 +29,8 @@ #include "model.h" -#define MD5_RETURN_FALSE_IF_FAIL( expression ) if ( !( expression ) ) { globalErrorStream() << "md5 parse failed: " # expression "\n"; return false; } else +//#define MD5_RETURN_FALSE_IF_FAIL( expression ) if ( !( expression ) ) { globalErrorStream() << "md5 parse failed: " # expression "\n"; return false; } else +#define MD5_RETURN_FALSE_IF_FAIL( expression ) do{ if ( !( expression ) ) { globalErrorStream() << "md5 parse failed: " # expression "\n"; return false; } }while( 0 ) bool MD5_parseToken( Tokeniser& tokeniser, const char* string ){ const char* token = tokeniser.getToken(); diff --git a/radiant/camwindow.cpp b/radiant/camwindow.cpp index ca7e26a0..1c782e43 100644 --- a/radiant/camwindow.cpp +++ b/radiant/camwindow.cpp @@ -845,6 +845,7 @@ void camwnd_update_xor_rectangle( CamWnd& self, rect_t area ){ gboolean selection_button_press( GtkWidget* widget, GdkEventButton* event, WindowObserver* observer ){ if ( event->type == GDK_BUTTON_PRESS ) { + gtk_widget_grab_focus( widget ); observer->onMouseDown( WindowVector_forDouble( event->x, event->y ), button_for_button( event->button ), modifiers_for_state( event->state ) ); } return FALSE; @@ -886,6 +887,11 @@ gboolean selection_motion_freemove( GtkWidget *widget, GdkEventMotion *event, Wi } gboolean wheelmove_scroll( GtkWidget* widget, GdkEventScroll* event, CamWnd* camwnd ){ + //gtk_window_set_focus( camwnd->m_parent, camwnd->m_gl_widget ); + gtk_widget_grab_focus( camwnd->m_gl_widget ); + if( !gtk_window_is_active( camwnd->m_parent ) ) + gtk_window_present( camwnd->m_parent ); + if ( event->direction == GDK_SCROLL_UP ) { Camera_Freemove_updateAxes( camwnd->getCamera() ); if( camwnd->m_bFreeMove || !g_camwindow_globals.m_bZoomInToPointer ){ diff --git a/radiant/eclass_doom3.cpp b/radiant/eclass_doom3.cpp index 61380f78..a358dcce 100644 --- a/radiant/eclass_doom3.cpp +++ b/radiant/eclass_doom3.cpp @@ -84,7 +84,8 @@ inline void printParseError( const char* message ){ globalErrorStream() << message; } -#define PARSE_RETURN_FALSE_IF_FAIL( expression ) if ( !( expression ) ) { printParseError( FILE_LINE "\nparse failed: " # expression "\n" ); return false; } else +//#define PARSE_RETURN_FALSE_IF_FAIL( expression ) if ( !( expression ) ) { printParseError( FILE_LINE "\nparse failed: " # expression "\n" ); return false; } else +#define PARSE_RETURN_FALSE_IF_FAIL( expression ) do{ if ( !( expression ) ) { printParseError( FILE_LINE "\nparse failed: " # expression "\n" ); return false; } }while( 0 ) bool EntityClassDoom3_parseToken( Tokeniser& tokeniser ){ const char* token = tokeniser.getToken(); diff --git a/radiant/entity.cpp b/radiant/entity.cpp index e1fa5260..d18f9456 100644 --- a/radiant/entity.cpp +++ b/radiant/entity.cpp @@ -306,6 +306,19 @@ void Entity_createFromSelection( const char* name, const Vector3& origin ){ bool brushesSelected = Scene_countSelectedBrushes( GlobalSceneGraph() ) != 0; + //is important to have retexturing here; if doing in the end, undo doesn't succeed; + if ( string_compare_nocase_n( name, "trigger_", 8 ) == 0 && brushesSelected ){ + const char* shader = g_pGameDescription->getKeyValue( "shader_trigger" ); + if ( shader && *shader ){ + Scene_PatchSetShader_Selected( GlobalSceneGraph(), shader ); + Scene_BrushSetShader_Selected( GlobalSceneGraph(), shader ); + } + else{ + Scene_PatchSetShader_Selected( GlobalSceneGraph(), "textures/common/trigger" ); + Scene_BrushSetShader_Selected( GlobalSceneGraph(), "textures/common/trigger" ); + } + } + if ( !( entityClass->fixedsize || isModel ) && !brushesSelected ) { globalErrorStream() << "failed to create a group entity - no brushes are selected\n"; return; @@ -392,18 +405,6 @@ void Entity_createFromSelection( const char* name, const Vector3& origin ){ Node_getEntity( node )->setKeyValue( "model", model ); } } - - if ( string_compare_nocase_n( name, "trigger_", 8 ) == 0 && brushesSelected ){ - const char* shader = g_pGameDescription->getKeyValue( "shader_trigger" ); - if ( shader && *shader ){ - Scene_PatchSetShader_Selected( GlobalSceneGraph(), shader ); - Scene_BrushSetShader_Selected( GlobalSceneGraph(), shader ); - } - else{ - Scene_PatchSetShader_Selected( GlobalSceneGraph(), "textures/common/trigger" ); - Scene_BrushSetShader_Selected( GlobalSceneGraph(), "textures/common/trigger" ); - } - } } #if 0 diff --git a/radiant/entity.h b/radiant/entity.h index eaf73cbb..9096287a 100644 --- a/radiant/entity.h +++ b/radiant/entity.h @@ -32,6 +32,7 @@ void Scene_EntitySetClassname_Selected( const char* classname ); typedef struct _GtkWidget GtkWidget; const char* misc_model_dialog( GtkWidget* parent ); +void Entity_setColour(); typedef struct _GtkMenu GtkMenu; void Entity_constructMenu( GtkMenu* menu ); diff --git a/radiant/entityinspector.cpp b/radiant/entityinspector.cpp index 9ebeec4e..4905cf01 100644 --- a/radiant/entityinspector.cpp +++ b/radiant/entityinspector.cpp @@ -222,6 +222,52 @@ ShaderAttribute( const char* key ) : StringAttribute( key ){ }; +class ColorAttribute : public EntityAttribute +{ +CopiedString m_key; +BrowsedPathEntry m_entry; +NonModalEntry m_nonModal; +public: +ColorAttribute( const char* key ) : + m_key( key ), + m_entry( BrowseCaller( *this ) ), + m_nonModal( ApplyCaller( *this ), UpdateCaller( *this ) ){ + m_nonModal.connect( m_entry.m_entry.m_entry ); +} +void release(){ + delete this; +} +GtkWidget* getWidget() const { + return GTK_WIDGET( m_entry.m_entry.m_frame ); +} +void apply(){ + StringOutputStream value( 64 ); + value << gtk_entry_get_text( GTK_ENTRY( m_entry.m_entry.m_entry ) ); + Scene_EntitySetKeyValue_Selected_Undoable( m_key.c_str(), value.c_str() ); +} +typedef MemberCaller ApplyCaller; +void update(){ + StringOutputStream value( 64 ); + value << SelectedEntity_getValueForKey( m_key.c_str() ); + gtk_entry_set_text( GTK_ENTRY( m_entry.m_entry.m_entry ), value.c_str() ); +} +typedef MemberCaller UpdateCaller; +void browse( const BrowsedPathEntry::SetPathCallback& setPath ){ + //const char *filename = misc_model_dialog( gtk_widget_get_toplevel( GTK_WIDGET( m_entry.m_entry.m_frame ) ) ); + + /* hijack BrowsedPathEntry to call colour chooser */ + Entity_setColour(); + +// if ( filename != 0 ) { +// setPath( filename ); +// apply(); +// } + update(); +} +typedef MemberCaller1 BrowseCaller; +}; + + class ModelAttribute : public EntityAttribute { CopiedString m_key; @@ -847,7 +893,34 @@ void SetComment( EntityClass* eclass ){ g_current_comment = eclass; GtkTextBuffer* buffer = gtk_text_view_get_buffer( g_entityClassComment ); - gtk_text_buffer_set_text( buffer, eclass->comments(), -1 ); + //gtk_text_buffer_set_text( buffer, eclass->comments(), -1 ); + const char* comment = eclass->comments(), *c; + int offset = 0, pattern_start = -1, spaces = 0; + + gtk_text_buffer_set_text( buffer, comment, -1 ); + + // Catch patterns like "\nstuff :" used to describe keys and spawnflags, and make them bold for readability. + + for( c = comment; *c; ++c, ++offset ) { + if( *c == '\n' ) { + pattern_start = offset; + spaces = 0; + } + else if( pattern_start >= 0 && ( *c < 'a' || *c > 'z' ) && ( *c < 'A' || *c > 'Z' ) && ( *c < '0' || *c > '9' ) && ( *c != '_' ) ) { + if( *c == ':' && spaces <= 1 ) { + GtkTextIter iter_start, iter_end; + + gtk_text_buffer_get_iter_at_offset( buffer, &iter_start, pattern_start ); + gtk_text_buffer_get_iter_at_offset( buffer, &iter_end, offset ); + gtk_text_buffer_apply_tag_by_name( buffer, "bold", &iter_start, &iter_end ); + } + + if( *c == ' ' ) + ++spaces; + else + pattern_start = -1; + } + } } void SurfaceFlags_setEntityClass( EntityClass* eclass ){ @@ -948,7 +1021,7 @@ Creators m_creators; public: EntityAttributeFactory(){ m_creators.insert( Creators::value_type( "string", &StatelessAttributeCreator::create ) ); - m_creators.insert( Creators::value_type( "color", &StatelessAttributeCreator::create ) ); + m_creators.insert( Creators::value_type( "color", &StatelessAttributeCreator::create ) ); m_creators.insert( Creators::value_type( "integer", &StatelessAttributeCreator::create ) ); m_creators.insert( Creators::value_type( "real", &StatelessAttributeCreator::create ) ); m_creators.insert( Creators::value_type( "shader", &StatelessAttributeCreator::create ) ); @@ -1416,6 +1489,10 @@ GtkWidget* EntityInspector_constructWindow( GtkWindow* toplevel ){ gtk_widget_show( GTK_WIDGET( text ) ); gtk_container_add( GTK_CONTAINER( scr ), GTK_WIDGET( text ) ); g_entityClassComment = text; + { + GtkTextBuffer *buffer = gtk_text_view_get_buffer( text ); + gtk_text_buffer_create_tag( buffer, "bold", "weight", PANGO_WEIGHT_BOLD, NULL ); + } } } } diff --git a/radiant/gtkdlgs.cpp b/radiant/gtkdlgs.cpp index d0738e8d..3669107a 100644 --- a/radiant/gtkdlgs.cpp +++ b/radiant/gtkdlgs.cpp @@ -970,7 +970,7 @@ EMessageBoxReturn DoLightIntensityDlg( int *intensity ){ // ============================================================================= // Add new shader tag dialog -EMessageBoxReturn DoShaderTagDlg( CopiedString* tag, char* title ){ +EMessageBoxReturn DoShaderTagDlg( CopiedString* tag, const char* title ){ ModalDialog dialog; GtkEntry* textentry; ModalDialogButton ok_button( dialog, eIDOK ); @@ -1031,7 +1031,7 @@ EMessageBoxReturn DoShaderTagDlg( CopiedString* tag, char* title ){ return ret; } -EMessageBoxReturn DoShaderInfoDlg( const char* name, const char* filename, char* title ){ +EMessageBoxReturn DoShaderInfoDlg( const char* name, const char* filename, const char* title ){ ModalDialog dialog; ModalDialogButton ok_button( dialog, eIDOK ); diff --git a/radiant/gtkdlgs.h b/radiant/gtkdlgs.h index dfebe8f8..3c3e76ee 100644 --- a/radiant/gtkdlgs.h +++ b/radiant/gtkdlgs.h @@ -35,8 +35,8 @@ #include "string/string.h" EMessageBoxReturn DoLightIntensityDlg( int *intensity ); -EMessageBoxReturn DoShaderTagDlg( CopiedString *tag, char* title ); -EMessageBoxReturn DoShaderInfoDlg( const char* name, const char* filename, char* title ); +EMessageBoxReturn DoShaderTagDlg( CopiedString *tag, const char* title ); +EMessageBoxReturn DoShaderInfoDlg( const char* name, const char* filename, const char* title ); EMessageBoxReturn DoTextureLayout( float *fx, float *fy ); void DoTextEditor( const char* filename, int cursorpos, int length, bool external_editor ); diff --git a/radiant/mainframe.cpp b/radiant/mainframe.cpp index 75662b23..1c956db0 100644 --- a/radiant/mainframe.cpp +++ b/radiant/mainframe.cpp @@ -1,4 +1,4 @@ -/* +/* Copyright (C) 1999-2006 Id Software, Inc. and contributors. For a list of contributors, see the accompanying CONTRIBUTORS file. @@ -438,12 +438,28 @@ GtkWindow* BuildDialog(){ GtkVBox* vbox2 = create_dialog_vbox( 0, 4 ); gtk_container_add( GTK_CONTAINER( frame ), GTK_WIDGET( vbox2 ) ); + const char* engine; +#if defined( WIN32 ) + engine = g_pGameDescription->getRequiredKeyValue( "engine_win32" ); +#elif defined( __linux__ ) || defined ( __FreeBSD__ ) + engine = g_pGameDescription->getRequiredKeyValue( "engine_linux" ); +#elif defined( __APPLE__ ) + engine = g_pGameDescription->getRequiredKeyValue( "engine_macos" ); +#else +#error "unsupported platform" +#endif + StringOutputStream text( 256 ); + text << "Select directory, where game executable sits (typically \"" << engine << "\")\n"; + GtkLabel* label = GTK_LABEL( gtk_label_new( text.c_str() ) ); + gtk_widget_show( GTK_WIDGET( label ) ); + gtk_container_add( GTK_CONTAINER( vbox2 ), GTK_WIDGET( label ) ); + { PreferencesPage preferencesPage( *this, GTK_WIDGET( vbox2 ) ); Paths_constructPreferences( preferencesPage ); } - return create_simple_modal_dialog_window( "Engine Path Not Found", m_modal, GTK_WIDGET( frame ) ); + return create_simple_modal_dialog_window( "Engine Path Configuration", m_modal, GTK_WIDGET( frame ) ); } }; diff --git a/radiant/preferences.cpp b/radiant/preferences.cpp index 52ea8877..78757c39 100644 --- a/radiant/preferences.cpp +++ b/radiant/preferences.cpp @@ -444,7 +444,7 @@ void CGameDialog::Init(){ } } } - if ( m_bGamePrompt || !currentGameDescription ) { + if ( !currentGameDescription ) { Create(); DoGameDialog(); // use m_nComboSelect to identify the game to run as and set the globals diff --git a/radiant/preferences.h b/radiant/preferences.h index 8793d039..4b44f97f 100644 --- a/radiant/preferences.h +++ b/radiant/preferences.h @@ -245,7 +245,7 @@ std::list mGames; CGameDialog() : m_sGameFile( "" ), - m_bGamePrompt( true ), + m_bGamePrompt( false ), m_bForceLogConsole( false ){ } virtual ~CGameDialog(); diff --git a/radiant/texwindow.cpp b/radiant/texwindow.cpp index 926937ea..efc5f432 100644 --- a/radiant/texwindow.cpp +++ b/radiant/texwindow.cpp @@ -335,10 +335,10 @@ TextureBrowser() : m_rmbSelected( false ), m_searchedTags( false ), m_tags( false ), + m_move_started( false ), m_uniformTextureSize( 160 ), m_uniformTextureMinSize( 48 ), - m_hideNonShadersInCommon( true ), - m_move_started( false ){ + m_hideNonShadersInCommon( true ){ } }; @@ -779,6 +779,7 @@ void visit( const char* minor, const _QERPlugImageTable& table ) const { }; void TextureBrowser_ShowDirectory( TextureBrowser& textureBrowser, const char* directory ){ + textureBrowser.m_searchedTags = false; if ( TextureBrowser_showWads() ) { Archive* archive = GlobalFileSystem().getArchive( directory ); ASSERT_NOTNULL( archive ); @@ -1377,6 +1378,7 @@ void BuildStoreAvailableTags( GtkListStore* storeAvailable, gboolean TextureBrowser_button_press( GtkWidget* widget, GdkEventButton* event, TextureBrowser* textureBrowser ){ if ( event->type == GDK_BUTTON_PRESS ) { + gtk_widget_grab_focus( widget ); if ( event->button == 3 ) { if ( GlobalTextureBrowser().m_tags ) { textureBrowser->m_rmbSelected = true; @@ -1451,6 +1453,10 @@ gboolean TextureBrowser_motion( GtkWidget *widget, GdkEventMotion *event, Textur } gboolean TextureBrowser_scroll( GtkWidget* widget, GdkEventScroll* event, TextureBrowser* textureBrowser ){ + gtk_widget_grab_focus( widget ); + if( !gtk_window_is_active( textureBrowser->m_parent ) ) + gtk_window_present( textureBrowser->m_parent ); + if ( event->direction == GDK_SCROLL_UP ) { TextureBrowser_MouseWheel( *textureBrowser, true ); } @@ -2048,7 +2054,7 @@ void TextureBrowser_SetNotex(){ name << GlobalRadiant().getAppPath() << "bitmaps/notex.png"; g_notex = name.c_str(); - name = NULL; + name.clear(); name << GlobalRadiant().getAppPath() << "bitmaps/shadernotex.png"; g_shadernotex = name.c_str(); } diff --git a/radiant/xywindow.cpp b/radiant/xywindow.cpp index 8b2da7cb..9a1be033 100644 --- a/radiant/xywindow.cpp +++ b/radiant/xywindow.cpp @@ -746,6 +746,8 @@ void xy_update_xor_rectangle( XYWnd& self, rect_t area ){ gboolean xywnd_button_press( GtkWidget* widget, GdkEventButton* event, XYWnd* xywnd ){ if ( event->type == GDK_BUTTON_PRESS ) { + gtk_widget_grab_focus( xywnd->GetWidget() ); + if( !xywnd->Active() ){ g_pParentWnd->SetActiveXY( xywnd ); } @@ -785,6 +787,11 @@ void xywnd_motion( gdouble x, gdouble y, guint state, void* data ){ } gboolean xywnd_wheel_scroll( GtkWidget* widget, GdkEventScroll* event, XYWnd* xywnd ){ + gtk_widget_grab_focus( xywnd->GetWidget() ); + GtkWindow* window = xywnd->m_parent != 0 ? xywnd->m_parent : MainFrame_getWindow(); + if( !gtk_window_is_active( window ) ) + gtk_window_present( window ); + if( !xywnd->Active() ){ g_pParentWnd->SetActiveXY( xywnd ); } diff --git a/tools/quake3/common/scriplib.c b/tools/quake3/common/scriplib.c index 1f0ac88d..95a09e94 100644 --- a/tools/quake3/common/scriplib.c +++ b/tools/quake3/common/scriplib.c @@ -263,7 +263,7 @@ skipspace: Error( "Line %i is incomplete\nFile location be: %s\n", scriptline, g_strLoadedFileLocation ); } script->script_p += 2; - while ( script->script_p[0] != '*' && script->script_p[1] != '/' ) + while ( script->script_p[0] != '*' || script->script_p[1] != '/' ) { if ( *script->script_p == '\n' ) { script->line++; diff --git a/tools/quake3/q3map2/portals.c b/tools/quake3/q3map2/portals.c index aee1446e..c1963e7c 100644 --- a/tools/quake3/q3map2/portals.c +++ b/tools/quake3/q3map2/portals.c @@ -668,7 +668,7 @@ int FloodEntities( tree_t *tree ){ node_t *headnode; entity_t *e, *tripped; const char *value; - int tripcount; + int tripcount = INT_MIN; headnode = tree->headnode; -- 2.39.2