diff --git a/TheForceEngine/TFE_Asset/spriteAsset_Jedi.cpp b/TheForceEngine/TFE_Asset/spriteAsset_Jedi.cpp
index 7d536198c..5164325bf 100644
--- a/TheForceEngine/TFE_Asset/spriteAsset_Jedi.cpp
+++ b/TheForceEngine/TFE_Asset/spriteAsset_Jedi.cpp
@@ -391,7 +391,7 @@ namespace TFE_Sprite_Jedi
 		return asset;
 	}
 
-	JediWax* loadWaxFromMemory(const u8* data, size_t size)
+	JediWax* loadWaxFromMemory(const u8* data, size_t size, bool transformOffsets)
 	{
 		const Wax* srcWax = (Wax*)data;
 
@@ -471,8 +471,16 @@ namespace TFE_Sprite_Jedi
 					WaxFrame* dstFrame = (WaxFrame*)((u8*)asset + frameOffset[f]);
 
 					// Some frames are shared between animations, so we need to read from the source, unmodified data.
-					dstFrame->offsetX = round16(mul16(dstAnim->worldWidth, intToFixed16(srcFrame->offsetX)));
-					dstFrame->offsetY = round16(mul16(dstAnim->worldHeight, intToFixed16(srcFrame->offsetY)));
+					if (transformOffsets)
+					{
+						dstFrame->offsetX = round16(mul16(dstAnim->worldWidth, intToFixed16(srcFrame->offsetX)));
+						dstFrame->offsetY = round16(mul16(dstAnim->worldHeight, intToFixed16(srcFrame->offsetY)));
+					}
+					else
+					{
+						dstFrame->offsetX = srcFrame->offsetX;
+						dstFrame->offsetY = srcFrame->offsetY;
+					}
 
 					WaxCell* dstCell = dstFrame->cellOffset ? (WaxCell*)((u8*)asset + dstFrame->cellOffset) : nullptr;
 					if (dstCell)
@@ -503,9 +511,12 @@ namespace TFE_Sprite_Jedi
 							}
 						}
 
-						dstFrame->offsetX = div16(-intToFixed16(dstFrame->offsetX), SPRITE_SCALE_FIXED);
-						const s32 adjOffsetY = mul16(intToFixed16(dstCell->sizeY), dstAnim->worldHeight) + intToFixed16(dstFrame->offsetY);
-						dstFrame->offsetY = div16(adjOffsetY, SPRITE_SCALE_FIXED);
+						if (transformOffsets)
+						{
+							dstFrame->offsetX = div16(-intToFixed16(dstFrame->offsetX), SPRITE_SCALE_FIXED);
+							const s32 adjOffsetY = mul16(intToFixed16(dstCell->sizeY), dstAnim->worldHeight) + intToFixed16(dstFrame->offsetY);
+							dstFrame->offsetY = div16(adjOffsetY, SPRITE_SCALE_FIXED);
+						}
 					}
 				}
 				if (v == 0)
diff --git a/TheForceEngine/TFE_Asset/spriteAsset_Jedi.h b/TheForceEngine/TFE_Asset/spriteAsset_Jedi.h
index 2987737a8..896e9eb05 100644
--- a/TheForceEngine/TFE_Asset/spriteAsset_Jedi.h
+++ b/TheForceEngine/TFE_Asset/spriteAsset_Jedi.h
@@ -96,7 +96,7 @@ namespace TFE_Sprite_Jedi
 	void freeLevelData();
 
 	JediFrame* loadFrameFromMemory(const u8* data, size_t size);
-	JediWax* loadWaxFromMemory(const u8* data, size_t size);
+	JediWax* loadWaxFromMemory(const u8* data, size_t size, bool transformOffsets = true);
 
 	const std::vector<JediWax*>& getWaxList(AssetPool pool = POOL_LEVEL);
 	const std::vector<JediFrame*>& getFrameList(AssetPool pool = POOL_LEVEL);
