From d5962b290c6fe0fd9e6e95aec069744f662d9e41 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Fri, 3 Feb 2017 21:34:49 +0100
Subject: [PATCH] - turned all menu items into actual objects.

This is needed for script export.
---
 src/dobjgc.cpp               |   2 +-
 src/menu/colorpickermenu.cpp |  22 ++--
 src/menu/joystickmenu.cpp    |  95 +++++++-------
 src/menu/listmenu.cpp        | 101 ++++++++-------
 src/menu/menu.cpp            |  29 +++++
 src/menu/menu.h              | 114 ++++++++++-------
 src/menu/menudef.cpp         |  84 ++++++-------
 src/menu/optionmenu.cpp      |  20 ++-
 src/menu/optionmenuitems.h   | 238 +++++++++++++++++++++++++----------
 src/menu/playerdisplay.cpp   |  21 ++--
 src/menu/playermenu.cpp      | 115 ++++++++---------
 src/menu/videomenu.cpp       |  30 ++---
 12 files changed, 499 insertions(+), 372 deletions(-)

diff --git a/src/dobjgc.cpp b/src/dobjgc.cpp
index 0a44599d0b..df1760dd70 100644
--- a/src/dobjgc.cpp
+++ b/src/dobjgc.cpp
@@ -324,7 +324,7 @@ static void MarkRoot()
 	Mark(Args);
 	Mark(screen);
 	Mark(StatusBar);
-	Mark(DMenu::CurrentMenu);
+	M_MarkMenus();
 	Mark(DIntermissionController::CurrentIntermission);
 	DThinker::MarkRoots();
 	FCanvasTextureInfo::Mark();
diff --git a/src/menu/colorpickermenu.cpp b/src/menu/colorpickermenu.cpp
index 0d92e1e45e..6ace5bd704 100644
--- a/src/menu/colorpickermenu.cpp
+++ b/src/menu/colorpickermenu.cpp
@@ -81,14 +81,14 @@ public:
 		// This menu uses some featurs that are hard to implement in an external control lump
 		// so it creates its own list of menu items.
 		desc->mItems.Resize(mStartItem+8);
-		desc->mItems[mStartItem+0] = new FOptionMenuItemStaticText(name, false);
-		desc->mItems[mStartItem+1] = new FOptionMenuItemStaticText(" ", false);
-		desc->mItems[mStartItem+2] = new FOptionMenuSliderVar("Red", &mRed, 0, 255, 15, 0);
-		desc->mItems[mStartItem+3] = new FOptionMenuSliderVar("Green", &mGreen, 0, 255, 15, 0);
-		desc->mItems[mStartItem+4] = new FOptionMenuSliderVar("Blue", &mBlue, 0, 255, 15, 0);
-		desc->mItems[mStartItem+5] = new FOptionMenuItemStaticText(" ", false);
-		desc->mItems[mStartItem+6] = new FOptionMenuItemCommand("Undo changes", "undocolorpic");
-		desc->mItems[mStartItem+7] = new FOptionMenuItemStaticText(" ", false);
+		desc->mItems[mStartItem+0] = new DOptionMenuItemStaticText(name, false);
+		desc->mItems[mStartItem+1] = new DOptionMenuItemStaticText(" ", false);
+		desc->mItems[mStartItem+2] = new DOptionMenuSliderVar("Red", &mRed, 0, 255, 15, 0);
+		desc->mItems[mStartItem+3] = new DOptionMenuSliderVar("Green", &mGreen, 0, 255, 15, 0);
+		desc->mItems[mStartItem+4] = new DOptionMenuSliderVar("Blue", &mBlue, 0, 255, 15, 0);
+		desc->mItems[mStartItem+5] = new DOptionMenuItemStaticText(" ", false);
+		desc->mItems[mStartItem+6] = new DOptionMenuItemCommand("Undo changes", "undocolorpic");
+		desc->mItems[mStartItem+7] = new DOptionMenuItemStaticText(" ", false);
 		desc->mSelectedItem = mStartItem + 2;
 		Init(parent, desc);
 		desc->mIndent = 0;
