[Bf-blender-cvs] [ee5284f] master: BGE: Dynamically-allocated action layers

Mitchell Stokes noreply at git.blender.org
Thu May 8 05:37:07 CEST 2014


Commit: ee5284faf6db96bb5029f6d2ab0b62336ef84e53
Author: Mitchell Stokes
Date:   Wed May 7 18:14:36 2014 -0700
https://developer.blender.org/rBee5284faf6db96bb5029f6d2ab0b62336ef84e53

BGE: Dynamically-allocated action layers

This patch removes the limitations on the number of action layers in the BGE.

BL_ActionManager currently uses a fixed array to keep track of the action layers. This patch replaces the fixed array with a map which allows for dynamic allocation of action layers. Layers (map items) are automatically removed on BL_ActionManager's update function. The maximum number of layers is roughly the value of a short. Backwards functionality is maintained and there are no changes to the Python API.

Task Discussion:
https://developer.blender.org/T39572

Author: Kevin Ednalino

Reviewers: moguri

Differential Revision: https://developer.blender.org/D491

===================================================================

M	source/blender/makesrna/intern/rna_actuator.c
M	source/gameengine/Converter/BL_ActionActuator.cpp
M	source/gameengine/Ketsji/BL_ActionManager.cpp
M	source/gameengine/Ketsji/BL_ActionManager.h

===================================================================

diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c
index 9880e7d..fd04fb4 100644
--- a/source/blender/makesrna/intern/rna_actuator.c
+++ b/source/blender/makesrna/intern/rna_actuator.c
@@ -661,7 +661,7 @@ static void rna_def_action_actuator(BlenderRNA *brna)
 	RNA_def_property_update(prop, NC_LOGIC, NULL);
 
 	prop = RNA_def_property(srna, "layer", PROP_INT, PROP_NONE);
-	RNA_def_property_range(prop, 0, 7); /* This should match BL_ActionManager::MAX_ACTION_LAYERS - 1 */
+	RNA_def_property_range(prop, 0, 32766); /* This should match BL_ActionManager::MAX_ACTION_LAYERS - 1 */
 	RNA_def_property_ui_text(prop, "Layer", "The animation layer to play the action on");
 	RNA_def_property_update(prop, NC_LOGIC, NULL);
 
diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp
index f8c5ffb..3dd013d 100644
--- a/source/gameengine/Converter/BL_ActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ActionActuator.cpp
@@ -35,6 +35,7 @@
 #include "BL_ArmatureObject.h"
 #include "BL_SkinDeformer.h"
 #include "BL_Action.h"
+#include "BL_ActionManager.h"
 #include "KX_GameObject.h"
 #include "STR_HashedString.h"
 #include "MEM_guardedalloc.h"
