mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-10-31 15:35:21 +01:00 
			
		
		
		
	Add inventory image animation API (#16538)
This commit is contained in:
		| @@ -10,10 +10,28 @@ | ||||
| #include "itemdef.h" | ||||
| #include "inventory.h" | ||||
| 
 | ||||
| ItemVisualsManager::ItemVisuals::~ItemVisuals() { | ||||
| 	if (wield_mesh.mesh) | ||||
| 		wield_mesh.mesh->drop(); | ||||
| } | ||||
| struct ItemVisualsManager::ItemVisuals | ||||
| { | ||||
| 	ItemMesh item_mesh; | ||||
| 	Palette *palette; | ||||
| 
 | ||||
| 	AnimationInfo inventory_normal; | ||||
| 	AnimationInfo inventory_overlay; | ||||
| 
 | ||||
| 	ItemVisuals() : | ||||
| 		palette(nullptr) | ||||
| 	{} | ||||
| 
 | ||||
| 	~ItemVisuals() | ||||
| 	{ | ||||
| 		inventory_normal.freeFrames(); | ||||
| 		inventory_overlay.freeFrames(); | ||||
| 		if (item_mesh.mesh) | ||||
| 			item_mesh.mesh->drop(); | ||||
| 	} | ||||
| 
 | ||||
| 	DISABLE_CLASS_COPY(ItemVisuals); | ||||
| }; | ||||
| 
 | ||||
| ItemVisualsManager::ItemVisuals *ItemVisualsManager::createItemVisuals( const ItemStack &item, | ||||
| 		Client *client) const | ||||
| @@ -24,13 +42,18 @@ ItemVisualsManager::ItemVisuals *ItemVisualsManager::createItemVisuals( const It | ||||
| 	IItemDefManager *idef = client->idef(); | ||||
| 
 | ||||
| 	const ItemDefinition &def = item.getDefinition(idef); | ||||
| 	std::string inventory_image = item.getInventoryImage(idef); | ||||
| 	std::string inventory_overlay = item.getInventoryOverlay(idef); | ||||
| 	std::string cache_key = def.name; | ||||
| 	if (!inventory_image.empty()) | ||||
| 		cache_key += "/" + inventory_image; | ||||
| 	if (!inventory_overlay.empty()) | ||||
| 		cache_key += ":" + inventory_overlay; | ||||
| 	ItemImageDef inventory_image = item.getInventoryImage(idef); | ||||
| 	ItemImageDef inventory_overlay = item.getInventoryOverlay(idef); | ||||
| 
 | ||||
| 	// Key only consists of item name + image name,
 | ||||
| 	// because animation currently cannot be overridden by meta
 | ||||
| 	std::ostringstream os(def.name); | ||||
| 	if (!inventory_image.name.empty()) | ||||
| 		os << "/" << inventory_image.name; | ||||
| 	if (!inventory_overlay.name.empty()) | ||||
| 		os << ":" << inventory_overlay.name; | ||||
| 	std::string cache_key = os.str(); | ||||
| 
 | ||||
| 
 | ||||
| 	// Skip if already in cache
 | ||||
| 	auto it = m_cached_item_visuals.find(cache_key); | ||||
| @@ -43,36 +66,105 @@ ItemVisualsManager::ItemVisuals *ItemVisualsManager::createItemVisuals( const It | ||||
| 	ITextureSource *tsrc = client->getTextureSource(); | ||||
| 
 | ||||
| 	// Create new ItemVisuals
 | ||||
| 	auto cc = std::make_unique<ItemVisuals>(); | ||||
| 	auto iv = std::make_unique<ItemVisuals>(); | ||||
| 
 | ||||
| 	cc->inventory_texture = NULL; | ||||
| 	if (!inventory_image.empty()) | ||||
| 		cc->inventory_texture = tsrc->getTexture(inventory_image); | ||||
| 	getItemMesh(client, item, &(cc->wield_mesh)); | ||||
| 	auto populate_texture_and_animation = [tsrc]( | ||||
| 			const ItemImageDef &image, | ||||
| 			AnimationInfo &animation) | ||||
| 	{ | ||||
| 		int frame_length_ms = 0; | ||||
| 		auto frames = std::make_unique<std::vector<FrameSpec>>(); | ||||
| 		if (image.name.empty()) { | ||||
| 			// no-op
 | ||||
| 		} else if (image.animation.type == TileAnimationType::TAT_NONE) { | ||||
| 			frames->push_back({0, tsrc->getTexture(image.name)}); | ||||
| 		} else { | ||||
| 			// Animated
 | ||||
| 			// Get inventory texture frames
 | ||||
| 			*frames = createAnimationFrames(tsrc, image.name, image.animation, frame_length_ms); | ||||
| 		} | ||||
| 		animation = AnimationInfo(frames.release(), frame_length_ms); | ||||
| 		// `frames` are freed in `ItemVisuals::~ItemVisuals`
 | ||||
| 	}; | ||||
| 
 | ||||
| 	cc->palette = tsrc->getPalette(def.palette_image); | ||||
| 	populate_texture_and_animation(inventory_image, iv->inventory_normal); | ||||
| 	populate_texture_and_animation(inventory_overlay, iv->inventory_overlay); | ||||
| 
 | ||||
| 	createItemMesh(client, def, | ||||
| 			iv->inventory_normal, | ||||
| 			iv->inventory_overlay, | ||||
| 			&(iv->item_mesh)); | ||||
| 
 | ||||
| 	iv->palette = tsrc->getPalette(def.palette_image); | ||||
| 
 | ||||
| 	// Put in cache
 | ||||
| 	ItemVisuals *ptr = cc.get(); | ||||
| 	m_cached_item_visuals[cache_key] = std::move(cc); | ||||
| 	ItemVisuals *ptr = iv.get(); | ||||
| 	m_cached_item_visuals[cache_key] = std::move(iv); | ||||
| 	return ptr; | ||||
| } | ||||
| 
 | ||||
| video::ITexture* ItemVisualsManager::getInventoryTexture(const ItemStack &item, | ||||
| // Needed because `ItemVisuals` is not known in the header.
 | ||||
| ItemVisualsManager::ItemVisualsManager() | ||||
| { | ||||
| 	m_main_thread = std::this_thread::get_id(); | ||||
| } | ||||
| 
 | ||||
| ItemVisualsManager::~ItemVisualsManager() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void ItemVisualsManager::clear() | ||||
| { | ||||
| 	m_cached_item_visuals.clear(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| video::ITexture *ItemVisualsManager::getInventoryTexture(const ItemStack &item, | ||||
| 		Client *client) const | ||||
| { | ||||
| 	ItemVisuals *iv = createItemVisuals(item, client); | ||||
| 	if (!iv) | ||||
| 		return nullptr; | ||||
| 	return iv->inventory_texture; | ||||
| 
 | ||||
| 	// Texture animation update (if >1 frame)
 | ||||
| 	return iv->inventory_normal.getTexture(client->getAnimationTime()); | ||||
| } | ||||
| 
 | ||||
| ItemMesh* ItemVisualsManager::getWieldMesh(const ItemStack &item, Client *client) const | ||||
| video::ITexture *ItemVisualsManager::getInventoryOverlayTexture(const ItemStack &item, | ||||
| 		Client *client) const | ||||
| { | ||||
| 	ItemVisuals *iv = createItemVisuals(item, client); | ||||
| 	if (!iv) | ||||
| 		return nullptr; | ||||
| 	return &(iv->wield_mesh); | ||||
| 
 | ||||
| 	// Texture animation update (if >1 frame)
 | ||||
| 	return iv->inventory_overlay.getTexture(client->getAnimationTime()); | ||||
| } | ||||
| 
 | ||||
| ItemMesh *ItemVisualsManager::getItemMesh(const ItemStack &item, Client *client) const | ||||
| { | ||||
| 	ItemVisuals *iv = createItemVisuals(item, client); | ||||
| 	return iv ? &(iv->item_mesh) : nullptr; | ||||
| } | ||||
| 
 | ||||
| AnimationInfo *ItemVisualsManager::getInventoryAnimation(const ItemStack &item, | ||||
| 		Client *client) const | ||||
| { | ||||
| 	ItemVisuals *iv = createItemVisuals(item, client); | ||||
| 	if (!iv || iv->inventory_normal.getFrameCount() <= 1) | ||||
| 		return nullptr; | ||||
| 	return &iv->inventory_normal; | ||||
| } | ||||
| 
 | ||||
| // Get item inventory overlay animation
 | ||||
| // returns nullptr if it is not animated
 | ||||
| AnimationInfo *ItemVisualsManager::getInventoryOverlayAnimation(const ItemStack &item, | ||||
| 		Client *client) const | ||||
| { | ||||
| 	ItemVisuals *iv = createItemVisuals(item, client); | ||||
| 	if (!iv || iv->inventory_overlay.getFrameCount() <= 1) | ||||
| 		return nullptr; | ||||
| 	return &iv->inventory_overlay; | ||||
| } | ||||
| 
 | ||||
| Palette* ItemVisualsManager::getPalette(const ItemStack &item, Client *client) const | ||||
|   | ||||
		Reference in New Issue
	
	Block a user