/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include "engines/grim/debug.h"
#include "engines/grim/model.h"
#include "engines/grim/resource.h"
#include "engines/grim/grim.h"
#include "engines/grim/set.h"
#include "engines/grim/gfx_base.h"
#include "engines/grim/colormap.h"
#include "engines/grim/animation.h"
#include "engines/grim/costume/model_component.h"
#include "engines/grim/costume/main_model_component.h"
#include "engines/grim/costume/mesh_component.h"
namespace Grim {
#define DEFAULT_COLORMAP "item.cmp"
ModelComponent::ModelComponent(Component *p, int parentID, const char *filename, Component *prevComponent, tag32 t) :
Component(p, parentID, filename, t),
_obj(nullptr), _hier(nullptr), _animation(nullptr), _animated(false) {
const char *comma = strchr(filename, ',');
// Can be called with a comma and a numeric parameter afterward, but
// the use for this parameter is currently unknown
// Example: At the "scrimshaw parlor" in Rubacava the object
// "manny_cafe.3do,1" is requested
if (comma) {
_name = Common::String(filename, comma);
warning("Comma in model components not supported: %s", filename);
}
_prevComp = prevComponent;
}
ModelComponent::~ModelComponent() {
if (_hier && _hier->_parent) {
_hier->_parent->removeChild(_hier);
}
delete _obj;
delete _animation;
}
void ModelComponent::init() {
if (_prevComp && _prevComp->isComponentType('M','M','D','L')) {
_previousCmap = _prevComp->getCMap();
}
// Skip loading if it was initialized
// by the sharing MainModelComponent
// constructor before
if (!_obj) {
CMapPtr cm = getCMap();
// Get the default colormap if we haven't found
// a valid colormap
if (!cm && g_grim->getCurrSet())
cm = g_grim->getCurrSet()->getCMap();
if (!cm) {
Debug::warning(Debug::Costumes, "No colormap specified for %s, using %s", _name.c_str(), DEFAULT_COLORMAP);
cm = g_resourceloader->getColormap(DEFAULT_COLORMAP);
}
// If we're the child of a mesh component, put our nodes in the
// parent object's tree.
if (_parent) {
MeshComponent *mc = static_cast(_parent);
_obj = g_resourceloader->loadModel(_name, cm, mc->getModel());
_hier = _obj->getHierarchy();
mc->getNode()->addChild(_hier);
} else {
_obj = g_resourceloader->loadModel(_name, cm);
_hier = _obj->getHierarchy();
Debug::warning(Debug::Costumes, "Parent of model %s wasn't a mesh", _name.c_str());
}
// Use parent availability to decide whether to default the
// component to being visible
if (_parent)
setKey(0);
else
setKey(1);
}
if (!_animation) {
_animation = new AnimManager();
}
}
void ModelComponent::setKey(int val) {
_visible = (val != 0);
_hier->_hierVisible = _visible;
}
void ModelComponent::reset() {
_visible = false;
_hier->_hierVisible = _visible;
}
AnimManager *ModelComponent::getAnimManager() const {
return _animation;
}
int ModelComponent::update(uint time) {
// First reset the current animation.
for (int i = 0; i < getNumNodes(); i++) {
_hier[i]._animPos = _hier[i]._pos;
_hier[i]._animRot = _hier[i]._rot;
}
_animated = false;
return 0;
}
void ModelComponent::animate() {
if (_animated) {
return;
}
_animation->animate(_hier, getNumNodes());
_animated = true;
}
void ModelComponent::resetColormap() {
CMap *cm;
cm = getCMap();
if (_obj && cm)
_obj->reload(cm);
}
void ModelComponent::restoreState(SaveGame *state) {
_hier->_hierVisible = _visible;
}
int ModelComponent::getNumNodes() {
return _obj->getNumNodes();
}
void ModelComponent::translateObject(ModelNode *node, bool reset) {
if (node->_parent)
translateObject(node->_parent, reset);
if (reset) {
node->translateViewpointFinish();
} else {
node->translateViewpointStart();
node->translateViewpoint();
}
}
void ModelComponent::translateObject(bool res) {
ModelNode *node = _hier->_parent;
if (node) {
translateObject(node, res);
}
}
void ModelComponent::draw() {
// If the object was drawn by being a component
// of it's parent then don't draw it
if (_parent && _parent->isVisible())
return;
// Need to translate object to be in accordance
// with the setup of the parent
translateObject(false);
_hier->draw();
// Need to un-translate when done
translateObject(true);
}
void ModelComponent::getBoundingBox(int *x1, int *y1, int *x2, int *y2) {
// If the object was drawn by being a component
// of it's parent then don't draw it
if (_parent && _parent->isVisible())
return;
// Need to translate object to be in accordance
// with the setup of the parent
translateObject(false);
_hier->getBoundingBox(x1, y1, x2, y2);
// Need to un-translate when done
translateObject(true);
}
} // end of namespace Grim