@@ -536,7 +537,7 @@ PyAttributeDef BL_ActionActuator::Attributes[] = {
 	KX_PYATTRIBUTE_RW_FUNCTION("action", BL_ActionActuator, pyattr_get_action, pyattr_set_action),
 	KX_PYATTRIBUTE_RO_FUNCTION("channelNames", BL_ActionActuator, pyattr_get_channel_names),
 	KX_PYATTRIBUTE_SHORT_RW("priority", 0, 100, false, BL_ActionActuator, m_priority),
-	KX_PYATTRIBUTE_SHORT_RW("layer", 0, 7, true, BL_ActionActuator, m_layer),
+	KX_PYATTRIBUTE_SHORT_RW("layer", 0, MAX_ACTION_LAYERS-1, true, BL_ActionActuator, m_layer),
 	KX_PYATTRIBUTE_FLOAT_RW("layerWeight", 0, 1.0, BL_ActionActuator, m_layer_weight),
 	KX_PYATTRIBUTE_RW_FUNCTION("frame", BL_ActionActuator, pyattr_get_frame, pyattr_set_frame),
 	KX_PYATTRIBUTE_STRING_RW("propName", 0, MAX_PROP_NAME, false, BL_ActionActuator, m_propname),
diff --git a/source/gameengine/Ketsji/BL_ActionManager.cpp b/source/gameengine/Ketsji/BL_ActionManager.cpp
index 404f276..07adce7 100644
--- a/source/gameengine/Ketsji/BL_ActionManager.cpp
+++ b/source/gameengine/Ketsji/BL_ActionManager.cpp
@@ -24,44 +24,72 @@
  *  \ingroup ketsji
  */
 
-#include "BL_ActionManager.h"
 #include "BL_Action.h"
+#include "BL_ActionManager.h"
 
-BL_ActionManager::BL_ActionManager(class KX_GameObject *obj)
+BL_ActionManager::BL_ActionManager(class KX_GameObject *obj):
+	m_obj(obj)
 {
-	for (int i=0; i<MAX_ACTION_LAYERS; ++i)
-		m_layers[i] = new BL_Action(obj);
 }
 
 BL_ActionManager::~BL_ActionManager()
 {
-	for (int i=0; i<MAX_ACTION_LAYERS; ++i)
-		delete m_layers[i];
+	BL_ActionMap::iterator it;
+
+	for (it = m_layers.begin(); it != m_layers.end(); it++)
+		delete it->second;
+
+	m_layers.clear();
+}
+
+BL_Action *BL_ActionManager::GetAction(short layer)
+{
+	BL_ActionMap::iterator it = m_layers.find(layer);
+
+	return (it != m_layers.end()) ? it->second : 0;
+}
+
+BL_Action* BL_ActionManager::AddAction(short layer)
+{
+	BL_Action *action = new BL_Action(m_obj);
+	m_layers[layer] = action;
+
+	return action;
 }
 
 float BL_ActionManager::GetActionFrame(short layer)
 {
-	return m_layers[layer]->GetFrame();
+	BL_Action *action = GetAction(layer);
+
+	return action ? action->GetFrame() : 0.f;
 }
 
 void BL_ActionManager::SetActionFrame(short layer, float frame)
 {
-	m_layers[layer]->SetFrame(frame);
+	BL_Action *action = GetAction(layer);
+
+	if (action) action->SetFrame(frame);
 }
 
 struct bAction *BL_ActionManager::GetCurrentAction(short layer)
 {
-	return m_layers[layer]->GetAction();
+	BL_Action *action = GetAction(layer);
+
+	return action ? action->GetAction() : 0;
 }
 
 void BL_ActionManager::SetPlayMode(short layer, short mode)
 {
-	m_layers[layer]->SetPlayMode(mode);
+	BL_Action *action = GetAction(layer);
+
+	if (action) action->SetPlayMode(mode);
 }
 
 void BL_ActionManager::SetTimes(short layer, float start, float end)
 {
-	m_layers[layer]->SetTimes(start, end);
+	BL_Action *action = GetAction(layer);
+
+	if (action) action->SetTimes(start, end);
 }
 
 bool BL_ActionManager::PlayAction(const char* name,
@@ -76,40 +104,53 @@ bool BL_ActionManager::PlayAction(const char* name,
 								float playback_speed,
 								short blend_mode)
 {
+	// Only this method will create layer if non-existent
+	BL_Action *action = GetAction(layer);
+	if (!action)
+		action = AddAction(layer);
+
 	// Disable layer blending on the first layer
 	if (layer == 0) layer_weight = -1.f;
 
-	return m_layers[layer]->Play(name, start, end, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed, blend_mode);
+	return action->Play(name, start, end, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed, blend_mode);
 }
 
 void BL_ActionManager::StopAction(short layer)
 {
-	m_layers[layer]->Stop();
+	BL_Action *action = GetAction(layer);
+
+	if (action) action->Stop();
 }
 
 bool BL_ActionManager::IsActionDone(short layer)
 {
-	return m_layers[layer]->IsDone();
+	BL_Action *action = GetAction(layer);
+
+	return action ? action->IsDone() : true;
 }
 
 void BL_ActionManager::Update(float curtime)
 {
-	for (int i=0; i<MAX_ACTION_LAYERS; ++i)
+	BL_ActionMap::iterator it;
+	for (it = m_layers.begin(); it != m_layers.end(); )
 	{
-		if (!m_layers[i]->IsDone())
-		{
-			m_layers[i]->Update(curtime);
+		if (it->second->IsDone()) {
+			delete it->second;
+			m_layers.erase(it++);
+		}
+		else {
+			it->second->Update(curtime);
+			++it;
 		}
 	}
 }
 
 void BL_ActionManager::UpdateIPOs()
 {
-	for (int i=0; i<MAX_ACTION_LAYERS; ++i)
+	BL_ActionMap::iterator it;
+	for (it = m_layers.begin(); it != m_layers.end(); ++it)
 	{
-		if (!m_layers[i]->IsDone())
-		{
-			m_layers[i]->UpdateIPOs();
-		}
+		if (!it->second->IsDone())
+			it->second->UpdateIPOs();
 	}
 }
diff --git a/source/gameengine/Ketsji/BL_ActionManager.h b/source/gameengine/Ketsji/BL_ActionManager.h
index be9097c..5b34025 100644
--- a/source/gameengine/Ketsji/BL_ActionManager.h
+++ b/source/gameengine/Ketsji/BL_ActionManager.h
@@ -31,7 +31,12 @@
 	#include "MEM_guardedalloc.h"
 #endif
 
-#define MAX_ACTION_LAYERS 8
+#include <map>
+
+// Currently, we use the max value of a short.
+// We should switch to unsigned short; doesn't make sense to support negative layers.
+// This will also give us 64k layers instead of 32k.
+#define MAX_ACTION_LAYERS 32767
 
 class BL_Action;
 
@@ -41,7 +46,20 @@ class BL_Action;
 class BL_ActionManager
 {
 private:
-	BL_Action* m_layers[MAX_ACTION_LAYERS];
+	typedef std::map<short,BL_Action*> BL_ActionMap;
+
+	class KX_GameObject* m_obj;
+	BL_ActionMap 		 m_layers;
+
+	/**
+	 * Check if an action exists
+	 */
+	BL_Action* GetAction(short layer);
+
+	/**
+	 * Add new action with given layer
+	 */
+	BL_Action* AddAction(short layer);
 
 public:
 	BL_ActionManager(class KX_GameObject* obj);




More information about the Bf-blender-cvs mailing list