diff --git a/TheForceEngine/TFE_Editor/assetBrowser.cpp b/TheForceEngine/TFE_Editor/assetBrowser.cpp
index d021c05e9..6eeb91ab4 100644
--- a/TheForceEngine/TFE_Editor/assetBrowser.cpp
+++ b/TheForceEngine/TFE_Editor/assetBrowser.cpp
@@ -366,6 +366,90 @@ namespace AssetBrowser
 				ImGui::Image(TFE_RenderBackend::getGpuPtr(frame->texGpu),
 					ImVec2((f32)texW, (f32)texH), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f));
 			}
+			else if (asset->type == TYPE_SPRITE)
+			{
+				EditorSprite* sprite = (EditorSprite*)getAssetData(asset->handle);
+				ImGui::LabelText("##Dim", "World Dim: %0.3f x %0.3f", sprite->frame[0].widthWS, sprite->frame[0].heightWS);
+				ImGui::LabelText("##AnimCount", "Animation Count: %d", (s32)sprite->anim.size());
+				ImGui::LabelText("##CellCount", "Cell Count: %d", (s32)sprite->cell.size());
+				ImGui::Separator();
+				bool reloadRequired = false;
+				s32 newPaletteIndex = sprite->paletteIndex;
+				listSelectionPalette("Palette", s_palettes, &newPaletteIndex);
+				if (newPaletteIndex != sprite->paletteIndex)
+				{
+					reloadRequired = true;
+				}
+
+				s32 newLightLevel = sprite->lightLevel;
+				if (s_palettes[newPaletteIndex].hasColormap)
+				{
+					ImGui::SliderInt("Light Level", &newLightLevel, 0, 32);
+				}
+				else
+				{
+					newLightLevel = 32;
+				}
+				if (newLightLevel != sprite->lightLevel)
+				{
+					reloadRequired = true;
+				}
+
+				if (reloadRequired)
+				{
+					reloadAsset(asset, newPaletteIndex, newLightLevel);
+					sprite = (EditorSprite*)getAssetData(asset->handle);
+				}
+				ImGui::Separator();
+				if (sprite->anim.size() > 1)
+				{
+					s32 animId = (s32)sprite->animId;
+					if (ImGui::SliderInt("Anim", &animId, 0, (s32)sprite->anim.size() - 1))
+					{
+						sprite->frameId = 0;
+					}
+					sprite->animId = (u8)animId;
+				}
+				const SpriteAnim* anim = &sprite->anim[sprite->animId];
+				if (anim->frameCount > 1)
+				{
+					s32 frameId = (s32)sprite->frameId;
+					ImGui::SliderInt("Frame", &frameId, 0, (s32)anim->frameCount - 1);
+					sprite->frameId = (u8)frameId;
+				}
+				// View
+				{
+					s32 viewId = (s32)sprite->viewId;
+					ImGui::SliderInt("View Angle", &viewId, 0, 31);
+					sprite->viewId = (u8)viewId;
+				}
+				ImGui::Separator();
+				// Get the actual cell...
+				s32 frameIndex = sprite->anim[sprite->animId].views[sprite->viewId].frameIndex[sprite->frameId];
+				SpriteFrame* frame = &sprite->frame[frameIndex];
+				SpriteCell* cell = &sprite->cell[frame->cellIndex];
+
+				s32 texW = cell->w;
+				s32 texH = cell->h;
+				s32 scale = max(1, min(4, s32(w) / (sprite->rect[2] - sprite->rect[0])));
+				texW *= scale;
+				texH *= scale;
+
+				f32 u0 = f32(cell->u) / (f32)sprite->texGpu->getWidth();
+				f32 v1 = f32(cell->v) / (f32)sprite->texGpu->getHeight();
+				f32 u1 = f32(cell->u + cell->w) / (f32)sprite->texGpu->getWidth();
+				f32 v0 = f32(cell->v + cell->h) / (f32)sprite->texGpu->getHeight();
+				if (frame->flip) { std::swap(u0, u1); }
+
+				// Handle the offset.
+				ImVec2 cursor = ImGui::GetCursorPos();
+				cursor.x += f32((frame->offsetX - sprite->rect[0]) * scale);
+				cursor.y += f32((frame->offsetY - sprite->rect[1]) * scale);
+				ImGui::SetCursorPos(cursor);
+
+				ImGui::Image(TFE_RenderBackend::getGpuPtr(sprite->texGpu),
+					ImVec2((f32)texW, (f32)texH), ImVec2(u0, v0), ImVec2(u1, v1));
+			}
 			else if (asset->type == TYPE_PALETTE)
 			{
 				EditorTexture* tex = (EditorTexture*)getAssetData(asset->handle);
@@ -1079,6 +1163,39 @@ namespace AssetBrowser
 		s_viewAssetList.push_back(asset);
 	}
 
