1 /* ResidualVM - A 3D game interpreter
2  *
3  * ResidualVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 /*
24  * This file is based on WME.
25  * http://dead-code.org/redir.php?target=wme
26  * Copyright (c) 2003-2013 Jan Nedoma and contributors
27  */
28 
29 #include "engines/wintermute/base/base_game.h"
30 #include "engines/wintermute/base/base_sprite.h"
31 #include "engines/wintermute/base/base_surface_storage.h"
32 #include "engines/wintermute/base/gfx/base_surface.h"
33 #include "engines/wintermute/base/gfx/x/material.h"
34 #include "engines/wintermute/base/gfx/x/loader_x.h"
35 #include "engines/wintermute/dcgf.h"
36 #include "engines/wintermute/utils/path_util.h"
37 #include "engines/wintermute/video/video_theora_player.h"
38 
39 namespace Wintermute {
40 
41 //////////////////////////////////////////////////////////////////////
42 // Construction/Destruction
43 //////////////////////////////////////////////////////////////////////
44 
45 //////////////////////////////////////////////////////////////////////////
Material(BaseGame * inGame)46 Material::Material(BaseGame *inGame) : BaseNamedObject(inGame),
47 									   _surface(nullptr), _ownedSurface(false),
48 									   _sprite(nullptr), _theora(nullptr) {
49 }
50 
51 //////////////////////////////////////////////////////////////////////////
~Material()52 Material::~Material() {
53 	if (_surface && _ownedSurface) {
54 		_gameRef->_surfaceStorage->removeSurface(_surface);
55 	}
56 
57 	_sprite = nullptr; // ref only
58 	_theora = nullptr;
59 }
60 
61 //////////////////////////////////////////////////////////////////////////
invalidateDeviceObjects()62 bool Material::invalidateDeviceObjects() {
63 	// as long as we don't support D3DX effects, there is nothing to be done here
64 	return true;
65 }
66 
67 //////////////////////////////////////////////////////////////////////////
restoreDeviceObjects()68 bool Material::restoreDeviceObjects() {
69 	return true;
70 }
71 
72 //////////////////////////////////////////////////////////////////////////
setTexture(const Common::String & filename,bool adoptName)73 bool Material::setTexture(const Common::String &filename, bool adoptName) {
74 	if (adoptName) {
75 		setName(PathUtil::getFileName(filename).c_str());
76 	}
77 
78 	_textureFilename = filename;
79 
80 	if (_surface && _ownedSurface) {
81 		_gameRef->_surfaceStorage->removeSurface(_surface);
82 	}
83 
84 	_surface = _gameRef->_surfaceStorage->addSurface(_textureFilename);
85 	_ownedSurface = true;
86 	_sprite = nullptr;
87 
88 	return _surface != nullptr;
89 }
90 
91 //////////////////////////////////////////////////////////////////////////
setSprite(BaseSprite * sprite,bool adoptName)92 bool Material::setSprite(BaseSprite *sprite, bool adoptName) {
93 	if (adoptName) {
94 		setName(PathUtil::getFileName(sprite->getFilename()).c_str());
95 	}
96 
97 	_textureFilename = sprite->getFilename();
98 	if (_surface && _ownedSurface) {
99 		_gameRef->_surfaceStorage->removeSurface(_surface);
100 	}
101 
102 	_surface = nullptr;
103 
104 	_sprite = sprite;
105 	_ownedSurface = false;
106 	_theora = nullptr;
107 
108 	return true;
109 }
110 
111 //////////////////////////////////////////////////////////////////////////
setTheora(VideoTheoraPlayer * theora,bool adoptName)112 bool Material::setTheora(VideoTheoraPlayer *theora, bool adoptName) {
113 	if (adoptName) {
114 		setName(PathUtil::getFileName(theora->_filename).c_str());
115 	}
116 	_textureFilename = theora->_filename;
117 
118 	if (_surface && _ownedSurface) {
119 		_gameRef->_surfaceStorage->removeSurface(_surface);
120 	}
121 
122 	_surface = nullptr;
123 
124 	_theora = theora;
125 	_ownedSurface = false;
126 
127 	return true;
128 }
129 
130 //////////////////////////////////////////////////////////////////////////
getSurface()131 BaseSurface *Material::getSurface() {
132 	if (_theora) {
133 		_theora->update();
134 		return _theora->getTexture();
135 	} else if (_sprite) {
136 		_sprite->getCurrentFrame();
137 		return _sprite->getSurface();
138 	} else {
139 		return _surface;
140 	}
141 }
142 
loadFromX(XFileLexer & lexer,const Common::String & filename)143 bool Material::loadFromX(XFileLexer &lexer, const Common::String &filename) {
144 	lexer.advanceToNextToken(); // skip optional name
145 	lexer.advanceOnOpenBraces();
146 
147 	_diffuse.r() = lexer.readFloat();
148 	_diffuse.g() = lexer.readFloat();
149 	_diffuse.b() = lexer.readFloat();
150 	_diffuse.a() = lexer.readFloat();
151 	lexer.skipTerminator(); // skip semicolon
152 
153 	_shininess = lexer.readFloat();
154 
155 	_specular.r() = lexer.readFloat();
156 	_specular.g() = lexer.readFloat();
157 	_specular.b() = lexer.readFloat();
158 	_specular.a() = 1.0f;
159 	lexer.skipTerminator(); // skip semicolon
160 
161 	_emissive.r() = lexer.readFloat();
162 	_emissive.g() = lexer.readFloat();
163 	_emissive.b() = lexer.readFloat();
164 	_emissive.a() = 1.0f;
165 	lexer.skipTerminator();
166 
167 	while (!lexer.eof()) {
168 		// according to assimp sources, we got both possibilities
169 		// wine also seems to support this
170 		// MSDN only names the first option
171 		if (lexer.tokenIsIdentifier("TextureFilename") || lexer.tokenIsIdentifier("TextureFileName")) {
172 			lexer.advanceToNextToken(); // skip optional name
173 			lexer.advanceOnOpenBraces();
174 
175 			Common::String textureFilename = lexer.readString();
176 			PathUtil::getDirectoryName(filename);
177 			setTexture(PathUtil::getDirectoryName(filename) + textureFilename);
178 			lexer.advanceToNextToken(); // skip semicolon
179 		} else if (lexer.tokenIsIdentifier()) {
180 			warning("Material::loadFromX unexpected token %i", lexer.getTypeOfToken());
181 			return false;
182 		} else {
183 			break;
184 		}
185 	}
186 
187 	lexer.advanceToNextToken(); // skip semicolon
188 	return true;
189 }
190 
191 } // namespace Wintermute
192