@@ -99,11 +99,7 @@ public:
 	{
 		if (mStartItem >= 0)
 		{
-			for(unsigned i=0;i<8;i++)
-			{
-				delete mDesc->mItems[mStartItem+i];
-				mDesc->mItems.Resize(mStartItem);
-			}
+			mDesc->mItems.Resize(mStartItem);
 			UCVarValue val;
 			val.Int = MAKERGB(int(mRed), int(mGreen), int(mBlue));
 			if (mCVar != NULL) mCVar->SetGenericRep (val, CVAR_Int);
diff --git a/src/menu/joystickmenu.cpp b/src/menu/joystickmenu.cpp
index f715dce4ae..702a6b09f0 100644
--- a/src/menu/joystickmenu.cpp
+++ b/src/menu/joystickmenu.cpp
@@ -66,11 +66,11 @@ FOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy);
 //
 //=============================================================================
 
-class FOptionMenuSliderJoySensitivity : public FOptionMenuSliderBase
+class DOptionMenuSliderJoySensitivity : public DOptionMenuSliderBase
 {
 public:
-	FOptionMenuSliderJoySensitivity(const char *label, double min, double max, double step, int showval)
-		: FOptionMenuSliderBase(label, min, max, step, showval)
+	DOptionMenuSliderJoySensitivity(const char *label, double min, double max, double step, int showval)
+		: DOptionMenuSliderBase(label, min, max, step, showval)
 	{
 	}
 
@@ -91,14 +91,14 @@ public:
 //
 //=============================================================================
 
-class FOptionMenuSliderJoyScale : public FOptionMenuSliderBase
+class DOptionMenuSliderJoyScale : public DOptionMenuSliderBase
 {
 	int mAxis;
 	int mNeg;
 	
 public:
-	FOptionMenuSliderJoyScale(const char *label, int axis, double min, double max, double step, int showval)
-		: FOptionMenuSliderBase(label, min, max, step, showval)
+	DOptionMenuSliderJoyScale(const char *label, int axis, double min, double max, double step, int showval)
+		: DOptionMenuSliderBase(label, min, max, step, showval)
 	{
 		mAxis = axis;
 		mNeg = 1;
@@ -123,14 +123,14 @@ public:
 //
 //=============================================================================
 
-class FOptionMenuSliderJoyDeadZone : public FOptionMenuSliderBase
+class DOptionMenuSliderJoyDeadZone : public DOptionMenuSliderBase
 {
 	int mAxis;
 	int mNeg;
 	
 public:
-	FOptionMenuSliderJoyDeadZone(const char *label, int axis, double min, double max, double step, int showval)
-		: FOptionMenuSliderBase(label, min, max, step, showval)
+	DOptionMenuSliderJoyDeadZone(const char *label, int axis, double min, double max, double step, int showval)
+		: DOptionMenuSliderBase(label, min, max, step, showval)
 	{
 		mAxis = axis;
 		mNeg = 1;
@@ -155,13 +155,13 @@ public:
 //
 //=============================================================================
 
-class FOptionMenuItemJoyMap : public FOptionMenuItemOptionBase
+class DOptionMenuItemJoyMap : public DOptionMenuItemOptionBase
 {
 	int mAxis;
 public:
 
-	FOptionMenuItemJoyMap(const char *label, int axis, const char *values, int center)
-		: FOptionMenuItemOptionBase(label, "none", values, NULL, center)
+	DOptionMenuItemJoyMap(const char *label, int axis, const char *values, int center)
+		: DOptionMenuItemOptionBase(label, "none", values, NULL, center)
 	{
 		mAxis = axis;
 	}
@@ -206,13 +206,13 @@ public:
 //
 //=============================================================================
 
-class FOptionMenuItemInverter : public FOptionMenuItemOptionBase
+class DOptionMenuItemInverter : public DOptionMenuItemOptionBase
 {
 	int mAxis;
 public:
 
-	FOptionMenuItemInverter(const char *label, int axis, int center)
-		: FOptionMenuItemOptionBase(label, "none", "YesNo", NULL, center)
+	DOptionMenuItemInverter(const char *label, int axis, int center)
+		: DOptionMenuItemOptionBase(label, "none", "YesNo", NULL, center)
 	{
 		mAxis = axis;
 	}
@@ -244,12 +244,13 @@ IMPLEMENT_CLASS(DJoystickConfigMenu, false, false)
 //
 //=============================================================================
 
-class FOptionMenuItemJoyConfigMenu : public FOptionMenuItemSubmenu
+class DOptionMenuItemJoyConfigMenu : public DOptionMenuItemSubmenu
 {
+	DECLARE_CLASS(DOptionMenuItemJoyConfigMenu, DOptionMenuItemSubmenu)
 	IJoystickConfig *mJoy;
 public:
-	FOptionMenuItemJoyConfigMenu(const char *label, IJoystickConfig *joy)
-		: FOptionMenuItemSubmenu(label, "JoystickConfigMenu")
+	DOptionMenuItemJoyConfigMenu(const char *label = nullptr, IJoystickConfig *joy = nullptr)
+		: DOptionMenuItemSubmenu(label, "JoystickConfigMenu")
 	{
 		mJoy = joy;
 	}
@@ -257,10 +258,12 @@ public:
 	bool Activate()
 	{
 		UpdateJoystickConfigMenu(mJoy);
-		return FOptionMenuItemSubmenu::Activate();
+		return DOptionMenuItemSubmenu::Activate();
 	}
 };
 
+IMPLEMENT_CLASS(DOptionMenuItemJoyConfigMenu, false, false)
+
 
 /*=======================================
  *
@@ -274,16 +277,12 @@ FOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy)
 	if (desc != NULL && (*desc)->mType == MDESC_OptionsMenu)
 	{
 		FOptionMenuDescriptor *opt = (FOptionMenuDescriptor *)*desc;
-		FOptionMenuItem *it;
-		for(unsigned i=0;i<opt->mItems.Size();i++)
-		{
-			delete opt->mItems[i];
-			opt->mItems.Clear();
-		}
+		DOptionMenuItem *it;
+		opt->mItems.Clear();
 		if (joy == NULL)
 		{
 			opt->mTitle = "Configure Controller";
-			it = new FOptionMenuItemStaticText("Invalid controller specified for menu", false);
+			it = new DOptionMenuItemStaticText("Invalid controller specified for menu", false);
 			opt->mItems.Push(it);
 		}
 		else
@@ -292,34 +291,34 @@ FOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy)
 
 			SELECTED_JOYSTICK = joy;
 
-			it = new FOptionMenuSliderJoySensitivity("Overall sensitivity", 0, 2, 0.1, 3);
+			it = new DOptionMenuSliderJoySensitivity("Overall sensitivity", 0, 2, 0.1, 3);
 			opt->mItems.Push(it);
-			it = new FOptionMenuItemStaticText(" ", false);
+			it = new DOptionMenuItemStaticText(" ", false);
 			opt->mItems.Push(it);
 
 			if (joy->GetNumAxes() > 0)
 			{
-				it = new FOptionMenuItemStaticText("Axis Configuration", true);
+				it = new DOptionMenuItemStaticText("Axis Configuration", true);
 				opt->mItems.Push(it);
 
 				for (int i = 0; i < joy->GetNumAxes(); ++i)
 				{
-					it = new FOptionMenuItemStaticText(" ", false);
+					it = new DOptionMenuItemStaticText(" ", false);
 					opt->mItems.Push(it);
 
-					it = new FOptionMenuItemJoyMap(joy->GetAxisName(i), i, "JoyAxisMapNames", false);
+					it = new DOptionMenuItemJoyMap(joy->GetAxisName(i), i, "JoyAxisMapNames", false);
 					opt->mItems.Push(it);
-					it = new FOptionMenuSliderJoyScale("Overall sensitivity", i, 0, 4, 0.1, 3);
+					it = new DOptionMenuSliderJoyScale("Overall sensitivity", i, 0, 4, 0.1, 3);
 					opt->mItems.Push(it);
-					it = new FOptionMenuItemInverter("Invert", i, false);
+					it = new DOptionMenuItemInverter("Invert", i, false);
 					opt->mItems.Push(it);
-					it = new FOptionMenuSliderJoyDeadZone("Dead Zone", i, 0, 0.9, 0.05, 3);
+					it = new DOptionMenuSliderJoyDeadZone("Dead Zone", i, 0, 0.9, 0.05, 3);
 					opt->mItems.Push(it);
 				}
 			}
 			else
 			{
-				it = new FOptionMenuItemStaticText("No configurable axes", false);
+				it = new DOptionMenuItemStaticText("No configurable axes", false);
 				opt->mItems.Push(it);
 			}
 		}
@@ -341,11 +340,7 @@ void UpdateJoystickMenu(IJoystickConfig *selected)
 	if (desc != NULL && (*desc)->mType == MDESC_OptionsMenu)
 	{
 		FOptionMenuDescriptor *opt = (FOptionMenuDescriptor *)*desc;
-		FOptionMenuItem *it;
-		for(unsigned i=0;i<opt->mItems.Size();i++)
-		{
-			delete opt->mItems[i];
-		}
+		DOptionMenuItem *it;
 		opt->mItems.Clear();
 
 		int i;
@@ -369,40 +364,40 @@ void UpdateJoystickMenu(IJoystickConfig *selected)
 		}
 
 		// Todo: Block joystick for changing this one.
-		it = new FOptionMenuItemOption("Enable controller support", "use_joystick", "YesNo", NULL, false);
+		it = new DOptionMenuItemOption("Enable controller support", "use_joystick", "YesNo", NULL, false);
 		opt->mItems.Push(it);
 		#ifdef _WIN32
-			it = new FOptionMenuItemOption("Enable DirectInput controllers", "joy_dinput", "YesNo", NULL, false);
+			it = new DOptionMenuItemOption("Enable DirectInput controllers", "joy_dinput", "YesNo", NULL, false);
 			opt->mItems.Push(it);
-			it = new FOptionMenuItemOption("Enable XInput controllers", "joy_xinput", "YesNo", NULL, false);
+			it = new DOptionMenuItemOption("Enable XInput controllers", "joy_xinput", "YesNo", NULL, false);
 			opt->mItems.Push(it);
-			it = new FOptionMenuItemOption("Enable raw PlayStation 2 adapters", "joy_ps2raw", "YesNo", NULL, false);
+			it = new DOptionMenuItemOption("Enable raw PlayStation 2 adapters", "joy_ps2raw", "YesNo", NULL, false);
 			opt->mItems.Push(it);
 		#endif
 
-		it = new FOptionMenuItemStaticText(" ", false);
+		it = new DOptionMenuItemStaticText(" ", false);
 		opt->mItems.Push(it);
 
 		if (Joysticks.Size() == 0)
 		{
-			it = new FOptionMenuItemStaticText("No controllers detected", false);
+			it = new DOptionMenuItemStaticText("No controllers detected", false);
 			opt->mItems.Push(it);
 			if (!use_joystick)
 			{
-				it = new FOptionMenuItemStaticText("Controller support must be", false);
+				it = new DOptionMenuItemStaticText("Controller support must be", false);
 				opt->mItems.Push(it);
-				it = new FOptionMenuItemStaticText("enabled to detect any", false);
+				it = new DOptionMenuItemStaticText("enabled to detect any", false);
 				opt->mItems.Push(it);
 			}
 		}
 		else
 		{
-			it = new FOptionMenuItemStaticText("Configure controllers:", false);
+			it = new DOptionMenuItemStaticText("Configure controllers:", false);
 			opt->mItems.Push(it);
 
 			for (int i = 0; i < (int)Joysticks.Size(); ++i)
 			{
-				it = new FOptionMenuItemJoyConfigMenu(Joysticks[i]->GetName(), Joysticks[i]);
+				it = new DOptionMenuItemJoyConfigMenu(Joysticks[i]->GetName(), Joysticks[i]);
 				opt->mItems.Push(it);
 				if (i == itemnum) opt->mSelectedItem = opt->mItems.Size();
 			}
diff --git a/src/menu/listmenu.cpp b/src/menu/listmenu.cpp
index 455ea6c4bd..03223b6a7c 100644
--- a/src/menu/listmenu.cpp
+++ b/src/menu/listmenu.cpp
@@ -101,7 +101,7 @@ void DListMenu::Init(DMenu *parent, FListMenuDescriptor *desc)
 //
 //=============================================================================
 
-FListMenuItem *DListMenu::GetItem(FName name)
+DListMenuItem *DListMenu::GetItem(FName name)
 {
 	for(unsigned i=0;i<mDesc->mItems.Size(); i++)
 	{
@@ -274,30 +274,27 @@ void DListMenu::Drawer ()
 // base class for menu items
 //
 //=============================================================================
+IMPLEMENT_CLASS(DListMenuItem, true, false)
 
-FListMenuItem::~FListMenuItem()
-{
-}
-
-bool FListMenuItem::CheckCoordinate(int x, int y)
+bool DListMenuItem::CheckCoordinate(int x, int y)
 {
 	return false;
 }
 
-void FListMenuItem::Ticker()
+void DListMenuItem::Ticker()
 {
 }
 
-void FListMenuItem::Drawer(bool selected)
+void DListMenuItem::Drawer(bool selected)
 {
 }
 
-bool FListMenuItem::Selectable()
+bool DListMenuItem::Selectable()
 {
 	return false;
 }
 
-void FListMenuItem::DrawSelector(int xofs, int yofs, FTextureID tex)
+void DListMenuItem::DrawSelector(int xofs, int yofs, FTextureID tex)
 {
 	if (tex.isNull())
 	{
@@ -318,57 +315,57 @@ void FListMenuItem::DrawSelector(int xofs, int yofs, FTextureID tex)
 	}
 }
 
-bool FListMenuItem::Activate()
+bool DListMenuItem::Activate()
 {
 	return false;	// cannot be activated
 }
 
-FName FListMenuItem::GetAction(int *pparam)
+FName DListMenuItem::GetAction(int *pparam)
 {
 	return mAction;
 }
 
-bool FListMenuItem::SetString(int i, const char *s)
+bool DListMenuItem::SetString(int i, const char *s)
 {
 	return false;
 }
 
-bool FListMenuItem::GetString(int i, char *s, int len)
+bool DListMenuItem::GetString(int i, char *s, int len)
 {
 	return false;
 }
 
-bool FListMenuItem::SetValue(int i, int value)
+bool DListMenuItem::SetValue(int i, int value)
 {
 	return false;
 }
 
-bool FListMenuItem::GetValue(int i, int *pvalue)
+bool DListMenuItem::GetValue(int i, int *pvalue)
 {
 	return false;
 }
 
-void FListMenuItem::Enable(bool on)
+void DListMenuItem::Enable(bool on)
 {
 	mEnabled = on;
 }
 
-bool FListMenuItem::MenuEvent(int mkey, bool fromcontroller)
+bool DListMenuItem::MenuEvent(int mkey, bool fromcontroller)
 {
 	return false;
 }
 
-bool FListMenuItem::MouseEvent(int type, int x, int y)
+bool DListMenuItem::MouseEvent(int type, int x, int y)
 {
 	return false;
 }
 
-bool FListMenuItem::CheckHotkey(int c) 
+bool DListMenuItem::CheckHotkey(int c) 
 { 
 	return false; 
 }
 
-int FListMenuItem::GetWidth() 
+int DListMenuItem::GetWidth() 
 { 
 	return 0; 
 }
@@ -379,15 +376,16 @@ int FListMenuItem::GetWidth()
 // static patch
 //
 //=============================================================================
+IMPLEMENT_CLASS(DListMenuItemStaticPatch, false, false)
 
-FListMenuItemStaticPatch::FListMenuItemStaticPatch(int x, int y, FTextureID patch, bool centered)
-: FListMenuItem(x, y)
+DListMenuItemStaticPatch::DListMenuItemStaticPatch(int x, int y, FTextureID patch, bool centered)
+: DListMenuItem(x, y)
 {
 	mTexture = patch;
 	mCentered = centered;
 }
 	
-void FListMenuItemStaticPatch::Drawer(bool selected)
+void DListMenuItemStaticPatch::Drawer(bool selected)
 {
 	if (!mTexture.Exists())
 	{
@@ -414,21 +412,22 @@ void FListMenuItemStaticPatch::Drawer(bool selected)
 // static text
 //
 //=============================================================================
+IMPLEMENT_CLASS(DListMenuItemStaticText, false, false)
 
-FListMenuItemStaticText::FListMenuItemStaticText(int x, int y, const char *text, FFont *font, EColorRange color, bool centered)
-: FListMenuItem(x, y)
+DListMenuItemStaticText::DListMenuItemStaticText(int x, int y, const char *text, FFont *font, EColorRange color, bool centered)
+: DListMenuItem(x, y)
 {
-	mText = ncopystring(text);
+	mText = text;
 	mFont = font;
 	mColor = color;
 	mCentered = centered;
 }
 	
-void FListMenuItemStaticText::Drawer(bool selected)
+void DListMenuItemStaticText::Drawer(bool selected)
 {
-	const char *text = mText;
-	if (text != NULL)
+	if (mText.IsNotEmpty())
 	{
+		const char *text = mText;
 		if (*text == '$') text = GStrings(text+1);
 		if (mYpos >= 0)
 		{
@@ -445,53 +444,49 @@ void FListMenuItemStaticText::Drawer(bool selected)
 	}
 }
 
-FListMenuItemStaticText::~FListMenuItemStaticText()
-{
-	if (mText != NULL) delete [] mText;
-}
-
 //=============================================================================
 //
 // base class for selectable items
 //
 //=============================================================================
+IMPLEMENT_CLASS(DListMenuItemSelectable, false, false)
 
-FListMenuItemSelectable::FListMenuItemSelectable(int x, int y, int height, FName action, int param)
-: FListMenuItem(x, y, action)
+DListMenuItemSelectable::DListMenuItemSelectable(int x, int y, int height, FName action, int param)
+: DListMenuItem(x, y, action)
 {
 	mHeight = height;
 	mParam = param;
 	mHotkey = 0;
 }
 
-bool FListMenuItemSelectable::CheckCoordinate(int x, int y)
+bool DListMenuItemSelectable::CheckCoordinate(int x, int y)
 {
 	return mEnabled && y >= mYpos && y < mYpos + mHeight;	// no x check here
 }
 
-bool FListMenuItemSelectable::Selectable()
+bool DListMenuItemSelectable::Selectable()
 {
 	return mEnabled;
 }
 
-bool FListMenuItemSelectable::Activate()
+bool DListMenuItemSelectable::Activate()
 {
 	M_SetMenu(mAction, mParam);
 	return true;
 }
 
-FName FListMenuItemSelectable::GetAction(int *pparam)
+FName DListMenuItemSelectable::GetAction(int *pparam)
 {
 	if (pparam != NULL) *pparam = mParam;
 	return mAction;
 }
 
-bool FListMenuItemSelectable::CheckHotkey(int c) 
+bool DListMenuItemSelectable::CheckHotkey(int c) 
 { 
 	return c == tolower(mHotkey); 
 }
 
-bool FListMenuItemSelectable::MouseEvent(int type, int x, int y)
+bool DListMenuItemSelectable::MouseEvent(int type, int x, int y)
 {
 	if (type == DMenu::MOUSE_Release)
 	{
@@ -508,9 +503,10 @@ bool FListMenuItemSelectable::MouseEvent(int type, int x, int y)
 // text item
 //
 //=============================================================================
+IMPLEMENT_CLASS(DListMenuItemText, false, false)
 
-FListMenuItemText::FListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, EColorRange color2, FName child, int param)
-: FListMenuItemSelectable(x, y, height, child, param)
+DListMenuItemText::DListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, EColorRange color2, FName child, int param)
+: DListMenuItemSelectable(x, y, height, child, param)
 {
 	mText = ncopystring(text);
 	mFont = font;
@@ -519,7 +515,7 @@ FListMenuItemText::FListMenuItemText(int x, int y, int height, int hotkey, const
 	mHotkey = hotkey;
 }
 
-FListMenuItemText::~FListMenuItemText()
+void DListMenuItemText::OnDestroy()
 {
 	if (mText != NULL)
 	{
@@ -527,7 +523,7 @@ FListMenuItemText::~FListMenuItemText()
 	}
 }
 
-void FListMenuItemText::Drawer(bool selected)
+void DListMenuItemText::Drawer(bool selected)
 {
 	const char *text = mText;
 	if (text != NULL)
@@ -537,7 +533,7 @@ void FListMenuItemText::Drawer(bool selected)
 	}
 }
 
-int FListMenuItemText::GetWidth() 
+int DListMenuItemText::GetWidth() 
 { 
 	const char *text = mText;
 	if (text != NULL)
@@ -554,20 +550,21 @@ int FListMenuItemText::GetWidth()
 // patch item
 //
 //=============================================================================
+IMPLEMENT_CLASS(DListMenuItemPatch, false, false)
 
-FListMenuItemPatch::FListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param)
-: FListMenuItemSelectable(x, y, height, child, param)
+DListMenuItemPatch::DListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param)
+: DListMenuItemSelectable(x, y, height, child, param)
 {
 	mHotkey = hotkey;
 	mTexture = patch;
 }
 
-void FListMenuItemPatch::Drawer(bool selected)
+void DListMenuItemPatch::Drawer(bool selected)
 {
 	screen->DrawTexture (TexMan(mTexture), mXpos, mYpos, DTA_Clean, true, TAG_DONE);
 }
 
-int FListMenuItemPatch::GetWidth() 
+int DListMenuItemPatch::GetWidth() 
 {
 	return mTexture.isValid() 
 		? TexMan[mTexture]->GetScaledWidth() 
diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp
index a3e7532f99..acec65f902 100644
--- a/src/menu/menu.cpp
+++ b/src/menu/menu.cpp
@@ -85,6 +85,35 @@ static bool		MenuEnabled = true;
 #define KEY_REPEAT_DELAY	(TICRATE*5/12)
 #define KEY_REPEAT_RATE		(3)
 
+//============================================================================
+//
+//
+//
+//============================================================================
+
+size_t FListMenuDescriptor::PropagateMark()
+{
+	for (auto item : mItems) GC::Mark(item);
+	return 0;
+}
+
+size_t FOptionMenuDescriptor::PropagateMark()
+{
+	for (auto item : mItems) GC::Mark(item);
+	return 0;
+}
+
+void M_MarkMenus()
+{
+	MenuDescriptorList::Iterator it(MenuDescriptors);
+	MenuDescriptorList::Pair *pair;
+	while (it.NextPair(pair))
+	{
+		//GC::Mark(pair->Value);	// once the descriptors have been made objects.
+		pair->Value->PropagateMark();
+	}
+	GC::Mark(DMenu::CurrentMenu);
+}
 //============================================================================
 //
 // DMenu base class
diff --git a/src/menu/menu.h b/src/menu/menu.h
index 04ae7e3f7a..24833f280d 100644
--- a/src/menu/menu.h
+++ b/src/menu/menu.h
@@ -89,14 +89,15 @@ struct FMenuDescriptor
 	const PClass *mClass;
 
 	virtual ~FMenuDescriptor() {}
+	virtual size_t PropagateMark() { return 0;  }
 };
 
-class FListMenuItem;
-class FOptionMenuItem;
+class DListMenuItem;
+class DOptionMenuItem;
 
 struct FListMenuDescriptor : public FMenuDescriptor
 {
-	TDeletingArray<FListMenuItem *> mItems;
+	TArray<DListMenuItem *> mItems;
 	int mSelectedItem;
 	int mSelectOfsX;
 	int mSelectOfsY;
@@ -127,6 +128,8 @@ struct FListMenuDescriptor : public FMenuDescriptor
 		mFontColor = CR_UNTRANSLATED;
 		mFontColor2 = CR_UNTRANSLATED;
 	}
+	
+	size_t PropagateMark() override;
 };
 
 struct FOptionMenuSettings
@@ -143,7 +146,7 @@ struct FOptionMenuSettings
 
 struct FOptionMenuDescriptor : public FMenuDescriptor
 {
-	TDeletingArray<FOptionMenuItem *> mItems;
+	TArray<DOptionMenuItem *> mItems;
 	FString mTitle;
 	int mSelectedItem;
 	int mDrawTop;
@@ -154,7 +157,7 @@ struct FOptionMenuDescriptor : public FMenuDescriptor
 	bool mDontDim;
 
 	void CalcIndent();
-	FOptionMenuItem *GetItem(FName name);
+	DOptionMenuItem *GetItem(FName name);
 	void Reset()
 	{
 		// Reset the default settings (ignore all other values in the struct)
@@ -163,7 +166,7 @@ struct FOptionMenuDescriptor : public FMenuDescriptor
 		mIndent = 0;
 		mDontDim = 0;
 	}
-
+	size_t PropagateMark() override;
 };
 						
 
@@ -252,8 +255,9 @@ public:
 //
 //=============================================================================
 
-class FListMenuItem
+class DListMenuItem : public DObject
 {
+	DECLARE_CLASS(DListMenuItem, DObject)
 protected:
 	int mXpos, mYpos;
 	FName mAction;
@@ -261,7 +265,7 @@ protected:
 public:
 	bool mEnabled;
 
-	FListMenuItem(int xpos = 0, int ypos = 0, FName action = NAME_None)
+	DListMenuItem(int xpos = 0, int ypos = 0, FName action = NAME_None)
 	{
 		mXpos = xpos;
 		mYpos = ypos;
@@ -269,8 +273,6 @@ public:
 		mEnabled = true;
 	}
 
-	virtual ~FListMenuItem();
-
 	virtual bool CheckCoordinate(int x, int y);
 	virtual void Ticker();
 	virtual void Drawer(bool selected);
@@ -293,28 +295,31 @@ public:
 	void SetX(int x) { mXpos = x; }
 };	
 
-class FListMenuItemStaticPatch : public FListMenuItem
+class DListMenuItemStaticPatch : public DListMenuItem
 {
+	DECLARE_CLASS(DListMenuItemStaticPatch, DListMenuItem)
 protected:
 	FTextureID mTexture;
 	bool mCentered;
 
+	DListMenuItemStaticPatch() {}
 public:
-	FListMenuItemStaticPatch(int x, int y, FTextureID patch, bool centered);
+	DListMenuItemStaticPatch(int x, int y, FTextureID patch, bool centered);
 	void Drawer(bool selected);
 };
 
-class FListMenuItemStaticText : public FListMenuItem
+class DListMenuItemStaticText : public DListMenuItem
 {
+	DECLARE_CLASS(DListMenuItemStaticText, DListMenuItem)
 protected:
-	const char *mText;
+	FString mText;
 	FFont *mFont;
 	EColorRange mColor;
 	bool mCentered;
 
+	DListMenuItemStaticText() {}
 public:
-	FListMenuItemStaticText(int x, int y, const char *text, FFont *font, EColorRange color, bool centered);
-	~FListMenuItemStaticText();
+	DListMenuItemStaticText(int x, int y, const char *text, FFont *font, EColorRange color, bool centered);
 	void Drawer(bool selected);
 };
 
@@ -324,8 +329,10 @@ public:
 //
 //=============================================================================
 
-class FListMenuItemPlayerDisplay : public FListMenuItem
+class DListMenuItemPlayerDisplay : public DListMenuItem
 {
+	DECLARE_CLASS(DListMenuItemPlayerDisplay, DListMenuItem)
+
 	FListMenuDescriptor *mOwner;
 	FTexture *mBackdrop;
 	FRemapTable mRemap;
@@ -346,6 +353,7 @@ class FListMenuItemPlayerDisplay : public FListMenuItem
 	void UpdateRandomClass();
 	void UpdateTranslation();
 
+	DListMenuItemPlayerDisplay() {}
 public:
 
 	enum
@@ -357,8 +365,8 @@ public:
 		PDF_TRANSLATE = 0x10005,
 	};
 
-	FListMenuItemPlayerDisplay(FListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action);
-	~FListMenuItemPlayerDisplay();
+	DListMenuItemPlayerDisplay(FListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action);
+	void OnDestroy() override;
 	virtual void Ticker();
 	virtual void Drawer(bool selected);
 	bool SetValue(int i, int value);
@@ -371,15 +379,17 @@ public:
 //
 //=============================================================================
 
-class FListMenuItemSelectable : public FListMenuItem
+class DListMenuItemSelectable : public DListMenuItem
 {
+	DECLARE_CLASS(DListMenuItemSelectable, DListMenuItem)
 protected:
 	int mHotkey;
 	int mHeight;
 	int mParam;
 
+	DListMenuItemSelectable() {}
 public:
-	FListMenuItemSelectable(int x, int y, int height, FName childmenu, int mParam = -1);
+	DListMenuItemSelectable(int x, int y, int height, FName childmenu, int mParam = -1);
 	bool CheckCoordinate(int x, int y);
 	bool Selectable();
 	bool CheckHotkey(int c);
@@ -388,24 +398,30 @@ public:
 	FName GetAction(int *pparam);
 };
 
-class FListMenuItemText : public FListMenuItemSelectable
+class DListMenuItemText : public DListMenuItemSelectable
 {
+	DECLARE_CLASS(DListMenuItemText, DListMenuItemSelectable)
 	const char *mText;
 	FFont *mFont;
 	EColorRange mColor;
 	EColorRange mColorSelected;
+
+	DListMenuItemText() {}
 public:
-	FListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, EColorRange color2, FName child, int param = 0);
-	~FListMenuItemText();
+	DListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, EColorRange color2, FName child, int param = 0);
+	void OnDestroy() override;
 	void Drawer(bool selected);
 	int GetWidth();
 };
 
-class FListMenuItemPatch : public FListMenuItemSelectable
+class DListMenuItemPatch : public DListMenuItemSelectable
 {
+	DECLARE_CLASS(DListMenuItemPatch, DListMenuItemSelectable)
 	FTextureID mTexture;
+
+	DListMenuItemPatch() {}
 public:
-	FListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param = 0);
+	DListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param = 0);
 	void Drawer(bool selected);
 	int GetWidth();
 };
@@ -416,8 +432,9 @@ public:
 //
 //=============================================================================
 
-class FPlayerNameBox : public FListMenuItemSelectable
+class DPlayerNameBox : public DListMenuItemSelectable
 {
+	DECLARE_CLASS(DPlayerNameBox, DListMenuItemSelectable)
 	FString mText;
 	FFont *mFont;
 	EColorRange mFontColor;
@@ -428,10 +445,10 @@ class FPlayerNameBox : public FListMenuItemSelectable
 
 	void DrawBorder (int x, int y, int len);
 
+	DPlayerNameBox() {}
 public:
 
-	FPlayerNameBox(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action);
-	~FPlayerNameBox();
+	DPlayerNameBox(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action);
 	bool SetString(int i, const char *s);
 	bool GetString(int i, char *s, int len);
 	void Drawer(bool selected);
@@ -444,8 +461,9 @@ public:
 //
 //=============================================================================
 
-class FValueTextItem : public FListMenuItemSelectable
+class DValueTextItem : public DListMenuItemSelectable
 {
+	DECLARE_CLASS(DValueTextItem, DListMenuItemSelectable)
 	TArray<FString> mSelections;
 	FString mText;
 	int mSelection;
@@ -453,10 +471,10 @@ class FValueTextItem : public FListMenuItemSelectable
 	EColorRange mFontColor;
 	EColorRange mFontColor2;
 
+	DValueTextItem() {}
 public:
 
-	FValueTextItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values);
-	~FValueTextItem();
+	DValueTextItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values);
 	bool SetString(int i, const char *s);
 	bool SetValue(int i, int value);
 	bool GetValue(int i, int *pvalue);
@@ -470,8 +488,9 @@ public:
 //
 //=============================================================================
 
-class FSliderItem : public FListMenuItemSelectable
+class DSliderItem : public DListMenuItemSelectable
 {
+	DECLARE_CLASS(DSliderItem, DListMenuItemSelectable)
 	FString mText;
 	FFont *mFont;
 	EColorRange mFontColor;
@@ -481,10 +500,10 @@ class FSliderItem : public FListMenuItemSelectable
 
 	void DrawSlider (int x, int y);
 
+	DSliderItem() {}
 public:
 
-	FSliderItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step);
-	~FSliderItem();
+	DSliderItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step);
 	bool SetValue(int i, int value);
 	bool GetValue(int i, int *pvalue);
 	bool MenuEvent (int mkey, bool fromcontroller);
@@ -504,22 +523,22 @@ class DListMenu : public DMenu
 
 protected:
 	FListMenuDescriptor *mDesc;
-	FListMenuItem *mFocusControl;
+	DListMenuItem *mFocusControl;
 
 public:
 	DListMenu(DMenu *parent = NULL, FListMenuDescriptor *desc = NULL);
 	virtual void Init(DMenu *parent = NULL, FListMenuDescriptor *desc = NULL);
-	FListMenuItem *GetItem(FName name);
+	DListMenuItem *GetItem(FName name);
 	bool Responder (event_t *ev);
 	bool MenuEvent (int mkey, bool fromcontroller);
 	bool MouseEvent(int type, int x, int y);
 	void Ticker ();
 	void Drawer ();
-	void SetFocus(FListMenuItem *fc)
+	void SetFocus(DListMenuItem *fc)
 	{
 		mFocusControl = fc;
 	}
-	bool CheckFocus(FListMenuItem *fc)
+	bool CheckFocus(DListMenuItem *fc)
 	{
 		return mFocusControl == fc;
 	}
@@ -536,8 +555,9 @@ public:
 //
 //=============================================================================
 
-class FOptionMenuItem : public FListMenuItem
+class DOptionMenuItem : public DListMenuItem
 {
+	DECLARE_ABSTRACT_CLASS(DOptionMenuItem, DListMenuItem)
 protected:
 	FString mLabel;
 	bool mCentered;
@@ -545,14 +565,13 @@ protected:
 	void drawLabel(int indent, int y, EColorRange color, bool grayed = false);
 public:
 
-	FOptionMenuItem(const char *text, FName action = NAME_None, bool center = false)
-		: FListMenuItem(0, 0, action)
+	DOptionMenuItem(const char *text = nullptr, FName action = NAME_None, bool center = false)
+		: DListMenuItem(0, 0, action)
 	{
 		mLabel = text;
 		mCentered = center;
 	}
 
-	~FOptionMenuItem();
 	virtual int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected);
 	virtual bool Selectable();
 	virtual int GetIndent();
@@ -594,13 +613,13 @@ class DOptionMenu : public DMenu
 	bool CanScrollUp;
 	bool CanScrollDown;
 	int VisBottom;
-	FOptionMenuItem *mFocusControl;
+	DOptionMenuItem *mFocusControl;
 
 protected:
 	FOptionMenuDescriptor *mDesc;
 
 public:
-	FOptionMenuItem *GetItem(FName name);
+	DOptionMenuItem *GetItem(FName name);
 	DOptionMenu(DMenu *parent = NULL, FOptionMenuDescriptor *desc = NULL);
 	virtual void Init(DMenu *parent = NULL, FOptionMenuDescriptor *desc = NULL);
 	int FirstSelectable();
@@ -610,11 +629,11 @@ public:
 	void Ticker ();
 	void Drawer ();
 	const FOptionMenuDescriptor *GetDescriptor() const { return mDesc; }
-	void SetFocus(FOptionMenuItem *fc)
+	void SetFocus(DOptionMenuItem *fc)
 	{
 		mFocusControl = fc;
 	}
-	bool CheckFocus(FOptionMenuItem *fc)
+	bool CheckFocus(DOptionMenuItem *fc)
 	{
 		return mFocusControl == fc;
 	}
@@ -682,6 +701,7 @@ void M_StartMessage(const char *message, int messagemode, FName action = NAME_No
 DMenu *StartPickerMenu(DMenu *parent, const char *name, FColorCVar *cvar);
 void M_RefreshModesList ();
 void M_InitVideoModesMenu ();
+void M_MarkMenus();
 
 
 #endif
\ No newline at end of file
diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp
index f684a8babd..a8822470f8 100644
--- a/src/menu/menudef.cpp
+++ b/src/menu/menudef.cpp
@@ -294,7 +294,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
 			sc.MustGetString();
 			FTextureID tex = GetMenuTexture(sc.String);
 
-			FListMenuItem *it = new FListMenuItemStaticPatch(x, y, tex, centered);
+			DListMenuItem *it = new DListMenuItemStaticPatch(x, y, tex, centered);
 			desc->mItems.Push(it);
 		}
 		else if (sc.Compare("StaticText") || sc.Compare("StaticTextCentered"))
@@ -315,7 +315,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
 				cr = V_FindFontColor(sc.String);
 				if (cr == CR_UNTRANSLATED && !sc.Compare("untranslated")) cr = desc->mFontColor;
 			}
-			FListMenuItem *it = new FListMenuItemStaticText(x, y, label, desc->mFont, cr, centered);
+			DListMenuItem *it = new DListMenuItemStaticText(x, y, label, desc->mFont, cr, centered);
 			desc->mItems.Push(it);
 		}
 		else if (sc.Compare("PatchItem"))
@@ -335,7 +335,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
 				param = sc.Number;
 			}
 
-			FListMenuItem *it = new FListMenuItemPatch(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, tex, action, param);
+			DListMenuItem *it = new DListMenuItemPatch(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, tex, action, param);
 			desc->mItems.Push(it);
 			desc->mYpos += desc->mLinespacing;
 			if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1;
@@ -357,7 +357,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
 				param = sc.Number;
 			}
 
-			FListMenuItem *it = new FListMenuItemText(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, param);
+			DListMenuItem *it = new DListMenuItemText(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, param);
 			desc->mItems.Push(it);
 			desc->mYpos += desc->mLinespacing;
 			if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1;
@@ -414,7 +414,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
 					action = sc.String;
 				}
 			}
-			FListMenuItemPlayerDisplay *it = new FListMenuItemPlayerDisplay(desc, x, y, c1, c2, noportrait, action);
+			DListMenuItemPlayerDisplay *it = new DListMenuItemPlayerDisplay(desc, x, y, c1, c2, noportrait, action);
 			desc->mItems.Push(it);
 		}
 		else if (sc.Compare("PlayerNameBox"))
@@ -426,7 +426,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
 			int ofs = sc.Number;
 			sc.MustGetStringName(",");
 			sc.MustGetString();
-			FListMenuItem *it = new FPlayerNameBox(desc->mXpos, desc->mYpos, desc->mLinespacing, ofs, text, desc->mFont, desc->mFontColor, sc.String);
+			DListMenuItem *it = new DPlayerNameBox(desc->mXpos, desc->mYpos, desc->mLinespacing, ofs, text, desc->mFont, desc->mFontColor, sc.String);
 			desc->mItems.Push(it);
 			desc->mYpos += desc->mLinespacing;
 			if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1;
@@ -444,7 +444,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
 				sc.MustGetString();
 				values = sc.String;
 			}
-			FListMenuItem *it = new FValueTextItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, values);
+			DListMenuItem *it = new DValueTextItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, values);
 			desc->mItems.Push(it);
 			desc->mYpos += desc->mLinespacing;
 			if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1;
@@ -465,7 +465,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
 			sc.MustGetStringName(",");
 			sc.MustGetNumber();
 			int step = sc.Number;
-			FListMenuItem *it = new FSliderItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, action, min, max, step);
+			DListMenuItem *it = new DSliderItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, action, min, max, step);
 			desc->mItems.Push(it);
 			desc->mYpos += desc->mLinespacing;
 			if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1;
@@ -739,7 +739,7 @@ static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc)
 			FString label = sc.String;
 			sc.MustGetStringName(",");
 			sc.MustGetString();
-			FOptionMenuItem *it = new FOptionMenuItemSubmenu(label, sc.String);
+			DOptionMenuItem *it = new DOptionMenuItemSubmenu(label, sc.String);
 			desc->mItems.Push(it);
 		}
 		else if (sc.Compare("Option"))
@@ -764,7 +764,7 @@ static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc)
 					center = sc.Number;
 				}
 			}
-			FOptionMenuItem *it = new FOptionMenuItemOption(label, cvar, values, check, center);
+			DOptionMenuItem *it = new DOptionMenuItemOption(label, cvar, values, check, center);
 			desc->mItems.Push(it);
 		}
 		else if (sc.Compare("Command"))
@@ -773,7 +773,7 @@ static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc)
 			FString label = sc.String;
 			sc.MustGetStringName(",");
 			sc.MustGetString();
-			FOptionMenuItem *it = new FOptionMenuItemCommand(label, sc.String);
+			DOptionMenuItem *it = new DOptionMenuItemCommand(label, sc.String);
 			desc->mItems.Push(it);
 		}
 		else if (sc.Compare("SafeCommand"))
@@ -790,7 +790,7 @@ static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc)
 				sc.MustGetString();
 				prompt = sc.String;
 			}
-			FOptionMenuItem *it = new FOptionMenuItemSafeCommand(label, command, prompt);
+			DOptionMenuItem *it = new DOptionMenuItemSafeCommand(label, command, prompt);
 			desc->mItems.Push(it);
 		}
 		else if (sc.Compare("Control") || sc.Compare("MapControl"))
@@ -800,7 +800,7 @@ static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc)
 			FString label = sc.String;
 			sc.MustGetStringName(",");
 			sc.MustGetString();
-			FOptionMenuItem *it = new FOptionMenuItemControl(label, sc.String, map? &AutomapBindings : &Bindings);
+			DOptionMenuItem *it = new DOptionMenuItemControl(label, sc.String, map? &AutomapBindings : &Bindings);
 			desc->mItems.Push(it);
 		}
 		else if (sc.Compare("ColorPicker"))
@@ -809,7 +809,7 @@ static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc)
 			FString label = sc.String;
 			sc.MustGetStringName(",");
 			sc.MustGetString();
-			FOptionMenuItem *it = new FOptionMenuItemColorPicker(label, sc.String);
+			DOptionMenuItem *it = new DOptionMenuItemColorPicker(label, sc.String);
 			desc->mItems.Push(it);
 		}
 		else if (sc.Compare("StaticText"))
@@ -817,7 +817,7 @@ static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc)
 			sc.MustGetString();
 			FString label = sc.String;
 			EColorRange cr = ParseOptionColor(sc, desc);
-			FOptionMenuItem *it = new FOptionMenuItemStaticText(label, cr);
+			DOptionMenuItem *it = new DOptionMenuItemStaticText(label, cr);
 			desc->mItems.Push(it);
 		}
 		else if (sc.Compare("StaticTextSwitchable"))
@@ -831,7 +831,7 @@ static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc)
 			sc.MustGetString();
 			FName action = sc.String;
 			EColorRange cr = ParseOptionColor(sc, desc);
-			FOptionMenuItem *it = new FOptionMenuItemStaticTextSwitchable(label, label2, action, cr);
+			DOptionMenuItem *it = new DOptionMenuItemStaticTextSwitchable(label, label2, action, cr);
 			desc->mItems.Push(it);
 		}
 		else if (sc.Compare("Slider"))
@@ -856,13 +856,13 @@ static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc)
 				sc.MustGetNumber();
 				showvalue = sc.Number;
 			}
-			FOptionMenuItem *it = new FOptionMenuSliderCVar(text, action, min, max, step, showvalue);
+			DOptionMenuItem *it = new DOptionMenuSliderCVar(text, action, min, max, step, showvalue);
 			desc->mItems.Push(it);
 		}
 		else if (sc.Compare("screenresolution"))
 		{
 			sc.MustGetString();
-			FOptionMenuItem *it = new FOptionMenuScreenResolutionLine(sc.String);
+			DOptionMenuItem *it = new DOptionMenuScreenResolutionLine(sc.String);
 			desc->mItems.Push(it);
 		}
 		// [TP] -- Text input widget
@@ -881,7 +881,7 @@ static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc)
 				check = sc.String;
 			}
 
-			FOptionMenuItem* it = new FOptionMenuTextField( label, cvar, check );
+			DOptionMenuItem* it = new DOptionMenuTextField( label, cvar, check );
 			desc->mItems.Push( it );
 		}
 		// [TP] -- Number input widget
@@ -918,7 +918,7 @@ static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc)
 				}
 			}
 
-			FOptionMenuItem* it = new FOptionMenuNumberField( label, cvar,
+			DOptionMenuItem* it = new DOptionMenuNumberField( label, cvar,
 				minimum, maximum, step, check );
 			desc->mItems.Push( it );
 		}
@@ -1081,16 +1081,16 @@ static void BuildEpisodeMenu()
 				ld->mSelectedItem = ld->mItems.Size();
 				for(unsigned i = 0; i < AllEpisodes.Size(); i++)
 				{
-					FListMenuItem *it;
+					DListMenuItem *it;
 					if (AllEpisodes[i].mPicName.IsNotEmpty())
 					{
 						FTextureID tex = GetMenuTexture(AllEpisodes[i].mPicName);
-						it = new FListMenuItemPatch(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, 
+						it = new DListMenuItemPatch(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, 
 							tex, NAME_Skillmenu, i);
 					}
 					else
 					{
-						it = new FListMenuItemText(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, 
+						it = new DListMenuItemText(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, 
 							AllEpisodes[i].mEpisodeName, ld->mFont, ld->mFontColor, ld->mFontColor2, NAME_Skillmenu, i);
 					}
 					ld->mItems.Push(it);
@@ -1123,7 +1123,7 @@ static void BuildEpisodeMenu()
 		od->mDontDim = false;
 		for(unsigned i = 0; i < AllEpisodes.Size(); i++)
 		{
-			FOptionMenuItemSubmenu *it = new FOptionMenuItemSubmenu(AllEpisodes[i].mEpisodeName, "Skillmenu", i);
+			DOptionMenuItemSubmenu *it = new DOptionMenuItemSubmenu(AllEpisodes[i].mEpisodeName, "Skillmenu", i);
 			od->mItems.Push(it);
 		}
 	}
@@ -1179,7 +1179,7 @@ static void BuildPlayerclassMenu()
 			if (numclassitems <= 1)
 			{
 				// create a dummy item that auto-chooses the default class.
-				FListMenuItemText *it = new FListMenuItemText(0, 0, 0, 'p', "player", 
+				DListMenuItemText *it = new DListMenuItemText(0, 0, 0, 'p', "player", 
 					ld->mFont,ld->mFontColor, ld->mFontColor2, NAME_Episodemenu, -1000);
 				ld->mAutoselect = ld->mItems.Push(it);
 				success = true;
@@ -1205,7 +1205,7 @@ static void BuildPlayerclassMenu()
 						const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type);
 						if (pname != NULL)
 						{
-							FListMenuItemText *it = new FListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname,
+							DListMenuItemText *it = new DListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname,
 								pname, ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, i);
 							ld->mItems.Push(it);
 							ld->mYpos += ld->mLinespacing;
@@ -1215,7 +1215,7 @@ static void BuildPlayerclassMenu()
 				}
 				if (n > 1 && !gameinfo.norandomplayerclass)
 				{
-					FListMenuItemText *it = new FListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, 'r',
+					DListMenuItemText *it = new DListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, 'r',
 						"$MNU_RANDOM", ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, -1);
 					ld->mItems.Push(it);
 				}
@@ -1224,7 +1224,7 @@ static void BuildPlayerclassMenu()
 					const char *pname = GetPrintableDisplayName(PlayerClasses[0].Type);
 					if (pname != NULL)
 					{
-						FListMenuItemText *it = new FListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname,
+						DListMenuItemText *it = new DListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname,
 							pname, ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, 0);
 						ld->mItems.Push(it);
 					}
@@ -1259,12 +1259,12 @@ static void BuildPlayerclassMenu()
 				const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type);
 				if (pname != NULL)
 				{
-					FOptionMenuItemSubmenu *it = new FOptionMenuItemSubmenu(pname, "Episodemenu", i);
+					DOptionMenuItemSubmenu *it = new DOptionMenuItemSubmenu(pname, "Episodemenu", i);
 					od->mItems.Push(it);
 				}
 			}
 		}
-		FOptionMenuItemSubmenu *it = new FOptionMenuItemSubmenu("Random", "Episodemenu", -1);
+		DOptionMenuItemSubmenu *it = new DOptionMenuItemSubmenu("Random", "Episodemenu", -1);
 		od->mItems.Push(it);
 	}
 }
@@ -1344,14 +1344,14 @@ static void InitKeySections()
 			for (unsigned i = 0; i < KeySections.Size(); i++)
 			{
 				FKeySection *sect = &KeySections[i];
-				FOptionMenuItem *item = new FOptionMenuItemStaticText(" ", false);
+				DOptionMenuItem *item = new DOptionMenuItemStaticText(" ", false);
 				menu->mItems.Push(item);
-				item = new FOptionMenuItemStaticText(sect->mTitle, true);
+				item = new DOptionMenuItemStaticText(sect->mTitle, true);
 				menu->mItems.Push(item);
 				for (unsigned j = 0; j < sect->mActions.Size(); j++)
 				{
 					FKeyAction *act = &sect->mActions[j];
-					item = new FOptionMenuItemControl(act->mTitle, act->mAction, &Bindings);
+					item = new DOptionMenuItemControl(act->mTitle, act->mAction, &Bindings);
 					menu->mItems.Push(item);
 				}
 			}
@@ -1410,10 +1410,6 @@ void M_StartupSkillMenu(FGameStartup *gs)
 				FName n = ld->mItems[i]->GetAction(NULL);
 				if (n == NAME_Startgame || n == NAME_StartgameConfirm) 
 				{
-					for(unsigned j=i; j<ld->mItems.Size(); j++)
-					{
-						delete ld->mItems[j];
-					}
 					ld->mItems.Resize(i);
 					break;
 				}
@@ -1469,7 +1465,7 @@ void M_StartupSkillMenu(FGameStartup *gs)
 			for(unsigned int i = 0; i < AllSkills.Size(); i++)
 			{
 				FSkillInfo &skill = AllSkills[i];
-				FListMenuItem *li;
+				DListMenuItem *li;
 				// Using a different name for skills that must be confirmed makes handling this easier.
 				FName action = (skill.MustConfirm && !AllEpisodes[gs->Episode].mNoSkill) ?
 					NAME_StartgameConfirm : NAME_Startgame;
@@ -1482,13 +1478,13 @@ void M_StartupSkillMenu(FGameStartup *gs)
 				if (skill.PicName.Len() != 0 && pItemText == NULL)
 				{
 					FTextureID tex = GetMenuTexture(skill.PicName);
-					li = new FListMenuItemPatch(ld->mXpos, y, ld->mLinespacing, skill.Shortcut, tex, action, i);
+					li = new DListMenuItemPatch(ld->mXpos, y, ld->mLinespacing, skill.Shortcut, tex, action, i);
 				}
 				else
 				{
 					EColorRange color = (EColorRange)skill.GetTextColor();
 					if (color == CR_UNTRANSLATED) color = ld->mFontColor;
-					li = new FListMenuItemText(x, y, ld->mLinespacing, skill.Shortcut, 
+					li = new DListMenuItemText(x, y, ld->mLinespacing, skill.Shortcut, 
 									pItemText? *pItemText : skill.MenuName, ld->mFont, color,ld->mFontColor2, action, i);
 				}
 				ld->mItems.Push(li);
@@ -1528,16 +1524,12 @@ fail:
 	else
 	{
 		od = static_cast<FOptionMenuDescriptor*>(*desc);
-		for(unsigned i=0;i<od->mItems.Size(); i++)
-		{
-			delete od->mItems[i];
-		}
 		od->mItems.Clear();
 	}
 	for(unsigned int i = 0; i < AllSkills.Size(); i++)
 	{
 		FSkillInfo &skill = AllSkills[i];
-		FOptionMenuItem *li;
+		DOptionMenuItem *li;
 		// Using a different name for skills that must be confirmed makes handling this easier.
 		const char *action = (skill.MustConfirm && !AllEpisodes[gs->Episode].mNoSkill) ?
 			"StartgameConfirm" : "Startgame";
@@ -1547,7 +1539,7 @@ fail:
 		{
 			pItemText = skill.MenuNamesForPlayerClass.CheckKey(gs->PlayerClass);
 		}
-		li = new FOptionMenuItemSubmenu(pItemText? *pItemText : skill.MenuName, action, i);
+		li = new DOptionMenuItemSubmenu(pItemText? *pItemText : skill.MenuName, action, i);
 		od->mItems.Push(li);
 		if (!done)
 		{
diff --git a/src/menu/optionmenu.cpp b/src/menu/optionmenu.cpp
index f9a29b6f53..f6e129ebca 100644
--- a/src/menu/optionmenu.cpp
+++ b/src/menu/optionmenu.cpp
@@ -124,8 +124,10 @@ int DOptionMenu::FirstSelectable()
 //
 //
 //=============================================================================
+IMPLEMENT_CLASS(DOptionMenuItem, true, false)
 
-FOptionMenuItem *DOptionMenu::GetItem(FName name)
+
+DOptionMenuItem *DOptionMenu::GetItem(FName name)
 {
 	for(unsigned i=0;i<mDesc->mItems.Size(); i++)
 	{
@@ -476,21 +478,17 @@ void DOptionMenu::Drawer ()
 //
 //=============================================================================
 
-FOptionMenuItem::~FOptionMenuItem()
-{
-}
-
-int FOptionMenuItem::Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
+int DOptionMenuItem::Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected)
 {
 	return indent;
 }
 
-bool FOptionMenuItem::Selectable()
+bool DOptionMenuItem::Selectable()
 {
 	return true;
 }
 
-bool FOptionMenuItem::MouseEvent(int type, int x, int y)
+bool DOptionMenuItem::MouseEvent(int type, int x, int y)
 {
 	if (Selectable() && type == DMenu::MOUSE_Release)
 	{
@@ -499,7 +497,7 @@ bool FOptionMenuItem::MouseEvent(int type, int x, int y)
 	return false;
 }
 
-int  FOptionMenuItem::GetIndent()
+int  DOptionMenuItem::GetIndent()
 {
 	if (mCentered)
 	{
@@ -510,7 +508,7 @@ int  FOptionMenuItem::GetIndent()
 	return SmallFont->StringWidth(label);
 }
 
-void FOptionMenuItem::drawLabel(int indent, int y, EColorRange color, bool grayed)
+void DOptionMenuItem::drawLabel(int indent, int y, EColorRange color, bool grayed)
 {
 	const char *label = mLabel.GetChars();
 	if (*label == '$') label = GStrings(label+1);
@@ -545,7 +543,7 @@ void FOptionMenuDescriptor::CalcIndent()
 //
 //=============================================================================
 
-FOptionMenuItem *FOptionMenuDescriptor::GetItem(FName name)
+DOptionMenuItem *FOptionMenuDescriptor::GetItem(FName name)
 {
 	for(unsigned i=0;i<mItems.Size(); i++)
 	{
diff --git a/src/menu/optionmenuitems.h b/src/menu/optionmenuitems.h
index c3cb7297a4..0acaea9ccc 100644
--- a/src/menu/optionmenuitems.h
+++ b/src/menu/optionmenuitems.h
@@ -46,12 +46,16 @@ void M_SetVideoMode();
 //
 //=============================================================================
 
-class FOptionMenuItemSubmenu : public FOptionMenuItem
+class DOptionMenuItemSubmenu : public DOptionMenuItem
 {
+	DECLARE_CLASS(DOptionMenuItemSubmenu, DOptionMenuItem)
+
 	int mParam;
+protected:
+	DOptionMenuItemSubmenu() { }
 public:
-	FOptionMenuItemSubmenu(const char *label, const char *menu, int param = 0)
-		: FOptionMenuItem(label, menu)
+	DOptionMenuItemSubmenu(const char *label, const char *menu, int param = 0)
+		: DOptionMenuItem(label, menu)
 	{
 		mParam = param;
 	}
@@ -70,6 +74,9 @@ public:
 	}
 };
 
+#ifndef NO_IMP
+IMPLEMENT_CLASS(DOptionMenuItemSubmenu, false, false)
+#endif
 
 //=============================================================================
 //
@@ -77,11 +84,14 @@ public:
 //
 //=============================================================================
 
-class FOptionMenuItemCommand : public FOptionMenuItemSubmenu
+class DOptionMenuItemCommand : public DOptionMenuItemSubmenu
 {
+	DECLARE_CLASS(DOptionMenuItemCommand, DOptionMenuItem)
+protected:
+	DOptionMenuItemCommand() { }
 public:
-	FOptionMenuItemCommand(const char *label, const char *menu)
-		: FOptionMenuItemSubmenu(label, menu)
+	DOptionMenuItemCommand(const char *label, const char *menu)
+		: DOptionMenuItemSubmenu(label, menu)
 	{
 	}
 
@@ -94,21 +104,27 @@ public:
 
 };
 
+#ifndef NO_IMP
+IMPLEMENT_CLASS(DOptionMenuItemCommand, false, false)
+#endif
+
 //=============================================================================
 //
 // Executes a CCMD after confirmation, action is a CCMD name
 //
 //=============================================================================
 
-class FOptionMenuItemSafeCommand : public FOptionMenuItemCommand
+class DOptionMenuItemSafeCommand : public DOptionMenuItemCommand
 {
+	DECLARE_CLASS(DOptionMenuItemSafeCommand, DOptionMenuItemCommand)
 	// action is a CCMD
+	DOptionMenuItemSafeCommand() { }
 protected:
 	FString mPrompt;
 
 public:
-	FOptionMenuItemSafeCommand(const char *label, const char *menu, const char *prompt)
-		: FOptionMenuItemCommand(label, menu)
+	DOptionMenuItemSafeCommand(const char *label, const char *menu, const char *prompt)
+		: DOptionMenuItemCommand(label, menu)
 		, mPrompt(prompt)
 	{
 	}
@@ -120,7 +136,7 @@ public:
 			C_DoCommand(mAction);
 			return true;
 		}
-		return FOptionMenuItemCommand::MenuEvent(mkey, fromcontroller);
+		return DOptionMenuItemCommand::MenuEvent(mkey, fromcontroller);
 	}
 
 	bool Activate()
@@ -148,19 +164,26 @@ public:
 	}
 };
 
+#ifndef NO_IMP
+IMPLEMENT_CLASS(DOptionMenuItemSafeCommand, false, false)
+#endif
+
 //=============================================================================
 //
 // Base class for option lists
 //
 //=============================================================================
 
-class FOptionMenuItemOptionBase : public FOptionMenuItem
+class DOptionMenuItemOptionBase : public DOptionMenuItem
 {
+	DECLARE_ABSTRACT_CLASS(DOptionMenuItemOptionBase, DOptionMenuItem)
 protected:
 	// action is a CVAR
 	FName mValues;	// Entry in OptionValues table
 	FBaseCVar *mGrayCheck;
 	int mCenter;
+
+	DOptionMenuItemOptionBase() {}
 public:
 
 	enum
@@ -168,8 +191,8 @@ public:
 		OP_VALUES = 0x11001
 	};
 
-	FOptionMenuItemOptionBase(const char *label, const char *menu, const char *values, const char *graycheck, int center)
-		: FOptionMenuItem(label, menu)
+	DOptionMenuItemOptionBase(const char *label, const char *menu, const char *values, const char *graycheck, int center)
+		: DOptionMenuItem(label, menu)
 	{
 		mValues = values;
 		mGrayCheck = (FBoolCVar*)FindCVar(graycheck, NULL);
@@ -193,8 +216,6 @@ public:
 		return false;
 	}
 
-
-
 	//=============================================================================
 	virtual int GetSelection() = 0;
 	virtual void SetSelection(int Selection) = 0;
@@ -246,14 +267,14 @@ public:
 			}
 			else
 			{
-				return FOptionMenuItem::MenuEvent(mkey, fromcontroller);
+				return DOptionMenuItem::MenuEvent(mkey, fromcontroller);
 			}
 			SetSelection(Selection);
 			S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
 		}
 		else
 		{
-			return FOptionMenuItem::MenuEvent(mkey, fromcontroller);
+			return DOptionMenuItem::MenuEvent(mkey, fromcontroller);
 		}
 		return true;
 	}
@@ -264,20 +285,27 @@ public:
 	}
 };
 
+#ifndef NO_IMP
+IMPLEMENT_CLASS(DOptionMenuItemOptionBase, true, false)
+#endif
+
 //=============================================================================
 //
 // Change a CVAR, action is the CVAR name
 //
 //=============================================================================
 
-class FOptionMenuItemOption : public FOptionMenuItemOptionBase
+class DOptionMenuItemOption : public DOptionMenuItemOptionBase
 {
+	DECLARE_CLASS(DOptionMenuItemOption, DOptionMenuItemOptionBase)
 	// action is a CVAR
 	FBaseCVar *mCVar;
+
+	DOptionMenuItemOption() {}
 public:
 
-	FOptionMenuItemOption(const char *label, const char *menu, const char *values, const char *graycheck, int center)
-		: FOptionMenuItemOptionBase(label, menu, values, graycheck, center)
+	DOptionMenuItemOption(const char *label, const char *menu, const char *values, const char *graycheck, int center)
+		: DOptionMenuItemOptionBase(label, menu, values, graycheck, center)
 	{
 		mCVar = FindCVar(mAction, NULL);
 	}
@@ -338,6 +366,10 @@ public:
 	}
 };
 
+#ifndef NO_IMP
+IMPLEMENT_CLASS(DOptionMenuItemOption, false, false)
+#endif
+
 //=============================================================================
 //
 // This class is used to capture the key to be used as the new key binding
@@ -370,7 +402,7 @@ public:
 		if (mParentMenu->IsKindOf(RUNTIME_CLASS(DOptionMenu)))
 		{
 			DOptionMenu *m = barrier_cast<DOptionMenu*>(mParentMenu);
-			FListMenuItem *it = m->GetItem(NAME_Controlmessage);
+			DListMenuItem *it = m->GetItem(NAME_Controlmessage);
 			if (it != NULL)
 			{
 				it->SetValue(0, which);
@@ -408,15 +440,18 @@ IMPLEMENT_CLASS(DEnterKey, true, false)
 //
 //=============================================================================
 
-class FOptionMenuItemControl : public FOptionMenuItem
+class DOptionMenuItemControl : public DOptionMenuItem
 {
+	DECLARE_CLASS(DOptionMenuItemControl, DOptionMenuItemOption)
 	FKeyBindings *mBindings;
 	int mInput;
 	bool mWaiting;
+
+	DOptionMenuItemControl() {}
 public:
 
-	FOptionMenuItemControl(const char *label, const char *menu, FKeyBindings *bindings)
-		: FOptionMenuItem(label, menu)
+	DOptionMenuItemControl(const char *label, const char *menu, FKeyBindings *bindings)
+		: DOptionMenuItem(label, menu)
 	{
 		mBindings = bindings;
 		mWaiting = false;
@@ -478,24 +513,30 @@ public:
 	}
 };
 
+#ifndef NO_IMP
+IMPLEMENT_CLASS(DOptionMenuItemControl, false, false)
+#endif
 //=============================================================================
 //
 //
 //
 //=============================================================================
 
-class FOptionMenuItemStaticText : public FOptionMenuItem
+class DOptionMenuItemStaticText : public DOptionMenuItem
 {
+	DECLARE_CLASS(DOptionMenuItemStaticText, DOptionMenuItem)
 	EColorRange mColor;
+
+	DOptionMenuItemStaticText() {}
 public:
-	FOptionMenuItemStaticText(const char *label, bool header)
-		: FOptionMenuItem(label, NAME_None, true)
+	DOptionMenuItemStaticText(const char *label, bool header)
+		: DOptionMenuItem(label, NAME_None, true)
 	{
 		mColor = header ? OptionSettings.mFontColorHeader : OptionSettings.mFontColor;
 	}
 
-	FOptionMenuItemStaticText(const char *label, EColorRange cr)
-		: FOptionMenuItem(label, NAME_None, true)
+	DOptionMenuItemStaticText(const char *label, EColorRange cr)
+		: DOptionMenuItem(label, NAME_None, true)
 	{
 		mColor = cr;
 	}
@@ -513,21 +554,27 @@ public:
 
 };
 
+#ifndef NO_IMP
+IMPLEMENT_CLASS(DOptionMenuItemStaticText, false, false)
+#endif
+
 //=============================================================================
 //
 //
 //
 //=============================================================================
 
-class FOptionMenuItemStaticTextSwitchable : public FOptionMenuItem
+class DOptionMenuItemStaticTextSwitchable : public DOptionMenuItem
 {
+	DECLARE_CLASS(DOptionMenuItemStaticTextSwitchable, DOptionMenuItem)
 	EColorRange mColor;
 	FString mAltText;
 	int mCurrent;
 
+	DOptionMenuItemStaticTextSwitchable() {}
 public:
-	FOptionMenuItemStaticTextSwitchable(const char *label, const char *label2, FName action, EColorRange cr)
-		: FOptionMenuItem(label, action, true)
+	DOptionMenuItemStaticTextSwitchable(const char *label, const char *label2, FName action, EColorRange cr)
+		: DOptionMenuItem(label, action, true)
 	{
 		mColor = cr;
 		mAltText = label2;
@@ -570,23 +617,30 @@ public:
 	}
 };
 
+#ifndef NO_IMP
+IMPLEMENT_CLASS(DOptionMenuItemStaticTextSwitchable, false, false)
+#endif
+
 //=============================================================================
 //
 //
 //
 //=============================================================================
 
-class FOptionMenuSliderBase : public FOptionMenuItem
+class DOptionMenuSliderBase : public DOptionMenuItem
 {
+	DECLARE_ABSTRACT_CLASS(DOptionMenuSliderBase, DOptionMenuItem)
 	// action is a CVAR
 	double mMin, mMax, mStep;
 	int mShowValue;
 	int mDrawX;
 	int mSliderShort;
 
+protected:
+	DOptionMenuSliderBase() {}
 public:
-	FOptionMenuSliderBase(const char *label, double min, double max, double step, int showval)
-		: FOptionMenuItem(label, NAME_None)
+	DOptionMenuSliderBase(const char *label, double min, double max, double step, int showval)
+		: DOptionMenuItem(label, NAME_None)
 	{
 		mMin = min;
 		mMax = max;
@@ -669,7 +723,7 @@ public:
 		}
 		else
 		{
-			return FOptionMenuItem::MenuEvent(mkey, fromcontroller);
+			return DOptionMenuItem::MenuEvent(mkey, fromcontroller);
 		}
 		if (fabs(value) < FLT_EPSILON) value = 0;
 		SetSliderValue(clamp(value, mMin, mMax));
@@ -713,18 +767,25 @@ public:
 
 };
 
+#ifndef NO_IMP
+IMPLEMENT_CLASS(DOptionMenuSliderBase, true, false)
+#endif
+
 //=============================================================================
 //
 //
 //
 //=============================================================================
 
-class FOptionMenuSliderCVar : public FOptionMenuSliderBase
+class DOptionMenuSliderCVar : public DOptionMenuSliderBase
 {
+	DECLARE_CLASS(DOptionMenuSliderCVar, DOptionMenuSliderBase)
 	FBaseCVar *mCVar;
+
+	DOptionMenuSliderCVar() {}
 public:
-	FOptionMenuSliderCVar(const char *label, const char *menu, double min, double max, double step, int showval)
-		: FOptionMenuSliderBase(label, min, max, step, showval)
+	DOptionMenuSliderCVar(const char *label, const char *menu, double min, double max, double step, int showval)
+		: DOptionMenuSliderBase(label, min, max, step, showval)
 	{
 		mCVar = FindCVar(menu, NULL);
 	}
@@ -752,19 +813,26 @@ public:
 	}
 };
 
+#ifndef NO_IMP
+IMPLEMENT_CLASS(DOptionMenuSliderCVar, false, false)
+#endif
+
 //=============================================================================
 //
 //
 //
 //=============================================================================
 
-class FOptionMenuSliderVar : public FOptionMenuSliderBase
+class DOptionMenuSliderVar : public DOptionMenuSliderBase
 {
+	DECLARE_CLASS(DOptionMenuSliderVar, DOptionMenuSliderBase)
 	float *mPVal;
+
+	DOptionMenuSliderVar() {}
 public:
 
-	FOptionMenuSliderVar(const char *label, float *pVal, double min, double max, double step, int showval)
-		: FOptionMenuSliderBase(label, min, max, step, showval)
+	DOptionMenuSliderVar(const char *label, float *pVal, double min, double max, double step, int showval)
+		: DOptionMenuSliderBase(label, min, max, step, showval)
 	{
 		mPVal = pVal;
 	}
@@ -780,15 +848,22 @@ public:
 	}
 };
 
+#ifndef NO_IMP
+IMPLEMENT_CLASS(DOptionMenuSliderVar, false, false)
+#endif
+
 //=============================================================================
 //
 // // Edit a key binding, Action is the CCMD to bind
 //
 //=============================================================================
 
-class FOptionMenuItemColorPicker : public FOptionMenuItem
+class DOptionMenuItemColorPicker : public DOptionMenuItem
 {
+	DECLARE_CLASS(DOptionMenuItemColorPicker, DOptionMenuItem)
 	FColorCVar *mCVar;
+
+	DOptionMenuItemColorPicker() {}
 public:
 
 	enum
@@ -796,8 +871,8 @@ public:
 		CPF_RESET = 0x20001,
 	};
 
-	FOptionMenuItemColorPicker(const char *label, const char *menu)
-		: FOptionMenuItem(label, menu)
+	DOptionMenuItemColorPicker(const char *label, const char *menu)
+		: DOptionMenuItem(label, menu)
 	{
 		FBaseCVar *cv = FindCVar(menu, NULL);
 		if (cv != NULL && cv->GetRealType() == CVAR_Color)
@@ -848,12 +923,20 @@ public:
 	}
 };
 
-class FOptionMenuScreenResolutionLine : public FOptionMenuItem
+#ifndef NO_IMP
+IMPLEMENT_CLASS(DOptionMenuItemColorPicker, false, false)
+#endif
+
+class DOptionMenuScreenResolutionLine : public DOptionMenuItem
 {
+	DECLARE_CLASS(DOptionMenuScreenResolutionLine, DOptionMenuItem)
+
 	FString mResTexts[3];
 	int mSelection;
 	int mHighlight;
 	int mMaxValid;
+
+	DOptionMenuScreenResolutionLine() {}
 public:
 
 	enum
@@ -863,8 +946,8 @@ public:
 		SRL_HIGHLIGHT = 0x30004,
 	};
 
-	FOptionMenuScreenResolutionLine(const char *action)
-		: FOptionMenuItem("", action)
+	DOptionMenuScreenResolutionLine(const char *action)
+		: DOptionMenuItem("", action)
 	{
 		mSelection = 0;
 		mHighlight = -1;
@@ -936,7 +1019,7 @@ public:
 		}
 		else 
 		{
-			return FOptionMenuItem::MenuEvent(mkey, fromcontroller);
+			return DOptionMenuItem::MenuEvent(mkey, fromcontroller);
 		}
 		return false;
 	}
@@ -945,7 +1028,7 @@ public:
 	{
 		int colwidth = screen->GetWidth() / 3;
 		mSelection = x / colwidth;
-		return FOptionMenuItem::MouseEvent(type, x, y);
+		return DOptionMenuItem::MouseEvent(type, x, y);
 	}
 
 	bool Activate()
@@ -988,20 +1071,27 @@ public:
 	}
 };
 
+#ifndef NO_IMP
+IMPLEMENT_CLASS(DOptionMenuScreenResolutionLine, false, false)
+#endif
 
 //=============================================================================
 //
-// [TP] FOptionMenuFieldBase
+// [TP] DOptionMenuFieldBase
 //
 // Base class for input fields
 //
 //=============================================================================
 
-class FOptionMenuFieldBase : public FOptionMenuItem
+class DOptionMenuFieldBase : public DOptionMenuItem
 {
+	DECLARE_ABSTRACT_CLASS(DOptionMenuFieldBase, DOptionMenuItem)
+
+protected:
+	DOptionMenuFieldBase() {}
 public:
-	FOptionMenuFieldBase ( const char* label, const char* menu, const char* graycheck ) :
-		FOptionMenuItem ( label, menu ),
+	DOptionMenuFieldBase ( const char* label, const char* menu, const char* graycheck ) :
+		DOptionMenuItem ( label, menu ),
 		mCVar ( FindCVar( mAction, NULL )),
 		mGrayCheck (( graycheck && strlen( graycheck )) ? FindCVar( graycheck, NULL ) : NULL ) {}
 
@@ -1064,19 +1154,26 @@ protected:
 	FBaseCVar* mGrayCheck;
 };
 
+#ifndef NO_IMP
+IMPLEMENT_CLASS(DOptionMenuFieldBase, true, false)
+#endif
+
 //=============================================================================
 //
-// [TP] FOptionMenuTextField
+// [TP] DOptionMenuTextField
 //
 // A text input field widget, for use with string CVars.
 //
 //=============================================================================
 
-class FOptionMenuTextField : public FOptionMenuFieldBase
+class DOptionMenuTextField : public DOptionMenuFieldBase
 {
+	DECLARE_CLASS(DOptionMenuTextField, DOptionMenuFieldBase)
+
+	DOptionMenuTextField() {}
 public:
-	FOptionMenuTextField ( const char *label, const char* menu, const char* graycheck ) :
-		FOptionMenuFieldBase ( label, menu, graycheck ),
+	DOptionMenuTextField ( const char *label, const char* menu, const char* graycheck ) :
+		DOptionMenuFieldBase ( label, menu, graycheck ),
 		mEntering ( false ) {}
 
 	FString Represent()
@@ -1099,7 +1196,7 @@ public:
 			int newindent = screen->GetWidth() - tlen - CURSORSPACE;
 			if (newindent < indent) indent = newindent;
 		}
-		return FOptionMenuFieldBase::Draw(desc, y, indent, selected);
+		return DOptionMenuFieldBase::Draw(desc, y, indent, selected);
 	}
 
 	bool MenuEvent ( int mkey, bool fromcontroller )
@@ -1131,7 +1228,7 @@ public:
 			return true;
 		}
 
-		return FOptionMenuItem::MenuEvent( mkey, fromcontroller );
+		return DOptionMenuItem::MenuEvent( mkey, fromcontroller );
 	}
 
 private:
@@ -1139,21 +1236,28 @@ private:
 	char mEditName[128];
 };
 
+#ifndef NO_IMP
+IMPLEMENT_CLASS(DOptionMenuTextField, false, false)
+#endif
+
 //=============================================================================
 //
-// [TP] FOptionMenuNumberField
+// [TP] DOptionMenuNumberField
 //
 // A numeric input field widget, for use with number CVars where sliders are inappropriate (i.e.
 // where the user is interested in the exact value specifically)
 //
 //=============================================================================
 
-class FOptionMenuNumberField : public FOptionMenuFieldBase
+class DOptionMenuNumberField : public DOptionMenuFieldBase
 {
+	DECLARE_CLASS(DOptionMenuNumberField, DOptionMenuFieldBase)
+
+	DOptionMenuNumberField() {}
 public:
-	FOptionMenuNumberField ( const char *label, const char* menu, float minimum, float maximum,
+	DOptionMenuNumberField ( const char *label, const char* menu, float minimum, float maximum,
 		float step, const char* graycheck )
-		: FOptionMenuFieldBase ( label, menu, graycheck ),
+		: DOptionMenuFieldBase ( label, menu, graycheck ),
 		mMinimum ( minimum ),
 		mMaximum ( maximum ),
 		mStep ( step )
@@ -1186,7 +1290,7 @@ public:
 					value = mMinimum;
 			}
 			else
-				return FOptionMenuItem::MenuEvent( mkey, fromcontroller );
+				return DOptionMenuItem::MenuEvent( mkey, fromcontroller );
 
 			UCVarValue vval;
 			vval.Float = value;
@@ -1202,3 +1306,7 @@ private:
 	float mMaximum;
 	float mStep;
 };
+
+#ifndef NO_IMP
+IMPLEMENT_CLASS(DOptionMenuNumberField, false, false)
+#endif
diff --git a/src/menu/playerdisplay.cpp b/src/menu/playerdisplay.cpp
index c3d11a43a3..bba255bcfd 100644
--- a/src/menu/playerdisplay.cpp
+++ b/src/menu/playerdisplay.cpp
@@ -354,9 +354,10 @@ void FBackdropTexture::Render()
 //
 //
 //=============================================================================
+IMPLEMENT_CLASS(DListMenuItemPlayerDisplay, false, false)
 
-FListMenuItemPlayerDisplay::FListMenuItemPlayerDisplay(FListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action)
-: FListMenuItem(x, y, action)
+DListMenuItemPlayerDisplay::DListMenuItemPlayerDisplay(FListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action)
+: DListMenuItem(x, y, action)
 {
 	mOwner = menu;
 
@@ -388,7 +389,7 @@ FListMenuItemPlayerDisplay::FListMenuItemPlayerDisplay(FListMenuDescriptor *menu
 //
 //=============================================================================
 
-FListMenuItemPlayerDisplay::~FListMenuItemPlayerDisplay()
+void DListMenuItemPlayerDisplay::OnDestroy()
 {
 	delete mBackdrop;
 }
@@ -399,7 +400,7 @@ FListMenuItemPlayerDisplay::~FListMenuItemPlayerDisplay()
 //
 //=============================================================================
 
-void FListMenuItemPlayerDisplay::UpdateRandomClass()
+void DListMenuItemPlayerDisplay::UpdateRandomClass()
 {
 	if (--mRandomTimer < 0)
 	{
@@ -425,7 +426,7 @@ void FListMenuItemPlayerDisplay::UpdateRandomClass()
 //
 //=============================================================================
 
-void FListMenuItemPlayerDisplay::UpdateTranslation()
+void DListMenuItemPlayerDisplay::UpdateTranslation()
 {
 	int PlayerColor = players[consoleplayer].userinfo.GetColor();
 	int	PlayerSkin = players[consoleplayer].userinfo.GetSkin();
@@ -445,7 +446,7 @@ void FListMenuItemPlayerDisplay::UpdateTranslation()
 //
 //=============================================================================
 
-void FListMenuItemPlayerDisplay::SetPlayerClass(int classnum, bool force)
+void DListMenuItemPlayerDisplay::SetPlayerClass(int classnum, bool force)
 {
 	if (classnum < 0 || classnum >= (int)PlayerClasses.Size ())
 	{
@@ -475,7 +476,7 @@ void FListMenuItemPlayerDisplay::SetPlayerClass(int classnum, bool force)
 //
 //=============================================================================
 
-bool FListMenuItemPlayerDisplay::UpdatePlayerClass()
+bool DListMenuItemPlayerDisplay::UpdatePlayerClass()
 {
 	if (mOwner->mSelectedItem >= 0)
 	{
@@ -497,7 +498,7 @@ bool FListMenuItemPlayerDisplay::UpdatePlayerClass()
 //
 //=============================================================================
 
-bool FListMenuItemPlayerDisplay::SetValue(int i, int value)
+bool DListMenuItemPlayerDisplay::SetValue(int i, int value)
 {
 	switch (i)
 	{
@@ -529,7 +530,7 @@ bool FListMenuItemPlayerDisplay::SetValue(int i, int value)
 //
 //=============================================================================
 
-void FListMenuItemPlayerDisplay::Ticker()
+void DListMenuItemPlayerDisplay::Ticker()
 {
 	if (mClassNum < 0) UpdateRandomClass();
 
@@ -549,7 +550,7 @@ void FListMenuItemPlayerDisplay::Ticker()
 //
 //=============================================================================
 
-void FListMenuItemPlayerDisplay::Drawer(bool selected)
+void DListMenuItemPlayerDisplay::Drawer(bool selected)
 {
 	if (mMode == 0 && !UpdatePlayerClass())
 	{
diff --git a/src/menu/playermenu.cpp b/src/menu/playermenu.cpp
index ea22fdd71d..ea2489e9c2 100644
--- a/src/menu/playermenu.cpp
+++ b/src/menu/playermenu.cpp
@@ -60,9 +60,10 @@ EXTERN_CVAR (Bool, cl_run)
 // Player's name
 //
 //=============================================================================
+IMPLEMENT_CLASS(DPlayerNameBox, false, false)
 
-FPlayerNameBox::FPlayerNameBox(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action)
-: FListMenuItemSelectable(x, y, height, action)
+DPlayerNameBox::DPlayerNameBox(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action)
+: DListMenuItemSelectable(x, y, height, action)
 {
 	mText = text;
 	mFont = font;
@@ -72,17 +73,13 @@ FPlayerNameBox::FPlayerNameBox(int x, int y, int height, int frameofs, const cha
 	mEntering = false;
 }
 
-FPlayerNameBox::~FPlayerNameBox()
-{
-}
-
 //=============================================================================
 //
 //
 //
 //=============================================================================
 
-bool FPlayerNameBox::SetString(int i, const char *s)
+bool DPlayerNameBox::SetString(int i, const char *s)
 {
 	if (i == 0)
 	{
@@ -93,7 +90,7 @@ bool FPlayerNameBox::SetString(int i, const char *s)
 	return false;
 }
 
-bool FPlayerNameBox::GetString(int i, char *s, int len)
+bool DPlayerNameBox::GetString(int i, char *s, int len)
 {
 	if (i == 0)
 	{
@@ -110,7 +107,7 @@ bool FPlayerNameBox::GetString(int i, char *s, int len)
 //
 //=============================================================================
 
-void FPlayerNameBox::DrawBorder (int x, int y, int len)
+void DPlayerNameBox::DrawBorder (int x, int y, int len)
 {
 	FTexture *left = TexMan[TexMan.CheckForTexture("M_LSLEFT", FTexture::TEX_MiscPatch)];
 	FTexture *mid = TexMan[TexMan.CheckForTexture("M_LSCNTR", FTexture::TEX_MiscPatch)];
@@ -149,7 +146,7 @@ void FPlayerNameBox::DrawBorder (int x, int y, int len)
 //
 //=============================================================================
 
-void FPlayerNameBox::Drawer(bool selected)
+void DPlayerNameBox::Drawer(bool selected)
 {
 	const char *text = mText;
 	if (text != NULL)
@@ -185,7 +182,7 @@ void FPlayerNameBox::Drawer(bool selected)
 //
 //=============================================================================
 
-bool FPlayerNameBox::MenuEvent(int mkey, bool fromcontroller)
+bool DPlayerNameBox::MenuEvent(int mkey, bool fromcontroller)
 {
 	if (mkey == MKEY_Enter)
 	{
@@ -215,9 +212,10 @@ bool FPlayerNameBox::MenuEvent(int mkey, bool fromcontroller)
 // items for the player menu
 //
 //=============================================================================
+IMPLEMENT_CLASS(DValueTextItem, false, false)
 
-FValueTextItem::FValueTextItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values)
-: FListMenuItemSelectable(x, y, height, action)
+DValueTextItem::DValueTextItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values)
+: DListMenuItemSelectable(x, y, height, action)
 {
 	mText = text;
 	mFont = font;
@@ -237,17 +235,13 @@ FValueTextItem::FValueTextItem(int x, int y, int height, const char *text, FFont
 	}
 }
 
-FValueTextItem::~FValueTextItem()
-{
-}
-
 //=============================================================================
 //
 //
 //
 //=============================================================================
 
-bool FValueTextItem::SetString(int i, const char *s)
+bool DValueTextItem::SetString(int i, const char *s)
 {
 	// should actually use the index...
 	FString str = s;
@@ -262,7 +256,7 @@ bool FValueTextItem::SetString(int i, const char *s)
 //
 //=============================================================================
 
-bool FValueTextItem::SetValue(int i, int value)
+bool DValueTextItem::SetValue(int i, int value)
 {
 	if (i == 0)
 	{
@@ -272,7 +266,7 @@ bool FValueTextItem::SetValue(int i, int value)
 	return false;
 }
 
-bool FValueTextItem::GetValue(int i, int *pvalue)
+bool DValueTextItem::GetValue(int i, int *pvalue)
 {
 	if (i == 0)
 	{
@@ -288,7 +282,7 @@ bool FValueTextItem::GetValue(int i, int *pvalue)
 //
 //=============================================================================
 
-bool FValueTextItem::MenuEvent (int mkey, bool fromcontroller)
+bool DValueTextItem::MenuEvent (int mkey, bool fromcontroller)
 {
 	if (mSelections.Size() > 1)
 	{
@@ -314,7 +308,7 @@ bool FValueTextItem::MenuEvent (int mkey, bool fromcontroller)
 //
 //=============================================================================
 
-void FValueTextItem::Drawer(bool selected)
+void DValueTextItem::Drawer(bool selected)
 {
 	const char *text = mText;
 
@@ -335,9 +329,10 @@ void FValueTextItem::Drawer(bool selected)
 // items for the player menu
 //
 //=============================================================================
+IMPLEMENT_CLASS(DSliderItem, false, false)
 
-FSliderItem::FSliderItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step)
-: FListMenuItemSelectable(x, y, height, action)
+DSliderItem::DSliderItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step)
+: DListMenuItemSelectable(x, y, height, action)
 {
 	mText = text;
 	mFont = font;
@@ -348,17 +343,13 @@ FSliderItem::FSliderItem(int x, int y, int height, const char *text, FFont *font
 	mStep = step;
 }
 
-FSliderItem::~FSliderItem()
-{
-}
-
 //=============================================================================
 //
 //
 //
 //=============================================================================
 
-bool FSliderItem::SetValue(int i, int value)
+bool DSliderItem::SetValue(int i, int value)
 {
 	if (i == 0)
 	{
@@ -368,7 +359,7 @@ bool FSliderItem::SetValue(int i, int value)
 	return false;
 }
 
-bool FSliderItem::GetValue(int i, int *pvalue)
+bool DSliderItem::GetValue(int i, int *pvalue)
 {
 	if (i == 0)
 	{
@@ -384,7 +375,7 @@ bool FSliderItem::GetValue(int i, int *pvalue)
 //
 //=============================================================================
 
-bool FSliderItem::MenuEvent (int mkey, bool fromcontroller)
+bool DSliderItem::MenuEvent (int mkey, bool fromcontroller)
 {
 	if (mkey == MKEY_Left)
 	{
@@ -407,7 +398,7 @@ bool FSliderItem::MenuEvent (int mkey, bool fromcontroller)
 //
 //=============================================================================
 
-bool FSliderItem::MouseEvent(int type, int x, int y)
+bool DSliderItem::MouseEvent(int type, int x, int y)
 {
 	DListMenu *lm = static_cast<DListMenu*>(DMenu::CurrentMenu);
 	if (type != DMenu::MOUSE_Click)
@@ -447,7 +438,7 @@ bool FSliderItem::MouseEvent(int type, int x, int y)
 //
 //=============================================================================
 
-void FSliderItem::DrawSlider (int x, int y)
+void DSliderItem::DrawSlider (int x, int y)
 {
 	int range = mMaxrange - mMinrange;
 	int cur = mSelection - mMinrange;
@@ -473,7 +464,7 @@ void FSliderItem::DrawSlider (int x, int y)
 //
 //=============================================================================
 
-void FSliderItem::Drawer(bool selected)
+void DSliderItem::Drawer(bool selected)
 {
 	const char *text = mText;
 
@@ -508,11 +499,11 @@ class DPlayerMenu : public DListMenu
 	void UpdateTranslation();
 	void SendNewColor (int red, int green, int blue);
 
-	void PlayerNameChanged(FListMenuItem *li);
-	void ColorSetChanged (FListMenuItem *li);
-	void ClassChanged (FListMenuItem *li);
-	void AutoaimChanged (FListMenuItem *li);
-	void SkinChanged (FListMenuItem *li);
+	void PlayerNameChanged(DListMenuItem *li);
+	void ColorSetChanged (DListMenuItem *li);
+	void ClassChanged (DListMenuItem *li);
+	void AutoaimChanged (DListMenuItem *li);
+	void SkinChanged (DListMenuItem *li);
 
 
 public:
@@ -536,7 +527,7 @@ IMPLEMENT_CLASS(DPlayerMenu, false, false)
 
 void DPlayerMenu::Init(DMenu *parent, FListMenuDescriptor *desc)
 {
-	FListMenuItem *li;
+	DListMenuItem *li;
 
 	Super::Init(parent, desc);
 	PickPlayerClass();
@@ -545,14 +536,14 @@ void DPlayerMenu::Init(DMenu *parent, FListMenuDescriptor *desc)
 	li = GetItem(NAME_Playerdisplay);
 	if (li != NULL)
 	{
-		li->SetValue(FListMenuItemPlayerDisplay::PDF_ROTATION, 0);
-		li->SetValue(FListMenuItemPlayerDisplay::PDF_MODE, 1);
-		li->SetValue(FListMenuItemPlayerDisplay::PDF_TRANSLATE, 1);
-		li->SetValue(FListMenuItemPlayerDisplay::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum());
+		li->SetValue(DListMenuItemPlayerDisplay::PDF_ROTATION, 0);
+		li->SetValue(DListMenuItemPlayerDisplay::PDF_MODE, 1);
+		li->SetValue(DListMenuItemPlayerDisplay::PDF_TRANSLATE, 1);
+		li->SetValue(DListMenuItemPlayerDisplay::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum());
 		if (PlayerClass != NULL && !(GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN) &&
 			players[consoleplayer].userinfo.GetPlayerClassNum() != -1)
 		{
-			li->SetValue(FListMenuItemPlayerDisplay::PDF_SKIN, players[consoleplayer].userinfo.GetSkin());
+			li->SetValue(DListMenuItemPlayerDisplay::PDF_SKIN, players[consoleplayer].userinfo.GetSkin());
 		}
 	}
 
@@ -664,10 +655,10 @@ bool DPlayerMenu::Responder (event_t *ev)
 	{
 		// turn the player sprite around
 		mRotation = 8 - mRotation;
-		FListMenuItem *li = GetItem(NAME_Playerdisplay);
+		DListMenuItem *li = GetItem(NAME_Playerdisplay);
 		if (li != NULL)
 		{
-			li->SetValue(FListMenuItemPlayerDisplay::PDF_ROTATION, mRotation);
+			li->SetValue(DListMenuItemPlayerDisplay::PDF_ROTATION, mRotation);
 		}
 		return true;
 	}
@@ -754,7 +745,7 @@ void DPlayerMenu::SendNewColor (int red, int green, int blue)
 
 void DPlayerMenu::UpdateColorsets()
 {
-	FListMenuItem *li = GetItem(NAME_Color);
+	DListMenuItem *li = GetItem(NAME_Color);
 	if (li != NULL)
 	{
 		int sel = 0;
@@ -790,7 +781,7 @@ void DPlayerMenu::UpdateSkins()
 {
 	int sel = 0;
 	int skin;
-	FListMenuItem *li = GetItem(NAME_Skin);
+	DListMenuItem *li = GetItem(NAME_Skin);
 	if (li != NULL)
 	{
 		if (GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN ||
@@ -821,7 +812,7 @@ void DPlayerMenu::UpdateSkins()
 		li = GetItem(NAME_Playerdisplay);
 		if (li != NULL)
 		{
-			li->SetValue(FListMenuItemPlayerDisplay::PDF_SKIN, skin);
+			li->SetValue(DListMenuItemPlayerDisplay::PDF_SKIN, skin);
 		}
 	}
 	UpdateTranslation();
@@ -833,7 +824,7 @@ void DPlayerMenu::UpdateSkins()
 //
 //=============================================================================
 
-void DPlayerMenu::PlayerNameChanged(FListMenuItem *li)
+void DPlayerMenu::PlayerNameChanged(DListMenuItem *li)
 {
 	char pp[MAXPLAYERNAME+1];
 	const char *p;
@@ -861,7 +852,7 @@ void DPlayerMenu::PlayerNameChanged(FListMenuItem *li)
 //
 //=============================================================================
 
-void DPlayerMenu::ColorSetChanged (FListMenuItem *li)
+void DPlayerMenu::ColorSetChanged (DListMenuItem *li)
 {
 	int	sel;
 
@@ -871,9 +862,9 @@ void DPlayerMenu::ColorSetChanged (FListMenuItem *li)
 
 		if (sel > 0) mycolorset = PlayerColorSets[sel-1];
 
-		FListMenuItem *red   = GetItem(NAME_Red);
-		FListMenuItem *green = GetItem(NAME_Green);
-		FListMenuItem *blue  = GetItem(NAME_Blue);
+		DListMenuItem *red   = GetItem(NAME_Red);
+		DListMenuItem *green = GetItem(NAME_Green);
+		DListMenuItem *blue  = GetItem(NAME_Blue);
 
 		// disable the sliders if a valid colorset is selected
 		if (red != NULL) red->Enable(mycolorset == -1);
@@ -894,7 +885,7 @@ void DPlayerMenu::ColorSetChanged (FListMenuItem *li)
 //
 //=============================================================================
 
-void DPlayerMenu::ClassChanged (FListMenuItem *li)
+void DPlayerMenu::ClassChanged (DListMenuItem *li)
 {
 	if (PlayerClasses.Size () == 1)
 	{
@@ -917,7 +908,7 @@ void DPlayerMenu::ClassChanged (FListMenuItem *li)
 		li = GetItem(NAME_Playerdisplay);
 		if (li != NULL)
 		{
-			li->SetValue(FListMenuItemPlayerDisplay::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum());
+			li->SetValue(DListMenuItemPlayerDisplay::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum());
 		}
 	}
 }
@@ -928,7 +919,7 @@ void DPlayerMenu::ClassChanged (FListMenuItem *li)
 //
 //=============================================================================
 
-void DPlayerMenu::SkinChanged (FListMenuItem *li)
+void DPlayerMenu::SkinChanged (DListMenuItem *li)
 {
 	if (GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN ||
 		players[consoleplayer].userinfo.GetPlayerClassNum() == -1)
@@ -948,7 +939,7 @@ void DPlayerMenu::SkinChanged (FListMenuItem *li)
 		li = GetItem(NAME_Playerdisplay);
 		if (li != NULL)
 		{
-			li->SetValue(FListMenuItemPlayerDisplay::PDF_SKIN, sel);
+			li->SetValue(DListMenuItemPlayerDisplay::PDF_SKIN, sel);
 		}
 	}
 }
@@ -959,7 +950,7 @@ void DPlayerMenu::SkinChanged (FListMenuItem *li)
 //
 //=============================================================================
 
-void DPlayerMenu::AutoaimChanged (FListMenuItem *li)
+void DPlayerMenu::AutoaimChanged (DListMenuItem *li)
 {
 	int	sel;
 
@@ -980,7 +971,7 @@ bool DPlayerMenu::MenuEvent (int mkey, bool fromcontroller)
 	int v;
 	if (mDesc->mSelectedItem >= 0)
 	{
-		FListMenuItem *li = mDesc->mItems[mDesc->mSelectedItem];
+		DListMenuItem *li = mDesc->mItems[mDesc->mSelectedItem];
 		if (li->MenuEvent(mkey, fromcontroller))
 		{
 			FName current = li->GetAction(NULL);
@@ -1076,7 +1067,7 @@ bool DPlayerMenu::MenuEvent (int mkey, bool fromcontroller)
 bool DPlayerMenu::MouseEvent(int type, int x, int y)
 {
 	int v;
-	FListMenuItem *li = mFocusControl;
+	DListMenuItem *li = mFocusControl;
 	bool res = Super::MouseEvent(type, x, y);
 	if (li == NULL) li = mFocusControl;
 	if (li != NULL)
diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp
index 29192a60bc..aad6e411a3 100644
--- a/src/menu/videomenu.cpp
+++ b/src/menu/videomenu.cpp
@@ -104,16 +104,16 @@ CUSTOM_CVAR (Bool, vid_tft, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
 	FOptionMenuDescriptor *opt = GetVideoModeMenu();
 	if (opt != NULL)
 	{
-		FOptionMenuItem *it = opt->GetItem("menu_screenratios");
+		DOptionMenuItem *it = opt->GetItem("menu_screenratios");
 		if (it != NULL)
 		{
 			if (self)
 			{
-				it->SetString(FOptionMenuItemOptionBase::OP_VALUES, "RatiosTFT");
+				it->SetString(DOptionMenuItemOptionBase::OP_VALUES, "RatiosTFT");
 			}
 			else
 			{
-				it->SetString(FOptionMenuItemOptionBase::OP_VALUES, "Ratios");
+				it->SetString(DOptionMenuItemOptionBase::OP_VALUES, "Ratios");
 			}
 		}
 	}
@@ -148,9 +148,9 @@ public:
 			mDesc->mSelectedItem < (int)mDesc->mItems.Size())
 		{
 			int sel;
-			bool selected = mDesc->mItems[mDesc->mSelectedItem]->GetValue(FOptionMenuScreenResolutionLine::SRL_SELECTION, &sel);
+			bool selected = mDesc->mItems[mDesc->mSelectedItem]->GetValue(DOptionMenuScreenResolutionLine::SRL_SELECTION, &sel);
 			bool res = Super::MenuEvent(mkey, fromcontroller);
-			if (selected) mDesc->mItems[mDesc->mSelectedItem]->SetValue(FOptionMenuScreenResolutionLine::SRL_SELECTION, sel);
+			if (selected) mDesc->mItems[mDesc->mSelectedItem]->SetValue(DOptionMenuScreenResolutionLine::SRL_SELECTION, sel);
 			return res;
 		}
 		return Super::MenuEvent(mkey, fromcontroller);
@@ -236,10 +236,10 @@ static void BuildModesList (int hiwidth, int hiheight, int hi_bits)
 	{
 		for (i = NAME_res_0; i<= NAME_res_9; i++)
 		{
-			FOptionMenuItem *it = opt->GetItem((ENamedName)i);
+			DOptionMenuItem *it = opt->GetItem((ENamedName)i);
 			if (it != NULL)
 			{
-				it->SetValue(FOptionMenuScreenResolutionLine::SRL_HIGHLIGHT, -1);
+				it->SetValue(DOptionMenuScreenResolutionLine::SRL_HIGHLIGHT, -1);
 				for (c = 0; c < 3; c++)
 				{
 					bool haveMode = false;
@@ -260,16 +260,16 @@ static void BuildModesList (int hiwidth, int hiheight, int hi_bits)
 					{
 						if (width == hiwidth && height == hiheight)
 						{
-							it->SetValue(FOptionMenuScreenResolutionLine::SRL_SELECTION, c);
-							it->SetValue(FOptionMenuScreenResolutionLine::SRL_HIGHLIGHT, c);
+							it->SetValue(DOptionMenuScreenResolutionLine::SRL_SELECTION, c);
+							it->SetValue(DOptionMenuScreenResolutionLine::SRL_HIGHLIGHT, c);
 						}
 						
 						mysnprintf (strtemp, countof(strtemp), "%dx%d%s", width, height, letterbox?TEXTCOLOR_BROWN" LB":"");
-						it->SetString(FOptionMenuScreenResolutionLine::SRL_INDEX+c, strtemp);
+						it->SetString(DOptionMenuScreenResolutionLine::SRL_INDEX+c, strtemp);
 					}
 					else
 					{
-						it->SetString(FOptionMenuScreenResolutionLine::SRL_INDEX+c, "");
+						it->SetString(DOptionMenuScreenResolutionLine::SRL_INDEX+c, "");
 					}
 				}
 			}
@@ -359,12 +359,12 @@ static bool GetSelectedSize (int *width, int *height)
 	{
 		int line = opt->mSelectedItem;
 		int hsel;
-		FOptionMenuItem *it = opt->mItems[line];
-		if (it->GetValue(FOptionMenuScreenResolutionLine::SRL_SELECTION, &hsel))
+		DOptionMenuItem *it = opt->mItems[line];
+		if (it->GetValue(DOptionMenuScreenResolutionLine::SRL_SELECTION, &hsel))
 		{
 			char buffer[32];
 			char *breakpt;
-			if (it->GetString(FOptionMenuScreenResolutionLine::SRL_INDEX+hsel, buffer, sizeof(buffer)))
+			if (it->GetString(DOptionMenuScreenResolutionLine::SRL_INDEX+hsel, buffer, sizeof(buffer)))
 			{
 				*width = (int)strtoll (buffer, &breakpt, 10);
 				*height = (int)strtoll (breakpt+1, NULL, 10);
@@ -423,7 +423,7 @@ static void SetModesMenu (int w, int h, int bits)
 	FOptionMenuDescriptor *opt = GetVideoModeMenu();
 	if (opt != NULL)
 	{
-		FOptionMenuItem *it;
+		DOptionMenuItem *it;
 		if (testingmode <= 1)
 		{
 			it = opt->GetItem(NAME_VMEnterText);