diff --git a/modules/extensions_framework/__init__.py b/modules/extensions_framework/__init__.py
index 8e7ee390800526a48a2198c671fec6f70226b1c4..4581046b21552da689ac765e333152819cf87b58 100644
--- a/modules/extensions_framework/__init__.py
+++ b/modules/extensions_framework/__init__.py
@@ -116,26 +116,28 @@ def init_properties(obj, props, cache=True):
 			continue
 
 def ef_initialise_properties(cls):
-	"""This is a class decorator that should be used on
+	"""This is a function that should be called on
 	sub-classes of declarative_property_group in order
 	to ensure that they are initialised when the addon
 	is loaded.
 	
 	"""
 	
-	for property_group_parent in cls.ef_attach_to:
-		if property_group_parent is not None:
-			prototype = getattr(bpy.types, property_group_parent)
-			if not hasattr(prototype, cls.__name__):
-				init_properties(prototype, [{
-					'type': 'pointer',
-					'attr': cls.__name__,
-					'ptype': cls,
-					'name': cls.__name__,
-					'description': cls.__name__
-				}])
-	
-	init_properties(cls, cls.properties)
+	if not cls.ef_initialised:
+		for property_group_parent in cls.ef_attach_to:
+			if property_group_parent is not None:
+				prototype = getattr(bpy.types, property_group_parent)
+				if not hasattr(prototype, cls.__name__):
+					init_properties(prototype, [{
+						'type': 'pointer',
+						'attr': cls.__name__,
+						'ptype': cls,
+						'name': cls.__name__,
+						'description': cls.__name__
+					}])
+		
+		init_properties(cls, cls.properties)
+		cls.ef_initialised = True
 	
 	return cls
 
@@ -150,6 +152,30 @@ def ef_register_initialise_properties(cls):
 	ef_initialise_properties(cls)
 	return cls
 
+def ef_remove_properties(cls):
+	"""This is a function that should be called on
+	sub-classes of declarative_property_group in order
+	to ensure that they are un-initialised when the addon
+	is unloaded.
+	
+	"""
+	
+	if cls.ef_initialised:
+		for prop in cls.properties:
+			if hasattr(cls, prop['attr']):
+				delattr(cls, prop['attr'])
+		added_property_cache[cls] = []
+		
+		for property_group_parent in cls.ef_attach_to:
+			if property_group_parent is not None:
+				prototype = getattr(bpy.types, property_group_parent)
+				if hasattr(prototype, cls.__name__):
+					delattr(prototype, cls.__name__)
+		
+		cls.ef_initialised = False
+	
+	return cls
+
 class declarative_property_group(bpy.types.IDPropertyGroup):
 	"""A declarative_property_group describes a set of logically
 	related properties, using a declarative style to list each
@@ -169,6 +195,8 @@ class declarative_property_group(bpy.types.IDPropertyGroup):
 	
 	"""
 	
+	ef_initialised = False
+	
 	"""This property tells extensions_framework which bpy.type(s)
 	to attach this IDPropertyGroup to. If left as an empty list,
 	it will not be attached to any type, but its properties will