Skip to content

Commit

Permalink
Refactor|Resources: ResourceSystem has ownership of animation groups
Browse files Browse the repository at this point in the history
  • Loading branch information
danij-deng committed Nov 16, 2013
1 parent ffeee15 commit ac65261
Show file tree
Hide file tree
Showing 8 changed files with 282 additions and 169 deletions.
151 changes: 112 additions & 39 deletions doomsday/client/include/resource/animgroups.h
@@ -1,8 +1,7 @@
/**
* @file animgroups.h (Material) Animation groups.
/** @file animgroups.h Material animation group.
*
* @author Copyright &copy; 2003-2013 Jaakko Keränen <jaakko.keranen@iki.fi>
* @author Copyright &copy; 2005-2013 Daniel Swanson <danij@dengine.net>
* @authors Copyright © 2003-2013 Jaakko Keränen <jaakko.keranen@iki.fi>
* @authors Copyright © 2005-2013 Daniel Swanson <danij@dengine.net>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
Expand All @@ -19,52 +18,126 @@
* 02110-1301 USA</small>
*/

#ifndef LIBDENG_RESOURCE_ANIMGROUPS_H
#define LIBDENG_RESOURCE_ANIMGROUPS_H
#ifndef DENG_RESOURCE_ANIMATIONGROUP_H
#define DENG_RESOURCE_ANIMATIONGROUP_H

#include "Texture"
#include "dd_types.h"
#include "TextureManifest"
#include <QList>

#ifdef __cplusplus
extern "C" {
#endif
namespace de {

/**
* (Material) Animation group frame.
* Material Animation group.
*
* @ingroup resource
*/
typedef struct animframe_s
class AnimGroup
{
void *textureManifest;
ushort tics;
ushort randomTics;
} animframe_t;
public:
/**
* A single frame in the animation.
*/
struct Frame
{
public:
/**
* Returns the texture manifest for the frame.
*/
TextureManifest &textureManifest() const;

/**
* (Material) Animation group.
* @ingroup resource
*/
typedef struct animgroup_s
{
int id;
int flags;
int count;
animframe_t *frames;
} animgroup_t;
/**
* Returns the duration of the frame in tics.
*/
ushort tics() const;

/**
* Returns the additional duration of the frame tics.
*/
ushort randomTics() const;

friend class AnimGroup;

private:
Frame(TextureManifest &textureManifest, ushort tics, ushort randomTics);

TextureManifest *_textureManifest;
ushort _tics;
ushort _randomTics;
};

typedef QList<Frame *> Frames;

public:
/**
* Construct a new animation group.
*
* @param uniqueId Unique identifier to associate with the group.
* @param flags @ref animationGroupFlags
*/
AnimGroup(int uniqueId, int flags = 0);

/**
* Returns the unique identifier associated with the animation.
*/
int id() const;

/**
* @return @ref animationGroupFlags
*/
int flags() const;

/**
* Returns @c true iff at least one frame in the animation uses the specified
* @a textureManifest
*
* @see frames()
*/
bool hasFrameFor(TextureManifest const &textureManifest) const;

/**
* Append a new frame to the animation.
*
* @param texture Manifest for the texture to use during the frame.
* @param tics Duration of the frame in tics.
* @param randomTics Random duration of the frame in tics.
*
* @return The new frame.
*/
Frame &newFrame(TextureManifest &textureManifest, ushort tics,
ushort randomTics = 0);

/**
* Clear all frames in the animation.
*/
void clearAllFrames();

/**
* Returns the total number of frames in the animation.
*/
inline int frameCount() const { return allFrames().count(); }

/// @return Number of animation/precache groups.
int R_AnimGroupCount(void);
/**
* Convenient method of returning a frame in the animation by @a index.
* It is assumed that the index is within valid [0..frameCount) range.
*
* @see frameCount()
*/
inline Frame &frame(int index) const { return *allFrames().at(index); }

/// To be called to destroy all animation groups when they are no longer needed.
void R_ClearAnimGroups(void);
/**
* Provides access to the frame list for efficient traversal.
*
* @see frame()
*/
Frames const &allFrames() const;

/// @return AnimGroup associated with @a animGroupNum else @c NULL
animgroup_t const *R_ToAnimGroup(int animGroupNum);
private:
DENG2_PRIVATE(d)
};

/// @return @c true iff @a texture is linked to the identified @a animGroupNum.
boolean R_IsTextureInAnimGroup(Uri const *texture, int animGroupNum);
typedef AnimGroup::Frame AnimGroupFrame;

#ifdef __cplusplus
} // extern "C"
#endif
} // namespace de

#endif /* LIBDENG_RESOURCE_ANIMGROUPS_H */
#endif // DENG_RESOURCE_ANIMATIONGROUP_H
23 changes: 23 additions & 0 deletions doomsday/client/include/resource/resourcesystem.h
Expand Up @@ -21,6 +21,7 @@

#include "def_data.h"
#include "resourceclass.h"
#include "resource/animgroups.h"
#ifdef __CLIENT__
# include "Fonts"
#endif
Expand Down Expand Up @@ -133,6 +134,28 @@ class ResourceSystem : public de::System

#endif