+	// Return true if 'str' matches the 'filter', taking into account special symbols.
+	bool editorStringFilter(const char* str, const char* filter, size_t filterLength)
+	{
+		for (size_t i = 0; i < filterLength; i++)
+		{
+			if (filter[i] == '?') { continue; }
+			if (tolower(str[i]) != tolower(filter[i])) { return false; }
+		}
+		return true;
+	}
+
+	// Returns true if it passes the filter.
+	bool editorFilter(const char* name)
+	{
+		// No filter applied.
+		if (s_viewInfo.assetFilter[0] == 0 || s_viewInfo.filterLen == 0) { return true; }
+
+		// Make sure the name is at least as long as the filter.
+		const size_t nameLength = strlen(name);
+		if (nameLength < s_viewInfo.filterLen) { return false; }
+
+		// See if there is a match...
+		const size_t validLength = nameLength - s_viewInfo.filterLen + 1;
+		for (size_t i = 0; i < validLength; i++)
+		{
+			if (editorStringFilter(&name[i], s_viewInfo.assetFilter, s_viewInfo.filterLen))
+			{
+				return true;
+			}
+		}
+		return false;
+	}
+
 	void updateAssetList()
 	{
 		// Only Dark Forces for now.
@@ -1097,7 +1214,8 @@ namespace AssetBrowser
 			const Asset* projAsset = s_projectAssetList[TYPE_TEXTURE].data();
 			for (u32 i = 0; i < count; i++, projAsset++)
 			{
-				if (!isLevelTexture(projAsset->name.c_str())) { continue; }
+				const char* name = projAsset->name.c_str();
+				if (!editorFilter(name) || !isLevelTexture(name)) { continue; }
 				loadAsset(projAsset);
 			}
 		}
@@ -1107,7 +1225,8 @@ namespace AssetBrowser
 			const Asset* projAsset = s_projectAssetList[TYPE_FRAME].data();
 			for (u32 i = 0; i < count; i++, projAsset++)
 			{
-				if (!isLevelFrame(projAsset->name.c_str())) { continue; }
+				const char* name = projAsset->name.c_str();
+				if (!editorFilter(name) || !isLevelFrame(name)) { continue; }
 				loadAsset(projAsset);
 			}
 		}
@@ -1117,7 +1236,8 @@ namespace AssetBrowser
 			const Asset* projAsset = s_projectAssetList[TYPE_SPRITE].data();
 			for (u32 i = 0; i < count; i++, projAsset++)
 			{
-				if (!isLevelSprite(projAsset->name.c_str())) { continue; }
+				const char* name = projAsset->name.c_str();
+				if (!editorFilter(name) || !isLevelSprite(name)) { continue; }
 				loadAsset(projAsset);
 			}
 		}
