diff --git a/toonz/sources/common/tmetaimage/tmetaimage.cpp b/toonz/sources/common/tmetaimage/tmetaimage.cpp
index f7af5d5..b3e48e8 100644
--- a/toonz/sources/common/tmetaimage/tmetaimage.cpp
+++ b/toonz/sources/common/tmetaimage/tmetaimage.cpp
@@ -5,16 +5,23 @@
 
 //---------------------------------------------------------
 
-TMetaObject::TMetaObject(const TStringId &typeName):
+TMetaObject::TMetaObject(const TMetaObject &other):
   m_handler(),
-  m_data(*this)
+  m_data(*this, other.data())
+    { setType(other.getType()); }
+
+//---------------------------------------------------------
+
+TMetaObject::TMetaObject(const TStringId &typeName, const TVariant &data):
+  m_handler(),
+  m_data(*this, data)
     { setType(typeName); }
 
 //---------------------------------------------------------
 
-TMetaObject::TMetaObject(const std::string &typeName):
+TMetaObject::TMetaObject(const std::string &typeName, const TVariant &data):
   m_handler(),
-  m_data(*this)
+  m_data(*this, data)
     { setType(typeName); }
 
 //---------------------------------------------------------
@@ -43,6 +50,18 @@ TMetaObject::onVariantChanged(const TVariant &value)
 
 //---------------------------------------------------------
 
