From 953b5b038d4302692386c368d249aef56642697d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Kera=CC=88nen?= Date: Fri, 31 Jul 2015 20:01:12 +0300 Subject: [PATCH] Model Renderer|ClientPlayer: Observe psprite and current weapon changes When the game notifies about current weapon and psprite state changes, ClientPlayer checks that (respectively) if there is a 3D model asset available with the weapon's identifier, and triggers animation sequences. Also started setting up support for ModelRenderer in vispsprite_t. --- doomsday/apps/client/include/clientplayer.h | 2 + doomsday/apps/client/include/def_main.h | 2 +- .../include/render/playerweaponanimator.h | 4 ++ .../apps/client/include/render/vissprite.h | 7 ++++ doomsday/apps/client/src/clientapp.cpp | 10 +++++ doomsday/apps/client/src/clientplayer.cpp | 20 +++++---- doomsday/apps/client/src/def_main.cpp | 2 +- .../apps/client/src/render/mobjanimator.cpp | 5 ++- .../apps/client/src/render/modelrenderer.cpp | 2 +- .../src/render/playerweaponanimator.cpp | 42 +++++++++++++++++++ 10 files changed, 85 insertions(+), 11 deletions(-) diff --git a/doomsday/apps/client/include/clientplayer.h b/doomsday/apps/client/include/clientplayer.h index 3c07b404ba..9fa0ffca6f 100644 --- a/doomsday/apps/client/include/clientplayer.h +++ b/doomsday/apps/client/include/clientplayer.h @@ -93,6 +93,8 @@ class ClientPlayer : public Player */ void setWeaponAssetId(de::String const &id); + void weaponStateChanged(struct state_s const *state); + private: DENG2_PRIVATE(d) }; diff --git a/doomsday/apps/client/include/def_main.h b/doomsday/apps/client/include/def_main.h index 3f947c69bc..b27bc57ab7 100644 --- a/doomsday/apps/client/include/def_main.h +++ b/doomsday/apps/client/include/def_main.h @@ -151,7 +151,7 @@ void Def_PostInit(); */ void Def_Read(); -de::String Def_GetStateName(state_t *state); +de::String Def_GetStateName(state_t const *state); /** * Can we reach 'snew' if we start searching from 'sold'? diff --git a/doomsday/apps/client/include/render/playerweaponanimator.h b/doomsday/apps/client/include/render/playerweaponanimator.h index bfe771e344..0a947e2906 100644 --- a/doomsday/apps/client/include/render/playerweaponanimator.h +++ b/doomsday/apps/client/include/render/playerweaponanimator.h @@ -34,6 +34,10 @@ class PlayerWeaponAnimator public: PlayerWeaponAnimator(ClientPlayer *plr); + void setAsset(de::String const &identifier); + + void stateChanged(state_t const *state); + MobjAnimator &animator(); void advanceTime(de::TimeDelta const &elapsed); diff --git a/doomsday/apps/client/include/render/vissprite.h b/doomsday/apps/client/include/render/vissprite.h index d28ceca39e..b45102aaab 100644 --- a/doomsday/apps/client/include/render/vissprite.h +++ b/doomsday/apps/client/include/render/vissprite.h @@ -22,6 +22,7 @@ #define CLIENT_RENDER_VISSPRITE_H #include +#include #include "render/billboard.h" #include "rend_model.h" @@ -188,6 +189,12 @@ struct vispsprite_t de::dfloat yawAngleOffset; de::dfloat inter; ///< Frame interpolation, 0..1 } model; + struct vispsprite_model2_s { + de::ModelDrawable const *drawable; + de::ModelDrawable::Animator const *animator; + float modelTransform[16]; + de::gl::Cull cullFace; + } model2; } data; }; diff --git a/doomsday/apps/client/src/clientapp.cpp b/doomsday/apps/client/src/clientapp.cpp index e3e7962f53..97edefc8e9 100644 --- a/doomsday/apps/client/src/clientapp.cpp +++ b/doomsday/apps/client/src/clientapp.cpp @@ -255,6 +255,16 @@ DENG2_PIMPL(ClientApp) DownloadDialog::showCompletedDownload(); break; + case DD_NOTIFY_PSPRITE_STATE_CHANGED: + if(data) + { + auto const *args = (ddnotify_psprite_state_changed_t *) data; + self.players().at(args->player) + .as() + .weaponStateChanged(args->state); + } + break; + case DD_NOTIFY_PLAYER_WEAPON_CHANGED: if(data) { diff --git a/doomsday/apps/client/src/clientplayer.cpp b/doomsday/apps/client/src/clientplayer.cpp index 9bb1326f7e..05c31a6a5d 100644 --- a/doomsday/apps/client/src/clientplayer.cpp +++ b/doomsday/apps/client/src/clientplayer.cpp @@ -30,6 +30,7 @@ DENG2_PIMPL(ClientPlayer) clplayerstate_t clPlayerState; DemoTimer demoTimer; + state_t const *lastPSpriteState = nullptr; String weaponAssetId; Instance(Public *i) @@ -40,12 +41,6 @@ DENG2_PIMPL(ClientPlayer) zap(clPlayerState); zap(demoTimer); } - - void prepareAssets() - { - // Is there a model for the weapon? - qDebug() << "-=- looking for" << "model.weapon." + weaponAssetId; - } }; ClientPlayer::ClientPlayer() @@ -106,7 +101,18 @@ void ClientPlayer::setWeaponAssetId(String const &id) { if(id != d->weaponAssetId) { + LOG_WIP("weapon asset: %s") << id; d->weaponAssetId = id; - d->prepareAssets(); + d->playerWeaponAnimator.setAsset("model.weapon." + id); + d->playerWeaponAnimator.stateChanged(d->lastPSpriteState); + } +} + +void ClientPlayer::weaponStateChanged(state_t const *state) +{ + if(state != d->lastPSpriteState) + { + d->lastPSpriteState = state; + d->playerWeaponAnimator.stateChanged(state); } } diff --git a/doomsday/apps/client/src/def_main.cpp b/doomsday/apps/client/src/def_main.cpp index 3ab3df11ff..d6669481d8 100644 --- a/doomsday/apps/client/src/def_main.cpp +++ b/doomsday/apps/client/src/def_main.cpp @@ -1636,7 +1636,7 @@ bool Def_SameStateSequence(state_t *snew, state_t *sold) return false; } -String Def_GetStateName(state_t *state) +String Def_GetStateName(state_t const *state) { if(!state) return "(nullptr)"; dint const idx = ::runtimeDefs.states.indexOf(state); diff --git a/doomsday/apps/client/src/render/mobjanimator.cpp b/doomsday/apps/client/src/render/mobjanimator.cpp index ad5d881c2d..439a607271 100644 --- a/doomsday/apps/client/src/render/mobjanimator.cpp +++ b/doomsday/apps/client/src/render/mobjanimator.cpp @@ -39,6 +39,8 @@ void MobjAnimator::triggerByState(String const &stateName) auto found = _stateAnims->constFind(stateName); if(found == _stateAnims->constEnd()) return; + LOG_WIP("triggerByState: ") << stateName; + foreach(ModelRenderer::AnimSequence const &seq, found.value()) { // Test for the probability of this animation. @@ -58,7 +60,8 @@ void MobjAnimator::triggerByState(String const &stateName) start(animId, node); - qDebug() << "starting" << seq.name; + LOG_WIP(" Starting anim: " _E(b)) << seq.name; + break; } } diff --git a/doomsday/apps/client/src/render/modelrenderer.cpp b/doomsday/apps/client/src/render/modelrenderer.cpp index e49c558632..458a253c2b 100644 --- a/doomsday/apps/client/src/render/modelrenderer.cpp +++ b/doomsday/apps/client/src/render/modelrenderer.cpp @@ -352,7 +352,7 @@ void ModelRenderer::render(vissprite_t const &spr) Matrix4f localMat = Matrix4f::rotate(-90 + (spr.pose.viewAligned? spr.pose.yawAngleOffset : - spr.pose.yaw), + spr.pose.yaw), Vector3f(0, 1, 0) /* vertical axis for yaw */); gl::Cull culling = gl::Back; diff --git a/doomsday/apps/client/src/render/playerweaponanimator.cpp b/doomsday/apps/client/src/render/playerweaponanimator.cpp index effb477f50..734f866dcd 100644 --- a/doomsday/apps/client/src/render/playerweaponanimator.cpp +++ b/doomsday/apps/client/src/render/playerweaponanimator.cpp @@ -19,6 +19,7 @@ #include "render/playerweaponanimator.h" #include "render/mobjanimator.h" #include "clientplayer.h" +#include "clientapp.h" using namespace de; @@ -26,16 +27,57 @@ DENG2_PIMPL_NOREF(PlayerWeaponAnimator) { ClientPlayer *player; std::unique_ptr animator; + Matrix4f transform; + gl::Cull cullFace; Instance(ClientPlayer *plr) : player(plr) {} + + void setupAsset(String const &identifier) + { + // Is there a model for the weapon? + if(modelBank().has(identifier)) + { + // Prepare the animation state of the model. + ModelBank::ModelWithData loaded = modelBank().modelAndData(identifier); + ModelDrawable &model = *loaded.first; + animator.reset(new MobjAnimator(identifier, model)); + + // The basic transformation of the model. + auto const &aux = loaded.second->as(); + cullFace = aux.cull; + transform = aux.transformation; + } + else + { + animator.reset(); + } + } + + static ModelBank &modelBank() + { + return ClientApp::renderSystem().modelRenderer().bank(); + } }; PlayerWeaponAnimator::PlayerWeaponAnimator(ClientPlayer *plr) : d(new Instance(plr)) {} +void PlayerWeaponAnimator::setAsset(String const &identifier) +{ + d->setupAsset(identifier); +} + +void PlayerWeaponAnimator::stateChanged(state_t const *state) +{ + if(d->animator) + { + d->animator->triggerByState(Def_GetStateName(state)); + } +} + MobjAnimator &PlayerWeaponAnimator::animator() { DENG2_ASSERT(bool(d->animator));