/**
* Returns the total number of animation/precache groups.
*/
int animGroupCount();

/**
* Destroys all the animation groups.
*/
void clearAllAnimGroups();

/**
* Returns the AnimGroup associated with @a index; otherwise @c 0.
*/
de::AnimGroup *animGroup(int index);

/**
* Construct a new animation group.
*
* @param flags @ref animationGroupFlags
*/
de::AnimGroup &newAnimGroup(int flags);

public: /// @todo Should be private:
void initCompositeTextures();
void initFlatTextures();
Expand Down
2 changes: 1 addition & 1 deletion doomsday/client/src/dd_main.cpp
Expand Up @@ -1410,7 +1410,7 @@ bool App_ChangeGame(Game &game, bool allowReload)
B_BindDefaults();
B_InitialContextActivations();
#endif
R_ClearAnimGroups();
App_ResourceSystem().clearAllAnimGroups();

// Reset the world back to it's initial state (unload the map, reset players, etc...).
App_World().reset();
Expand Down
49 changes: 21 additions & 28 deletions doomsday/client/src/def_main.cpp
Expand Up @@ -920,22 +920,16 @@ static void readAllDefinitions()
LOG_INFO(String("readAllDefinitions: Completed in %1 seconds.").arg(begunAt.since(), 0, 'g', 2));
}

static animgroup_t const *findAnimGroupForTexture(TextureManifest &manifest)
static AnimGroup const *findAnimGroupForTexture(TextureManifest &textureManifest)
{
// Group ids are 1-based.
// Search backwards to allow patching.
for(int i = R_AnimGroupCount(); i > 0; i--)
for(int i = App_ResourceSystem().animGroupCount(); i > 0; i--)
{
animgroup_t const *anim = R_ToAnimGroup(i);
for(int j = 0; j < anim->count; ++j)
AnimGroup *animGroup = App_ResourceSystem().animGroup(i);
if(animGroup->hasFrameFor(textureManifest))
{
animframe_t const *frame = &anim->frames[j];
if(!frame->textureManifest) continue;

if(&manifest == frame->textureManifest)
{
return anim;
}
return animGroup;
}
}
return 0; // Not found.
Expand Down Expand Up @@ -999,47 +993,46 @@ static void generateMaterialDefForTexture(TextureManifest &manifest)
st->texture = reinterpret_cast<uri_s *>(new de::Uri(texUri));

// Is there an animation for this?
animgroup_t const *anim = findAnimGroupForTexture(manifest);
if(anim && anim->count > 1)
AnimGroup const *anim = findAnimGroupForTexture(manifest);
if(anim && anim->frameCount() > 1)
{
animframe_t const *animFrame;
AnimGroupFrame const *animFrame;

// Determine the start frame.
int startFrame = 0;
while(anim->frames[startFrame].textureManifest != &manifest)
while(&anim->frame(startFrame).textureManifest() != &manifest)
{
startFrame++;
}

// Just animate the first in the sequence?
if(startFrame && (anim->flags & AGF_FIRST_ONLY))
if(startFrame && (anim->flags() & AGF_FIRST_ONLY))
return;

// Complete configuration of the first stage.
animFrame = &anim->frames[startFrame];
st->tics = animFrame->tics + animFrame->randomTics;
if(animFrame->randomTics)
animFrame = &anim->frame(startFrame);
st->tics = animFrame->tics() + animFrame->randomTics();
if(animFrame->randomTics())
{
st->variance = animFrame->randomTics / float( st->tics );
st->variance = animFrame->randomTics() / float( st->tics );
}

// Add further stages according to the animation group.
startFrame++;
for(int i = 0; i < anim->count - 1; ++i)
for(int i = 0; i < anim->frameCount() - 1; ++i)
{
int frame = de::wrap(startFrame + i, 0, anim->count);
int frame = de::wrap(startFrame + i, 0, anim->frameCount());

animFrame = &anim->frames[frame];
if(!animFrame->textureManifest) continue;
TextureManifest &frameManifest = *reinterpret_cast<TextureManifest *>(animFrame->textureManifest);
animFrame = &anim->frame(frame);
TextureManifest &frameManifest = animFrame->textureManifest();

int layerIdx = DED_AddMaterialLayerStage(&mat->layers[0]);
ded_material_layer_stage_t *st = &mat->layers[0].stages[layerIdx];
st->texture = reinterpret_cast<uri_s *>(new de::Uri(frameManifest.composeUrn()));
st->tics = animFrame->tics + animFrame->randomTics;
if(animFrame->randomTics)
st->tics = animFrame->tics() + animFrame->randomTics();
if(animFrame->randomTics())
{
st->variance = animFrame->randomTics / float( st->tics );
st->variance = animFrame->randomTics() / float( st->tics );
}
}
}
Expand Down
1 change: 0 additions & 1 deletion doomsday/client/src/render/r_main.cpp
Expand Up @@ -581,7 +581,6 @@ void R_Update()

void R_Shutdown()
{
R_ClearAnimGroups();
R_ShutdownSprites();
Models_Shutdown();
R_ShutdownSvgs();
Expand Down

0 comments on commit ac65261

Please sign in to comment.