+void
+TMetaObject::setDefaults()
+  { m_data.reset(); if (m_handler) m_handler->setDefaults(); }
+
+//---------------------------------------------------------
+
+TMetaObject*
+TMetaObject::clone() const
+  { return new TMetaObject(*this); }
+
+//---------------------------------------------------------
+
 TMetaObject::Registry&
 TMetaObject::registry() {
   static Registry registry;
@@ -74,9 +93,13 @@ TMetaImage::TMetaImage()
 
 //---------------------------------------------------------
 
-TMetaImage::TMetaImage(const TMetaImage &other):
-  m_objects(*Reader(other))
-  { }
+TMetaImage::TMetaImage(const TMetaImage &other) {
+  Reader reader(other);
+  m_objects.reserve(reader->size());
+  for(TMetaObjectListCW::iterator i = reader->begin(); i != reader->end(); ++i)
+    if (*i)
+      m_objects.push_back( TMetaObjectP((*i)->clone()) );
+}
 
 //---------------------------------------------------------
 
diff --git a/toonz/sources/image/tzm/tiio_tzm.cpp b/toonz/sources/image/tzm/tiio_tzm.cpp
index 7a8421f..0435259 100644
--- a/toonz/sources/image/tzm/tiio_tzm.cpp
+++ b/toonz/sources/image/tzm/tiio_tzm.cpp
@@ -58,7 +58,7 @@ namespace {
         TVariant &frameData = m_data["frames"][frameId.expand()];
         TVariant &objectsData = frameData["objects"];
         objectsData.setType(TVariant::List);
-        for(TMetaObjectRefList::const_iterator i = reader->begin(); i != reader->end(); ++i) {
+        for(TMetaObjectListCW::iterator i = reader->begin(); i != reader->end(); ++i) {
           if (*i) {
             TVariant &objectData = objectsData[ objectsData.size() ];
             objectData["type"].setString( (*i)->getTypeName() );
@@ -162,7 +162,7 @@ namespace {
             for(int j = 0; j < objectsData.size(); ++j) {
               const TVariant &objectData = objectsData[j];
               if (!objectData["type"].getString().empty()) {
-                TMetaObjectR obj( new TMetaObject(objectData["type"].getString()) );
+                TMetaObjectP obj( new TMetaObject(objectData["type"].getString()) );
                 obj->data() = objectData["data"];
                 writer->push_back(obj);
               }
diff --git a/toonz/sources/include/tmetaimage.h b/toonz/sources/include/tmetaimage.h
index f172e48..09a5cc0 100644
--- a/toonz/sources/include/tmetaimage.h
+++ b/toonz/sources/include/tmetaimage.h
@@ -7,6 +7,7 @@
 #include "tthreadmessage.h"
 #include "tsmartpointer.h"
 #include "tvariant.h"
+#include "tconstwrapper.h"
 
 #include <QReadLocker>
 #include <QWriteLocker>
@@ -28,9 +29,11 @@
 
 class TMetaObject;
 class TMetaObjectHandler;
-typedef TSmartPointerT<TMetaObject> TMetaObjectP;
-typedef TSmartRefT<TMetaObject> TMetaObjectR;
-typedef std::vector<TMetaObjectR> TMetaObjectRefList;
+typedef TSmartPointerT<TMetaObject> TMetaObjectP;  //!< smart pointer to TMetaObject
+typedef TMetaObjectP::Holder        TMetaObjectH;  //!< smart holder of TMetaObject
+typedef TMetaObjectP::Const         TMetaObjectPC; //!< smart pointer to constant TMetaObject
+typedef std::vector<TMetaObjectP> TMetaObjectList;
+typedef TConstArrayWrapperT<TMetaObjectPC, TMetaObjectP> TMetaObjectListCW; // TMetaObjectListConstWrapper
 
 //-------------------------------------------------------------------
 
@@ -56,9 +59,11 @@ private:
   TMetaObjectHandler *m_handler;
   TVariant m_data;
 
+  TMetaObject(const TMetaObject &other);
+
 public:
-  explicit TMetaObject(const TStringId &typeName = TStringId());
-  explicit TMetaObject(const std::string &typeName);
+  explicit TMetaObject(const TStringId &typeName = TStringId(), const TVariant &data = TVariant());
+  explicit TMetaObject(const std::string &typeName, const TVariant &data = TVariant());
   ~TMetaObject();
 
   void setType(const TStringId &name);
@@ -75,6 +80,8 @@ public:
   inline TVariant& data()
     { return m_data; }
 
+  void setDefaults();
+
   template<typename T>
   const T* getHandler() const
     { return dynamic_cast<const T*>(m_handler); }
@@ -82,8 +89,13 @@ public:
   T* getHandler()
     { return dynamic_cast<T*>(m_handler); }
 
+  TMetaObjectHandler* handler() { return m_handler; }
+  const TMetaObjectHandler* handler() const { return m_handler; }
+
   void onVariantChanged(const TVariant &value) override;
 
+  virtual TMetaObject* clone() const;
+
   static Registry& registry();
   static void registerType(const TStringId &name, Fabric fabric);
   static void unregisterType(const TStringId &name);
@@ -96,9 +108,18 @@ public:
 //-------------------------------------------------------------------
 
 class DVAPI TMetaObjectHandler {
+protected:
+  class LockEvents {
+  public:
+    TMetaObjectHandler &owner;
+    explicit LockEvents(TMetaObjectHandler &owner):
+      owner(owner) { ++owner.m_locks; }
+    ~LockEvents() { --owner.m_locks; }
+  };
+
 private:
   TMetaObject &m_object;
-  TAtomicVar m_fixingData;
+  TAtomicVar m_locks;
 
 public:
   TMetaObjectHandler(TMetaObject &object):
@@ -115,18 +136,17 @@ public:
     { return object().data(); }
 
 protected:
+  virtual void onSetDefaults() { }
   virtual void onDataChanged(const TVariant &value) { }
   virtual void onFixData() { }
 
 public:
+  void setDefaults()
+    { onSetDefaults(); }
   void dataChanged(const TVariant &value)
-    { if (m_fixingData == 0) onDataChanged(value); }
-
-  void fixData() {
-    ++m_fixingData;
-    if (m_fixingData == 1) onFixData();
-    --m_fixingData;
-  }
+    { if (m_locks == 0) onDataChanged(value); }
+  void fixData()
+    { LockEvents lock(*this); onFixData(); }
 };
 
 //-------------------------------------------------------------------
@@ -138,16 +158,19 @@ public:
   class Reader: public QReadLocker {
   private:
     const TMetaImage &m_image;
+    const TMetaObjectListCW m_objects;
   public:
     Reader(const TMetaImage &image):
-      QReadLocker(&image.m_rwLock), m_image(image) { }
+      QReadLocker(&image.m_rwLock),
+      m_image(image),
+      m_objects(image.m_objects) { }
     const TMetaImage& image() const
       { return m_image; }
-    const TMetaObjectRefList& get() const
-      { return m_image.m_objects; }
-    const TMetaObjectRefList& operator*() const
+    const TMetaObjectListCW& get() const
+      { return m_objects; }
+    const TMetaObjectListCW& operator*() const
       { return get(); }
-    const TMetaObjectRefList* operator->() const
+    const TMetaObjectListCW* operator->() const
       { return &get(); }
   };
 
@@ -159,20 +182,21 @@ public:
       QWriteLocker(&image.m_rwLock), m_image(image) { }
     TMetaImage& image() const
       { return m_image; }
-    TMetaObjectRefList& get() const
+    TMetaObjectList& get() const
       { return m_image.m_objects; }
-    TMetaObjectRefList& operator*() const
+    TMetaObjectList& operator*() const
       { return get(); }
-    TMetaObjectRefList* operator->() const
+    TMetaObjectList* operator->() const
       { return &get(); }
   };
 
 private:
   mutable QReadWriteLock m_rwLock;
-  TMetaObjectRefList m_objects;
+  TMetaObjectList m_objects;
 
-  //! not implemented
   TMetaImage(const TMetaImage &other);
+
+  //! not implemented
   TMetaImage &operator=(const TMetaImage &) { return *this; }
 
 public:
diff --git a/toonz/sources/tnztools/modifiers/modifierassistants.cpp b/toonz/sources/tnztools/modifiers/modifierassistants.cpp
index 99a8ad8..03a71c0 100644
--- a/toonz/sources/tnztools/modifiers/modifierassistants.cpp
+++ b/toonz/sources/tnztools/modifiers/modifierassistants.cpp
@@ -86,7 +86,7 @@ TModifierAssistants::scanAssistants(
         if (draw) { glPushMatrix(); tglMultMatrix(imageToTrack); }
 
         TMetaImage::Reader reader(*metaImage);
-        for(TMetaObjectRefList::const_iterator i = reader->begin(); i != reader->end(); ++i)
+        for(TMetaObjectListCW::iterator i = reader->begin(); i != reader->end(); ++i)
           if (*i)
           if (const TAssistant *assistant = (*i)->getHandler<TAssistant>())
           {