Initial commit
This commit is contained in:
463
engines/wintermute/ext/wme_shadowmanager.cpp
Normal file
463
engines/wintermute/ext/wme_shadowmanager.cpp
Normal file
@@ -0,0 +1,463 @@
|
||||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "engines/metaengine.h"
|
||||
#include "engines/wintermute/wintermute.h"
|
||||
#include "engines/wintermute/base/base_game.h"
|
||||
#include "engines/wintermute/base/base_engine.h"
|
||||
#include "engines/wintermute/base/scriptables/script_stack.h"
|
||||
#include "engines/wintermute/base/scriptables/script_value.h"
|
||||
#include "engines/wintermute/base/gfx/3dlight.h"
|
||||
#include "engines/wintermute/ad/ad_game.h"
|
||||
#include "engines/wintermute/ad/ad_scene.h"
|
||||
#include "engines/wintermute/ad/ad_scene_geometry.h"
|
||||
#include "engines/wintermute/ad/ad_actor_3dx.h"
|
||||
#include "engines/wintermute/ext/wme_shadowmanager.h"
|
||||
#include "engines/wintermute/ext/plugin_event.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
IMPLEMENT_PERSISTENT(SXShadowManager, false)
|
||||
|
||||
BaseScriptable *makeSXShadowManager(BaseGame *inGame, ScStack *stack) {
|
||||
return new SXShadowManager(inGame, stack);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXShadowManager::SXShadowManager(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
|
||||
stack->correctParams(0);
|
||||
|
||||
PluginEventEntry event;
|
||||
event._type = WME_EVENT_UPDATE;
|
||||
event._callback = callback;
|
||||
event._plugin = this;
|
||||
_game->pluginEvents().subscribeEvent(event);
|
||||
|
||||
_defaultLightPos = DXVector3(1.0f, 200.0f, 1.0f);
|
||||
_minShadow = 0.1f;
|
||||
_maxShadow = 1.0f;
|
||||
_useSmartShadows = false;
|
||||
_shadowColor = 0x80000000;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXShadowManager::~SXShadowManager() {
|
||||
PluginEventEntry event;
|
||||
event._type = WME_EVENT_UPDATE;
|
||||
event._callback = callback;
|
||||
event._plugin = this;
|
||||
_game->pluginEvents().unsubscribeEvent(event);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char *SXShadowManager::scToString() {
|
||||
return "[shadowmanager object]";
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXShadowManager::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Run()
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Run") == 0) {
|
||||
stack->correctParams(0);
|
||||
|
||||
run();
|
||||
|
||||
stack->pushBool(true);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Stop()
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Stop") == 0) {
|
||||
stack->correctParams(0);
|
||||
|
||||
stop();
|
||||
|
||||
stack->pushBool(true);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AddActor(string)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "AddActor") == 0) {
|
||||
stack->correctParams(1);
|
||||
|
||||
AdObject *obj = (AdObject *)stack->pop()->getNative();
|
||||
if (obj) {
|
||||
if (strcmp(obj->scGetProperty("Type")->getString(), "actor3dx") == 0) {
|
||||
AdActor3DX *actor = (AdActor3DX *)obj;
|
||||
stack->pushBool(addActor(actor));
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// RemoveActor(string)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "RemoveActor") == 0) {
|
||||
stack->correctParams(1);
|
||||
|
||||
// nothing todo
|
||||
|
||||
stack->pushBool(true);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// RemoveAllActors()
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "RemoveAllActors") == 0) {
|
||||
stack->correctParams(0);
|
||||
|
||||
stack->pushBool(removeAllActors());
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetNumLights()
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "GetNumLights") == 0) {
|
||||
stack->correctParams(0);
|
||||
|
||||
// nothing todo
|
||||
|
||||
stack->pushInt(0);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetLightInfo()
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "GetLightInfo") == 0) {
|
||||
stack->correctParams(1);
|
||||
|
||||
// nothing todo
|
||||
|
||||
stack->pushBool(true);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetDefaultLightPos(float, float, float)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "SetDefaultLightPos") == 0) {
|
||||
stack->correctParams(3);
|
||||
|
||||
_defaultLightPos._x = stack->pop()->getFloat();
|
||||
_defaultLightPos._y = stack->pop()->getFloat();
|
||||
_defaultLightPos._z = stack->pop()->getFloat();
|
||||
|
||||
stack->pushBool(true);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EnableLight(string)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "EnableLight") == 0) {
|
||||
stack->correctParams(1);
|
||||
const char *lightName = stack->pop()->getString();
|
||||
|
||||
stack->pushBool(enableLight(lightName));
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// DisableLight(string)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "DisableLight") == 0) {
|
||||
stack->correctParams(1);
|
||||
const char *lightName = stack->pop()->getString();
|
||||
|
||||
stack->pushBool(disableLight(lightName));
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
stack->pushNULL();
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScValue *SXShadowManager::scGetProperty(const char *name) {
|
||||
_scValue->setNULL();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// DefaultLightPos
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "DefaultLightPos") == 0) {
|
||||
_scValue->setProperty("x", _defaultLightPos._x);
|
||||
_scValue->setProperty("y", _defaultLightPos._y);
|
||||
_scValue->setProperty("z", _defaultLightPos._z);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// DefaultLightPosX
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "DefaultLightPosX") == 0) {
|
||||
_scValue->setFloat(_defaultLightPos._x);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// DefaultLightPosY
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "DefaultLightPosY") == 0) {
|
||||
_scValue->setFloat(_defaultLightPos._y);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// DefaultLightPosZ
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "DefaultLightPosZ") == 0) {
|
||||
_scValue->setFloat(_defaultLightPos._z);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MinShadow
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "MinShadow") == 0) {
|
||||
_scValue->setFloat(_minShadow);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MaxShadow
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "MaxShadow") == 0) {
|
||||
_scValue->setFloat(_maxShadow);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// UseSmartShadows
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "UseSmartShadows") == 0) {
|
||||
_scValue->setBool(_useSmartShadows);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXShadowManager::scSetProperty(const char *name, ScValue *value) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// DefaultLightPos
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "DefaultLightPos") == 0) {
|
||||
_defaultLightPos._x = value->getProp("x")->getFloat();
|
||||
_defaultLightPos._y = value->getProp("y")->getFloat();
|
||||
_defaultLightPos._z = value->getProp("z")->getFloat();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// DefaultLightPosX
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "DefaultLightPosX") == 0) {
|
||||
_defaultLightPos._x = value->getFloat();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// DefaultLightPosY
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "DefaultLightPosY") == 0) {
|
||||
_defaultLightPos._y = value->getFloat();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// DefaultLightPosZ
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "DefaultLightPosZ") == 0) {
|
||||
_defaultLightPos._z = value->getFloat();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MinShadow
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "MinShadow") == 0) {
|
||||
_minShadow = value->getFloat();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MaxShadow
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "MaxShadow") == 0) {
|
||||
_maxShadow = value->getFloat();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// UseSmartShadows
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "UseSmartShadows") == 0) {
|
||||
_useSmartShadows = value->getBool();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXShadowManager::persist(BasePersistenceManager *persistMgr) {
|
||||
BaseScriptable::persist(persistMgr);
|
||||
|
||||
if (!persistMgr->getIsSaving()) {
|
||||
PluginEventEntry event;
|
||||
event._type = WME_EVENT_UPDATE;
|
||||
event._callback = callback;
|
||||
event._plugin = this;
|
||||
_game->pluginEvents().subscribeEvent(event);
|
||||
|
||||
// Actor and light lists is not get restored, plugin is not designed to work this way.
|
||||
// Lists get refreshed by game script on scene change.
|
||||
_actors.clear();
|
||||
_lights.clear();
|
||||
}
|
||||
|
||||
persistMgr->transferUint32(TMEMBER(_lastTime));
|
||||
persistMgr->transferVector3d(TMEMBER(_defaultLightPos));
|
||||
persistMgr->transferFloat(TMEMBER(_minShadow));
|
||||
persistMgr->transferFloat(TMEMBER(_maxShadow));
|
||||
persistMgr->transferBool(TMEMBER(_useSmartShadows));
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
void SXShadowManager::callback(void *eventData1, void *eventData2) {
|
||||
SXShadowManager *shadowManager = (SXShadowManager *)eventData2;
|
||||
|
||||
uint32 time = shadowManager->_game->scGetProperty("CurrentTime")->getInt();
|
||||
if (time - shadowManager->_lastTime > 20) {
|
||||
shadowManager->_lastTime = time;
|
||||
shadowManager->update();
|
||||
}
|
||||
}
|
||||
|
||||
void SXShadowManager::update() {
|
||||
if (_useSmartShadows) {
|
||||
AdGame *adGame = (AdGame *)_game;
|
||||
if (!adGame->_scene || !adGame->_scene->_geom)
|
||||
return;
|
||||
|
||||
for (auto actorIt = _actors.begin(); actorIt != _actors.end(); ++actorIt) {
|
||||
_shadowColor = 0x00000000;
|
||||
float shadowWeight = 0.0f;
|
||||
uint32 numLights = 0;
|
||||
for (auto lightIt = _lights.begin(); lightIt != _lights.end(); ++lightIt) {
|
||||
if (!lightIt->second)
|
||||
continue;
|
||||
auto light = lightIt->first;
|
||||
|
||||
if (light->_isSpotlight)
|
||||
continue;
|
||||
|
||||
float weight1 = 0.0 * 0.11f; // TODO
|
||||
|
||||
float r = RGBCOLGetR(light->_diffuseColor) / 255.0f;
|
||||
float g = RGBCOLGetG(light->_diffuseColor) / 255.0f;
|
||||
float b = RGBCOLGetB(light->_diffuseColor) / 255.0f;
|
||||
float brightness = (r + g + b) / 3.0f;
|
||||
float weight2 = brightness * 0.59f;
|
||||
|
||||
float weight3 = 0.0 * 0.3; // TODO
|
||||
|
||||
shadowWeight += (weight1 + weight2 + weight3);
|
||||
|
||||
numLights++;
|
||||
}
|
||||
if (numLights != 0)
|
||||
shadowWeight /= numLights;
|
||||
_shadowColor = (byte)(shadowWeight * 255) << 24;
|
||||
|
||||
actorIt->first->_shadowLightPos = _defaultLightPos;
|
||||
actorIt->first->_shadowColor = _shadowColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SXShadowManager::run() {
|
||||
_lastTime = _game->scGetProperty("CurrentTime")->getInt();
|
||||
_lights.clear();
|
||||
AdGame *adGame = (AdGame *)_game;
|
||||
if (!adGame->_scene || !adGame->_scene->_geom)
|
||||
return;
|
||||
for (int32 l = 0; l < adGame->_scene->_geom->_lights.getSize(); l++) {
|
||||
auto light = adGame->_scene->_geom->_lights[l];
|
||||
_lights.push_back(Common::Pair<Light3D *, bool>(light, true));
|
||||
}
|
||||
}
|
||||
|
||||
void SXShadowManager::stop() {
|
||||
_lights.clear();
|
||||
}
|
||||
|
||||
bool SXShadowManager::addActor(AdActor3DX *actorObj) {
|
||||
if (_useSmartShadows) {
|
||||
_actors.push_back(Common::Pair<AdActor3DX *, uint32>(actorObj, actorObj->_shadowColor));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SXShadowManager::removeAllActors() {
|
||||
for (auto it = _actors.begin(); it != _actors.end(); ++it) {
|
||||
it->first->_shadowColor = it->second;
|
||||
}
|
||||
_actors.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SXShadowManager::enableLight(const char *lightName) {
|
||||
for (auto it = _lights.begin(); it != _lights.end(); ++it) {
|
||||
if (scumm_stricmp(it->first->_name, lightName) == 0)
|
||||
it->second = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SXShadowManager::disableLight(const char *lightName) {
|
||||
for (auto it = _lights.begin(); it != _lights.end(); ++it) {
|
||||
if (scumm_stricmp(it->first->_name, lightName) == 0)
|
||||
it->second = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
Reference in New Issue
Block a user