@@ -1127,7 +1247,8 @@ namespace AssetBrowser
 			const Asset* projAsset = s_projectAssetList[TYPE_PALETTE].data();
 			for (u32 i = 0; i < count; i++, projAsset++)
 			{
-				if (!isLevelPalette(projAsset->name.c_str())) { continue; }
+				const char* name = projAsset->name.c_str();
+				if (!editorFilter(name) || !isLevelPalette(name)) { continue; }
 
 				Archive* archive = getArchive(projAsset->archiveName.c_str(), projAsset->gameId);
 				Asset asset;
diff --git a/TheForceEngine/TFE_Editor/editorSprite.cpp b/TheForceEngine/TFE_Editor/editorSprite.cpp
index c69750a94..f3e91e39d 100644
--- a/TheForceEngine/TFE_Editor/editorSprite.cpp
+++ b/TheForceEngine/TFE_Editor/editorSprite.cpp
@@ -117,11 +117,8 @@ namespace TFE_Editor
 
 		if (type == SPRITE_WAX)
 		{
-			JediWax* wax = TFE_Sprite_Jedi::loadWaxFromMemory(buffer.data(), len);
-			if (!wax)
-			{
-				return -1;
-			}
+			JediWax* wax = TFE_Sprite_Jedi::loadWaxFromMemory(buffer.data(), len, false);
+			if (!wax) { return -1; }
 
 			// Allocate
 			if (id < 0) { id = allocateSprite(filename); }
@@ -134,15 +131,21 @@ namespace TFE_Editor
 			// First gather all of the cells.
 			s_waxDataMap.clear();
 			s_waxDataList.clear();
+
+			outSprite->rect[0] =  INT_MAX;
+			outSprite->rect[1] =  INT_MAX;
+			outSprite->rect[2] = -INT_MAX;
+			outSprite->rect[3] = -INT_MAX;
+
 			for (s32 animId = 0; animId < wax->animCount; animId++)
 			{
 				WaxAnim* anim = WAX_AnimPtr(wax, animId);
 				if (!anim) { continue; }
-
+								
 				SpriteAnim outAnim;
-				outAnim.frameRate = anim->frameRate;
-				outAnim.frameCount = anim->frameCount;
-				outAnim.worldWidth = fixed16ToFloat(anim->worldWidth);
+				outAnim.frameRate   = anim->frameRate;
+				outAnim.frameCount  = anim->frameCount;
+				outAnim.worldWidth  = fixed16ToFloat(anim->worldWidth);
 				outAnim.worldHeight = fixed16ToFloat(anim->worldHeight);
 				for (s32 v = 0; v < WAX_MAX_VIEWS; v++)
 				{
@@ -167,11 +170,16 @@ namespace TFE_Editor
 						SpriteFrame outFrame;
 						outFrame.cellIndex = id;
 						outFrame.flip = frame->flip;
-						outFrame.offsetX = frame->offsetX;
-						outFrame.offsetY = frame->offsetY;
-						outFrame.widthWS = fixed16ToFloat(frame->widthWS);
+						outFrame.offsetX =  frame->offsetX;
+						outFrame.offsetY =  frame->offsetY;
+						outFrame.widthWS  = fixed16ToFloat(frame->widthWS);
 						outFrame.heightWS = fixed16ToFloat(frame->heightWS);
 						outSprite->frame.push_back(outFrame);
+
+						outSprite->rect[0] = min(outSprite->rect[0], frame->offsetX);
+						outSprite->rect[1] = min(outSprite->rect[1], frame->offsetY);
+						outSprite->rect[2] = max(outSprite->rect[2], frame->offsetX + cell->sizeX);
+						outSprite->rect[3] = max(outSprite->rect[3], frame->offsetY + cell->sizeY);
 					}
 				}
 				outSprite->anim.push_back(outAnim);
diff --git a/TheForceEngine/TFE_Editor/editorSprite.h b/TheForceEngine/TFE_Editor/editorSprite.h
index 5561f623c..aaf3be053 100644
--- a/TheForceEngine/TFE_Editor/editorSprite.h
+++ b/TheForceEngine/TFE_Editor/editorSprite.h
@@ -51,9 +51,13 @@ namespace TFE_Editor
 		std::vector<SpriteFrame> frame;
 		std::vector<SpriteCell>  cell;
 
+		s32 rect[4];
+
 		u8   paletteIndex = 0;
 		u8   lightLevel = 32;
-		u8   pad[2];
+		u8   animId = 0;
+		u8   viewId = 0;
+		u32  frameId = 0;
 		char name[64] = "";
 	};
 	enum SpriteSourceType