diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp
index 84a09b2d15..091c6a50bf 100644
--- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp
+++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp
@@ -215,7 +215,7 @@ void BOARD_ADAPTER::addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2
         {
             PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
 
-            if( text->GetLayer() == aLayerId && text->IsVisible() )
+            if( text->GetLayer() == aLayerId )
             {
                 if( !aVisibilityFlags.test( LAYER_FP_TEXT ) )
                     continue;
diff --git a/api/proto/board/board_types.proto b/api/proto/board/board_types.proto
index 2356fa5aac..f01a94aa10 100644
--- a/api/proto/board/board_types.proto
+++ b/api/proto/board/board_types.proto
@@ -768,6 +768,7 @@ message Field
   FieldId id = 1;
   string name = 2;
   BoardText text = 3;
+  bool visible = 4;
 }
 
 enum FootprintMountingStyle
diff --git a/api/proto/common/types/base_types.proto b/api/proto/common/types/base_types.proto
index f491a1aed2..dbef5f95c6 100644
--- a/api/proto/common/types/base_types.proto
+++ b/api/proto/common/types/base_types.proto
@@ -291,7 +291,8 @@ message TextAttributes
   bool                        italic               = 7;
   bool                        bold                 = 8;
   bool                        underlined           = 9;
-  bool                        visible              = 10;
+  // Visible now exposed only at the field level
+  // bool                        visible              = 10;
   bool                        mirrored             = 11;
   bool                        multiline            = 12;
   bool                        keep_upright         = 13;
@@ -305,7 +306,7 @@ message Text
   kiapi.common.types.Vector2        position   = 2;
   kiapi.common.types.TextAttributes attributes = 3;
 
-  // Reserved for future use; base objects don't support locking right nos
+  // Reserved for future use; base objects don't support locking right now
   //kiapi.common.types.LockedState    locked     = 4;
 
   string                            text       = 5;
@@ -318,7 +319,7 @@ message TextBox
   kiapi.common.types.Vector2        bottom_right = 3;
   kiapi.common.types.TextAttributes attributes   = 4;
 
-  // Reserved for future use; base objects don't support locking right nos
+  // Reserved for future use; base objects don't support locking right now
   //kiapi.common.types.LockedState    locked       = 5;
 
   string                            text         = 6;
diff --git a/common/eda_text.cpp b/common/eda_text.cpp
index e73a78e9d9..1dd4ceab08 100644
--- a/common/eda_text.cpp
+++ b/common/eda_text.cpp
@@ -48,7 +48,7 @@
 #include <font/outline_font.h>
 #include <geometry/shape_poly_set.h>
 #include <properties/property_validators.h>
-#include <ctl_flags.h>         // for CTL_OMIT_HIDE definition
+#include <ctl_flags.h>
 #include <api/api_enums.h>
 #include <api/api_utils.h>
 #include <api/common/types/base_types.pb.h>
@@ -95,7 +95,8 @@ GR_TEXT_V_ALIGN_T EDA_TEXT::MapVertJustify( int aVertJustify )
 EDA_TEXT::EDA_TEXT( const EDA_IU_SCALE& aIuScale, const wxString& aText ) :
         m_text( aText ),
         m_IuScale( aIuScale ),
-        m_render_cache_font( nullptr )
+        m_render_cache_font( nullptr ),
+        m_visible( true )
 {
     SetTextSize( VECTOR2I( EDA_UNIT_UTILS::Mils2IU( m_IuScale, DEFAULT_SIZE_TEXT ),
                            EDA_UNIT_UTILS::Mils2IU( m_IuScale, DEFAULT_SIZE_TEXT ) ) );
@@ -122,6 +123,7 @@ EDA_TEXT::EDA_TEXT( const EDA_TEXT& aText ) :
 
     m_attributes = aText.m_attributes;
     m_pos = aText.m_pos;
+    m_visible = aText.m_visible;
 
     m_render_cache_font = aText.m_render_cache_font;
     m_render_cache_text = aText.m_render_cache_text;
@@ -157,6 +159,7 @@ EDA_TEXT& EDA_TEXT::operator=( const EDA_TEXT& aText )
 
     m_attributes = aText.m_attributes;
     m_pos = aText.m_pos;
+    m_visible = aText.m_visible;
 
     m_render_cache_font = aText.m_render_cache_font;
     m_render_cache_text = aText.m_render_cache_text;
@@ -207,7 +210,6 @@ void EDA_TEXT::Serialize( google::protobuf::Any &aContainer ) const
     attrs->set_italic( IsItalic() );
     attrs->set_bold( IsBold() );
     attrs->set_underlined( GetAttributes().m_Underlined );
-    attrs->set_visible( IsVisible() );
     attrs->set_mirrored( IsMirrored() );
     attrs->set_multiline( IsMultilineAllowed() );
     attrs->set_keep_upright( IsKeepUpright() );
@@ -236,7 +238,6 @@ bool EDA_TEXT::Deserialize( const google::protobuf::Any &aContainer )
         attrs.m_Bold = text.attributes().bold();
         attrs.m_Italic = text.attributes().italic();
         attrs.m_Underlined = text.attributes().underlined();
-        attrs.m_Visible = text.attributes().visible();
         attrs.m_Mirrored = text.attributes().mirrored();
         attrs.m_Multiline = text.attributes().multiline();
         attrs.m_KeepUpright = text.attributes().keep_upright();
@@ -376,7 +377,7 @@ void EDA_TEXT::SetBoldFlag( bool aBold )
 
 void EDA_TEXT::SetVisible( bool aVisible )
 {
-    m_attributes.m_Visible = aVisible;
+    m_visible = aVisible;
     ClearRenderCache();
 }
 
@@ -1036,8 +1037,7 @@ void EDA_TEXT::SetFontIndex( int aIdx )
 
 bool EDA_TEXT::IsDefaultFormatting() const
 {
-    return ( IsVisible()
-             && !IsMirrored()
+    return ( !IsMirrored()
              && GetHorizJustify() == GR_TEXT_H_ALIGN_CENTER
              && GetVertJustify() == GR_TEXT_V_ALIGN_CENTER
              && GetTextThickness() == 0
@@ -1109,13 +1109,8 @@ void EDA_TEXT::Format( OUTPUTFORMATTER* aFormatter, int aControlBits ) const
         aFormatter->Print( ")" ); // (justify
     }
 
-    if( !( aControlBits & CTL_OMIT_HIDE ) && !IsVisible() )
-        KICAD_FORMAT::FormatBool( aFormatter, "hide", true );
-
     if( !( aControlBits & CTL_OMIT_HYPERLINK ) && HasHyperlink() )
-    {
         aFormatter->Print( "(href %s)", aFormatter->Quotew( GetHyperlink() ).c_str() );
-    }
 
     aFormatter->Print( ")" ); // (effects
 }
@@ -1375,9 +1370,6 @@ static struct EDA_TEXT_DESC
         propMgr.AddProperty( new PROPERTY<EDA_TEXT, bool>( _HKI( "Mirrored" ),
                 &EDA_TEXT::SetMirrored, &EDA_TEXT::IsMirrored ),
                 textProps );
-        propMgr.AddProperty( new PROPERTY<EDA_TEXT, bool>( _HKI( "Visible" ),
-                &EDA_TEXT::SetVisible, &EDA_TEXT::IsVisible ),
-                textProps );
         propMgr.AddProperty( new PROPERTY<EDA_TEXT, int>( _HKI( "Width" ),
                 &EDA_TEXT::SetTextWidth, &EDA_TEXT::GetTextWidth,
                 PROPERTY_DISPLAY::PT_SIZE ),
diff --git a/common/font/text_attributes.cpp b/common/font/text_attributes.cpp
index bd1040e04d..eee03d9204 100644
--- a/common/font/text_attributes.cpp
+++ b/common/font/text_attributes.cpp
@@ -32,7 +32,6 @@ TEXT_ATTRIBUTES::TEXT_ATTRIBUTES( KIFONT::FONT* aFont ) :
     m_Bold( false ),
     m_Underlined( false ),
     m_Color( KIGFX::COLOR4D::UNSPECIFIED ),
-    m_Visible( true ),
     m_Mirrored( false ),
     m_Multiline( true ),
     m_KeepUpright( false ),
@@ -93,9 +92,6 @@ int TEXT_ATTRIBUTES::Compare( const TEXT_ATTRIBUTES& aRhs ) const
     if( retv )
         return retv;
 
-    if( m_Visible != aRhs.m_Visible )
-        return m_Visible - aRhs.m_Visible;
-
     if( m_Mirrored != aRhs.m_Mirrored )
         return m_Mirrored - aRhs.m_Mirrored;
 
@@ -125,7 +121,6 @@ std::ostream& operator<<( std::ostream& aStream, const TEXT_ATTRIBUTES& aAttribu
             << "Bold: " << aAttributes.m_Bold << std::endl
             << "Underline: " << aAttributes.m_Underlined << std::endl
             << "Color: " << aAttributes.m_Color << std::endl
-            << "Visible " << aAttributes.m_Visible << std::endl
             << "Mirrored " << aAttributes.m_Mirrored << std::endl
             << "Multilined: " << aAttributes.m_Multiline << std::endl
             << "Size: " << aAttributes.m_Size << std::endl
diff --git a/eeschema/dialogs/dialog_field_properties.cpp b/eeschema/dialogs/dialog_field_properties.cpp
index 653c523ac0..4ac1b74420 100644
--- a/eeschema/dialogs/dialog_field_properties.cpp
+++ b/eeschema/dialogs/dialog_field_properties.cpp
@@ -543,17 +543,17 @@ bool DIALOG_FIELD_PROPERTIES::TransferDataFromWindow()
 }
 
 
-void DIALOG_FIELD_PROPERTIES::updateText( EDA_TEXT* aText )
+void DIALOG_FIELD_PROPERTIES::updateText( SCH_FIELD* aField )
 {
-    if( aText->GetTextWidth() != m_size )
-        aText->SetTextSize( VECTOR2I( m_size, m_size ) );
+    if( aField->GetTextWidth() != m_size )
+        aField->SetTextSize( VECTOR2I( m_size, m_size ) );
 
-    aText->SetFont( m_font );
-    aText->SetVisible( m_isVisible );
-    aText->SetTextAngle( m_isVertical ? ANGLE_VERTICAL : ANGLE_HORIZONTAL );
-    aText->SetItalic( m_isItalic );
-    aText->SetBold( m_isBold );
-    aText->SetTextColor( m_color );
+    aField->SetFont( m_font );
+    aField->SetVisible( m_isVisible );
+    aField->SetTextAngle( m_isVertical ? ANGLE_VERTICAL : ANGLE_HORIZONTAL );
+    aField->SetItalic( m_isItalic );
+    aField->SetBold( m_isBold );
+    aField->SetTextColor( m_color );
 }
 
 
diff --git a/eeschema/dialogs/dialog_field_properties.h b/eeschema/dialogs/dialog_field_properties.h
index 32f0822c33..ee12b1ce73 100644
--- a/eeschema/dialogs/dialog_field_properties.h
+++ b/eeschema/dialogs/dialog_field_properties.h
@@ -62,7 +62,7 @@ public:
 protected:
     void init();
 
-    void updateText( EDA_TEXT* aText );
+    void updateText( SCH_FIELD* aField );
 
     void onScintillaCharAdded( wxStyledTextEvent &aEvent );
 
diff --git a/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp b/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp
index 68c0cb5674..cb390f4bd1 100644
--- a/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp
+++ b/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp
@@ -284,9 +284,6 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::processItem( SCH_COMMIT* aCommit,
             eda_text->SetVertJustify( vAlign );
         }
 
-        if( m_visible->Get3StateValue() != wxCHK_UNDETERMINED )
-            eda_text->SetVisible( m_visible->GetValue() );
-
         if( m_italic->Get3StateValue() != wxCHK_UNDETERMINED )
             eda_text->SetItalic( m_italic->GetValue() );
 
@@ -320,6 +317,9 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::processItem( SCH_COMMIT* aCommit,
 
     if( SCH_FIELD* sch_field = dynamic_cast<SCH_FIELD*>( aItem ) )
     {
+        if( m_visible->Get3StateValue() != wxCHK_UNDETERMINED )
+            sch_field->SetVisible( m_visible->GetValue() );
+
         if( m_showFieldNames->Get3StateValue() != wxCHK_UNDETERMINED )
             sch_field->SetNameShown( m_showFieldNames->GetValue() );
     }
diff --git a/eeschema/sch_field.cpp b/eeschema/sch_field.cpp
index 662db19d2c..c5508c1456 100644
--- a/eeschema/sch_field.cpp
+++ b/eeschema/sch_field.cpp
@@ -22,14 +22,6 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-/*
- * Fields are texts attached to a symbol, some of which have a special meaning.
- * Fields 0 and 1 are very important: reference and value.
- * Field 2 is used as default footprint name.
- * Field 3 is used to point to a datasheet (usually a URL).
- * Fields 4+ are user fields.  They can be renamed and can appear in reports.
- */
-
 #include <wx/log.h>
 #include <wx/menu.h>
 
@@ -39,13 +31,8 @@
 #include <sch_edit_frame.h>
 #include <plotters/plotter.h>
 #include <bitmaps.h>
-#include <core/mirror.h>
 #include <kiway.h>
 #include <symbol_library.h>
-#include <sch_symbol.h>
-#include <sch_field.h>
-#include <sch_label.h>
-#include <schematic.h>
 #include <settings/color_settings.h>
 #include <string_utils.h>
 #include <trace_helpers.h>
@@ -83,12 +70,20 @@ SCH_FIELD::SCH_FIELD( const VECTOR2I& aPos, int aFieldId, SCH_ITEM* aParent,
 }
 
 
-SCH_FIELD::SCH_FIELD( SCH_ITEM* aParent, int aFieldId, const wxString& aName) :
+SCH_FIELD::SCH_FIELD( SCH_ITEM* aParent, int aFieldId, const wxString& aName ) :
         SCH_FIELD( VECTOR2I(), aFieldId, aParent, aName )
 {
 }
 
 
+SCH_FIELD::SCH_FIELD( SCH_TEXT* aText ) :
+        SCH_FIELD( VECTOR2I(), INVALID_FIELD, nullptr, wxEmptyString )
+{
+    SCH_ITEM::operator=( *aText );
+    EDA_TEXT::operator=( *aText );
+}
+
+
 SCH_FIELD::SCH_FIELD( const SCH_FIELD& aField ) :
         SCH_ITEM( aField ),
         EDA_TEXT( aField )
@@ -515,6 +510,7 @@ void SCH_FIELD::Print( const SCH_RENDER_SETTINGS* aSettings, int aUnit, int aBod
 void SCH_FIELD::ImportValues( const SCH_FIELD& aSource )
 {
     SetAttributes( aSource );
+    SetVisible( aSource.IsVisible() );
     SetNameShown( aSource.IsNameShown() );
     SetCanAutoplace( aSource.CanAutoplace() );
 }
diff --git a/eeschema/sch_field.h b/eeschema/sch_field.h
index 2a56f62127..1cf2c24188 100644
--- a/eeschema/sch_field.h
+++ b/eeschema/sch_field.h
@@ -34,6 +34,7 @@
 #include "scintilla_tricks.h"
 
 class SCH_EDIT_FRAME;
+class SCH_TEXT;
 
 
 /**
@@ -56,6 +57,8 @@ public:
     SCH_FIELD( SCH_ITEM* aParent, int aFieldId = INVALID_FIELD,
                const wxString& aName = wxEmptyString );
 
+    SCH_FIELD( SCH_TEXT* aText );
+
     SCH_FIELD( const SCH_FIELD& aText );
 
     ~SCH_FIELD() override
diff --git a/eeschema/sch_io/kicad_legacy/sch_io_kicad_legacy_lib_cache.cpp b/eeschema/sch_io/kicad_legacy/sch_io_kicad_legacy_lib_cache.cpp
index 6e88717413..fdb1adc842 100644
--- a/eeschema/sch_io/kicad_legacy/sch_io_kicad_legacy_lib_cache.cpp
+++ b/eeschema/sch_io/kicad_legacy/sch_io_kicad_legacy_lib_cache.cpp
@@ -957,7 +957,7 @@ SCH_SHAPE* SCH_IO_KICAD_LEGACY_LIB_CACHE::loadCircle( LINE_READER& aReader )
 }
 
 
-SCH_TEXT* SCH_IO_KICAD_LEGACY_LIB_CACHE::loadText( LINE_READER& aReader,
+SCH_ITEM* SCH_IO_KICAD_LEGACY_LIB_CACHE::loadText( LINE_READER& aReader,
                                                    int aMajorVersion, int aMinorVersion )
 {
     const char* line = aReader.Line();
@@ -1002,12 +1002,27 @@ SCH_TEXT* SCH_IO_KICAD_LEGACY_LIB_CACHE::loadText( LINE_READER& aReader,
         str.Replace( "''", "\"" );
     }
 
-    SCH_TEXT* text = new SCH_TEXT( center, str, LAYER_DEVICE );
-    text->SetTextAngle( EDA_ANGLE( angleInTenths, TENTHS_OF_A_DEGREE_T ) );
-    text->SetTextSize( size );
-    text->SetVisible( visible );
-    text->SetUnit( unit );
-    text->SetBodyStyle( bodyStyle );
+    SCH_ITEM* sch_item = nullptr;
+    EDA_TEXT* eda_text = nullptr;
+
+    if( !visible )
+    {
+        SCH_FIELD* field = new SCH_FIELD( center, -1, nullptr );
+        sch_item = field;
+        eda_text = field;
+    }
+    else
+    {
+        SCH_TEXT* sch_text = new SCH_TEXT( center, str, LAYER_DEVICE );
+        sch_item = sch_text;
+        eda_text = sch_text;
+    }
+
+    eda_text->SetTextAngle( EDA_ANGLE( angleInTenths, TENTHS_OF_A_DEGREE_T ) );
+    eda_text->SetTextSize( size );
+    eda_text->SetVisible( visible );
+    sch_item->SetUnit( unit );
+    sch_item->SetBodyStyle( bodyStyle );
 
     // Here things are murky and not well defined.  At some point it appears the format
     // was changed to add text properties.  However rather than add the token to the end of
@@ -1021,37 +1036,37 @@ SCH_TEXT* SCH_IO_KICAD_LEGACY_LIB_CACHE::loadText( LINE_READER& aReader,
              && !is_eol( *line ) )
     {
         if( strCompare( "Italic", line, &line ) )
-            text->SetItalicFlag( true );
+            eda_text->SetItalicFlag( true );
         else if( !strCompare( "Normal", line, &line ) )
-            SCH_PARSE_ERROR( "invalid text stype, expected 'Normal' or 'Italic'", aReader, line );
+            SCH_PARSE_ERROR( "invalid eda_text stype, expected 'Normal' or 'Italic'", aReader, line );
 
         if( parseInt( aReader, line, &line ) > 0 )
-            text->SetBoldFlag( true );
+            eda_text->SetBoldFlag( true );
 
-        // Some old libaries version > 2.0 do not have these options for text justification:
+        // Some old libaries version > 2.0 do not have these options for eda_text justification:
         if( !is_eol( *line ) )
         {
             switch( parseChar( aReader, line, &line ) )
             {
-            case 'L': text->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );   break;
-            case 'C': text->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER ); break;
-            case 'R': text->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );  break;
-            default: SCH_PARSE_ERROR( "invalid horizontal text justication; expected L, C, or R",
+            case 'L': eda_text->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );   break;
+            case 'C': eda_text->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER ); break;
+            case 'R': eda_text->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );  break;
+            default: SCH_PARSE_ERROR( "invalid horizontal eda_text justication; expected L, C, or R",
                                       aReader, line );
             }
 
             switch( parseChar( aReader, line, &line ) )
             {
-            case 'T': text->SetVertJustify( GR_TEXT_V_ALIGN_TOP );    break;
-            case 'C': text->SetVertJustify( GR_TEXT_V_ALIGN_CENTER ); break;
-            case 'B': text->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM ); break;
-            default: SCH_PARSE_ERROR( "invalid vertical text justication; expected T, C, or B",
+            case 'T': eda_text->SetVertJustify( GR_TEXT_V_ALIGN_TOP );    break;
+            case 'C': eda_text->SetVertJustify( GR_TEXT_V_ALIGN_CENTER ); break;
+            case 'B': eda_text->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM ); break;
+            default: SCH_PARSE_ERROR( "invalid vertical eda_text justication; expected T, C, or B",
                                       aReader, line );
             }
         }
     }
 
-    return text;
+    return sch_item;
 }
 
 
diff --git a/eeschema/sch_io/kicad_legacy/sch_io_kicad_legacy_lib_cache.h b/eeschema/sch_io/kicad_legacy/sch_io_kicad_legacy_lib_cache.h
index 99a69f7213..e1d6794567 100644
--- a/eeschema/sch_io/kicad_legacy/sch_io_kicad_legacy_lib_cache.h
+++ b/eeschema/sch_io/kicad_legacy/sch_io_kicad_legacy_lib_cache.h
@@ -76,7 +76,7 @@ private:
     void              loadDocs();
     static SCH_SHAPE* loadArc( LINE_READER& aReader );
     static SCH_SHAPE* loadCircle( LINE_READER& aReader );
-    static SCH_TEXT*  loadText( LINE_READER& aReader, int aMajorVersion, int aMinorVersion );
+    static SCH_ITEM*  loadText( LINE_READER& aReader, int aMajorVersion, int aMinorVersion );
     static SCH_SHAPE* loadRect( LINE_READER& aReader );
     static SCH_PIN*   loadPin( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader );
     static SCH_SHAPE* loadPolyLine( LINE_READER& aReader );
diff --git a/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr.cpp b/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr.cpp
index 1eb23fe2b7..98954cdbd9 100644
--- a/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr.cpp
+++ b/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr.cpp
@@ -911,6 +911,9 @@ void SCH_IO_KICAD_SEXPR::saveField( SCH_FIELD* aField )
                                                        aField->GetPosition().y ).c_str(),
                   EDA_UNIT_UTILS::FormatAngle( aField->GetTextAngle() ).c_str() );
 
+    if( !aField->IsVisible() )
+        KICAD_FORMAT::FormatBool( m_out, "hide", true );
+
     if( aField->IsNameShown() )
         KICAD_FORMAT::FormatBool( m_out, "show_name", true );
 
diff --git a/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_lib_cache.cpp b/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_lib_cache.cpp
index 0b796e685d..8336e04a3a 100644
--- a/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_lib_cache.cpp
+++ b/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_lib_cache.cpp
@@ -427,6 +427,9 @@ void SCH_IO_KICAD_SEXPR_LIB_CACHE::saveField( SCH_FIELD* aField, OUTPUTFORMATTER
     if( !aField->CanAutoplace() )
         aFormatter.Print( "(do_not_autoplace)" );
 
+    if( !aField->IsVisible() )
+        KICAD_FORMAT::FormatBool( &aFormatter, "hide", true );
+
     aField->Format( &aFormatter, 0 );
     aFormatter.Print( ")" );
 }
diff --git a/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.cpp b/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.cpp
index 9e60ca6eee..2e2890850e 100644
--- a/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.cpp
+++ b/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.cpp
@@ -825,7 +825,7 @@ void SCH_IO_KICAD_SEXPR_PARSER::parseEDA_TEXT( EDA_TEXT* aText, bool aConvertOve
 
         case T_hide:
         {
-            bool hide = parseMaybeAbsentBool( true );
+            bool hide = parseMaybeAbsentBool( false );
             aText->SetVisible( !hide );
             break;
         }
@@ -1039,6 +1039,11 @@ SCH_FIELD* SCH_IO_KICAD_SEXPR_PARSER::parseProperty( std::unique_ptr<LIB_SYMBOL>
             NeedRIGHT();
             break;
 
+        case T_hide:
+            field->SetVisible( !parseBool() );
+            NeedRIGHT();
+            break;
+
         case T_effects:
             parseEDA_TEXT( static_cast<EDA_TEXT*>( field.get() ), field->GetId() == VALUE_FIELD );
             break;
@@ -1058,7 +1063,7 @@ SCH_FIELD* SCH_IO_KICAD_SEXPR_PARSER::parseProperty( std::unique_ptr<LIB_SYMBOL>
         }
 
         default:
-            Expecting( "id, at, show_name, do_not_autoplace, or effects" );
+            Expecting( "id, at, hide, show_name, do_not_autoplace, or effects" );
         }
     }
 
@@ -1845,7 +1850,7 @@ SCH_SHAPE* SCH_IO_KICAD_SEXPR_PARSER::parseSymbolRectangle()
 }
 
 
-SCH_TEXT* SCH_IO_KICAD_SEXPR_PARSER::parseSymbolText()
+SCH_ITEM* SCH_IO_KICAD_SEXPR_PARSER::parseSymbolText()
 {
     wxCHECK_MSG( CurTok() == T_text, nullptr,
                  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a text token." ) );
@@ -1897,6 +1902,10 @@ SCH_TEXT* SCH_IO_KICAD_SEXPR_PARSER::parseSymbolText()
         }
     }
 
+    // Convert hidden symbol text (which is no longer supported) into a hidden field
+    if( !text->IsVisible() )
+        return new SCH_FIELD( text.get(), -1 );
+
     return text.release();
 }
 
@@ -2294,6 +2303,11 @@ SCH_FIELD* SCH_IO_KICAD_SEXPR_PARSER::parseSchField( SCH_ITEM* aParent )
             NeedRIGHT();
             break;
 
+        case T_hide:
+            field->SetVisible( !parseBool() );
+            NeedRIGHT();
+            break;
+
         case T_effects:
             parseEDA_TEXT( static_cast<EDA_TEXT*>( field.get() ), field->GetId() == VALUE_FIELD );
             break;
@@ -2313,7 +2327,7 @@ SCH_FIELD* SCH_IO_KICAD_SEXPR_PARSER::parseSchField( SCH_ITEM* aParent )
         }
 
         default:
-            Expecting( "id, at, show_name, do_not_autoplace or effects" );
+            Expecting( "id, at, hide, show_name, do_not_autoplace or effects" );
         }
     }
 
@@ -4341,6 +4355,9 @@ SCH_TEXT* SCH_IO_KICAD_SEXPR_PARSER::parseSchText()
 
         case T_effects:
             parseEDA_TEXT( static_cast<EDA_TEXT*>( text.get() ), true );
+
+            // Hidden schematic text is no longer supported
+            text->SetVisible( true );
             break;
 
         case T_iref:    // legacy format; current is a T_property (aka SCH_FIELD)
diff --git a/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.h b/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.h
index b36ccfd02a..f1f7572bb3 100644
--- a/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.h
+++ b/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.h
@@ -202,7 +202,7 @@ private:
     SCH_PIN* parseSymbolPin();
     SCH_SHAPE* parseSymbolPolyLine();
     SCH_SHAPE* parseSymbolRectangle();
-    SCH_TEXT* parseSymbolText();
+    SCH_ITEM* parseSymbolText();
     SCH_TEXTBOX* parseSymbolTextBox();
 
     void parsePAGE_INFO( PAGE_INFO& aPageInfo );
diff --git a/eeschema/sch_text.cpp b/eeschema/sch_text.cpp
index 4752fb49db..451bc3778c 100644
--- a/eeschema/sch_text.cpp
+++ b/eeschema/sch_text.cpp
@@ -771,7 +771,6 @@ static struct SCH_TEXT_DESC
         propMgr.InheritsAfter( TYPE_HASH( SCH_TEXT ), TYPE_HASH( EDA_TEXT ) );
 
         propMgr.Mask( TYPE_HASH( SCH_TEXT ), TYPE_HASH( EDA_TEXT ), _HKI( "Mirrored" ) );
-        propMgr.Mask( TYPE_HASH( SCH_TEXT ), TYPE_HASH( EDA_TEXT ), _HKI( "Visible" ) );
         propMgr.Mask( TYPE_HASH( SCH_TEXT ), TYPE_HASH( EDA_TEXT ), _HKI( "Width" ) );
         propMgr.Mask( TYPE_HASH( SCH_TEXT ), TYPE_HASH( EDA_TEXT ), _HKI( "Height" ) );
         propMgr.Mask( TYPE_HASH( SCH_TEXT ), TYPE_HASH( EDA_TEXT ), _HKI( "Thickness" ) );
diff --git a/eeschema/sch_textbox.cpp b/eeschema/sch_textbox.cpp
index 6b9b28c910..521e60ab14 100644
--- a/eeschema/sch_textbox.cpp
+++ b/eeschema/sch_textbox.cpp
@@ -682,7 +682,6 @@ static struct SCH_TEXTBOX_DESC
 
         propMgr.Mask( TYPE_HASH( SCH_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Shape" ) );
 
-        propMgr.Mask( TYPE_HASH( SCH_TEXTBOX ), TYPE_HASH( EDA_TEXT ), _HKI( "Visible" ) );
         propMgr.Mask( TYPE_HASH( SCH_TEXTBOX ), TYPE_HASH( EDA_TEXT ), _HKI( "Width" ) );
         propMgr.Mask( TYPE_HASH( SCH_TEXTBOX ), TYPE_HASH( EDA_TEXT ), _HKI( "Height" ) );
         propMgr.Mask( TYPE_HASH( SCH_TEXTBOX ), TYPE_HASH( EDA_TEXT ), _HKI( "Thickness" ) );
diff --git a/eeschema/sim/sim_model.cpp b/eeschema/sim/sim_model.cpp
index 4cdbd07b66..c3854ae797 100644
--- a/eeschema/sim/sim_model.cpp
+++ b/eeschema/sim/sim_model.cpp
@@ -1420,13 +1420,14 @@ void SIM_MODEL::MigrateSimModel( T& aSymbol, const PROJECT* aProject )
     public:
         FIELD_INFO()
         {
-            m_Attributes.m_Visible = false;
+            m_Visible = false;
             m_Attributes.m_Size = VECTOR2I( DEFAULT_SIZE_TEXT * schIUScale.IU_PER_MILS,
                                             DEFAULT_SIZE_TEXT * schIUScale.IU_PER_MILS );
         };
 
         FIELD_INFO( const wxString& aText, SCH_FIELD* aField ) :
                 m_Text( aText ),
+                m_Visible( aField->IsVisible() ),
                 m_Attributes( aField->GetAttributes() ),
                 m_Pos( aField->GetPosition() )
         {}
@@ -1438,6 +1439,7 @@ void SIM_MODEL::MigrateSimModel( T& aSymbol, const PROJECT* aProject )
             SCH_FIELD field( aSymbol, -1, aFieldName );
 
             field.SetText( m_Text );
+            field.SetVisible( m_Visible );
             field.SetAttributes( m_Attributes );
             field.SetPosition( m_Pos );
 
@@ -1446,6 +1448,7 @@ void SIM_MODEL::MigrateSimModel( T& aSymbol, const PROJECT* aProject )
 
     public:
         wxString        m_Text;
+        bool            m_Visible;
         TEXT_ATTRIBUTES m_Attributes;
         VECTOR2I        m_Pos;
     };
diff --git a/include/ctl_flags.h b/include/ctl_flags.h
index d9fb82a861..c8f484d26f 100644
--- a/include/ctl_flags.h
+++ b/include/ctl_flags.h
@@ -34,10 +34,6 @@
                                                 ///< library).
 #define CTL_OMIT_AT                 (1 << 5)    ///< Omit position and rotation. (always saved
                                                 ///< with position 0,0 and rotation = 0 in library).
-
-// If set, when calling EDA_TEXT::Format, disable writing the "hide" keyword in save file.
-#define CTL_OMIT_HIDE               (1 << 6)    ///< Omit the hide attribute in .kicad_xxx files.
-
 #define CTL_OMIT_LIBNAME            (1 << 7)    ///< Omit lib alias when saving (used for
                                                 ///< board/not library)..
 #define CTL_OMIT_FOOTPRINT_VERSION  (1 << 8)    ///< Omit the version string from the (footprint)
diff --git a/include/eda_text.h b/include/eda_text.h
index 0bf4d5a05d..acffab98b5 100644
--- a/include/eda_text.h
+++ b/include/eda_text.h
@@ -163,7 +163,7 @@ public:
     void SetBold( bool aBold );
 
     /**
-     * Set only the italic flag, without changing the font.
+     * Set only the bold flag, without changing the font.
      *
      * Used when bulk-changing text attributes (e.g. from a dialog or import).
      */
@@ -171,7 +171,7 @@ public:
     bool IsBold() const                         { return m_attributes.m_Bold; }
 
     virtual void SetVisible( bool aVisible );
-    virtual bool IsVisible() const              { return m_attributes.m_Visible; }
+    virtual bool IsVisible() const              { return m_visible; }
 
     void SetMirrored( bool isMirrored );
     bool IsMirrored() const                     { return m_attributes.m_Mirrored; }
@@ -464,6 +464,7 @@ private:
     TEXT_ATTRIBUTES  m_attributes;
     wxString         m_unresolvedFontName;
     VECTOR2I         m_pos;
+    bool             m_visible;                 // For SCH_FIELDs and PCB_FIELDs
 };
 
 
diff --git a/include/font/text_attributes.h b/include/font/text_attributes.h
index 5a6110890a..734b7eebdb 100644
--- a/include/font/text_attributes.h
+++ b/include/font/text_attributes.h
@@ -136,7 +136,6 @@ public:
     bool              m_Bold;
     bool              m_Underlined;
     KIGFX::COLOR4D    m_Color;
-    bool              m_Visible;
     bool              m_Mirrored;
     bool              m_Multiline;
     VECTOR2I          m_Size;
@@ -159,9 +158,8 @@ struct std::hash<TEXT_ATTRIBUTES>
         return hash_val( aAttributes.m_Font, aAttributes.m_Halign, aAttributes.m_Valign,
                          aAttributes.m_Angle.AsDegrees(), aAttributes.m_LineSpacing,
                          aAttributes.m_StrokeWidth, aAttributes.m_Italic, aAttributes.m_Bold,
-                         aAttributes.m_Underlined, aAttributes.m_Color, aAttributes.m_Visible,
-                         aAttributes.m_Mirrored, aAttributes.m_Multiline, aAttributes.m_Size.x,
-                         aAttributes.m_Size.y );
+                         aAttributes.m_Underlined, aAttributes.m_Color, aAttributes.m_Mirrored,
+                         aAttributes.m_Multiline, aAttributes.m_Size.x, aAttributes.m_Size.y );
     }
 };
 
diff --git a/pcbnew/collectors.cpp b/pcbnew/collectors.cpp
index 91e0be696b..07ec161955 100644
--- a/pcbnew/collectors.cpp
+++ b/pcbnew/collectors.cpp
@@ -220,6 +220,9 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* aTestItem, void* aTestData
     case PCB_FIELD_T:
         field = static_cast<PCB_FIELD*>( aTestItem );
 
+        if( !field->IsVisible() )
+            return INSPECT_RESULT::CONTINUE;
+
         if( field->IsReference() && m_Guide->IgnoreFPReferences() )
             return INSPECT_RESULT::CONTINUE;
 
@@ -236,9 +239,6 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* aTestItem, void* aTestData
         {
             PCB_LAYER_ID layer = text->GetLayer();
 
-            if( !text->IsVisible() )
-                return INSPECT_RESULT::CONTINUE;
-
             if( m_Guide->IgnoreFPTextOnBack() && IsBackLayer( layer ) )
                 return INSPECT_RESULT::CONTINUE;
 
diff --git a/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp b/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp
index d326c41daa..b19494a287 100644
--- a/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp
+++ b/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp
@@ -364,6 +364,7 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::processItem( BOARD_COMMIT& aCommit, B
 {
     aCommit.Modify( aItem );
 
+    PCB_FIELD*          field = dynamic_cast<PCB_FIELD*>( aItem );
     PCB_TEXT*           text = dynamic_cast<PCB_TEXT*>( aItem );
     PCB_SHAPE*          shape = dynamic_cast<PCB_SHAPE*>( aItem );
     PCB_DIMENSION_BASE* dimension = dynamic_cast<PCB_DIMENSION_BASE*>( aItem );
@@ -412,9 +413,6 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::processItem( BOARD_COMMIT& aCommit, B
 
             if( parentFP )
             {
-                if( m_visible->Get3StateValue() != wxCHK_UNDETERMINED )
-                    text->SetVisible( m_visible->GetValue() );
-
                 if( m_keepUpright->Get3StateValue() != wxCHK_UNDETERMINED )
                     text->SetKeepUpright( m_keepUpright->GetValue() );
 
@@ -423,6 +421,12 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::processItem( BOARD_COMMIT& aCommit, B
             }
         }
 
+        if( field )
+        {
+            if( m_visible->Get3StateValue() != wxCHK_UNDETERMINED )
+                field->SetVisible( m_visible->GetValue() );
+        }
+
         if( !m_lineWidth.IsIndeterminate() )
         {
             if( shape )
diff --git a/pcbnew/dialogs/dialog_global_edit_text_and_graphics_base.cpp b/pcbnew/dialogs/dialog_global_edit_text_and_graphics_base.cpp
index 4ff9c97c76..8b155a376d 100644
--- a/pcbnew/dialogs/dialog_global_edit_text_and_graphics_base.cpp
+++ b/pcbnew/dialogs/dialog_global_edit_text_and_graphics_base.cpp
@@ -144,7 +144,7 @@ DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS_BASE::DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS_
 
 	fgSizer1->Add( 0, 0, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
 
-	m_visible = new wxCheckBox( m_specifiedValues, wxID_ANY, _("Visible  (text only)"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER );
+	m_visible = new wxCheckBox( m_specifiedValues, wxID_ANY, _("Visible  (fields only)"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER );
 	m_visible->SetValue(true);
 	fgSizer1->Add( m_visible, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 120 );
 
diff --git a/pcbnew/dialogs/dialog_global_edit_text_and_graphics_base.fbp b/pcbnew/dialogs/dialog_global_edit_text_and_graphics_base.fbp
index 12bc779b7a..13eb25eb53 100644
--- a/pcbnew/dialogs/dialog_global_edit_text_and_graphics_base.fbp
+++ b/pcbnew/dialogs/dialog_global_edit_text_and_graphics_base.fbp
@@ -1556,7 +1556,7 @@
                           <property name="gripper">0</property>
                           <property name="hidden">0</property>
                           <property name="id">wxID_ANY</property>
-                          <property name="label">Visible  (text only)</property>
+                          <property name="label">Visible  (fields only)</property>
                           <property name="max_size"></property>
                           <property name="maximize_button">0</property>
                           <property name="maximum_size"></property>
diff --git a/pcbnew/dialogs/dialog_text_properties.cpp b/pcbnew/dialogs/dialog_text_properties.cpp
index 8f350fd749..6562b9de34 100644
--- a/pcbnew/dialogs/dialog_text_properties.cpp
+++ b/pcbnew/dialogs/dialog_text_properties.cpp
@@ -136,7 +136,6 @@ DIALOG_TEXT_PROPERTIES::DIALOG_TEXT_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, PC
             m_SizeXCtrl,
             m_SizeYCtrl,
             m_ThicknessCtrl,
-            m_Visible,
             m_cbKnockout,
             m_KeepUpright,
             m_PositionXCtrl,
@@ -153,10 +152,6 @@ DIALOG_TEXT_PROPERTIES::DIALOG_TEXT_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, PC
         SetInitialFocus( m_MultiLineText );
         m_SingleLineSizer->Show( false );
 
-        // This option makes sense only for footprint texts; texts on board are always visible.
-        m_Visible->SetValue( true );
-        m_Visible->Show( false );
-
         m_KeepUpright->Show( false );
         m_statusLine->Show( false );
 
@@ -332,8 +327,6 @@ bool DIALOG_TEXT_PROPERTIES::TransferDataToWindow()
     m_posX.SetValue( m_item->GetFPRelativePosition().x );
     m_posY.SetValue( m_item->GetFPRelativePosition().y );
 
-    m_Visible->SetValue( m_item->IsVisible() );
-
     if( parentFP )
         m_KeepUpright->SetValue( m_item->IsKeepUpright() );
 
@@ -526,8 +519,6 @@ bool DIALOG_TEXT_PROPERTIES::TransferDataFromWindow()
 
     m_item->SetTextAngle( m_orientation.GetAngleValue().Normalize() );
 
-    m_item->SetVisible( m_Visible->GetValue() );
-
     if( m_KeepUpright->IsShown() )
         m_item->SetKeepUpright( m_KeepUpright->GetValue() );
 
diff --git a/pcbnew/dialogs/dialog_text_properties_base.cpp b/pcbnew/dialogs/dialog_text_properties_base.cpp
index 3224850913..e9a82e521c 100644
--- a/pcbnew/dialogs/dialog_text_properties_base.cpp
+++ b/pcbnew/dialogs/dialog_text_properties_base.cpp
@@ -83,9 +83,6 @@ DIALOG_TEXT_PROPERTIES_BASE::DIALOG_TEXT_PROPERTIES_BASE( wxWindow* parent, wxWi
 	m_cbLocked = new wxCheckBox( this, wxID_ANY, _("Locked"), wxDefaultPosition, wxDefaultSize, 0 );
 	gbSizer1->Add( m_cbLocked, wxGBPosition( 0, 0 ), wxGBSpan( 1, 3 ), wxRIGHT|wxLEFT, 5 );
 
-	m_Visible = new wxCheckBox( this, wxID_ANY, _("Visible"), wxDefaultPosition, wxDefaultSize, 0 );
-	gbSizer1->Add( m_Visible, wxGBPosition( 0, 4 ), wxGBSpan( 1, 1 ), wxRIGHT, 5 );
-
 	m_LayerLabel = new wxStaticText( this, wxID_ANY, _("Layer:"), wxDefaultPosition, wxDefaultSize, 0 );
 	m_LayerLabel->Wrap( -1 );
 	gbSizer1->Add( m_LayerLabel, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
diff --git a/pcbnew/dialogs/dialog_text_properties_base.fbp b/pcbnew/dialogs/dialog_text_properties_base.fbp
index 8131762f92..0c10e6a290 100644
--- a/pcbnew/dialogs/dialog_text_properties_base.fbp
+++ b/pcbnew/dialogs/dialog_text_properties_base.fbp
@@ -430,74 +430,6 @@
                 <property name="window_style"></property>
               </object>
             </object>
-            <object class="gbsizeritem" expanded="true">
-              <property name="border">5</property>
-              <property name="colspan">1</property>
-              <property name="column">4</property>
-              <property name="flag">wxRIGHT</property>
-              <property name="row">0</property>
-              <property name="rowspan">1</property>
-              <object class="wxCheckBox" expanded="false">
-                <property name="BottomDockable">1</property>
-                <property name="LeftDockable">1</property>
-                <property name="RightDockable">1</property>
-                <property name="TopDockable">1</property>
-                <property name="aui_layer">0</property>
-                <property name="aui_name"></property>
-                <property name="aui_position">0</property>
-                <property name="aui_row">0</property>
-                <property name="best_size"></property>
-                <property name="bg"></property>
-                <property name="caption"></property>
-                <property name="caption_visible">1</property>
-                <property name="center_pane">0</property>
-                <property name="checked">0</property>
-                <property name="close_button">1</property>
-                <property name="context_help"></property>
-                <property name="context_menu">1</property>
-                <property name="default_pane">0</property>
-                <property name="dock">Dock</property>
-                <property name="dock_fixed">0</property>
-                <property name="docking">Left</property>
-                <property name="drag_accept_files">0</property>
-                <property name="enabled">1</property>
-                <property name="fg"></property>
-                <property name="floatable">1</property>
-                <property name="font"></property>
-                <property name="gripper">0</property>
-                <property name="hidden">0</property>
-                <property name="id">wxID_ANY</property>
-                <property name="label">Visible</property>
-                <property name="max_size"></property>
-                <property name="maximize_button">0</property>
-                <property name="maximum_size"></property>
-                <property name="min_size"></property>
-                <property name="minimize_button">0</property>
-                <property name="minimum_size"></property>
-                <property name="moveable">1</property>
-                <property name="name">m_Visible</property>
-                <property name="pane_border">1</property>
-                <property name="pane_position"></property>
-                <property name="pane_size"></property>
-                <property name="permission">protected</property>
-                <property name="pin_button">1</property>
-                <property name="pos"></property>
-                <property name="resize">Resizable</property>
-                <property name="show">1</property>
-                <property name="size"></property>
-                <property name="style"></property>
-                <property name="subclass">; forward_declare</property>
-                <property name="toolbar_pane">0</property>
-                <property name="tooltip"></property>
-                <property name="validator_data_type"></property>
-                <property name="validator_style">wxFILTER_NONE</property>
-                <property name="validator_type">wxDefaultValidator</property>
-                <property name="validator_variable"></property>
-                <property name="window_extra_style"></property>
-                <property name="window_name"></property>
-                <property name="window_style"></property>
-              </object>
-            </object>
             <object class="gbsizeritem" expanded="true">
               <property name="border">5</property>
               <property name="colspan">1</property>
diff --git a/pcbnew/dialogs/dialog_text_properties_base.h b/pcbnew/dialogs/dialog_text_properties_base.h
index 9ed6365c23..066768a726 100644
--- a/pcbnew/dialogs/dialog_text_properties_base.h
+++ b/pcbnew/dialogs/dialog_text_properties_base.h
@@ -52,7 +52,6 @@ class DIALOG_TEXT_PROPERTIES_BASE : public DIALOG_SHIM
 		wxStaticText* m_TextLabel;
 		wxTextCtrl* m_SingleLineText;
 		wxCheckBox* m_cbLocked;
-		wxCheckBox* m_Visible;
 		wxStaticText* m_LayerLabel;
 		PCB_LAYER_BOX_SELECTOR* m_LayerSelectionCtrl;
 		wxCheckBox* m_cbKnockout;
diff --git a/pcbnew/dialogs/panel_fp_editor_field_defaults.cpp b/pcbnew/dialogs/panel_fp_editor_field_defaults.cpp
index 55e2112d89..72bb8e76c0 100644
--- a/pcbnew/dialogs/panel_fp_editor_field_defaults.cpp
+++ b/pcbnew/dialogs/panel_fp_editor_field_defaults.cpp
@@ -145,19 +145,33 @@ class TEXT_ITEMS_GRID_TABLE : public wxGridTableBase
     std::vector<TEXT_ITEM_INFO> m_items;
 
 public:
-    TEXT_ITEMS_GRID_TABLE( bool aForFieldProps ) : m_forFieldProps( aForFieldProps ) {}
+    TEXT_ITEMS_GRID_TABLE( bool aForFieldProps ) :
+            m_forFieldProps( aForFieldProps )
+    {}
 
     int GetNumberRows() override { return m_items.size(); }
-    int GetNumberCols() override { return 3; }
+    int GetNumberCols() override { return m_forFieldProps ? 3 : 2; }
 
     wxString GetColLabelValue( int aCol ) override
     {
-        switch( aCol )
+        if( m_forFieldProps )
         {
-        case 0: return m_forFieldProps ? _( "Value" ) : _( "Text Items" );
-        case 1: return _( "Show" );
-        case 2: return _( "Layer" );
-        default: return wxEmptyString;
+            switch( aCol )
+            {
+            case 0: return _( "Value" );
+            case 1: return _( "Show" );
+            case 2: return _( "Layer" );
+            default: return wxEmptyString;
+            }
+        }
+        else
+        {
+            switch( aCol )
+            {
+            case 0: return _( "Text Items" );
+            case 1: return _( "Layer " );
+            default: return wxEmptyString;
+            }
         }
     }
 
@@ -173,12 +187,24 @@ public:
 
     bool CanGetValueAs( int aRow, int aCol, const wxString& aTypeName ) override
     {
-        switch( aCol )
+        if( m_forFieldProps )
         {
-        case 0: return aTypeName == wxGRID_VALUE_STRING;
-        case 1: return aTypeName == wxGRID_VALUE_BOOL;
-        case 2: return aTypeName == wxGRID_VALUE_NUMBER;
-        default: wxFAIL; return false;
+            switch( aCol )
+            {
+            case 0: return aTypeName == wxGRID_VALUE_STRING;
+            case 1: return aTypeName == wxGRID_VALUE_BOOL;
+            case 2: return aTypeName == wxGRID_VALUE_NUMBER;
+            default: wxFAIL; return false;
+            }
+        }
+        else
+        {
+            switch( aCol )
+            {
+            case 0: return aTypeName == wxGRID_VALUE_STRING;
+            case 1: return aTypeName == wxGRID_VALUE_NUMBER;
+            default: wxFAIL; return false;
+            }
         }
     }
 
@@ -278,16 +304,10 @@ PANEL_FP_EDITOR_FIELD_DEFAULTS::PANEL_FP_EDITOR_FIELD_DEFAULTS( wxWindow*
     m_textItemsGrid->PushEventHandler( new GRID_TRICKS( m_textItemsGrid ) );
     m_textItemsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
 
-    attr = new wxGridCellAttr;
-    attr->SetRenderer( new wxGridCellBoolRenderer() );
-    attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
-    attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
-    m_textItemsGrid->SetColAttr( 1, attr );
-
     attr = new wxGridCellAttr;
     attr->SetRenderer( new GRID_CELL_LAYER_RENDERER( nullptr ) );
     attr->SetEditor( new GRID_CELL_LAYER_SELECTOR( nullptr, {} ) );
-    m_textItemsGrid->SetColAttr( 2, attr );
+    m_textItemsGrid->SetColAttr( 1, attr );
 
     m_layerNameitemsGrid->SetDefaultRowSize( m_layerNameitemsGrid->GetDefaultRowSize() + 4 );
 
@@ -337,8 +357,7 @@ void PANEL_FP_EDITOR_FIELD_DEFAULTS::loadFPSettings( const FOOTPRINT_EDITOR_SETT
         TEXT_ITEM_INFO item = aCfg->m_DesignSettings.m_DefaultFPTextItems[i];
 
         m_textItemsGrid->GetTable()->SetValue( i - 2, 0, item.m_Text );
-        m_textItemsGrid->GetTable()->SetValueAsBool( i - 2, 1, item.m_Visible );
-        m_textItemsGrid->GetTable()->SetValueAsLong( i - 2, 2, item.m_Layer );
+        m_textItemsGrid->GetTable()->SetValueAsLong( i - 2, 1, item.m_Layer );
     }
 
     for( auto& item : aCfg->m_DesignSettings.m_UserLayerNames )
@@ -416,10 +435,9 @@ bool PANEL_FP_EDITOR_FIELD_DEFAULTS::TransferDataFromWindow()
     for( int i = 0; i < m_textItemsGrid->GetNumberRows(); ++i )
     {
         wxString text = table->GetValue( i, 0 );
-        bool visible = table->GetValueAsBool( i, 1 );
-        PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( table->GetValueAsLong( i, 2 ) );
+        PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( table->GetValueAsLong( i, 1 ) );
 
-        cfg.m_DefaultFPTextItems.emplace_back( text, visible, layer );
+        cfg.m_DefaultFPTextItems.emplace_back( text, true, layer );
     }
 
     cfg.m_UserLayerNames.clear();
@@ -510,8 +528,7 @@ void PANEL_FP_EDITOR_FIELD_DEFAULTS::OnAddTextItem( wxCommandEvent& event )
 
     int newRow = m_textItemsGrid->GetNumberRows();
     table->AppendRows( 1 );
-    table->SetValueAsBool( newRow, 1, table->GetValueAsBool( newRow - 1, 1 ) );
-    table->SetValueAsLong( newRow, 2, table->GetValueAsLong( newRow - 1, 2 ) );
+    table->SetValueAsLong( newRow, 1, table->GetValueAsLong( newRow - 1, 1 ) );
 
     m_textItemsGrid->MakeCellVisible( newRow, 0 );
     m_textItemsGrid->SetGridCursor( newRow, 0 );
diff --git a/pcbnew/dialogs/panel_fp_editor_field_defaults_base.cpp b/pcbnew/dialogs/panel_fp_editor_field_defaults_base.cpp
index 83e1141146..5737a268af 100644
--- a/pcbnew/dialogs/panel_fp_editor_field_defaults_base.cpp
+++ b/pcbnew/dialogs/panel_fp_editor_field_defaults_base.cpp
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
+// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO *NOT* EDIT THIS FILE!
@@ -42,7 +42,7 @@ PANEL_FP_EDITOR_FIELD_DEFAULTS_BASE::PANEL_FP_EDITOR_FIELD_DEFAULTS_BASE( wxWind
 	// Columns
 	m_fieldPropsGrid->SetColSize( 0, 240 );
 	m_fieldPropsGrid->SetColSize( 1, 60 );
-	m_fieldPropsGrid->SetColSize( 2, 120 );
+	m_fieldPropsGrid->SetColSize( 2, 150 );
 	m_fieldPropsGrid->EnableDragColMove( false );
 	m_fieldPropsGrid->EnableDragColSize( true );
 	m_fieldPropsGrid->SetColLabelValue( 0, _("Value") );
@@ -83,21 +83,19 @@ PANEL_FP_EDITOR_FIELD_DEFAULTS_BASE::PANEL_FP_EDITOR_FIELD_DEFAULTS_BASE( wxWind
 	m_textItemsGrid = new WX_GRID( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxTAB_TRAVERSAL );
 
 	// Grid
-	m_textItemsGrid->CreateGrid( 0, 3 );
+	m_textItemsGrid->CreateGrid( 0, 2 );
 	m_textItemsGrid->EnableEditing( true );
 	m_textItemsGrid->EnableGridLines( true );
 	m_textItemsGrid->EnableDragGridSize( false );
 	m_textItemsGrid->SetMargins( 0, 0 );
 
 	// Columns
-	m_textItemsGrid->SetColSize( 0, 400 );
-	m_textItemsGrid->SetColSize( 1, 60 );
-	m_textItemsGrid->SetColSize( 2, 120 );
+	m_textItemsGrid->SetColSize( 0, 460 );
+	m_textItemsGrid->SetColSize( 1, 150 );
 	m_textItemsGrid->EnableDragColMove( false );
 	m_textItemsGrid->EnableDragColSize( true );
 	m_textItemsGrid->SetColLabelValue( 0, _("Text Items") );
-	m_textItemsGrid->SetColLabelValue( 1, _("Show") );
-	m_textItemsGrid->SetColLabelValue( 2, _("Layer") );
+	m_textItemsGrid->SetColLabelValue( 1, _("Layer") );
 	m_textItemsGrid->SetColLabelSize( wxGRID_AUTOSIZE );
 	m_textItemsGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
 
diff --git a/pcbnew/dialogs/panel_fp_editor_field_defaults_base.fbp b/pcbnew/dialogs/panel_fp_editor_field_defaults_base.fbp
index 6dd65cb96b..740a7d2042 100644
--- a/pcbnew/dialogs/panel_fp_editor_field_defaults_base.fbp
+++ b/pcbnew/dialogs/panel_fp_editor_field_defaults_base.fbp
@@ -181,7 +181,7 @@
                     <property name="col_label_values">&quot;Value&quot; &quot;Show&quot; &quot;Layer&quot;</property>
                     <property name="col_label_vert_alignment">wxALIGN_CENTER</property>
                     <property name="cols">3</property>
-                    <property name="column_sizes">240,60,120</property>
+                    <property name="column_sizes">240,60,150</property>
                     <property name="context_help"></property>
                     <property name="context_menu">1</property>
                     <property name="default_pane">0</property>
@@ -361,10 +361,10 @@
                     <property name="close_button">1</property>
                     <property name="col_label_horiz_alignment">wxALIGN_CENTER</property>
                     <property name="col_label_size">wxGRID_AUTOSIZE</property>
-                    <property name="col_label_values">&quot;Text Items&quot; &quot;Show&quot; &quot;Layer&quot;</property>
+                    <property name="col_label_values">&quot;Text Items&quot; &quot;Layer&quot;</property>
                     <property name="col_label_vert_alignment">wxALIGN_CENTER</property>
-                    <property name="cols">3</property>
-                    <property name="column_sizes">400,60,120</property>
+                    <property name="cols">2</property>
+                    <property name="column_sizes">460,150</property>
                     <property name="context_help"></property>
                     <property name="context_menu">1</property>
                     <property name="default_pane">0</property>
diff --git a/pcbnew/dialogs/panel_fp_editor_field_defaults_base.h b/pcbnew/dialogs/panel_fp_editor_field_defaults_base.h
index cce849fa2d..47db09b090 100644
--- a/pcbnew/dialogs/panel_fp_editor_field_defaults_base.h
+++ b/pcbnew/dialogs/panel_fp_editor_field_defaults_base.h
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
+// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO *NOT* EDIT THIS FILE!
diff --git a/pcbnew/drc/drc_rtree.h b/pcbnew/drc/drc_rtree.h
index 8f491f3d2e..a631e56f4b 100644
--- a/pcbnew/drc/drc_rtree.h
+++ b/pcbnew/drc/drc_rtree.h
@@ -27,7 +27,7 @@
 
 #include <board_item.h>
 #include <pad.h>
-#include <pcb_text.h>
+#include <pcb_field.h>
 #include <memory>
 #include <unordered_set>
 #include <set>
@@ -115,11 +115,8 @@ public:
     {
         wxCHECK( aTargetLayer != UNDEFINED_LAYER, /* void */ );
 
-        if( ( aItem->Type() == PCB_FIELD_T || aItem->Type() == PCB_TEXT_T )
-            && !static_cast<PCB_TEXT*>( aItem )->IsVisible() )
-        {
+        if( aItem->Type() == PCB_FIELD_T && !static_cast<PCB_FIELD*>( aItem )->IsVisible() )
             return;
-        }
 
         std::vector<const SHAPE*> subshapes;
         std::shared_ptr<SHAPE> shape = aItem->GetEffectiveShape( aRefLayer );
diff --git a/pcbnew/drc/drc_test_provider.cpp b/pcbnew/drc/drc_test_provider.cpp
index b805918d2c..d9b052f037 100644
--- a/pcbnew/drc/drc_test_provider.cpp
+++ b/pcbnew/drc/drc_test_provider.cpp
@@ -340,9 +340,9 @@ int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes,
 
 bool DRC_TEST_PROVIDER::isInvisibleText( const BOARD_ITEM* aItem ) const
 {
-    if( const PCB_TEXT* text = dynamic_cast<const PCB_TEXT*>( aItem ) )
+    if( const PCB_FIELD* field = dynamic_cast<const PCB_FIELD*>( aItem ) )
     {
-        if( !text->IsVisible() )
+        if( !field->IsVisible() )
             return true;
     }
 
diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp
index 2973f33624..452130e085 100644
--- a/pcbnew/footprint.cpp
+++ b/pcbnew/footprint.cpp
@@ -1455,15 +1455,17 @@ const BOX2I FOOTPRINT::GetBoundingBox( bool aIncludeText ) const
     // Groups do not contribute to the rect, only their members
     if( aIncludeText || noDrawItems )
     {
-        // Only PCB_TEXT and PCB_FIELD items are independently selectable;
-        // PCB_TEXTBOX items go in with other graphic items above.
+        // Only PCB_TEXT and PCB_FIELD items are independently selectable; PCB_TEXTBOX items go
+        // in with other graphic items above.
         for( PCB_TEXT* text : texts )
         {
             if( !isFPEdit && m_privateLayers.test( text->GetLayer() ) )
                 continue;
 
-            if( text->IsVisible() )
-                bbox.Merge( text->GetBoundingBox() );
+            if( text->Type() == PCB_FIELD_T && !text->IsVisible() )
+                continue;
+
+            bbox.Merge( text->GetBoundingBox() );
         }
 
         // This can be further optimized when aIncludeInvisibleText is true, but currently
@@ -3942,7 +3944,7 @@ void FOOTPRINT::TransformFPShapesToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_I
         {
             PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
 
-            if( aLayer != UNDEFINED_LAYER && text->GetLayer() == aLayer && text->IsVisible() )
+            if( aLayer != UNDEFINED_LAYER && text->GetLayer() == aLayer )
                 texts.push_back( text );
         }
 
@@ -3950,7 +3952,7 @@ void FOOTPRINT::TransformFPShapesToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_I
         {
             PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
 
-            if( aLayer != UNDEFINED_LAYER && textbox->GetLayer() == aLayer && textbox->IsVisible() )
+            if( aLayer != UNDEFINED_LAYER && textbox->GetLayer() == aLayer )
             {
                 // border
                 if( textbox->IsBorderEnabled() )
diff --git a/pcbnew/footprint_libraries_utils.cpp b/pcbnew/footprint_libraries_utils.cpp
index 8e28abf731..699373ddd5 100644
--- a/pcbnew/footprint_libraries_utils.cpp
+++ b/pcbnew/footprint_libraries_utils.cpp
@@ -1300,7 +1300,6 @@ FOOTPRINT* PCB_BASE_FRAME::CreateNewFootprint( wxString aFootprintName, const wx
     {
         PCB_TEXT* textItem = new PCB_TEXT( footprint );
         textItem->SetText( settings.m_DefaultFPTextItems[i].m_Text );
-        textItem->SetVisible( settings.m_DefaultFPTextItems[i].m_Visible );
         txt_layer = (PCB_LAYER_ID) settings.m_DefaultFPTextItems[i].m_Layer;
         textItem->SetLayer( txt_layer );
         default_pos.y += settings.GetTextSize( txt_layer ).y / 2;
diff --git a/pcbnew/pcb_dimension.cpp b/pcbnew/pcb_dimension.cpp
index ed871a17c6..34f5c157bf 100644
--- a/pcbnew/pcb_dimension.cpp
+++ b/pcbnew/pcb_dimension.cpp
@@ -1869,9 +1869,6 @@ static struct ALIGNED_DIMENSION_DESC
                 PROPERTY_DISPLAY::PT_SIZE ),
                 groupDimension );
 
-        propMgr.OverrideAvailability( TYPE_HASH( PCB_DIM_ALIGNED ), TYPE_HASH( EDA_TEXT ),
-                                      _HKI( "Visible" ),
-                                      []( INSPECTABLE* aItem ) { return false; } );
         propMgr.OverrideAvailability( TYPE_HASH( PCB_DIM_ALIGNED ), TYPE_HASH( EDA_TEXT ),
                                       _HKI( "Text" ),
                                       []( INSPECTABLE* aItem ) { return false; } );
@@ -1905,9 +1902,6 @@ static struct ORTHOGONAL_DIMENSION_DESC
         propMgr.InheritsAfter( TYPE_HASH( PCB_DIM_ORTHOGONAL ), TYPE_HASH( PCB_DIMENSION_BASE ) );
         propMgr.InheritsAfter( TYPE_HASH( PCB_DIM_ORTHOGONAL ), TYPE_HASH( PCB_DIM_ALIGNED ) );
 
-        propMgr.OverrideAvailability( TYPE_HASH( PCB_DIM_ORTHOGONAL ), TYPE_HASH( EDA_TEXT ),
-                                      _HKI( "Visible" ),
-                                      []( INSPECTABLE* aItem ) { return false; } );
         propMgr.OverrideAvailability( TYPE_HASH( PCB_DIM_ORTHOGONAL ), TYPE_HASH( EDA_TEXT ),
                                       _HKI( "Text" ),
                                       []( INSPECTABLE* aItem ) { return false; } );
@@ -1946,9 +1940,6 @@ static struct RADIAL_DIMENSION_DESC
                 PROPERTY_DISPLAY::PT_SIZE ),
                 groupDimension );
 
-        propMgr.OverrideAvailability( TYPE_HASH( PCB_DIM_RADIAL ), TYPE_HASH( EDA_TEXT ),
-                                      _HKI( "Visible" ),
-                                      []( INSPECTABLE* aItem ) { return false; } );
         propMgr.OverrideAvailability( TYPE_HASH( PCB_DIM_RADIAL ), TYPE_HASH( EDA_TEXT ),
                                       _HKI( "Text" ),
                                       []( INSPECTABLE* aItem ) { return false; } );
@@ -1991,9 +1982,6 @@ static struct LEADER_DIMENSION_DESC
                 &PCB_DIM_LEADER::ChangeTextBorder, &PCB_DIM_LEADER::GetTextBorder ),
                 groupDimension );
 
-        propMgr.OverrideAvailability( TYPE_HASH( PCB_DIM_LEADER ), TYPE_HASH( EDA_TEXT ),
-                                      _HKI( "Visible" ),
-                                      []( INSPECTABLE* aItem ) { return false; } );
         propMgr.OverrideAvailability( TYPE_HASH( PCB_DIM_LEADER ), TYPE_HASH( EDA_TEXT ),
                                       _HKI( "Text" ),
                                       []( INSPECTABLE* aItem ) { return false; } );
@@ -2028,9 +2016,6 @@ static struct CENTER_DIMENSION_DESC
         propMgr.InheritsAfter( TYPE_HASH( PCB_DIM_CENTER ), TYPE_HASH( PCB_DIMENSION_BASE ) );
 
 
-        propMgr.OverrideAvailability( TYPE_HASH( PCB_DIM_CENTER ), TYPE_HASH( EDA_TEXT ),
-                                      _HKI( "Visible" ),
-                                      []( INSPECTABLE* aItem ) { return false; } );
         propMgr.OverrideAvailability( TYPE_HASH( PCB_DIM_CENTER ), TYPE_HASH( EDA_TEXT ),
                                       _HKI( "Text" ),
                                       []( INSPECTABLE* aItem ) { return false; } );
diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp
index d4550b9ca2..f01c6863df 100644
--- a/pcbnew/pcb_edit_frame.cpp
+++ b/pcbnew/pcb_edit_frame.cpp
@@ -2273,10 +2273,8 @@ static void processTextItem( const PCB_TEXT& aSrc, PCB_TEXT& aDest,
     }
     else
     {
-        // Careful: the visible bit and position are also set by SetAttributes()
-        bool visible = aDest.IsVisible();
+        // Careful: SetAttributes() will clobber the position
         aDest.SetAttributes( aSrc );
-        aDest.SetVisible( visible );
         aDest.SetFPRelativePosition( aSrc.GetFPRelativePosition() );
     }
 
diff --git a/pcbnew/pcb_field.cpp b/pcbnew/pcb_field.cpp
index 3696e710b0..c5b3703e86 100644
--- a/pcbnew/pcb_field.cpp
+++ b/pcbnew/pcb_field.cpp
@@ -56,6 +56,7 @@ void PCB_FIELD::Serialize( google::protobuf::Any &aContainer ) const
 
     field.set_name( GetCanonicalName().ToStdString() );
     field.mutable_id()->set_id( GetId() );
+    field.set_visible( IsVisible() );
 
     aContainer.PackFrom( field );
 }
@@ -82,6 +83,8 @@ bool PCB_FIELD::Deserialize( const google::protobuf::Any &aContainer )
         PCB_TEXT::Deserialize( anyText );
     }
 
+    SetVisible( field.visible() );
+
     if( field.text().layer() == kiapi::board::types::BoardLayer::BL_UNKNOWN )
         SetLayer( F_SilkS );
 
diff --git a/pcbnew/pcb_io/cadstar/cadstar_pcb_archive_loader.cpp b/pcbnew/pcb_io/cadstar/cadstar_pcb_archive_loader.cpp
index f4266db6f0..2fcf41a1c3 100644
--- a/pcbnew/pcb_io/cadstar/cadstar_pcb_archive_loader.cpp
+++ b/pcbnew/pcb_io/cadstar/cadstar_pcb_archive_loader.cpp
@@ -3257,11 +3257,11 @@ void CADSTAR_PCB_ARCHIVE_LOADER::addAttribute( const ATTRIBUTE_LOCATION& aCadsta
                                                FOOTPRINT* aFootprint,
                                                const wxString& aAttributeValue )
 {
-    PCB_TEXT* txt;
+    PCB_FIELD* field;
 
     if( aCadstarAttributeID == COMPONENT_NAME_ATTRID )
     {
-        txt = &aFootprint->Reference(); //text should be set outside this function
+        field = &aFootprint->Reference(); //text should be set outside this function
     }
     else if( aCadstarAttributeID == PART_NAME_ATTRID )
     {
@@ -3269,15 +3269,15 @@ void CADSTAR_PCB_ARCHIVE_LOADER::addAttribute( const ATTRIBUTE_LOCATION& aCadsta
         {
             // Use PART_NAME_ATTRID as the value is value field is blank
             aFootprint->SetValue( aAttributeValue );
-            txt = &aFootprint->Value();
+            field = &aFootprint->Value();
         }
         else
         {
-            txt = new PCB_TEXT( aFootprint );
-            aFootprint->Add( txt );
-            txt->SetText( aAttributeValue );
+            field = new PCB_FIELD( aFootprint, -1, aCadstarAttributeID );
+            aFootprint->Add( field );
+            field->SetText( aAttributeValue );
         }
-        txt->SetVisible( false ); //make invisible to avoid clutter.
+        field->SetVisible( false ); //make invisible to avoid clutter.
     }
     else if( aCadstarAttributeID != COMPONENT_NAME_2_ATTRID
              && getAttributeName( aCadstarAttributeID ) == wxT( "Value" ) )
@@ -3289,78 +3289,78 @@ void CADSTAR_PCB_ARCHIVE_LOADER::addAttribute( const ATTRIBUTE_LOCATION& aCadsta
         }
 
         aFootprint->SetValue( aAttributeValue );
-        txt = &aFootprint->Value();
-        txt->SetVisible( false ); //make invisible to avoid clutter.
+        field = &aFootprint->Value();
+        field->SetVisible( false ); //make invisible to avoid clutter.
     }
     else
     {
-        txt = new PCB_TEXT( aFootprint );
-        aFootprint->Add( txt );
-        txt->SetText( aAttributeValue );
-        txt->SetVisible( false ); //make all user attributes invisible to avoid clutter.
+        field = new PCB_FIELD( aFootprint, -1, aCadstarAttributeID );
+        aFootprint->Add( field );
+        field->SetText( aAttributeValue );
+        field->SetVisible( false ); //make all user attributes invisible to avoid clutter.
         //TODO: Future improvement - allow user to decide what to do with attributes
     }
 
-    txt->SetPosition( getKiCadPoint( aCadstarAttrLoc.Position ) );
-    txt->SetLayer( getKiCadLayer( aCadstarAttrLoc.LayerID ) );
-    txt->SetMirrored( aCadstarAttrLoc.Mirror );
-    txt->SetTextAngle( getAngle( aCadstarAttrLoc.OrientAngle ) );
+    field->SetPosition( getKiCadPoint( aCadstarAttrLoc.Position ) );
+    field->SetLayer( getKiCadLayer( aCadstarAttrLoc.LayerID ) );
+    field->SetMirrored( aCadstarAttrLoc.Mirror );
+    field->SetTextAngle( getAngle( aCadstarAttrLoc.OrientAngle ) );
 
     if( aCadstarAttrLoc.Mirror ) // If mirroring, invert angle to match CADSTAR
-        txt->SetTextAngle( -txt->GetTextAngle() );
+        field->SetTextAngle( -field->GetTextAngle() );
 
-    applyTextCode( txt, aCadstarAttrLoc.TextCodeID );
+    applyTextCode( field, aCadstarAttrLoc.TextCodeID );
 
-    txt->SetKeepUpright( false ); //Keeping it upright seems to result in incorrect orientation
+    field->SetKeepUpright( false ); //Keeping it upright seems to result in incorrect orientation
 
     switch( aCadstarAttrLoc.Alignment )
     {
     case ALIGNMENT::NO_ALIGNMENT: // Default for Single line text is Bottom Left
-        FixTextPositionNoAlignment( txt );
+        FixTextPositionNoAlignment( field );
         KI_FALLTHROUGH;
     case ALIGNMENT::BOTTOMLEFT:
-        txt->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
-        txt->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
+        field->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
+        field->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
         break;
 
     case ALIGNMENT::BOTTOMCENTER:
-        txt->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
-        txt->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
+        field->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
+        field->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
         break;
 
     case ALIGNMENT::BOTTOMRIGHT:
-        txt->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
-        txt->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
+        field->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
+        field->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
         break;
 
     case ALIGNMENT::CENTERLEFT:
-        txt->SetVertJustify( GR_TEXT_V_ALIGN_CENTER );
-        txt->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
+        field->SetVertJustify( GR_TEXT_V_ALIGN_CENTER );
+        field->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
         break;
 
     case ALIGNMENT::CENTERCENTER:
-        txt->SetVertJustify( GR_TEXT_V_ALIGN_CENTER );
-        txt->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
+        field->SetVertJustify( GR_TEXT_V_ALIGN_CENTER );
+        field->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
         break;
 
     case ALIGNMENT::CENTERRIGHT:
-        txt->SetVertJustify( GR_TEXT_V_ALIGN_CENTER );
-        txt->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
+        field->SetVertJustify( GR_TEXT_V_ALIGN_CENTER );
+        field->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
         break;
 
     case ALIGNMENT::TOPLEFT:
-        txt->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
-        txt->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
+        field->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
+        field->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
         break;
 
     case ALIGNMENT::TOPCENTER:
-        txt->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
-        txt->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
+        field->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
+        field->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
         break;
 
     case ALIGNMENT::TOPRIGHT:
-        txt->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
-        txt->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
+        field->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
+        field->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
         break;
 
     default:
@@ -3416,8 +3416,6 @@ void CADSTAR_PCB_ARCHIVE_LOADER:: applyTextCode( EDA_TEXT*          aKiCadText,
         aKiCadText->SetTextSize(
                 VECTOR2I( EDA_UNIT_UTILS::Mils2IU( pcbIUScale, DEFAULT_SIZE_TEXT ),
                           EDA_UNIT_UTILS::Mils2IU( pcbIUScale, DEFAULT_SIZE_TEXT ) ) );
-
-        aKiCadText->SetVisible( false );
     }
     else
     {
diff --git a/pcbnew/pcb_io/easyeda/pcb_io_easyeda_parser.cpp b/pcbnew/pcb_io/easyeda/pcb_io_easyeda_parser.cpp
index 755836b376..3d8a5206eb 100644
--- a/pcbnew/pcb_io/easyeda/pcb_io_easyeda_parser.cpp
+++ b/pcbnew/pcb_io/easyeda/pcb_io_easyeda_parser.cpp
@@ -791,6 +791,11 @@ void PCB_IO_EASYEDA_PARSER::ParseToBoardItemContainer(
             {
                 text = footprint->GetField( VALUE_FIELD );
             }
+            else if( arr[12] == wxS( "none" ) )
+            {
+                text = new PCB_FIELD( aContainer, -1 );
+                static_cast<PCB_FIELD*>( text )->SetVisible( false );
+            }
             else
             {
                 text = new PCB_TEXT( aContainer );
@@ -826,8 +831,6 @@ void PCB_IO_EASYEDA_PARSER::ParseToBoardItemContainer(
 
             //arr[11] // Geometry data
 
-            text->SetVisible( arr[12] != wxS( "none" ) );
-
             wxString font = arr[14];
             if( !font.IsEmpty() )
                 text->SetFont( KIFONT::FONT::GetFont( font ) );
diff --git a/pcbnew/pcb_io/easyedapro/pcb_io_easyedapro_parser.cpp b/pcbnew/pcb_io/easyedapro/pcb_io_easyedapro_parser.cpp
index 435371b357..033e2976be 100644
--- a/pcbnew/pcb_io/easyedapro/pcb_io_easyedapro_parser.cpp
+++ b/pcbnew/pcb_io/easyedapro/pcb_io_easyedapro_parser.cpp
@@ -1671,51 +1671,51 @@ void PCB_IO_EASYEDAPRO_PARSER::ParseBoard(
 
                 PCB_LAYER_ID klayer = LayerToKi( attr.layer );
 
-                PCB_TEXT* text = nullptr;
-                bool      add = false;
+                PCB_FIELD* field = nullptr;
+                bool       add = false;
 
                 if( attr.key == wxS( "Designator" ) )
                 {
                     if( attr.key == wxS( "Designator" ) )
                     {
-                        text = footprint->GetField( REFERENCE_FIELD );
+                        field = footprint->GetField( REFERENCE_FIELD );
                     }
                     else
                     {
-                        text = new PCB_TEXT( footprint.get() );
+                        field = new PCB_FIELD( footprint.get(), -1, attr.key );
                         add = true;
                     }
 
                     if( attr.fontName != wxS( "default" ) )
-                        text->SetFont( KIFONT::FONT::GetFont( attr.fontName ) );
+                        field->SetFont( KIFONT::FONT::GetFont( attr.fontName ) );
 
                     if( attr.valVisible && attr.keyVisible )
                     {
-                        text->SetText( attr.key + ':' + attr.value );
+                        field->SetText( attr.key + ':' + attr.value );
                     }
                     else if( attr.keyVisible )
                     {
-                        text->SetText( attr.key );
+                        field->SetText( attr.key );
                     }
                     else
                     {
-                        text->SetText( attr.value );
+                        field->SetVisible( false );
+                        field->SetText( attr.value );
                     }
 
-                    text->SetVisible( attr.keyVisible || attr.valVisible );
-                    text->SetLayer( klayer );
-                    text->SetPosition( ScalePos( attr.position ) );
-                    text->SetTextAngleDegrees( footprint->IsFlipped() ? -attr.rotation
-                                                                      : attr.rotation );
-                    text->SetIsKnockout( attr.inverted );
-                    text->SetTextThickness( ScaleSize( attr.strokeWidth ) );
-                    text->SetTextSize( VECTOR2D( ScaleSize( attr.height * 0.55 ),
-                                                 ScaleSize( attr.height * 0.6 ) ) );
+                    field->SetLayer( klayer );
+                    field->SetPosition( ScalePos( attr.position ) );
+                    field->SetTextAngleDegrees( footprint->IsFlipped() ? -attr.rotation
+                                                                       : attr.rotation );
+                    field->SetIsKnockout( attr.inverted );
+                    field->SetTextThickness( ScaleSize( attr.strokeWidth ) );
+                    field->SetTextSize( VECTOR2D( ScaleSize( attr.height * 0.55 ),
+                                                  ScaleSize( attr.height * 0.6 ) ) );
 
-                    AlignText( text, attr.textOrigin );
+                    AlignText( field, attr.textOrigin );
 
                     if( add )
-                        footprint->Add( text, ADD_MODE::APPEND );
+                        footprint->Add( field, ADD_MODE::APPEND );
                 }
             }
             else if( type == wxS( "PAD_NET" ) )
diff --git a/pcbnew/pcb_io/fabmaster/import_fabmaster.cpp b/pcbnew/pcb_io/fabmaster/import_fabmaster.cpp
index f3a678914c..c76e613256 100644
--- a/pcbnew/pcb_io/fabmaster/import_fabmaster.cpp
+++ b/pcbnew/pcb_io/fabmaster/import_fabmaster.cpp
@@ -2411,14 +2411,9 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
                     }
 
                     if( layer == F_SilkS || layer == B_SilkS )
-                    {
                         txt = &( fp->Reference() );
-                        txt->SetVisible( true );
-                    }
                     else
-                    {
                         txt = new PCB_TEXT( fp );
-                    }
 
                     OPT_VECTOR2I flip_point = std::nullopt;
                     if( src->mirror )
@@ -2588,6 +2583,7 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
                         std::unique_ptr<PCB_TEXT> txt = std::make_unique<PCB_TEXT>( fp );
 
                         OPT_VECTOR2I flip_point;
+
                         if( src->mirror )
                             flip_point = VECTOR2I( src->x, src->y );
 
@@ -2596,9 +2592,16 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
                         // FABMASTER doesn't have visibility flags but layers that are not silk
                         // should be hidden by default to prevent clutter.
                         if( txt->GetLayer() != F_SilkS && txt->GetLayer() != B_SilkS )
-                            txt->SetVisible( false );
+                        {
+                            PCB_FIELD* field = new PCB_FIELD( txt.get(), -1 );
+                            field->SetVisible( false );
+                            fp->Add( field, ADD_MODE::APPEND );
+                        }
+                        else
+                        {
+                            fp->Add( txt.release(), ADD_MODE::APPEND );
+                        }
 
-                        fp->Add( txt.release(), ADD_MODE::APPEND );
                         break;
                     }
                     default:
diff --git a/pcbnew/pcb_io/ipc2581/pcb_io_ipc2581.cpp b/pcbnew/pcb_io/ipc2581/pcb_io_ipc2581.cpp
index b7fb29bca1..cbb461ff4c 100644
--- a/pcbnew/pcb_io/ipc2581/pcb_io_ipc2581.cpp
+++ b/pcbnew/pcb_io/ipc2581/pcb_io_ipc2581.cpp
@@ -616,9 +616,6 @@ void PCB_IO_IPC2581::addKnockoutText( wxXmlNode* aContentNode, PCB_TEXT* aText )
 void PCB_IO_IPC2581::addText( wxXmlNode* aContentNode, EDA_TEXT* aText,
                               const KIFONT::METRICS& aFontMetrics )
 {
-    if( !aText->IsVisible() )
-        return;
-
     KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
     KIFONT::FONT*              font = aText->GetFont();
     TEXT_ATTRIBUTES            attrs = aText->GetAttributes();
diff --git a/pcbnew/pcb_io/kicad_legacy/pcb_io_kicad_legacy.cpp b/pcbnew/pcb_io/kicad_legacy/pcb_io_kicad_legacy.cpp
index 7895b43319..3a5102da66 100644
--- a/pcbnew/pcb_io/kicad_legacy/pcb_io_kicad_legacy.cpp
+++ b/pcbnew/pcb_io/kicad_legacy/pcb_io_kicad_legacy.cpp
@@ -1240,6 +1240,14 @@ void PCB_IO_KICAD_LEGACY::loadFOOTPRINT( FOOTPRINT* aFootprint )
             }
 
             loadMODULE_TEXT( text );
+
+            // Convert hidden footprint text (which is no longer supported) to a hidden field
+            if( !text->IsVisible() && text->Type() == PCB_TEXT_T )
+            {
+                aFootprint->Remove( text );
+                aFootprint->Add( new PCB_FIELD( text, -1 ) );
+                delete text;
+            }
         }
         else if( TESTLINE( "Po" ) )
         {
diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp
index d221495365..2ff79424ab 100644
--- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp
+++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp
@@ -1958,11 +1958,11 @@ void PCB_IO_KICAD_SEXPR::formatTenting( const PADSTACK& aPadstack ) const
 
 void PCB_IO_KICAD_SEXPR::format( const PCB_TEXT* aText ) const
 {
-    FOOTPRINT*  parentFP = aText->GetParentFootprint();
-    std::string prefix;
-    std::string type;
-    VECTOR2I    pos = aText->GetTextPos();
-    bool        isField = dynamic_cast<const PCB_FIELD*>( aText ) != nullptr;
+    FOOTPRINT*       parentFP = aText->GetParentFootprint();
+    std::string      prefix;
+    std::string      type;
+    VECTOR2I         pos = aText->GetTextPos();
+    const PCB_FIELD* field = dynamic_cast<const PCB_FIELD*>( aText );
 
     // Always format dimension text as gr_text
     if( dynamic_cast<const PCB_DIMENSION_BASE*>( aText ) )
@@ -1981,7 +1981,7 @@ void PCB_IO_KICAD_SEXPR::format( const PCB_TEXT* aText ) const
         prefix = "gr";
     }
 
-    if( !isField )
+    if( !field )
     {
         m_out->Print( "(%s_text %s %s",
                       prefix.c_str(),
@@ -2001,23 +2001,21 @@ void PCB_IO_KICAD_SEXPR::format( const PCB_TEXT* aText ) const
 
     formatLayer( aText->GetLayer(), aText->IsKnockout() );
 
-    if( parentFP && !aText->IsVisible() )
+    if( field && !field->IsVisible() )
         KICAD_FORMAT::FormatBool( m_out, "hide", true );
 
     KICAD_FORMAT::FormatUuid( m_out, aText->m_Uuid );
 
-    int ctl_flags = m_ctl | CTL_OMIT_HIDE;
-
     // Currently, texts have no specific color and no hyperlink.
     // so ensure they are never written in kicad_pcb file
-    ctl_flags |= CTL_OMIT_COLOR | CTL_OMIT_HYPERLINK;
+    int ctl_flags = CTL_OMIT_COLOR | CTL_OMIT_HYPERLINK;
 
     aText->EDA_TEXT::Format( m_out, ctl_flags );
 
     if( aText->GetFont() && aText->GetFont()->IsOutline() )
         formatRenderCache( aText );
 
-    if( !isField )
+    if( !field )
         m_out->Print( ")" );
 }
 
@@ -2077,8 +2075,7 @@ void PCB_IO_KICAD_SEXPR::format( const PCB_TEXTBOX* aTextBox ) const
 
     KICAD_FORMAT::FormatUuid( m_out, aTextBox->m_Uuid );
 
-    // PCB_TEXTBOXes are never hidden, so always omit "hide" attribute
-    aTextBox->EDA_TEXT::Format( m_out, m_ctl | CTL_OMIT_HIDE );
+    aTextBox->EDA_TEXT::Format( m_out, 0 );
 
     if( aTextBox->Type() != PCB_TABLECELL_T )
     {
diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp
index aa9803881a..2123c9df44 100644
--- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp
+++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp
@@ -3354,6 +3354,18 @@ PCB_TEXT* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_TEXT( BOARD_ITEM* aParent, PCB_TEX
 
     parsePCB_TEXT_effects( text.get(), aBaseText );
 
+    if( parentFP )
+    {
+        // Convert hidden footprint text (which is no longer supported) into a hidden field
+        if( !text->IsVisible() && text->Type() == PCB_TEXT_T )
+            return new PCB_FIELD( text.get(), -1 );
+    }
+    else
+    {
+        // Hidden PCB text is no longer supported
+        text->SetVisible( true );
+    }
+
     return text.release();
 }
 
diff --git a/pcbnew/pcb_io/odbpp/odb_feature.cpp b/pcbnew/pcb_io/odbpp/odb_feature.cpp
index 0f8cb13bbd..058b9317d5 100644
--- a/pcbnew/pcb_io/odbpp/odb_feature.cpp
+++ b/pcbnew/pcb_io/odbpp/odb_feature.cpp
@@ -752,25 +752,34 @@ void FEATURES_MANAGER::InitFeatureList( PCB_LAYER_ID aLayer, std::vector<BOARD_I
         {
         case PCB_TRACE_T:
         case PCB_ARC_T:
-        case PCB_VIA_T: add_track( static_cast<PCB_TRACK*>( item ) ); break;
+        case PCB_VIA_T:
+            add_track( static_cast<PCB_TRACK*>( item ) );
+            break;
 
-        case PCB_ZONE_T: add_zone( static_cast<ZONE*>( item ) ); break;
+        case PCB_ZONE_T:
+            add_zone( static_cast<ZONE*>( item ) );
+            break;
 
-        case PCB_PAD_T: add_pad( static_cast<PAD*>( item ) ); break;
+        case PCB_PAD_T:
+            add_pad( static_cast<PAD*>( item ) );
+            break;
 
-        case PCB_SHAPE_T: add_shape( static_cast<PCB_SHAPE*>( item ) ); break;
+        case PCB_SHAPE_T:
+            add_shape( static_cast<PCB_SHAPE*>( item ) );
+            break;
 
         case PCB_TEXT_T:
-        case PCB_FIELD_T: add_text( item ); break;
+        case PCB_FIELD_T:
+            add_text( item );
+            break;
+
         case PCB_TEXTBOX_T:
-        {
-            PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
             add_text( item );
 
-            if( textbox->IsBorderEnabled() )
-                add_shape( textbox );
-        }
-        break;
+            if( static_cast<PCB_TEXTBOX*>( item )->IsBorderEnabled() )
+                add_shape( static_cast<PCB_TEXTBOX*>( item ) );
+
+            break;
 
         case PCB_DIMENSION_T:
         case PCB_TARGET_T:
diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp
index d52e140b92..7fd676382f 100644
--- a/pcbnew/pcb_painter.cpp
+++ b/pcbnew/pcb_painter.cpp
@@ -659,6 +659,9 @@ bool PCB_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer )
         break;
 
     case PCB_FIELD_T:
+        draw( static_cast<const PCB_FIELD*>( item ), aLayer );
+        break;
+
     case PCB_TEXT_T:
         draw( static_cast<const PCB_TEXT*>( item ), aLayer );
         break;
@@ -2186,11 +2189,18 @@ void PCB_PAINTER::draw( const PCB_REFERENCE_IMAGE* aBitmap, int aLayer )
 }
 
 
+void PCB_PAINTER::draw( const PCB_FIELD* aField, int aLayer )
+{
+    if( aField->IsVisible() )
+        draw( static_cast<const PCB_TEXT*>( aField ), aLayer );
+}
+
+
 void PCB_PAINTER::draw( const PCB_TEXT* aText, int aLayer )
 {
     wxString resolvedText( aText->GetShownText( true ) );
 
-    if( resolvedText.Length() == 0 || !aText->GetAttributes().m_Visible )
+    if( resolvedText.Length() == 0 )
         return;
 
     if( aLayer == LAYER_LOCKED_ITEM_SHADOW )    // happens only if locked
diff --git a/pcbnew/pcb_painter.h b/pcbnew/pcb_painter.h
index 98a4d28c2f..a6f8bd4f4a 100644
--- a/pcbnew/pcb_painter.h
+++ b/pcbnew/pcb_painter.h
@@ -52,6 +52,7 @@ class FOOTPRINT;
 class ZONE;
 class PCB_REFERENCE_IMAGE;
 class PCB_TEXT;
+class PCB_FIELD;
 class PCB_TEXTBOX;
 class PCB_TABLE;
 class PCB_DIMENSION_BASE;
@@ -200,6 +201,7 @@ protected:
     void draw( const PAD* aPad, int aLayer );
     void draw( const PCB_SHAPE* aSegment, int aLayer );
     void draw( const PCB_REFERENCE_IMAGE* aBitmap, int aLayer );
+    void draw( const PCB_FIELD* aField, int aLayer );
     void draw( const PCB_TEXT* aText, int aLayer );
     void draw( const PCB_TEXTBOX* aText, int aLayer );
     void draw( const PCB_TABLE* aTable, int aLayer );
diff --git a/pcbnew/pcb_tablecell.cpp b/pcbnew/pcb_tablecell.cpp
index c81e666181..7313e96053 100644
--- a/pcbnew/pcb_tablecell.cpp
+++ b/pcbnew/pcb_tablecell.cpp
@@ -200,7 +200,6 @@ static struct PCB_TABLECELL_DESC
         propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Style" ) );
         propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Color" ) );
 
-        propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Visible" ) );
         propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Width" ) );
         propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Height" ) );
         propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Thickness" ) );
diff --git a/pcbnew/pcb_text.cpp b/pcbnew/pcb_text.cpp
index 4e5448fa42..106c7480c6 100644
--- a/pcbnew/pcb_text.cpp
+++ b/pcbnew/pcb_text.cpp
@@ -278,9 +278,6 @@ void PCB_TEXT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_IT
     if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
         aList.emplace_back( _( "Status" ), _( "Locked" ) );
 
-    if( parentFP )
-        aList.emplace_back( _( "Display" ), IsVisible() ? _( "Yes" ) : _( "No" ) );
-
     aList.emplace_back( _( "Layer" ), GetLayerName() );
 
     aList.emplace_back( _( "Mirror" ), IsMirrored() ? _( "Yes" ) : _( "No" ) );
@@ -640,9 +637,6 @@ static struct PCB_TEXT_DESC
                     return false;
                 };
 
-        propMgr.OverrideAvailability( TYPE_HASH( PCB_TEXT ), TYPE_HASH( EDA_TEXT ),
-                                      _HKI( "Visible" ), isFootprintText );
-
         propMgr.OverrideAvailability( TYPE_HASH( PCB_TEXT ), TYPE_HASH( EDA_TEXT ),
                                       _HKI( "Keep Upright" ), isFootprintText );
 
diff --git a/pcbnew/pcb_textbox.cpp b/pcbnew/pcb_textbox.cpp
index 9902c3a03c..591b4a5b8b 100644
--- a/pcbnew/pcb_textbox.cpp
+++ b/pcbnew/pcb_textbox.cpp
@@ -97,7 +97,6 @@ void PCB_TEXTBOX::Serialize( google::protobuf::Any &aContainer ) const
     attrs->set_italic( IsItalic() );
     attrs->set_bold( IsBold() );
     attrs->set_underlined( GetAttributes().m_Underlined );
-    attrs->set_visible( IsVisible() );
     attrs->set_mirrored( IsMirrored() );
     attrs->set_multiline( IsMultilineAllowed() );
     attrs->set_keep_upright( IsKeepUpright() );
@@ -133,7 +132,6 @@ bool PCB_TEXTBOX::Deserialize( const google::protobuf::Any &aContainer )
         attrs.m_Bold = text.attributes().bold();
         attrs.m_Italic = text.attributes().italic();
         attrs.m_Underlined = text.attributes().underlined();
-        attrs.m_Visible = text.attributes().visible();
         attrs.m_Mirrored = text.attributes().mirrored();
         attrs.m_Multiline = text.attributes().multiline();
         attrs.m_KeepUpright = text.attributes().keep_upright();
@@ -816,7 +814,6 @@ static struct PCB_TEXTBOX_DESC
         propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Width" ) );
         propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Style" ) );
         propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Filled" ) );
-        propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_TEXT ), _HKI( "Visible" ) );
         propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_TEXT ), _HKI( "Color" ) );
 
         const wxString borderProps = _( "Border Properties" );
diff --git a/pcbnew/pcb_textbox.h b/pcbnew/pcb_textbox.h
index 841aea80e1..02d8877188 100644
--- a/pcbnew/pcb_textbox.h
+++ b/pcbnew/pcb_textbox.h
@@ -96,10 +96,6 @@ public:
 
     wxString GetShownText( bool aAllowExtraText, int aDepth = 0 ) const override;
 
-    /// PCB_TEXTBOXes are always visible:
-    void SetVisible( bool aVisible ) override { /* do nothing */}
-    bool IsVisible() const override { return true; }
-
     bool Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const override;
 
     std::vector<VECTOR2I> GetAnchorAndOppositeCorner() const;
diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp
index bfe5c391bf..c48ba9d420 100644
--- a/pcbnew/plot_board_layers.cpp
+++ b/pcbnew/plot_board_layers.cpp
@@ -910,9 +910,6 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
                 if( !itemplotter.GetPlotFPText() )
                     return;
 
-                if( !aText.IsVisible() && !itemplotter.GetPlotInvisibleText()  )
-                    return;
-
                 if( aText.GetText() == wxT( "${REFERENCE}" ) && !itemplotter.GetPlotReference() )
                     return;
 
@@ -946,6 +943,9 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
                 if( field->IsValue() && !itemplotter.GetPlotValue() )
                     continue;
 
+                if( !field->IsVisible() && !itemplotter.GetPlotInvisibleText() )
+                    continue;
+
                 if( field->IsOnLayer( layer ) )
                     plotFPTextItem( static_cast<const PCB_TEXT&>( *field ) );
             }
diff --git a/pcbnew/tools/pcb_selection_tool.cpp b/pcbnew/tools/pcb_selection_tool.cpp
index 9df271d116..fa31cb3d6e 100644
--- a/pcbnew/tools/pcb_selection_tool.cpp
+++ b/pcbnew/tools/pcb_selection_tool.cpp
@@ -2966,6 +2966,9 @@ bool PCB_SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibili
     case PCB_FIELD_T:
         field = static_cast<const PCB_FIELD*>( aItem );
 
+        if( !field->IsVisible() )
+            return false;
+
         if( field->IsReference() && !view()->IsLayerVisible( LAYER_FP_REFERENCES ) )
             return false;
 
@@ -2977,12 +2980,6 @@ bool PCB_SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibili
     case PCB_TEXT_T:
         text = static_cast<const PCB_TEXT*>( aItem );
 
-        if( !text->IsVisible() )
-        {
-            if( !m_isFootprintEditor )
-                return false;
-        }
-
         if( !layerVisible( text->GetLayer() ) )
             return false;
 
diff --git a/qa/tests/common/test_text_attributes.cpp b/qa/tests/common/test_text_attributes.cpp
index a841cb202d..464a15d404 100644
--- a/qa/tests/common/test_text_attributes.cpp
+++ b/qa/tests/common/test_text_attributes.cpp
@@ -109,14 +109,6 @@ BOOST_AUTO_TEST_CASE( Compare )
     BOOST_CHECK_LT( a, b );
 
     b.m_Color = KIGFX::COLOR4D( UNSPECIFIED_COLOR );
-    b.m_Visible = false;
-    BOOST_CHECK_GT( a, b );
-
-    b.m_Visible = true;
-    a.m_Visible = false;
-    BOOST_CHECK_LT( a, b );
-
-    a.m_Visible = true;
     a.m_Mirrored = true;
     BOOST_CHECK_GT( a, b );