Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,473 @@
/* 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/>.
*
*/
/*
This is a lightly modified version of MicroPather, from
github.com/leethomason/MicroPather. Modifications were made to fit with
ScummVM coding style and APIs.
The original copyright message is:
-------
Copyright (c) 2000-2013 Lee Thomason (www.grinninglizard.com)
Micropather
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef TETRAEDGE_TE_MICROPATHER
#define TETRAEDGE_TE_MICROPATHER
#include "common/array.h"
#include "common/util.h"
#include "common/types.h"
#include "math/utils.h"
/** @mainpage MicroPather
MicroPather is a path finder and A* solver (astar or a-star) written in platform independent
C++ that can be easily integrated into existing code. MicroPather focuses on being a path
finding engine for video games but is a generic A* solver. MicroPather is open source, with
a license suitable for open source or commercial use.
*/
namespace Tetraedge
{
namespace micropather
{
typedef uintptr MP_UPTR;
/**
Used to pass the cost of states from the cliet application to MicroPather. This
structure is copied in a vector.
@sa AdjacentCost
*/
struct StateCost
{
void* state; ///< The state as a void*
float cost; ///< The cost to the state. Use FLT_MAX for infinite cost.
};
/**
A pure abstract class used to define a set of callbacks.
The client application inherits from
this class, and the methods will be called when MicroPather::Solve() is invoked.
The notion of a "state" is very important. It must have the following properties:
- Unique
- Unchanging (unless MicroPather::Reset() is called)
If the client application represents states as objects, then the state is usually
just the object cast to a void*. If the client application sees states as numerical
values, (x,y) for example, then state is an encoding of these values. MicroPather
never interprets or modifies the value of state.
*/
class Graph
{
public:
virtual ~Graph() {}
/**
Return the least possible cost between 2 states. For example, if your pathfinding
is based on distance, this is simply the straight distance between 2 points on the
map. If you pathfinding is based on minimum time, it is the minimal travel time
between 2 points given the best possible terrain.
*/
virtual float LeastCostEstimate( void* stateStart, void* stateEnd ) = 0;
/**
Return the exact cost from the given state to all its neighboring states. This
may be called multiple times, or cached by the solver. It *must* return the same
exact values for every call to MicroPather::Solve(). It should generally be a simple,
fast function with no callbacks into the pather.
*/
virtual void AdjacentCost( void* state, Common::Array< micropather::StateCost > *adjacent ) = 0;
/**
This function is only used in DEBUG mode - it dumps output to stdout. Since void*
aren't really human readable, normally you print out some concise info (like "(1,2)")
without an ending newline.
*/
virtual void PrintStateInfo( void* state ) = 0;
};
class PathNode;
struct NodeCost
{
PathNode* node;
float cost;
};
/*
Every state (void*) is represented by a PathNode in MicroPather. There
can only be one PathNode for a given state.
*/
class PathNode
{
public:
void Init( unsigned _frame,
void* _state,
float _costFromStart,
float _estToGoal,
PathNode* _parent );
void Clear();
void InitSentinel() {
Clear();
Init( 0, 0, FLT_MAX, FLT_MAX, 0 );
prev = next = this;
}
void *state; // the client state
float costFromStart; // exact
float estToGoal; // estimated
float totalCost; // could be a function, but save some math.
PathNode* parent; // the parent is used to reconstruct the path
unsigned frame; // unique id for this path, so the solver can distinguish
// correct from stale values
int numAdjacent; // -1 is unknown & needs to be queried
int cacheIndex; // position in cache
PathNode *child[2]; // Binary search in the hash table. [left, right]
PathNode *next, *prev; // used by open queue
bool inOpen;
bool inClosed;
void Unlink() {
next->prev = prev;
prev->next = next;
next = prev = 0;
}
void AddBefore( PathNode* addThis ) {
addThis->next = this;
addThis->prev = prev;
prev->next = addThis;
prev = addThis;
}
#ifdef TETRAEDGE_MICROPATHER_DEBUG
void CheckList()
{
MPASSERT( totalCost == FLT_MAX );
for( PathNode* it = next; it != this; it=it->next ) {
MPASSERT( it->prev == this || it->totalCost >= it->prev->totalCost );
MPASSERT( it->totalCost <= it->next->totalCost );
}
}
#endif
void CalcTotalCost() {
if ( costFromStart < FLT_MAX && estToGoal < FLT_MAX )
totalCost = costFromStart + estToGoal;
else
totalCost = FLT_MAX;
}
private:
void operator=( const PathNode& );
};
/* Memory manager for the PathNodes. */
class PathNodePool
{
public:
PathNodePool( unsigned allocate, unsigned typicalAdjacent );
~PathNodePool();
// Free all the memory except the first block. Resets all memory.
void Clear();
// Essentially:
// pNode = Find();
// if ( !pNode )
// pNode = New();
//
// Get the PathNode associated with this state. If the PathNode already
// exists (allocated and is on the current frame), it will be returned.
// Else a new PathNode is allocated and returned. The returned object
// is always fully initialized.
//
// NOTE: if the pathNode exists (and is current) all the initialization
// parameters are ignored.
PathNode* GetPathNode( unsigned frame,
void* _state,
float _costFromStart,
float _estToGoal,
PathNode* _parent );
// Get a pathnode that is already in the pool.
PathNode* FetchPathNode( void* state );
// Store stuff in cache
bool PushCache( const NodeCost* nodes, int nNodes, int* start );
// Get neighbors from the cache
// Note - always access this with an offset. Can get re-allocated.
void GetCache( int start, int nNodes, NodeCost* nodes );
// Return all the allocated states. Useful for visuallizing what
// the pather is doing.
void AllStates( unsigned frame, Common::Array< void* >* stateVec );
private:
struct Block
{
Block* nextBlock;
PathNode pathNode[1];
};
unsigned Hash( void* voidval );
unsigned HashSize() const { return 1<<hashShift; }
unsigned HashMask() const { return ((1<<hashShift)-1); }
void AddPathNode( unsigned key, PathNode* p );
Block* NewBlock();
PathNode* Alloc();
PathNode** hashTable;
Block* firstBlock;
Block* blocks;
NodeCost* cache;
int cacheCap;
int cacheSize;
PathNode freeMemSentinel;
unsigned allocate; // how big a block of pathnodes to allocate at once
unsigned nAllocated; // number of pathnodes allocated (from Alloc())
unsigned nAvailable; // number available for allocation
unsigned hashShift;
unsigned totalCollide;
};
/* Used to cache results of paths. Much, much faster
to return an existing solution than to calculate
a new one. A post on this is here:
https://web.archive.org/web/20170714084918/http://grinninglizard.com/altera/programming/a-path-caching-2/
*/
class PathCache
{
public:
struct Item {
// The key:
void* start;
void* end;
bool KeyEqual( const Item& item ) const { return start == item.start && end == item.end; }
bool Empty() const { return start == 0 && end == 0; }
// Data:
void* next;
float cost; // from 'start' to 'next'. FLT_MAX if unsolveable.
unsigned Hash() const {
const unsigned char *p = (const unsigned char *)(&start);
uint h = 2166136261U;
for( unsigned i=0; i<sizeof(void*)*2; ++i, ++p ) {
h ^= *p;
h *= 16777619;
}
return h;
}
};
PathCache( int itemsToAllocate );
~PathCache();
void Reset();
void Add( const Common::Array< void* >& path, const Common::Array< float >& cost );
void AddNoSolution( void* end, void* states[], int count );
int Solve( void* startState, void* endState, Common::Array< void* >* path, float* totalCost );
int AllocatedBytes() const { return allocated * sizeof(Item); }
int UsedBytes() const { return nItems * sizeof(Item); }
int hit;
int miss;
private:
void AddItem( const Item& item );
const Item* Find( void* start, void* end );
Item* mem;
int allocated;
int nItems;
};
struct CacheData {
CacheData() { reset(); }
int nBytesAllocated;
int nBytesUsed;
float memoryFraction;
int hit;
int miss;
float hitFraction;
void reset() {
nBytesAllocated = 0;
nBytesUsed = 0;
memoryFraction = 0;
hit = 0;
miss = 0;
hitFraction = 0;
}
};
/**
Create a MicroPather object to solve for a best path. Detailed usage notes are
on the main page.
*/
class MicroPather
{
friend class micropather::PathNode;
public:
enum
{
SOLVED,
NO_SOLUTION,
START_END_SAME,
// internal
NOT_CACHED
};
/**
Construct the pather, passing a pointer to the object that implements
the Graph callbacks.
@param graph The "map" that implements the Graph callbacks.
@param allocate How many states should be internally allocated at a time. This
can be hard to get correct. The higher the value, the more memory
MicroPather will use.
- If you have a small map (a few thousand states?) it may make sense
to pass in the maximum value. This will cache everything, and MicroPather
will only need one main memory allocation. For a chess board, allocate
would be set to 8x8 (64)
- If your map is large, something like 1/4 the number of possible
states is good.
- If your state space is huge, use a multiple (5-10x) of the normal
path. "Occasionally" call Reset() to free unused memory.
@param typicalAdjacent Used to determine cache size. The typical number of adjacent states
to a given state. (On a chessboard, 8.) Higher values use a little
more memory.
@param cache Turn on path caching. Uses more memory (yet again) but at a huge speed
advantage if you may call the pather with the same path or sub-path, which
is common for pathing over maps in games.
*/
MicroPather( Graph* graph, unsigned allocate = 250, unsigned typicalAdjacent=6, bool cache=true );
~MicroPather();
/**
Solve for the path from start to end.
@param startState Input, the starting state for the path.
@param endState Input, the ending state for the path.
@param path Output, a vector of states that define the path. Empty if not found.
@param totalCost Output, the cost of the path, if found.
@return Success or failure, expressed as SOLVED, NO_SOLUTION, or START_END_SAME.
*/
int Solve( void* startState, void* endState, Common::Array< void* >* path, float* totalCost );
/**
Find all the states within a given cost from startState.
@param startState Input, the starting state for the path.
@param near All the states within 'maxCost' of 'startState', and cost to that state.
@param maxCost Input, the maximum cost that will be returned. (Higher values return
larger 'near' sets and take more time to compute.)
@return Success or failure, expressed as SOLVED or NO_SOLUTION.
*/
int SolveForNearStates( void* startState, Common::Array< StateCost >* near, float maxCost );
/** Should be called whenever the cost between states or the connection between states changes.
Also frees overhead memory used by MicroPather, and calling will free excess memory.
*/
void Reset();
// Debugging function to return all states that were used by the last "solve"
void StatesInPool( Common::Array< void* >* stateVec );
void GetCacheData( CacheData* data );
private:
MicroPather( const MicroPather& ); // undefined and unsupported
void operator=( const MicroPather ); // undefined and unsupported
void GoalReached( PathNode* node, void* start, void* end, Common::Array< void* > *path );
void GetNodeNeighbors( PathNode* node, Common::Array< NodeCost >* neighborNode );
#ifdef TETRAEDGE_MICROPATHER_DEBUG
void DumpStats();
#endif
PathNodePool pathNodePool;
Common::Array< StateCost > stateCostVec; // local to Solve, but put here to reduce memory allocation
Common::Array< NodeCost > nodeCostVec; // local to Solve, but put here to reduce memory allocation
Common::Array< float > costVec;
Graph* graph;
unsigned frame; // incremented with every solve, used to determine if cached data needs to be refreshed
PathCache* pathCache;
};
} // namespace micropather
} // namespace Tetraedge
#endif // TETRAEDGE_TE_MICROPATHER

View File

@@ -0,0 +1,376 @@
/* 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 "tetraedge/te/te_3d_object2.h"
namespace Tetraedge {
Te3DObject2::Te3DObject2() : _childListChanged(false), _parent(nullptr), _scale(1.0f, 1.0f, 1.0f), _color(255, 255, 255, 255), _visible(true), _colorInheritance(true) {
_onWorldVisibleChangedParentCallback.reset(
new TeCallback0Param<Te3DObject2>(this, &Te3DObject2::onWorldVisibleChangedSlot));
_onWorldColorChangedParentCallback.reset(
new TeCallback0Param<Te3DObject2>(this, &Te3DObject2::onParentWorldColorChanged));
_onWorldTransformationMatrixChangedParentCallback.reset(
new TeCallback0Param<Te3DObject2>(this, &Te3DObject2::onParentWorldTransformationMatrixChanged));
}
Te3DObject2::~Te3DObject2() {
for (auto *child : _children) {
child->setParent(nullptr);
}
// clear list in case parent->removeChild triggers a signal which ends up referencing it.
_children.clear();
if (parent()) {
parent()->removeChild(this);
}
setParent(nullptr);
}
void Te3DObject2::addChild(Te3DObject2 *newChild) {
assert(newChild != this && newChild != _parent);
for (auto *c : _children) {
if (c == newChild)
error("Trying to re-add child %s to object %s", newChild->name().c_str(), _name.c_str());
}
_children.push_back(newChild);
newChild->setParent(this);
_childListChangedSignal.call();
}
void Te3DObject2::addChildBefore(Te3DObject2 *newChild, const Te3DObject2 *ref) {
assert(newChild != this && newChild != _parent);
for (auto *c : _children) {
if (c == newChild)
error("Trying to re-add child %s to object %s", newChild->name().c_str(), _name.c_str());
}
Common::Array<Te3DObject2 *>::iterator iter;
for (iter = _children.begin(); iter != _children.end(); iter++) {
if (*iter == ref) {
_children.insert(iter, newChild);
break;
}
}
if (iter == _children.end())
_children.push_back(newChild);
newChild->setParent(this);
_childListChangedSignal.call();
}
Te3DObject2 *Te3DObject2::child(int offset) {
return _children[offset];
}
int Te3DObject2::childIndex(Te3DObject2 *c) const {
for (uint i = 0; i < _children.size(); i++) {
if (_children[i] == c)
return i;
}
return -1;
}
/*static*/
void Te3DObject2::deserialize(Common::ReadStream &stream, Te3DObject2 &dest, bool includesName /* = true */) {
if (includesName) {
Common::String str = deserializeString(stream);
dest.setName(str);
}
TeVector3f32 vect;
TeVector3f32::deserialize(stream, vect);
dest.setPosition(vect);
TeQuaternion quat;
TeQuaternion::deserialize(stream, quat);
dest.setRotation(quat);
TeVector3f32::deserialize(stream, vect);
dest.setScale(vect);
}
/*static*/
void Te3DObject2::serialize(Common::WriteStream &stream, Te3DObject2 &src) {
const Common::String &name = src.name();
stream.writeUint32LE(name.size());
stream.write(name.c_str(), name.size());
const TeVector3f32 pos = src.position();
TeVector3f32::serialize(stream, pos);
const TeQuaternion rot = src.rotation();
TeQuaternion::serialize(stream, rot);
const TeVector3f32 sca = src.scale();
TeVector3f32::serialize(stream, sca);
}
bool Te3DObject2::onParentWorldColorChanged() {
_onParentWorldColorChangedSignal.call();
return false;
}
bool Te3DObject2::onParentWorldTransformationMatrixChanged() {
_onParentWorldTransformationMatrixChangedSignal.call();
return false;
}
void Te3DObject2::removeChild(Te3DObject2 *child) {
uint i;
for (i = 0; i < _children.size(); i++) {
if (_children[i] == child) {
break;
}
}
if (i < _children.size()) {
_children[i]->setParent(nullptr);
_children.remove_at(i);
_childListChangedSignal.call();
} /*else {
// Print a warning?
// This happens on every scene change so this is a bit too noisy.
Common::String cname("nullptr");
if (child)
cname = child->name();
debug("Request to remove child (%s) which is not a child of this (%s).", cname.c_str(), name().c_str());
}*/
}
bool Te3DObject2::onWorldVisibleChangedSlot() {
_onWorldVisibleChangedSlotSignal.call();
return false;
}
void Te3DObject2::removeChildren() {
for (auto *child : _children) {
child->setParent(nullptr);
}
_children.clear();
_childListChangedSignal.call();
}
void Te3DObject2::rotate(const TeQuaternion &rot) {
const TeQuaternion newRot = rotation() * rot;
setRotation(newRot);
}
void Te3DObject2::setColor(const TeColor &col) {
_color = col;
_onParentWorldColorChangedSignal.call();
}
void Te3DObject2::setParent(Te3DObject2 *newparent) {
assert(newparent != this);
if (_parent) {
if (_onWorldVisibleChangedParentCallback)
_parent->onWorldVisibleChanged().remove(_onWorldVisibleChangedParentCallback);
if (_onWorldTransformationMatrixChangedParentCallback)
_parent->onWorldTransformationMatrixChanged().remove(_onWorldTransformationMatrixChangedParentCallback);
if (_onWorldColorChangedParentCallback)
_parent->onWorldColorChanged().remove(_onWorldColorChangedParentCallback);
}
_parent = newparent;
if (newparent) {
if (_onWorldVisibleChangedParentCallback)
_parent->onWorldVisibleChanged().push_back(_onWorldVisibleChangedParentCallback);
if (_onWorldTransformationMatrixChangedParentCallback)
_parent->onWorldTransformationMatrixChanged().push_back(_onWorldTransformationMatrixChangedParentCallback);
if (_onWorldColorChangedParentCallback)
_parent->onWorldColorChanged().push_back(_onWorldColorChangedParentCallback);
_onWorldVisibleChangedSlotSignal.call();
_onParentWorldTransformationMatrixChangedSignal.call();
_onParentWorldColorChangedSignal.call();
}
}
void Te3DObject2::setPosition(const TeVector3f32 &pos) {
if (_position == pos)
return;
// FIXME: remove this debugging code.
if ((_position - pos).length() > 2.0f && name() == "Kate" && _position != TeVector3f32()) {
debug("Large position move %s %s -> %s", name().c_str(),
_position.dump().c_str(), pos.dump().c_str());
}
_position = pos;
_onPositionChangedSignal.call();
_onParentWorldTransformationMatrixChangedSignal.call();
}
void Te3DObject2::setPositionFast(const TeVector3f32 &pos) {
_position = pos;
}
void Te3DObject2::setRotation(const TeQuaternion &rot) {
if (_rotation == rot)
return;
_rotation = rot;
_onParentWorldTransformationMatrixChangedSignal.call();
}
void Te3DObject2::setScale(const TeVector3f32 &scale) {
if (_scale == scale)
return;
_scale = scale;
_onParentWorldTransformationMatrixChangedSignal.call();
}
void Te3DObject2::setSize(const TeVector3f32 &size) {
if (_size == size)
return;
_size = size;
_onSizeChangedSignal.call();
}
void Te3DObject2::setVisible(bool visible) {
if (_visible == visible)
return;
_visible = visible;
onWorldVisibleChangedSlot();
}
void Te3DObject2::setZPosition(float zpos) {
TeVector3f32 pos = position();
pos.z() = zpos;
setPosition(pos);
}
TeMatrix4x4 Te3DObject2::transformationMatrix() {
TeMatrix4x4 retval;
retval.translate(position());
retval.rotate(rotation());
retval.scale(scale());
return retval;
}
void Te3DObject2::translate(const TeVector3f32 &vec) {
TeVector3f32 pos = position();
pos += vec;
setPosition(pos);
}
TeColor Te3DObject2::worldColor() {
if (!_parent || !_colorInheritance) {
return color();
} else {
const TeColor parentCol = _parent->worldColor();
const TeColor thisCol = color();
return parentCol * thisCol;
}
}
TeVector3f32 Te3DObject2::worldPosition() {
if (!_parent) {
return position();
} else {
return _parent->worldPosition() + position();
}
}
TeQuaternion Te3DObject2::worldRotation() {
if (!_parent) {
return rotation();
} else {
return _parent->worldRotation() * rotation();
}
}
TeVector3f32 Te3DObject2::worldScale() {
if (!_parent) {
return scale();
} else {
return _parent->worldScale() * scale();
}
}
TeMatrix4x4 Te3DObject2::worldTransformationMatrix() {
if (!_parent) {
return transformationMatrix();
} else {
return _parent->worldTransformationMatrix() * transformationMatrix();
}
}
bool Te3DObject2::worldVisible() {
if (!_parent) {
return visible();
} else {
return _parent->worldVisible() && visible();
}
}
/*static*/
bool Te3DObject2::loadAndCheckFourCC(Common::ReadStream &stream, const char *str) {
char buf[5];
buf[4] = '\0';
stream.read(buf, 4);
bool result = !strncmp(buf, str, 4);
if (!result)
debug("loadAndCheckFourCC: Look for %s, got %s", str, buf);
return result;
}
/*static*/
Common::String Te3DObject2::deserializeString(Common::ReadStream &stream) {
uint slen = stream.readUint32LE();
if (slen > 1024 * 1024)
error("Improbable string size %d", slen);
if (slen) {
char *buf = new char[slen + 1];
buf[slen] = '\0';
stream.read(buf, slen);
Common::String str(buf);
delete[] buf;
return str;
}
return Common::String();
}
/*static*/
void Te3DObject2::deserializeVectorArray(Common::ReadStream &stream, Common::Array<TeVector3f32> &dest) {
uint32 nentries = stream.readUint32LE();
if (nentries > 1000000)
error("TeFreeMoveZone improbable number of vectors %d", nentries);
dest.resize(nentries);
for (uint i = 0; i < nentries; i++)
TeVector3f32::deserialize(stream, dest[i]);
}
/*static*/
void Te3DObject2::deserializeUintArray(Common::ReadStream &stream, Common::Array<uint> &dest) {
uint32 nentries = stream.readUint32LE();
if (nentries > 1000000)
error("TeFreeMoveZone improbable number of ints %d", nentries);
dest.resize(nentries);
for (uint i = 0; i < nentries; i++)
dest[i] = stream.readUint32LE();
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,182 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_3D_OBJECT2_H
#define TETRAEDGE_TE_TE_3D_OBJECT2_H
#include "common/array.h"
#include "tetraedge/te/te_color.h"
#include "tetraedge/te/te_i_3d_object2.h"
#include "tetraedge/te/te_matrix4x4.h"
#include "tetraedge/te/te_quaternion.h"
#include "tetraedge/te/te_object.h"
#include "tetraedge/te/te_signal.h"
#include "tetraedge/te/te_vector3f32.h"
namespace Tetraedge {
class Te3DObject2 : public TeI3DObject2, public TeObject {
public:
Te3DObject2();
virtual ~Te3DObject2();
// note, probably should be Te*I*3DObject2 args here
virtual void addChild(Te3DObject2 *newChild);
virtual void addChildBefore(Te3DObject2 *newChild, const Te3DObject2 *ref);
virtual Te3DObject2 *child(int offset);
int childCount() {
return _children.size();
}
int childIndex(Te3DObject2 *childToFind) const;
const Common::Array<Te3DObject2 *> &childList() const {
return _children;
}
bool childListChanged() const {
return _childListChanged;
}
const TeColor &color() const {
return _color;
}
bool colorInheritance() const {
return _colorInheritance;
}
/* Note: Added control for includesName not in original as Syberia 2 data format uses
the file name as the model name. */
static void deserialize(Common::ReadStream &stream, Te3DObject2 &dest, bool includesName = true);
static void serialize(Common::WriteStream &stream, Te3DObject2 &src);
virtual void draw() {}
const Common::String &name() const {
return _name;
}
virtual bool onParentWorldColorChanged();
bool onParentWorldTransformationMatrixChanged();
bool onWorldVisibleChangedSlot();
TeSignal0Param &onPositionChanged() {
return _onPositionChangedSignal;
}
TeSignal0Param &onSizeChanged() {
return _onSizeChangedSignal;
}
TeSignal0Param &onWorldColorChanged() {
return _onParentWorldColorChangedSignal;
}
TeSignal0Param &onWorldTransformationMatrixChanged() {
return _onParentWorldTransformationMatrixChangedSignal;
}
TeSignal0Param &onWorldVisibleChanged() {
return _onWorldVisibleChangedSlotSignal;
}
Te3DObject2 *parent() {
return _parent;
}
virtual TeVector3f32 position() {
return _position;
}
virtual void removeChild(Te3DObject2 *toRemove);
virtual void removeChildren();
void rotate(const TeQuaternion &rot);
const TeQuaternion &rotation() {
return _rotation;
}
const TeVector3f32 &scale() const {
return _scale;
}
virtual void setColor(const TeColor &col);
virtual void setColorInheritance(bool val) {
_colorInheritance = val;
}
virtual bool setName(const Common::String &newName) {
_name = newName;
return true;
}
virtual void setParent(Te3DObject2 *newparent); // note, probably should be Te*I*3DObject2 arg
virtual void setPosition(const TeVector3f32 &pos);
virtual void setPositionFast(const TeVector3f32 &pos);
virtual void setRotation(const TeQuaternion &rot);
virtual void setScale(const TeVector3f32 &newScale);
virtual void setSize(const TeVector3f32 &newSize);
void setVisible(bool visible);
virtual void setZPosition(float zpos);
virtual TeVector3f32 size() {
return _size;
}
TeMatrix4x4 transformationMatrix();
virtual void translate(const TeVector3f32 &vec);
virtual void updateZ() {};
virtual bool visible() const {
return _visible;
}
TeColor worldColor();
virtual TeVector3f32 worldPosition();
TeQuaternion worldRotation();
TeVector3f32 worldScale();
virtual TeMatrix4x4 worldTransformationMatrix();
virtual bool worldVisible();
virtual float xSize() { return _size.x(); };
virtual float ySize() { return _size.y(); };
virtual float zSize() { return _size.z(); };
static bool loadAndCheckFourCC(Common::ReadStream &stream, const char *str);
static Common::String deserializeString(Common::ReadStream &stream);
static void deserializeVectorArray(Common::ReadStream &stream, Common::Array<TeVector3f32> &dest);
static void deserializeUintArray(Common::ReadStream &stream, Common::Array<uint> &dest);
protected:
TeVector3f32 _size;
TeVector3f32 _position;
TeQuaternion _rotation;
TeVector3f32 _scale;
private:
Common::Array<Te3DObject2 *> _children;
bool _childListChanged;
TeColor _color;
bool _colorInheritance;
Common::String _name;
Te3DObject2 *_parent;
bool _visible;
TeSignal0Param _childListChangedSignal;
TeSignal0Param _onWorldVisibleChangedSlotSignal;
TeSignal0Param _onPositionChangedSignal;
TeSignal0Param _onSizeChangedSignal;
TeSignal0Param _onParentWorldColorChangedSignal;
TeSignal0Param _onParentWorldTransformationMatrixChangedSignal;
TeICallback0ParamPtr _onWorldVisibleChangedParentCallback;
TeICallback0ParamPtr _onWorldTransformationMatrixChangedParentCallback;
TeICallback0ParamPtr _onWorldColorChangedParentCallback;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_3D_OBJECT2_H

View File

@@ -0,0 +1,122 @@
/* 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 "tetraedge/tetraedge.h"
#include "tetraedge/te/te_3d_texture.h"
#include "tetraedge/te/te_3d_texture_opengl.h"
#include "tetraedge/te/te_3d_texture_tinygl.h"
#include "tetraedge/te/te_resource_manager.h"
#include "tetraedge/te/te_renderer.h"
namespace Tetraedge {
Te3DTexture::Te3DTexture() : _createdTexture(false),
_loaded(false), _width(0), _height(0), _texHeight(0), _texWidth(0),
_topBorder(0), _leftBorder(0), _rightBorder(0), _btmBorder(0),
_flipY(false), _alphaOnly(false) {
}
Te3DTexture::~Te3DTexture() {
}
/*static*/
TeIntrusivePtr<Te3DTexture> Te3DTexture::load2(const TetraedgeFSNode &node, bool alphaOnly) {
const Common::Path fullPath = node.getPath().append(".3dtex");
TeResourceManager *resMgr = g_engine->getResourceManager();
if (!resMgr->exists(fullPath)) {
TeIntrusivePtr<Te3DTexture> retval(makeInstance());
if (!node.exists())
warning("Request to load unreadable texture %s", node.toString().c_str());
if (alphaOnly)
retval->setLoadAlphaOnly();
bool result = retval->load(node);
if (!result)
warning("Failed loading texture %s", node.toString().c_str());
retval->setAccessName(fullPath);
resMgr->addResource(retval.get());
return retval;
} else {
return resMgr->getResourceByName<Te3DTexture>(fullPath);
}
}
bool Te3DTexture::load(const TetraedgeFSNode &node) {
TeResourceManager *resmgr = g_engine->getResourceManager();
TeIntrusivePtr<TeImage> img = resmgr->getResource<TeImage>(node);
bool result = load(*img);
setAccessName(node.getPath().append(".3dtex"));
return result;
}
/*static*/
TeVector2s32 Te3DTexture::optimisedSize(const TeVector2s32 &size) {
//
// Note: When we enable optimized sizes it can leave artifacts around
// movies etc unless the render size is exactly 800x600.
//
// There is a workaround to clear some of the texture data in
// Te3DTextureOpenGL::load to fix this.
//
// The maths here is a bit funky but it just picks the nearest power of 2 (up)
int xsize = size._x - 1;
int ysize = size._y - 1;
xsize = (int)xsize >> 1 | xsize;
xsize = (int)xsize >> 2 | xsize;
xsize = (int)xsize >> 4 | xsize;
xsize = (int)xsize >> 8 | xsize;
int v1 = ((int)xsize >> 0x10 | xsize) + 1;
if (v1 < 8) {
v1 = 8;
}
ysize = (int)ysize >> 1 | ysize;
ysize = (int)ysize >> 2 | ysize;
ysize = (int)ysize >> 4 | ysize;
ysize = (int)ysize >> 8 | ysize;
int v2 = ((int)ysize >> 0x10 | ysize) + 1;
if (v2 < 8) {
v2 = 8;
}
return TeVector2s32(v1, v2);
}
/*static*/
Te3DTexture *Te3DTexture::makeInstance() {
Graphics::RendererType r = g_engine->preferredRendererType();
#if defined(USE_OPENGL_GAME)
if (r == Graphics::kRendererTypeOpenGL)
return new Te3DTextureOpenGL();
#endif
#if defined(USE_TINYGL)
if (r == Graphics::kRendererTypeTinyGL)
return new Te3DTextureTinyGL();
#endif
error("Couldn't create Te3DTexture for selected renderer");
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,92 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_3D_TEXTURE_H
#define TETRAEDGE_TE_TE_3D_TEXTURE_H
#include "common/path.h"
#include "common/ptr.h"
#include "common/str.h"
#include "tetraedge/te/te_image.h"
#include "tetraedge/te/te_intrusive_ptr.h"
#include "tetraedge/te/te_matrix4x4.h"
#include "tetraedge/te/te_resource.h"
#include "tetraedge/te/te_vector2s32.h"
namespace Tetraedge {
class Te3DTexture : public TeResource {
public:
Te3DTexture();
virtual ~Te3DTexture();
virtual void bind() const = 0;
virtual void copyCurrentRender(uint xoffset, uint yoffset, uint x, uint y) = 0;
virtual void create() = 0;
virtual void destroy() = 0;
virtual void forceTexData(uint gltexture, uint xsize, uint ysize) = 0;
bool hasAlpha() const { return _hasAlpha; }
bool load(const TetraedgeFSNode &path);
virtual bool load(const TeImage &img) = 0;
// The original passes a GL enum param, but it's only ever GL_INVALID or GL_ALPHA.
// Simplify to avoid leaking gl types.
static TeIntrusivePtr<Te3DTexture> load2(const TetraedgeFSNode &node, bool alphaOnly);
static TeVector2s32 optimisedSize(const TeVector2s32 &size);
virtual bool unload() = 0;
virtual void update(const TeImage &img, uint xoff, uint yoff) = 0;
virtual void writeTo(Graphics::Surface &surf) = 0;
uint width() const { return _width; }
uint height() const { return _height; }
void setLoadAlphaOnly() { _alphaOnly = true; }
static Te3DTexture *makeInstance();
protected:
uint _width;
uint _height;
bool _createdTexture;
bool _loaded;
TeMatrix4x4 _matrix;
bool _hasAlpha;
bool _alphaOnly;
uint _texWidth;
uint _texHeight;
uint _leftBorder;
uint _btmBorder;
uint _rightBorder;
uint _topBorder;
bool _flipY;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_3D_TEXTURE_H

View File

@@ -0,0 +1,232 @@
/* 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 "graphics/opengl/system_headers.h"
#include "tetraedge/tetraedge.h"
#include "tetraedge/te/te_3d_texture_opengl.h"
#include "tetraedge/te/te_resource_manager.h"
#include "tetraedge/te/te_renderer.h"
namespace Tetraedge {
static const uint NO_TEXTURE = 0xffffffff;
Te3DTextureOpenGL::Te3DTextureOpenGL() : _glTexture(NO_TEXTURE)/*, _glPixelFormat(GL_INVALID_ENUM)*/ {
create();
}
Te3DTextureOpenGL::~Te3DTextureOpenGL() {
destroy();
}
void Te3DTextureOpenGL::bind() const {
TeRenderer *renderer = g_engine->getRenderer();
glBindTexture(GL_TEXTURE_2D, _glTexture);
renderer->setMatrixMode(TeRenderer::MM_GL_TEXTURE);
renderer->loadMatrix(_matrix);
renderer->loadCurrentMatrixToGL();
renderer->setMatrixMode(TeRenderer::MM_GL_MODELVIEW);
}
void Te3DTextureOpenGL::copyCurrentRender(uint xoffset, uint yoffset, uint x, uint y) {
_matrix.setToIdentity();
const TeVector3f32 texScale((float)_width / _texWidth, (float)_height / _texHeight, 1.0);
_matrix.scale(texScale);
const TeVector3f32 offset((float)_leftBorder / _width, (float)_btmBorder / _height, 0.0);
_matrix.translate(offset);
const TeVector3f32 borderScale(
1.0 - (float)(_rightBorder + _leftBorder) / (float)_width,
1.0 - (float)(_topBorder + _btmBorder) / (float)_height, 1.0);
_matrix.scale(borderScale);
bind();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, x, y, _texWidth, _texHeight);
}
void Te3DTextureOpenGL::writeTo(Graphics::Surface &surf) {
Graphics::Surface fullTex;
fullTex.create(_texWidth, _texHeight, Graphics::PixelFormat::createFormatRGBA32());
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, fullTex.getPixels());
surf.create(_width, _height, fullTex.format);
surf.copyRectToSurface(fullTex, 0, 0, Common::Rect(_width, _height));
fullTex.free();
}
void Te3DTextureOpenGL::create() {
_flipY = false;
_leftBorder = _btmBorder = _texWidth = _texHeight = 0;
_rightBorder = _topBorder = _width = _height = 0;
_hasAlpha = false;
_loaded = false;
if (!_createdTexture)
glGenTextures(1, &_glTexture);
if (_glTexture == NO_TEXTURE) {
_createdTexture = false;
return;
}
_createdTexture = true;
glBindTexture(GL_TEXTURE_2D, _glTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
void Te3DTextureOpenGL::destroy() {
if (_createdTexture) {
glDeleteTextures(1, &_glTexture);
}
_createdTexture = false;
_loaded = false;
_glTexture = NO_TEXTURE;
}
void Te3DTextureOpenGL::forceTexData(uint gltexture, uint xsize, uint ysize) {
if (_glTexture != 0xffffffff)
destroy();
_glTexture = gltexture;
_width = xsize;
_height = ysize;
_texWidth = xsize;
_texHeight = ysize;
}
bool Te3DTextureOpenGL::load(const TeImage &img) {
setAccessName(img.getAccessName().append(".3dtex"));
_width = img.w;
_height = img.h;
_hasAlpha = img.format.aBits() > 0;
// TODO? set some other fields from the image here.
// For now just set defaults as these never get used in games.
_flipY = true; //img._flipY;
_leftBorder = 0; //img._leftBorder;
_btmBorder = 0; //img._btmBorder;
_rightBorder = 0; //img._rightBorder;
_topBorder = 0; //img._topBorder;
const TeVector2s32 optimizedSz = optimisedSize(img.bufSize());
_texWidth = optimizedSz._x;
_texHeight = optimizedSz._y;
glBindTexture(GL_TEXTURE_2D, _glTexture);
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
const void *imgdata = img.getPixels();
if (img.format == Graphics::PixelFormat::createFormatRGBA32()) {
Graphics::Surface surf;
if (_alphaOnly) {
surf.copyFrom(img);
// Slight hack: Move R data to A channel. Our image reader
// only reads data as RGB, so use red for alpha-only values.
uint32 *p = (uint32 *)surf.getPixels();
for (int y = 0; y < img.h; y++) {
for (int x = 0; x < img.w; x++) {
byte a, r, g, b;
img.format.colorToARGB(p[x], a, r, g ,b);
p[x] = img.format.ARGBToColor(r, r, r, r);
}
p += img.pitch / 4;
}
imgdata = surf.getPixels();
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, _texWidth, _texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, img.w, img.h, GL_RGBA, GL_UNSIGNED_BYTE, imgdata);
// FIXME: Slight hack.. sometimes artifacts appear because we draw
// a (half?)pixel outside the original texture. Clear one more row
// of the new texture with 0s to avoid artifacts.
if ((int)_texHeight > img.h) {
byte *buf = new byte[img.w * 4];
memset(buf, 0, img.w * 4);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, img.h, img.w, 1, GL_RGBA, GL_UNSIGNED_BYTE, buf);
delete [] buf;
}
// And the same for the right-hand-side
if ((int)_texWidth > img.w) {
byte *buf = new byte[img.h * 4];
memset(buf, 0, img.h * 4);
glTexSubImage2D(GL_TEXTURE_2D, 0, img.w, 0, 1, img.h, GL_RGBA, GL_UNSIGNED_BYTE, buf);
delete [] buf;
}
if (_alphaOnly)
surf.free();
} else {
warning("Te3DTexture::load can't send image format %s to GL.", img.format.toString().c_str());
}
_matrix.setToIdentity();
_matrix.scale(TeVector3f32((float)_width / _texWidth, (float)_height / _texHeight, 1.0f));
_matrix.translate(TeVector3f32((float)_leftBorder / _width, (float)_btmBorder / _height, 0.0f));
_matrix.scale(TeVector3f32(1.0 - (float)(_rightBorder + _leftBorder) / _width,
1.0 - (float)(_topBorder + _btmBorder) / _height, 1.0f));
if (_flipY) {
_matrix.translate(TeVector3f32(0.0f, 1.0f, 0.0f));
_matrix.scale(TeVector3f32(1.0f, -1.0f, 1.0f));
}
_loaded = true;
return true;
}
/*static*/
void Te3DTextureOpenGL::unbind() {
TeRenderer *renderer = g_engine->getRenderer();
renderer->setMatrixMode(TeRenderer::MM_GL_TEXTURE);
renderer->loadIdentityMatrix();
renderer->loadCurrentMatrixToGL();
glBindTexture(GL_TEXTURE_2D, 0);
renderer->setMatrixMode(TeRenderer::MM_GL_MODELVIEW);
}
bool Te3DTextureOpenGL::unload() {
glBindTexture(GL_TEXTURE_2D, _glTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
_loaded = false;
return true;
}
void Te3DTextureOpenGL::update(const TeImage &img, uint xoff, uint yoff) {
if (!img.w || !img.h)
return;
setAccessName(img.getAccessName().append(".3dtex"));
glBindTexture(GL_TEXTURE_2D, _glTexture);
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
const void *imgdata = img.getPixels();
glTexSubImage2D(GL_TEXTURE_2D, 0, xoff, yoff, img.w, img.h, GL_RGBA, GL_UNSIGNED_BYTE, imgdata);
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,60 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_3D_TEXTURE_OPENGL_H
#define TETRAEDGE_TE_TE_3D_TEXTURE_OPENGL_H
#if defined(USE_OPENGL_GAME)
#include "tetraedge/te/te_3d_texture.h"
namespace Tetraedge {
class Te3DTextureOpenGL : public Te3DTexture {
public:
Te3DTextureOpenGL();
virtual ~Te3DTextureOpenGL();
void bind() const override;
void copyCurrentRender(uint xoffset, uint yoffset, uint x, uint y) override;
void create() override;
void destroy() override;
void forceTexData(uint gltexture, uint xsize, uint ysize) override;
bool load(const TeImage &img) override;
static void unbind();
bool unload() override;
void update(const TeImage &img, uint xoff, uint yoff) override;
void writeTo(Graphics::Surface &surf) override;
private:
uint _glTexture;
//uint _glPixelFormat;
};
} // end namespace Tetraedge
#endif // USE_OPENGL
#endif // TETRAEDGE_TE_TE_3D_TEXTURE_OPENGL_H

View File

@@ -0,0 +1,200 @@
/* 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 "graphics/tinygl/tinygl.h"
#include "tetraedge/tetraedge.h"
#include "tetraedge/te/te_3d_texture_tinygl.h"
#include "tetraedge/te/te_resource_manager.h"
#include "tetraedge/te/te_renderer.h"
namespace Tetraedge {
static const uint NO_TEXTURE = 0xffffffff;
Te3DTextureTinyGL::Te3DTextureTinyGL() : _glTexture(NO_TEXTURE)/*, _glPixelFormat(TGL_INVALID_ENUM)*/ {
create();
}
Te3DTextureTinyGL::~Te3DTextureTinyGL() {
destroy();
}
void Te3DTextureTinyGL::bind() const {
TeRenderer *renderer = g_engine->getRenderer();
tglBindTexture(TGL_TEXTURE_2D, _glTexture);
renderer->setMatrixMode(TeRenderer::MM_GL_TEXTURE);
renderer->loadMatrix(_matrix);
renderer->loadCurrentMatrixToGL();
renderer->setMatrixMode(TeRenderer::MM_GL_MODELVIEW);
}
void Te3DTextureTinyGL::copyCurrentRender(uint xoffset, uint yoffset, uint x, uint y) {
_matrix.setToIdentity();
const TeVector3f32 texScale((float)_width / _texWidth, (float)_height / _texHeight, 1.0);
_matrix.scale(texScale);
const TeVector3f32 offset((float)_leftBorder / _width, (float)_btmBorder / _height, 0.0);
_matrix.translate(offset);
const TeVector3f32 borderScale(
1.0 - (float)(_rightBorder + _leftBorder) / (float)_width,
1.0 - (float)(_topBorder + _btmBorder) / (float)_height, 1.0);
_matrix.scale(borderScale);
bind();
//TODO: Come up with equivalent for TGL.
//tglCopyTexSubImage2D(TGL_TEXTURE_2D, 0, xoffset, yoffset, x, y, _texWidth, _texHeight);
}
void Te3DTextureTinyGL::writeTo(Graphics::Surface &surf) {
Graphics::Surface fullTex;
fullTex.create(_texWidth, _texHeight, Graphics::PixelFormat::createFormatRGBA32());
//TODO: Come up with equivalent for TGL.
//tglGetTexImage(TGL_TEXTURE_2D, 0, TGL_RGBA, TGL_UNSIGNED_BYTE, fullTex.getPixels());
surf.create(_width, _height, fullTex.format);
surf.copyRectToSurface(fullTex, 0, 0, Common::Rect(_width, _height));
fullTex.free();
}
void Te3DTextureTinyGL::create() {
_flipY = false;
_leftBorder = _btmBorder = _texWidth = _texHeight = 0;
_rightBorder = _topBorder = _width = _height = 0;
_hasAlpha = false;
_loaded = false;
if (!_createdTexture)
tglGenTextures(1, &_glTexture);
if (_glTexture == NO_TEXTURE) {
_createdTexture = false;
return;
}
_createdTexture = true;
tglBindTexture(TGL_TEXTURE_2D, _glTexture);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MAG_FILTER, TGL_LINEAR);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MIN_FILTER, TGL_LINEAR);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_S, TGL_CLAMP_TO_EDGE);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_T, TGL_CLAMP_TO_EDGE);
}
void Te3DTextureTinyGL::destroy() {
if (_createdTexture) {
tglDeleteTextures(1, &_glTexture);
}
_createdTexture = false;
_loaded = false;
_glTexture = NO_TEXTURE;
}
void Te3DTextureTinyGL::forceTexData(uint gltexture, uint xsize, uint ysize) {
if (_glTexture != 0xffffffff)
destroy();
_glTexture = gltexture;
_width = xsize;
_height = ysize;
_texWidth = xsize;
_texHeight = ysize;
}
bool Te3DTextureTinyGL::load(const TeImage &img) {
setAccessName(img.getAccessName().append(".3dtex"));
_width = img.w;
_height = img.h;
_hasAlpha = img.format.aBits() > 0;
// TODO? set some other fields from the image here.
// for now just set some good defaults.
_flipY = true; //img._flipY;
_leftBorder = 0; //img._leftBorder;
_btmBorder = 0; //img._btmBorder;
_rightBorder = 0; //img._rightBorder;
_topBorder = 0; //img._topBorder;
_texWidth = _width;
_texHeight = _height;
tglBindTexture(TGL_TEXTURE_2D, _glTexture);
// Note: these are unsupported in TGL but should be the defaults?
//tglPixelStorei(TGL_UNPACK_SWAP_BYTES, TGL_FALSE);
//tglPixelStorei(TGL_UNPACK_LSB_FIRST, TGL_FALSE);
//tglPixelStorei(TGL_UNPACK_ROW_LENGTH, 0);
//tglPixelStorei(TGL_UNPACK_SKIP_ROWS, 0);
//tglPixelStorei(TGL_UNPACK_SKIP_PIXELS, 0);
tglPixelStorei(TGL_UNPACK_ALIGNMENT, 1);
const void *imgdata = img.getPixels();
TGLenum destfmt = _alphaOnly ? TGL_ALPHA : TGL_RGBA;
if (img.format == Graphics::PixelFormat::createFormatRGBA32()) {
tglTexImage2D(TGL_TEXTURE_2D, 0, destfmt, img.w, img.h, 0, TGL_RGBA, TGL_UNSIGNED_BYTE, imgdata);
} else {
warning("Te3DTexture::load can't send image format %s to GL.", img.format.toString().c_str());
}
_matrix.setToIdentity();
_matrix.scale(TeVector3f32((float)_width / _texWidth, (float)_height / _texHeight, 1.0f));
_matrix.translate(TeVector3f32((float)_leftBorder / _width, (float)_btmBorder / _height, 0.0f));
_matrix.scale(TeVector3f32(1.0 - (float)(_rightBorder + _leftBorder) / _width,
1.0 - (float)(_topBorder + _btmBorder) / _height, 1.0f));
if (_flipY) {
_matrix.translate(TeVector3f32(0.0f, 1.0f, 0.0f));
_matrix.scale(TeVector3f32(1.0f, -1.0f, 1.0f));
}
_loaded = true;
return true;
}
/*static*/
void Te3DTextureTinyGL::unbind() {
TeRenderer *renderer = g_engine->getRenderer();
renderer->setMatrixMode(TeRenderer::MM_GL_TEXTURE);
renderer->loadIdentityMatrix();
renderer->loadCurrentMatrixToGL();
tglBindTexture(TGL_TEXTURE_2D, 0);
renderer->setMatrixMode(TeRenderer::MM_GL_MODELVIEW);
}
bool Te3DTextureTinyGL::unload() {
tglBindTexture(TGL_TEXTURE_2D, _glTexture);
tglTexImage2D(TGL_TEXTURE_2D, 0, TGL_RGB, 0, 0, 0, TGL_RGB, TGL_UNSIGNED_BYTE, NULL);
_loaded = false;
return true;
}
void Te3DTextureTinyGL::update(const TeImage &img, uint xoff, uint yoff) {
if (!img.w || !img.h)
return;
setAccessName(img.getAccessName().append(".3dtex"));
tglBindTexture(TGL_TEXTURE_2D, _glTexture);
// Note: these are unsupported in TGL but should be the defaults?
//tglPixelStorei(TGL_UNPACK_SWAP_BYTES, TGL_FALSE);
//tglPixelStorei(TGL_UNPACK_LSB_FIRST, TGL_FALSE);
//tglPixelStorei(TGL_UNPACK_ROW_LENGTH, 0);
//tglPixelStorei(TGL_UNPACK_SKIP_ROWS, 0);
//tglPixelStorei(TGL_UNPACK_SKIP_PIXELS, 0);
tglPixelStorei(TGL_UNPACK_ALIGNMENT, 1);
//TODO: Come up with equivalent for TGL.
//const void *imgdata = img.getPixels();
//tglTexSubImage2D(TGL_TEXTURE_2D, 0, xoff, yoff, img.w, img.h, TGL_RGBA, TGL_UNSIGNED_BYTE, imgdata);
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,60 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_3D_TEXTURE_TINYGL_H
#define TETRAEDGE_TE_TE_3D_TEXTURE_TINYGL_H
#if defined(USE_TINYGL)
#include "tetraedge/te/te_3d_texture.h"
namespace Tetraedge {
class Te3DTextureTinyGL : public Te3DTexture {
public:
Te3DTextureTinyGL();
virtual ~Te3DTextureTinyGL();
void bind() const override;
void copyCurrentRender(uint xoffset, uint yoffset, uint x, uint y) override;
void create() override;
void destroy() override;
void forceTexData(uint gltexture, uint xsize, uint ysize) override;
bool load(const TeImage &img) override;
static void unbind();
bool unload() override;
void update(const TeImage &img, uint xoff, uint yoff) override;
void writeTo(Graphics::Surface &surf) override;
private:
uint _glTexture;
//uint _glPixelFormat;
};
} // end namespace Tetraedge
#endif // USE_TINYGL
#endif // TETRAEDGE_TE_TE_3D_TEXTURE_TINYGL_H

View File

@@ -0,0 +1,29 @@
/* 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 "tetraedge/te/te_act_zone.h"
namespace Tetraedge {
TeActZone::TeActZone() : _flag1(false), _flag2(false) {
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,46 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_ACT_ZONE_H
#define TETRAEDGE_TE_TE_ACT_ZONE_H
#include "common/str.h"
#include "tetraedge/te/te_vector2f32.h"
namespace Tetraedge {
class TeActZone {
public:
TeActZone();
Common::String _s1;
Common::String _s2;
TeVector2f32 _points[4];
bool _flag1;
bool _flag2;
private:
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_ACT_ZONE_H

View File

@@ -0,0 +1,139 @@
/* 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 "tetraedge/te/te_animation.h"
namespace Tetraedge {
/*static*/
Common::Array<TeAnimation *> *TeAnimation::_animations = nullptr;
/*static*/
Common::Array<TeAnimation *> *TeAnimation::animations() {
if (!_animations)
_animations = new Common::Array<TeAnimation *>();
return _animations;
}
TeAnimation::TeAnimation() : _repeatCount(1), _dontRepeat(false) {
}
TeAnimation::~TeAnimation() {
stop();
}
void TeAnimation::cont() {
if (!_runTimer.running()) {
_runTimer.start();
Common::Array<TeAnimation *> *anims = animations();
Common::Array<TeAnimation *>::iterator iter;
for (iter = anims->begin(); iter != anims->end(); iter++) {
if (*iter == this) {
error("anim being resumed is already in active anims");
}
}
anims->push_back(this);
update(_runTimer.getTimeFromStart() / 1000.0);
}
}
void TeAnimation::removeThisFromAnimations() {
// Find and remove this one
Common::Array<TeAnimation *> *anims = animations();
Common::Array<TeAnimation *>::iterator iter;
for (iter = anims->begin(); iter != anims->end(); iter++) {
if (*iter == this) {
anims->erase(iter);
break;
}
}
for (iter = anims->begin(); iter != anims->end(); iter++) {
if (*iter == this) {
error("anim was added twice to active anims");
}
}
}
void TeAnimation::pause() {
if (_runTimer.running()) {
removeThisFromAnimations();
_runTimer.pause();
}
}
void TeAnimation::stop() {
if (_runTimer.running()) {
removeThisFromAnimations();
_runTimer.stop();
_onStopSignal.call();
}
}
void TeAnimation::reset() {
if (_runTimer.running()) {
removeThisFromAnimations();
stop();
}
}
void TeAnimation::seekToStart() {
_runTimer.stop();
_runTimer.start();
update(_runTimer.getTimeFromStart() / 1000.0);
}
/*static*/
void TeAnimation::pauseAll() {
for (auto &anim : *animations()) {
if (anim->_runTimer.running())
anim->pause();
}
}
/*static*/
void TeAnimation::resumeAll() {
for (auto &anim : *animations()) {
anim->cont();
}
}
/*static*/
void TeAnimation::cleanup() {
delete _animations;
_animations = nullptr;
}
/*static*/
void TeAnimation::updateAll() {
Common::Array<TeAnimation *> &anims = *animations();
// Note: update can cause events which cascade into animtaions
// getting deleted, so be careful about the numbers.
for (uint i = 0; i < anims.size(); i++) {
if (anims[i]->_runTimer.running()) {
double msFromStart = anims[i]->_runTimer.getTimeFromStart() / 1000.0;
anims[i]->update(msFromStart);
}
}
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,75 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_ANIMATION_H
#define TETRAEDGE_TE_TE_ANIMATION_H
#include "common/array.h"
#include "tetraedge/te/te_timer.h"
#include "tetraedge/te/te_signal.h"
namespace Tetraedge {
class TeAnimation {
public:
TeAnimation();
virtual ~TeAnimation();
virtual void cont();
virtual void pause();
virtual void stop();
virtual void reset();
void play() {
cont();
}
virtual void update(double millis) = 0;
void seekToStart();
//void staticDestroy();
static void pauseAll();
static void resumeAll();
static void updateAll();
static void cleanup();
TeSignal0Param &onStop() { return _onStopSignal; }
TeSignal0Param &onFinished() { return _onFinishedSignal; }
TeTimer _runTimer;
int _repeatCount;
protected:
bool _dontRepeat;
TeSignal0Param _onStopSignal;
TeSignal0Param _onFinishedSignal;
private:
void removeThisFromAnimations();
static Common::Array<TeAnimation *> *animations();
static Common::Array<TeAnimation *> *_animations;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_ANIMATION_H

View File

@@ -0,0 +1,257 @@
/* 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 "common/file.h"
#include "tetraedge/te/te_bezier_curve.h"
#include "tetraedge/te/te_mesh.h"
#include "tetraedge/te/te_renderer.h"
#include "tetraedge/tetraedge.h"
namespace Tetraedge {
TeBezierCurve::TeBezierCurve() : _length(0.0), _rawLength(0.0), _lengthNeedsUpdate(true),
_rawLengthNeedsUpdate(true), _numIterations(1000) {
}
//int TeBezierCurve::bounds(int start);
void TeBezierCurve::clear() {
_lengthNeedsUpdate = true;
_rawLengthNeedsUpdate = true;
_length = 0.0;
_controlPoints.clear();
}
void TeBezierCurve::draw() {
if (!worldVisible() || _controlPoints.empty())
return;
Common::SharedPtr<TeMesh> mesh1(TeMesh::makeInstance());
Common::SharedPtr<TeMesh> mesh2(TeMesh::makeInstance());
uint npoints = _controlPoints.size();
mesh1->setConf(npoints, npoints, TeMesh::MeshMode_Points, 0, 0);
for (uint i = 0; i < npoints; i++) {
mesh1->setVertex(i, _controlPoints[i]);
mesh1->setIndex(i, i);
}
mesh2->setConf(npoints, npoints, TeMesh::MeshMode_LineStrip, 0, 0);
for (uint i = 0; i < npoints; i++) {
mesh2->setVertex(i, _controlPoints[i]);
mesh2->setNormal(i, TeVector3f32(0.0f, 1.0f, 0.0));
mesh2->setIndex(i, i);
}
TeRenderer *renderer = g_engine->getRenderer();
const TeColor prevColor = renderer->currentColor();
renderer->pushMatrix();
renderer->multiplyMatrix(worldTransformationMatrix());
renderer->setCurrentColor(TeColor(0, 0xff, 0xff, 0xff));
mesh2->draw();
renderer->setCurrentColor(TeColor(0xff, 0, 0xff, 0xff));
mesh1->draw();
renderer->popMatrix();
renderer->setCurrentColor(prevColor);
}
float TeBezierCurve::length() {
if (_lengthNeedsUpdate) {
_length = 0.0;
_lengthNeedsUpdate = false;
_lengths.clear();
TeVector3f32 lastpt = _controlPoints[0];
lastpt.y() = 0;
for (uint i = 0; i < _numIterations; i++) {
float amount = (float)i / _numIterations;
TeVector3f32 pt = retrievePoint(amount);
pt.y() = 0;
float len = (lastpt - pt).length();
_length += len;
_lengths.push_back(_length);
lastpt = pt;
}
}
return _length;
}
void TeBezierCurve::pseudoTangent(float offset, TeVector3f32 &v1, TeVector3f32 &v2) {
const float step = 1.0f / _numIterations;
if (step + offset <= 1.0f) {
v1 = retrievePoint(offset);
v2 = retrievePoint(offset + step);
} else {
v1 = retrievePoint(offset - step);
v2 = retrievePoint(offset);
}
}
float TeBezierCurve::rawLength() {
if (_rawLengthNeedsUpdate) {
_rawLengthNeedsUpdate = false;
_rawLength = 0.0;
_rawLengths.clear();
_rawLengths.push_back(0.0);
for (uint i = 1; i < _controlPoints.size(); i++) {
const TeVector3f32 diff = _controlPoints[i] - _controlPoints[i - 1];
_rawLength += diff.length();
_rawLengths.push_back(_rawLength);
}
}
return _rawLength;
}
TeVector3f32 TeBezierCurve::retrievePoint(float offset) {
const int npoints = _controlPoints.size();
// Simple cases for small numbers of points.
if (npoints == 0)
return TeVector3f32();
else if (npoints == 1)
return _controlPoints[0];
else if (npoints == 2)
return _controlPoints[0] + (_controlPoints[1] - _controlPoints[0]) * offset;
// else, there are at least 3 points so need to actually interpolate.
const float rawlen = rawLength();
float proportion = 0.0f;
int startpt = 0;
while (startpt < npoints) {
proportion = _rawLengths[startpt] / rawlen;
if (proportion >= offset)
break;
startpt++;
}
float t;
if (proportion == offset) {
// Exactly on a point
t = 0.0f;
} else {
// Proportion between two points
float p1 = _rawLengths[startpt - 1];
float p2 = _rawLengths[startpt];
t = (rawlen * offset - p1) / (p2 - p1);
startpt--;
}
// Collect 4 points around the startpt (1 before, 2 after)
TeVector3f32 points[4];
const int maxPt = _controlPoints.size() - 1;
for (int p = 0; p < 4; p++) {
int ptno = CLIP(startpt + p - 1, 0, maxPt);
points[p] = _controlPoints[ptno];
}
// If we hit the end, linearly extend the last gradient.
if (startpt <= 0)
points[0] += (points[1] - points[2]);
if (startpt + 1 >= maxPt)
points[3] += (points[2] - points[1]);
return hermiteInterpolate(t, points, 0.0, 0.0);
}
void TeBezierCurve::setControlPoints(const Common::Array<TeVector3f32> &points) {
_lengthNeedsUpdate = true;
_rawLengthNeedsUpdate = true;
_controlPoints = points;
}
void TeBezierCurve::setNbIterations(uint iterations) {
_lengthNeedsUpdate = true;
_rawLengthNeedsUpdate = true;
_numIterations = iterations;
}
/*static*/
void TeBezierCurve::serialize(Common::WriteStream &stream, const TeBezierCurve &curve) {
error("TODO: Implement TeBezierCurve::serialize");
}
/*static*/
void TeBezierCurve::deserialize(Common::ReadStream &stream, TeBezierCurve &curve) {
Te3DObject2::deserialize(stream, curve);
curve._lengthNeedsUpdate = false;
curve._length = stream.readFloatLE();
uint32 npoints = stream.readUint32LE();
if (npoints > 1000000)
error("TeBezierCurve::deserialize improbable number of control ponts %d", npoints);
for (uint i = 0; i < npoints; i++) {
TeVector3f32 vec;
TeVector3f32::deserialize(stream, vec);
curve._controlPoints.push_back(vec);
}
}
void TeBezierCurve::loadBin(TetraedgeFSNode &node) {
Common::ScopedPtr<Common::SeekableReadStream> file(node.createReadStream());
Common::String fname = node.getPath().baseName();
if (fname.size() < 4)
error("TeBezierCurve::loadBin fname %s is too short", fname.c_str());
setName(fname.substr(0, fname.size() - 4));
// Load position / rotation / size
Te3DObject2::deserialize(*file, *this, false);
// Then it resets them?
setPosition(TeVector3f32());
setRotation(TeQuaternion());
setSize(TeVector3f32(1, 1, 1));
_lengthNeedsUpdate = true;
uint32 npoints = file->readUint32LE();
if (npoints > 1000000)
error("TeBezierCurve::loadBin improbable number of control ponts %d", npoints);
for (uint i = 0; i < npoints; i++) {
TeVector3f32 vec;
TeVector3f32::deserialize(*file, vec);
_controlPoints.push_back(vec);
}
}
/*static*/
TeVector3f32 TeBezierCurve::hermiteInterpolate(float t, const TeVector3f32 *points, float param_4, float param_5) {
assert(points);
const TeVector3f32 delta1 = ((points[1] - points[0]) * (param_5 + 1.0) * (1.0 - param_4)) / 2.0;
const TeVector3f32 delta2a = ((points[2] - points[1]) * (1.0 - param_5) * (1.0 - param_4)) / 2.0;
const TeVector3f32 delta2b = ((points[2] - points[1]) * (param_5 + 1.0) * (1.0 - param_4)) / 2.0;
const TeVector3f32 delta3 = ((points[3] - points[2]) * (1.0 - param_5) * (1.0 - param_4)) / 2.0;
const TeVector3f32 x1 = delta1 + delta2a;
const TeVector3f32 x2 = delta2b + delta3;
const float t2 = t * t;
const float t3 = t * t * t;
const TeVector3f32 h1a = points[1] * ((t3 + t3) - t2 * 3.0 + 1.0);
const TeVector3f32 h1b = x1 * ((t3 - (t2 + t2)) + t);
const TeVector3f32 h1 = (h1a + h1b) + (x2 * (t3 - t2));
return h1 + (points[2] * (t3 * -2.0 + t2 * 3.0));
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,72 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_BEZIER_CURVE_H
#define TETRAEDGE_TE_TE_BEZIER_CURVE_H
#include "common/array.h"
#include "tetraedge/te/te_3d_object2.h"
#include "tetraedge/te/te_references_counter.h"
#include "tetraedge/tetraedge.h"
namespace Tetraedge {
class TeBezierCurve : public Te3DObject2, public TeReferencesCounter {
public:
TeBezierCurve();
int bounds(int val);
void clear();
void draw() override;
float length();
void pseudoTangent(float f, TeVector3f32 &v1, TeVector3f32 &v2);
float rawLength();
TeVector3f32 retrievePoint(float offset);
void setControlPoints(const Common::Array<TeVector3f32> &points);
void setNbIterations(uint iterations);
static TeVector3f32 hermiteInterpolate(float param_2, const TeVector3f32 *points, float param_4, float param_5);
static void serialize(Common::WriteStream &stream, const TeBezierCurve &curve);
static void deserialize(Common::ReadStream &stream, TeBezierCurve &curve);
void loadBin(TetraedgeFSNode &node);
const Common::Array<TeVector3f32> &controlPoints() { return _controlPoints; }
uint numIterations() const { return _numIterations; }
private:
uint _numIterations;
float _length;
float _rawLength;
bool _lengthNeedsUpdate;
bool _rawLengthNeedsUpdate;
Common::Array<TeVector3f32> _controlPoints;
Common::Array<float> _rawLengths;
Common::Array<float> _lengths;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_BEZIER_CURVE_H

View File

@@ -0,0 +1,413 @@
/* 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 "tetraedge/tetraedge.h"
#include "tetraedge/te/te_button_layout.h"
#include "tetraedge/te/te_sound_manager.h"
#include "tetraedge/te/te_input_mgr.h"
#include "tetraedge/te/te_sprite_layout.h"
namespace Tetraedge {
class TeZPriorityMouseCallback : public TeCallback1Param<TeButtonLayout, const Common::Point &> {
public:
TeZPriorityMouseCallback(TeButtonLayout *layout, TMethod method) : TeCallback1Param<TeButtonLayout, const Common::Point &>(layout, method), _pri(0.0) {}
virtual float &priority() override {
_pri =_object->worldPosition().z();
return _pri;
}
float _pri;
};
/*static*/
bool TeButtonLayout::_mousePositionChangedCatched = false;
/*static*/
TeTimer *TeButtonLayout::_doubleValidationProtectionTimer = nullptr;
/*static*/
TeTimer *TeButtonLayout::getDoubleValidationProtectionTimer() {
if (!_doubleValidationProtectionTimer) {
_doubleValidationProtectionTimer = new TeTimer();
}
return _doubleValidationProtectionTimer;
}
TeButtonLayout::TeButtonLayout() : _currentState(BUTTON_STATE_UP),
_clickPassThrough(false), _validationSoundVolume(1.0),
_ignoreMouseEvents(false), _doubleValidationProtectionEnabled(true),
_upLayout(nullptr), _downLayout(nullptr), _rolloverLayout(nullptr),
_disabledLayout(nullptr), _hitZoneLayout(nullptr), _ownedLayouts(false)
{
_onMousePositionChangedMaxPriorityCallback.reset(new TeCallback1Param<TeButtonLayout, const Common::Point &>(this, &TeButtonLayout::onMousePositionChangedMaxPriority, FLT_MAX));
_onMousePositionChangedCallback.reset(new TeZPriorityMouseCallback(this, &TeButtonLayout::onMousePositionChanged));
_onMouseLeftDownCallback.reset(new TeZPriorityMouseCallback(this, &TeButtonLayout::onMouseLeftDown));
_onMouseLeftUpMaxPriorityCallback.reset(new TeCallback1Param<TeButtonLayout, const Common::Point &>(this, &TeButtonLayout::onMouseLeftUpMaxPriority, FLT_MAX));
_onMouseLeftUpCallback.reset(new TeZPriorityMouseCallback(this, &TeButtonLayout::onMouseLeftUp));
TeInputMgr *inputmgr = g_engine->getInputMgr();
inputmgr->_mouseMoveSignal.push_back(_onMousePositionChangedCallback);
inputmgr->_mouseMoveSignal.push_back(_onMousePositionChangedMaxPriorityCallback);
inputmgr->_mouseLDownSignal.push_back(_onMouseLeftDownCallback);
inputmgr->_mouseLUpSignal.push_back(_onMouseLeftUpCallback);
inputmgr->_mouseLUpSignal.push_back(_onMouseLeftUpMaxPriorityCallback);
setEditionColor(TeColor(128, 128, 128, 255));
if (!getDoubleValidationProtectionTimer()->running())
getDoubleValidationProtectionTimer()->start();
}
TeButtonLayout::~TeButtonLayout() {
TeInputMgr *inputmgr = g_engine->getInputMgr();
inputmgr->_mouseMoveSignal.remove(_onMousePositionChangedCallback);
inputmgr->_mouseMoveSignal.remove(_onMousePositionChangedMaxPriorityCallback);
inputmgr->_mouseLDownSignal.remove(_onMouseLeftDownCallback);
inputmgr->_mouseLUpSignal.remove(_onMouseLeftUpCallback);
inputmgr->_mouseLUpSignal.remove(_onMouseLeftUpMaxPriorityCallback);
if (_ownedLayouts) {
if (_upLayout)
delete _upLayout;
if (_downLayout)
delete _downLayout;
if (_rolloverLayout)
delete _rolloverLayout;
if (_hitZoneLayout)
delete _hitZoneLayout;
if (_disabledLayout)
delete _disabledLayout;
}
}
bool TeButtonLayout::isMouseIn(const TeVector2s32 &mouseloc) {
if (!_hitZoneLayout) {
return TeLayout::isMouseIn(mouseloc);
} else {
return _hitZoneLayout->isMouseIn(mouseloc);
}
}
void TeButtonLayout::load(const Common::Path &upImg, const Common::Path &downImg, const Common::Path &overImg) {
TeSpriteLayout *upSprite = nullptr;
if (!upImg.empty()) {
upSprite = new TeSpriteLayout();
if (!upSprite->load(upImg))
warning("Failed to load button up img %s", upImg.toString(Common::Path::kNativeSeparator).c_str());
}
setUpLayout(upSprite);
TeSpriteLayout *downSprite = nullptr;
if (!downImg.empty()) {
downSprite = new TeSpriteLayout();
if (!downSprite->load(downImg))
warning("Failed to load button down img %s", downImg.toString(Common::Path::kNativeSeparator).c_str());
}
setDownLayout(downSprite);
TeSpriteLayout *overSprite = nullptr;
if (!overImg.empty()) {
overSprite = new TeSpriteLayout();
if (!overSprite->load(overImg))
warning("Failed to load button over img %s", overImg.toString(Common::Path::kNativeSeparator).c_str());
}
setRollOverLayout(overSprite);
setHitZone(nullptr);
setDisabledLayout(nullptr);
_ownedLayouts = true;
}
bool TeButtonLayout::onMouseLeftDown(const Common::Point &pt) {
if (!worldVisible() || _currentState == BUTTON_STATE_DISABLED || _ignoreMouseEvents)
return false;
// Note: This doesn't exactly reproduce the original behavior, it's
// very simplified.
bool mouseIn = isMouseIn(pt);
//if (mouseIn)
// debug("mouse down on button '%s' (current state %d)", name().c_str(), _currentState);
enum State newState = _currentState;
switch (_currentState) {
case BUTTON_STATE_DOWN:
if (!mouseIn)
newState = BUTTON_STATE_UP;
/*
// TODO: should this be a click?
if (mouseIn) {
newState = BUTTON_STATE_UP;
debug("mouse clicked button '%s' (from leftdown)", name().c_str());
if (!_validationSound.empty()) {
TeSoundManager *sndMgr = g_engine->getSoundManager();
sndMgr->playFreeSound(_validationSound, _validationSoundVolume, "sfx");
}
setState(newState);
_onMouseClickValidatedSignal.call();
return !_clickPassThrough;
}*/
break;
case BUTTON_STATE_ROLLOVER:
case BUTTON_STATE_UP:
if (mouseIn)
newState = BUTTON_STATE_DOWN;
break;
case BUTTON_STATE_DISABLED:
break;
}
setState(newState);
return mouseIn && !_clickPassThrough;
}
bool TeButtonLayout::onMouseLeftUp(const Common::Point &pt) {
if (!worldVisible() || _currentState == BUTTON_STATE_DISABLED)
return false;
// Note: This doesn't exactly reproduce the original behavior, it's
// somewhat simplified.
bool mouseIn = isMouseIn(pt);
//if (mouseIn)
// debug("mouse up on button '%s' (current state %d)", name().c_str(), _currentState);
enum State newState = _currentState;
switch (_currentState) {
case BUTTON_STATE_DOWN:
newState = BUTTON_STATE_UP;
if (mouseIn) {
debug("mouse clicked button '%s' (from leftup)", name().c_str());
if (!_validationSound.empty()) {
TeSoundManager *sndMgr = g_engine->getSoundManager();
sndMgr->playFreeSound(_validationSound, _validationSoundVolume, "sfx");
}
setState(newState);
bool stopProcessing = _onMouseClickValidatedSignal.call();
return !_clickPassThrough || stopProcessing;
}
break;
case BUTTON_STATE_ROLLOVER:
case BUTTON_STATE_UP:
case BUTTON_STATE_DISABLED:
break;
}
setState(newState);
return mouseIn && !_clickPassThrough;
}
bool TeButtonLayout::onMousePositionChanged(const Common::Point &pt) {
if (!worldVisible() || _ignoreMouseEvents)
return false;
// Note: This doesn't exactly reproduce the original behavior, it's
// very simplified.
bool mouseIn = isMouseIn(pt);
enum State newState = _currentState;
switch (_currentState) {
case BUTTON_STATE_UP:
if (mouseIn) {
newState = BUTTON_STATE_ROLLOVER;
}
break;
case BUTTON_STATE_DOWN:
case BUTTON_STATE_ROLLOVER:
if (!mouseIn) {
newState = BUTTON_STATE_UP;
}
break;
case BUTTON_STATE_DISABLED:
break;
}
setState(newState);
return false;
}
void TeButtonLayout::reset() {
_intArr.clear();
State newState = (_currentState == BUTTON_STATE_DISABLED ? BUTTON_STATE_DISABLED : BUTTON_STATE_UP);
setState(newState);
}
void TeButtonLayout::resetTimeFromLastValidation() {
TeTimer *timer = getDoubleValidationProtectionTimer();
if (!timer->running()) {
timer->start();
}
timer->timeElapsed();
}
uint64 TeButtonLayout::timeFromLastValidation() {
// probably not needed because we reimplemented how this works.
error("TODO: Implement TeButtonLayout::timeFromLastValidation.");
}
void TeButtonLayout::setDisabledLayout(TeLayout *disabledLayout) {
if (_disabledLayout)
removeChild(_disabledLayout);
_disabledLayout = disabledLayout;
if (_disabledLayout) {
_sizeChanged = true;
addChild(_disabledLayout);
//_disabledLayout->setColor(TeColor(0, 0, 0, 0));
//_disabledLayout->setName(name() + "_disabledLayout");
}
setState(_currentState);
}
void TeButtonLayout::setHitZone(TeLayout *hitZoneLayout) {
if (_hitZoneLayout)
removeChild(_hitZoneLayout);
_hitZoneLayout = hitZoneLayout;
if (_hitZoneLayout) {
_sizeChanged = true;
addChild(_hitZoneLayout);
//_hitZoneLayout->setColor(TeColor(0, 0, 0xff, 0xff));
//_hitZoneLayout->setName(name() + "_hitZoneLayout");
}
}
void TeButtonLayout::setDownLayout(TeLayout *downLayout) {
if (_downLayout)
removeChild(_downLayout);
if (downLayout)
addChild(downLayout);
_downLayout = downLayout;
if (sizeType() == ABSOLUTE &&
size().x() == 1.0f && size().y() == 1.0f &&
!_upLayout && _downLayout) {
setSize(_downLayout->size());
}
//if (_downLayout) {
// _downLayout->setColor(TeColor(0, 0, 0, 0));
//_downLayout->setName(name() + "_downLayout");
//}
setState(_currentState);
}
void TeButtonLayout::setRollOverLayout(TeLayout *rollOverLayout) {
if (_rolloverLayout)
removeChild(_rolloverLayout);
_rolloverLayout = rollOverLayout;
if (_rolloverLayout) {
addChild(_rolloverLayout);
//_rolloverLayout->setName(name() + "_rolloverLayout");
}
// This is not a copy paste error, or at least, not *my*
// copy paste error.. it's what the original game does.
//if (_disabledLayout)
// _disabledLayout->setColor(TeColor(0, 0, 0, 0));
setState(_currentState);
}
void TeButtonLayout::setUpLayout(TeLayout *upLayout) {
if (_upLayout)
removeChild(_upLayout);
if (upLayout)
addChild(upLayout);
_upLayout = upLayout;
if (sizeType() == ABSOLUTE &&
size().x() == 1.0f && size().y() == 1.0f &&
!_downLayout && _upLayout) {
setSize(_upLayout->size());
}
if (_upLayout) {
//_upLayout->setColor(TeColor(0, 0, 0, 0));
//_upLayout->setName(name() + "_upLayout");
}
setState(_currentState);
}
void TeButtonLayout::setDoubleValidationProtectionEnabled(bool enable) {
_doubleValidationProtectionEnabled = enable;
}
void TeButtonLayout::setEnable(bool enable) {
if (enable && _currentState == BUTTON_STATE_DISABLED) {
_currentState = BUTTON_STATE_UP;
setState(_currentState);
} else if (!enable && _currentState != BUTTON_STATE_DISABLED) {
_currentState = BUTTON_STATE_DISABLED;
setState(_currentState);
}
}
void TeButtonLayout::setPosition(const TeVector3f32 &pos) {
TeLayout::setPosition(pos);
if (_currentState != BUTTON_STATE_DISABLED) {
//int somethingCount = 0;
if (!_intArr.empty()) {
// probably not needed as we reimplememted how this works.
error("TODO: Implement setPosition logic for up/down state");
}
// Original does something like this, but that breaks in
// Amerzone where the button position can move during a click.
//if (!_ignoreMouseEvents) {
// setState(somethingCount ? BUTTON_STATE_DOWN : BUTTON_STATE_UP);
//}
}
}
void TeButtonLayout::setState(State newState) {
if (_currentState != newState) {
switch (newState) {
case BUTTON_STATE_UP:
_onButtonChangedToStateUpSignal.call();
break;
case BUTTON_STATE_DOWN:
_onButtonChangedToStateDownSignal.call();
break;
case BUTTON_STATE_ROLLOVER:
_onButtonChangedToStateRolloverSignal.call();
break;
default:
break;
}
_currentState = newState;
}
if (_upLayout)
_upLayout->setVisible(_currentState == BUTTON_STATE_UP
|| (_currentState == BUTTON_STATE_ROLLOVER && _rolloverLayout == nullptr)
|| (_currentState == BUTTON_STATE_DOWN && _downLayout == nullptr)
|| (_currentState == BUTTON_STATE_DISABLED && _disabledLayout == nullptr));
if (_downLayout)
_downLayout->setVisible(_currentState == BUTTON_STATE_DOWN);
if (_disabledLayout)
_disabledLayout->setVisible(_currentState == BUTTON_STATE_DISABLED);
if (_rolloverLayout)
_rolloverLayout->setVisible(_currentState == BUTTON_STATE_ROLLOVER);
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,141 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_BUTTON_LAYOUT_H
#define TETRAEDGE_TE_TE_BUTTON_LAYOUT_H
#include "tetraedge/te/te_callback.h"
#include "tetraedge/te/te_layout.h"
#include "tetraedge/te/te_signal.h"
#include "tetraedge/te/te_timer.h"
#include "common/path.h"
namespace Common {
struct Point;
}
namespace Tetraedge {
class TeButtonLayout : public TeLayout {
public:
TeButtonLayout();
virtual ~TeButtonLayout();
enum State {
BUTTON_STATE_UP = 0,
BUTTON_STATE_DOWN = 1,
BUTTON_STATE_DISABLED = 2,
BUTTON_STATE_ROLLOVER = 3
};
uint64 doubleValidationProtectionTimeoutTime() { return 500; }
uint64 frozenValidationTimeoutTime() { return 500; }
virtual bool isMouseIn(const TeVector2s32 &mouseloc) override;
bool onMouseLeftDown(const Common::Point &pt);
bool onMouseLeftDownMaxPriority(const Common::Point &pt) { return false; }
bool onMouseLeftUp(const Common::Point &pt);
bool onMouseLeftUpMaxPriority(const Common::Point &pt) { return false; }
bool onMousePositionChanged(const Common::Point &pt);
bool onMousePositionChangedMaxPriority(const Common::Point &pt) {
_mousePositionChangedCatched = false;
return false;
}
void reset();
void resetTimeFromLastValidation();
uint64 timeFromLastValidation();
void setDisabledLayout(TeLayout *disabledLayout);
void setHitZone(TeLayout *hitZoneLayout);
void setDownLayout(TeLayout *downLayout);
void setRollOverLayout(TeLayout *rollOverLayout);
void setUpLayout(TeLayout *upLayout);
void setDoubleValidationProtectionEnabled(bool enable);
void setEnable(bool enable);
virtual void setPosition(const TeVector3f32 &pos) override;
void setClickPassThrough(bool val) {
_clickPassThrough = val;
}
void setValidationSound(const Common::Path &val) {
_validationSound = val;
}
void setValidationSoundVolume(float val) {
_validationSoundVolume = val;
}
void setState(State newState);
State state() const { return _currentState; };
TeSignal0Param &onMouseClickValidated() { return _onMouseClickValidatedSignal; };
TeSignal0Param &onButtonChangedToStateUpSignal() { return _onButtonChangedToStateUpSignal; };
TeSignal0Param &onButtonChangedToStateDownSignal() { return _onButtonChangedToStateDownSignal; };
TeSignal0Param &onButtonChangedToStateRolloverSignal() { return _onButtonChangedToStateRolloverSignal; };
TeLayout *upLayout() { return _upLayout; }
TeLayout *downLayout() { return _downLayout; }
void setIgnoreMouseEvents(bool val) { _ignoreMouseEvents = val; }
// From TeSpriteButton, a direct way to load the images.
void load(const Common::Path &upImg, const Common::Path &downImg, const Common::Path &overImg);
private:
static bool _mousePositionChangedCatched;
static TeTimer *getDoubleValidationProtectionTimer();
static TeTimer *_doubleValidationProtectionTimer;
bool _doubleValidationProtectionEnabled;
bool _ignoreMouseEvents;
bool _ownedLayouts;
bool _clickPassThrough;
State _currentState;
Common::Path _validationSound;
float _validationSoundVolume;
Common::Array<uint> _intArr;
TeICallback1ParamPtr<const Common::Point &> _onMousePositionChangedMaxPriorityCallback;
TeICallback1ParamPtr<const Common::Point &> _onMousePositionChangedCallback;
TeICallback1ParamPtr<const Common::Point &> _onMouseLeftDownCallback;
TeICallback1ParamPtr<const Common::Point &> _onMouseLeftUpMaxPriorityCallback;
TeICallback1ParamPtr<const Common::Point &> _onMouseLeftUpCallback;
TeLayout *_rolloverLayout;
TeLayout *_disabledLayout;
TeLayout *_hitZoneLayout;
TeLayout *_upLayout;
TeLayout *_downLayout;
TeSignal0Param _onMouseClickValidatedSignal;
TeSignal0Param _onButtonChangedToStateUpSignal;
TeSignal0Param _onButtonChangedToStateDownSignal;
TeSignal0Param _onButtonChangedToStateRolloverSignal;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_BUTTON_LAYOUT_H

View File

@@ -0,0 +1,133 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_CALLBACK_H
#define TETRAEDGE_TE_TE_CALLBACK_H
//#include "common/callback.h"
namespace Tetraedge {
class TeICallback0Param {
public:
virtual ~TeICallback0Param() {}
virtual bool operator()() = 0;
virtual bool call() = 0;
virtual float priority() const = 0;
virtual bool equals(const TeICallback0Param *other) const = 0;
};
/**
* TeCallback is similar to Common::Callback, but it takes 0 parameters,
* supports priority, and the function returns bool.
*/
template<class T> class TeCallback0Param : public TeICallback0Param {
public:
typedef bool(T::*TMethod)();
protected:
T *_object;
TMethod _method;
float _priority;
public:
TeCallback0Param(T *object, TMethod method, float priority_ = 0.0f): _object(object), _method(method), _priority(priority_) {}
virtual ~TeCallback0Param() {}
bool operator()() override { return (_object->*_method)(); }
bool call() override { return (_object->*_method)(); }
virtual float priority() const override { return _priority; }
bool equals(const TeICallback0Param *other) const override {
const TeCallback0Param<T> *o = dynamic_cast<const TeCallback0Param<T> *>(other);
return o && _object == o->_object && _method == o->_method;
}
//virtual void setPriority()
};
template<class T> class TeICallback1Param {
public:
virtual ~TeICallback1Param() {}
virtual bool operator()(T data) = 0;
virtual bool call(T data) = 0;
virtual float &priority() = 0;
virtual bool equals(const TeICallback1Param *other) const = 0;
};
template<class T, typename S> class TeCallback1Param : public TeICallback1Param<S> {
public:
typedef bool(T::*TMethod)(S);
protected:
T *_object;
TMethod _method;
float _priority;
public:
TeCallback1Param(T *object, TMethod method, float priority_ = 0.0f): _object(object), _method(method), _priority(priority_) {}
virtual ~TeCallback1Param() {}
bool operator()(S data) override { return (_object->*_method)(data); }
bool call(S data) override { return (_object->*_method)(data); }
virtual float &priority() override { return _priority; }
bool equals(const TeICallback1Param<S> *other) const override {
const TeCallback1Param<T, S> *o = dynamic_cast<const TeCallback1Param<T, S> *>(other);
return o && _object == o->_object && _method == o->_method;
}
//virtual void setPriority()
};
template<class S, class T> class TeICallback2Param {
public:
virtual ~TeICallback2Param() {}
virtual bool operator()(S data1, T data2) = 0;
virtual bool call(S data1, T data2) = 0;
virtual float &priority() = 0;
virtual bool equals(const TeICallback2Param *other) const = 0;
};
template<class C, class S, typename T> class TeCallback2Param : public TeICallback2Param<S, T> {
public:
typedef bool(C::*TMethod)(S, T);
protected:
C *_object;
TMethod _method;
float _priority;
public:
TeCallback2Param(C *object, TMethod method, float priority_ = 0.0f): _object(object), _method(method), _priority(priority_) {}
virtual ~TeCallback2Param() {}
bool operator()(S data1, T data2) override { return (_object->*_method)(data1, data2); }
bool call(S data1, T data2) override { return (_object->*_method)(data1, data2); }
virtual float &priority() override { return _priority; }
bool equals(const TeICallback2Param<S, T> *other) const override {
const TeCallback2Param<C, S, T> *o = dynamic_cast<const TeCallback2Param<C, S, T> *>(other);
return o && _object == o->_object && _method == o->_method;
}
//virtual void setPriority()
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_CALLBACK_H

View File

@@ -0,0 +1,300 @@
/* 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 "common/file.h"
#include "math/ray.h"
#include "tetraedge/tetraedge.h"
#include "tetraedge/te/te_camera.h"
#include "tetraedge/te/te_camera_xml_parser.h"
#include "tetraedge/te/te_core.h"
#include "tetraedge/te/te_matrix4x4.h"
#include "tetraedge/te/te_renderer.h"
namespace Tetraedge {
TeCamera::TeCamera() : _projectionMatrixType(0), _orthogonalParamL(0.0f),
_orthogonalParamR(1.0f), _orthogonalParamT(1.0f), _orthogonalParamB(0.0f),
_orthNearVal(10.0f), _orthFarVal(4000.0f), _transformA(0), /*_transformB(0),*/
_fov(40.0f), _aspectRatio(1.0f), _viewportX(0), _viewportY(0), _viewportW(0),
_viewportH(0)
{
}
void TeCamera::apply() {
//debug("TeCamera::apply %13s mtype %d fov %.2f persp %.2f orth(%.2f %.2f) pos %s scale %s rot %s", name().c_str(),
// _projectionMatrixType, _fov, _somePerspectiveVal, _orthNearVal, _orthFarVal,
// position().dump().c_str(), scale().dump().c_str(), rotation().dump().c_str());
applyProjection();
applyTransformations();
}
void TeCamera::applyProjection() {
TeRenderer *renderer = g_engine->getRenderer();
renderer->setCurrentCamera(this);
renderer->setViewport(_viewportX, _viewportY,
(uint)(_viewportW * _scale.x()), (uint)(_viewportH * _scale.y()));
renderer->setMatrixMode(TeRenderer::MatrixMode::MM_GL_PROJECTION);
updateProjectionMatrix();
renderer->setMatrixMode(TeRenderer::MatrixMode::MM_GL_PROJECTION);
renderer->loadCurrentMatrixToGL();
renderer->setMatrixMode(TeRenderer::MatrixMode::MM_GL_MODELVIEW);
}
void TeCamera::applyTransformations() {
TeRenderer *renderer = g_engine->getRenderer();
renderer->setMatrixMode(TeRenderer::MatrixMode::MM_GL_MODELVIEW);
TeMatrix4x4 matrix = worldTransformationMatrix();
matrix.inverse();
renderer->loadMatrix(matrix);
renderer->loadCurrentMatrixToGL();
}
void TeCamera::buildOrthoMatrix() {
float widthNorm = FLT_MAX;
if ((_orthogonalParamR - _orthogonalParamL) != 0.0) {
widthNorm = 1.0 / (_orthogonalParamR - _orthogonalParamL);
}
float heightNorm = FLT_MAX;
if (_orthogonalParamB - _orthogonalParamT != 0.0) {
heightNorm = 1.0 / (_orthogonalParamB - _orthogonalParamT);
}
float depthNorm = FLT_MAX;
if ((_orthFarVal - _orthNearVal) != 0.0) {
depthNorm = 1.0 / (_orthFarVal - _orthNearVal);
}
_projectionMatrix.setValue(0, 0, widthNorm * 2.0f);
_projectionMatrix.setValue(1, 0, 0.0);
_projectionMatrix.setValue(2, 0, 0.0);
_projectionMatrix.setValue(3, 0, 0.0);
_projectionMatrix.setValue(0, 1, 0.0);
_projectionMatrix.setValue(1, 1, heightNorm * 2.0f);
_projectionMatrix.setValue(2, 1, 0.0);
_projectionMatrix.setValue(3, 1, 0.0);
_projectionMatrix.setValue(0, 2, 0.0);
_projectionMatrix.setValue(1, 2, 0.0);
_projectionMatrix.setValue(2, 2, depthNorm * -2.0f);
_projectionMatrix.setValue(3, 2, 0.0);
_projectionMatrix.setValue(0, 3, -((_orthogonalParamR + _orthogonalParamL) * widthNorm));
_projectionMatrix.setValue(1, 3, -((_orthogonalParamB + _orthogonalParamT) * heightNorm));
_projectionMatrix.setValue(2, 3, -((_orthFarVal + _orthNearVal) * depthNorm));
_projectionMatrix.setValue(3, 3, 1.0);
}
void TeCamera::buildPerspectiveMatrix() {
_projectionMatrix = TeMatrix4x4();
float f = tanf(_fov * 0.5);
_projectionMatrix.setValue(0, 0, (1.0 / f) / ((float)_viewportW / _viewportH));
_projectionMatrix.setValue(1, 1, 1.0 / f);
_projectionMatrix.setValue(2, 2, (_orthNearVal + _orthFarVal) / (_orthNearVal - _orthFarVal));
_projectionMatrix.setValue(3, 2, (_orthNearVal * _orthFarVal) / (_orthNearVal - _orthFarVal));
_projectionMatrix.setValue(2, 3, -1);
_projectionMatrix.setValue(3, 3, 0.0);
}
void TeCamera::buildPerspectiveMatrix2() {
_projectionMatrix = TeMatrix4x4();
float f = tanf(_fov * 0.5);
_projectionMatrix.setValue(0, 0, 1.0 / f);
_projectionMatrix.setValue(1, 1, _aspectRatio / f);
_projectionMatrix.setValue(2, 2, -(_orthNearVal + _orthFarVal) / (_orthNearVal - _orthFarVal));
_projectionMatrix.setValue(3, 2, 1.0);
_projectionMatrix.setValue(2, 3, (_orthFarVal * 2) * _orthNearVal / (_orthNearVal - _orthFarVal));
_projectionMatrix.setValue(3, 3, 0.0);
}
void TeCamera::buildPerspectiveMatrix3() {
_projectionMatrix = TeMatrix4x4();
float f = tanf(_fov * 0.5);
_projectionMatrix.setValue(0, 0, (1.0 / f) / _aspectRatio);
_projectionMatrix.setValue(1, 1, 1.0 / f);
_projectionMatrix.setValue(2, 2, -(_orthNearVal + _orthFarVal) / (_orthNearVal - _orthFarVal));
_projectionMatrix.setValue(3, 2, 1.0);
_projectionMatrix.setValue(2, 3, (_orthFarVal * 2) * _orthNearVal / (_orthNearVal - _orthFarVal));
_projectionMatrix.setValue(3, 3, 0.0);
}
void TeCamera::draw() {
error("TODO: Implement TeCamera::draw");
}
Math::Ray TeCamera::getRay(const TeVector2s32 &pxloc) {
const Math::Vector3d origin = position();
// point offset relative to viewport
const float xval = (pxloc._x - _viewportX) / fabs(_viewportW);
const float yval = (_viewportH - (pxloc._y - _viewportY)) / fabs(_viewportH);
// normalized to -1..1
const TeVector3f32 projectedPoint(xval * 2.0f - 1.0f, yval * 2.0f - 1.0f, 1.0f);
TeMatrix4x4 projInverse = _projectionMatrix;
bool inverted = projInverse.inverse();
if (!inverted)
error("failed to invert camera projection");
TeVector3f32 unprojectedPoint = projInverse * projectedPoint;
unprojectedPoint.normalize();
TeQuaternion rot = _rotation;
rot.normalize();
TeMatrix4x4 rotMatrix = rot.toTeMatrix();
TeVector3f32 rayDir = rotMatrix * unprojectedPoint;
Math::Ray ray(origin, rayDir);
return ray;
}
void TeCamera::loadXml(const Common::Path &path) {
setName(path.baseName());
_projectionMatrixType = 3;
TeCore *core = g_engine->getCore();
TetraedgeFSNode cameraNode = core->findFile(path);
if (!cameraNode.isReadable()) {
//
// WORKAROUND: scenes/A3_Village/34015 has Camera34010, not 34015
//
Common::String spath = path.toString();
size_t pos = spath.find("34015.xml");
if (pos != Common::String::npos) {
spath.replace(pos + 4, 1, "0");
}
cameraNode = core->findFile(Common::Path(spath, '/'));
}
if (!cameraNode.isReadable()) {
warning("Can't open camera data %s", cameraNode.toString().c_str());
}
TeCameraXmlParser parser;
parser._cam = this;
if (!cameraNode.loadXML(parser))
error("TeCamera::loadXml: can't load file %s", cameraNode.toString().c_str());
if (!parser.parse())
error("TeCamera::loadXml: error parsing %s", cameraNode.toString().c_str());
}
void TeCamera::orthogonalParams(float left, float right, float top, float bottom) {
_orthogonalParamL = left;
_orthogonalParamR = right;
_orthogonalParamT = top;
_orthogonalParamB = bottom;
}
TeMatrix4x4 TeCamera::projectionMatrix() {
switch(_projectionMatrixType) {
case 1:
buildPerspectiveMatrix();
break;
case 2:
buildPerspectiveMatrix2();
break;
case 3:
buildPerspectiveMatrix3();
break;
case 4:
buildOrthoMatrix();
break;
}
return _projectionMatrix;
}
TeVector2f32 TeCamera::projectPoint(const TeVector3f32 &pt) {
_rotation.normalize();
TeMatrix4x4 worldInverse = worldTransformationMatrix();
worldInverse.inverse();
const TeVector3f32 projectedPt = _projectionMatrix * worldInverse * pt;
int halfViewportW = (int)_viewportW / 2;
int halfViewportH = (int)_viewportH / 2;
float projectedX = halfViewportW * (projectedPt.x() + 1.0) + _viewportX;
float projectedY = halfViewportH * (1.0 - projectedPt.y()) + _viewportY;
return TeVector2f32(projectedX, projectedY);
}
TeVector3f32 TeCamera::projectPoint3f32(const TeVector3f32 &pt) {
_rotation.normalize();
TeMatrix4x4 worldInverse = worldTransformationMatrix();
worldInverse.inverse();
const TeVector3f32 projectedPt = _projectionMatrix * worldInverse * pt;
int halfViewportW = (int)_viewportW / 2;
int halfViewportH = (int)_viewportH / 2;
float projectedX = halfViewportW * (projectedPt.x() + 1.0) + _viewportX;
float projectedY = halfViewportH * (1.0 - projectedPt.y()) + _viewportY;
return TeVector3f32(projectedX, projectedY, projectedPt.z());
}
void TeCamera::restore() {
TeRenderer *renderer = g_engine->getRenderer();
renderer->setCurrentColor(TeColor(255, 255, 255, 255));
renderer->setCurrentCamera(nullptr);
}
TeMatrix4x4 TeCamera::transformationMatrix() {
if (!_transformA)
return Te3DObject2::transformationMatrix();
TeMatrix4x4 retval;
warning("TODO: Implement TeCamera::transformationMatrix");
retval.setToIdentity();
return retval;
}
TeVector3f32 TeCamera::transformCoord(const TeVector3f32 &pt) {
_rotation.normalize();
TeQuaternion rot(-_rotation.x(), -_rotation.y(), -_rotation.z(), _rotation.w());
const TeMatrix4x4 rotMatrix = rot.toTeMatrix();
const TeVector3f32 transPt = (_projectionMatrix * rotMatrix) * pt;
const int halfVPWidth = abs((int)(_viewportW / 2));
const int halfVPHeight = abs((int)(_viewportH / 2));
TeVector3f32 retval;
retval.x() = halfVPWidth * (transPt.x() + 1);
retval.y() = halfVPHeight * (transPt.y() + 1);
retval.z() = transPt.z();
return retval;
}
TeVector3f32 TeCamera::transformPoint2Dto3D(const TeVector3f32 &pt) {
TeVector3f32 retval;
TeVector3f32 vp_br(_viewportX + _viewportW, _viewportY + _viewportH, 0.0f);
float x = (pt.x() - _viewportX) / (vp_br.x() - _viewportX);
float y = (pt.y() - _viewportY) / (vp_br.y() - _viewportY);
return TeVector3f32(x * 2 - 1.0f, -(y * 2 - 1.0f), 0.0);
}
void TeCamera::updateProjectionMatrix() {
TeRenderer *renderer = g_engine->getRenderer();
renderer->setMatrixMode(TeRenderer::MatrixMode::MM_GL_PROJECTION);
renderer->loadProjectionMatrix(projectionMatrix());
}
void TeCamera::viewport(int x, int y, uint w, uint h) {
_viewportX = x;
_viewportY = y;
_viewportW = w;
_viewportH = h;
_onViewportChangedSignal.call();
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,116 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_CAMERA_H
#define TETRAEDGE_TE_TE_CAMERA_H
#include "common/path.h"
#include "common/str.h"
#include "math/ray.h"
#include "tetraedge/te/te_3d_object2.h"
#include "tetraedge/te/te_matrix4x4.h"
#include "tetraedge/te/te_references_counter.h"
#include "tetraedge/te/te_vector2s32.h"
#include "tetraedge/te/te_vector2f32.h"
#include "tetraedge/te/te_vector3f32.h"
namespace Tetraedge {
class TeCamera : public Te3DObject2, public TeReferencesCounter {
public:
TeCamera();
void apply();
void applyProjection();
void applyTransformations();
void buildOrthoMatrix();
void buildPerspectiveMatrix();
void buildPerspectiveMatrix2();
void buildPerspectiveMatrix3();
void draw() override;
Math::Ray getRay(const TeVector2s32 &pxloc);
// Syberia 2 redefines loadBin to actually load XML.
// We just have a separate function.
void loadXml(const Common::Path &path);
void orthogonalParams(float f1, float f2, float f3, float f4);
TeMatrix4x4 projectionMatrix();
TeVector2f32 projectPoint(const TeVector3f32 &pt);
TeVector3f32 projectPoint3f32(const TeVector3f32 &pt);
static void restore();
TeMatrix4x4 transformationMatrix();
TeVector3f32 transformCoord(const TeVector3f32 &pt);
TeVector3f32 transformPoint2Dto3D(const TeVector3f32 &pt);
void viewport(int x, int y, uint width, uint height);
TeVector2f32 viewportSize() const { return TeVector2f32(_viewportW, _viewportH); }
TeSignal0Param &onViewportChangedSignal() { return _onViewportChangedSignal; }
void setFov(float fov) { _fov = fov; }
void setOrthoPlanes(float near, float far) {
_orthFarVal = far;
_orthNearVal = near;
}
void setProjMatrixType(int matrixType) { _projectionMatrixType = matrixType; }
int projMatrixType() const { return _projectionMatrixType; }
void setAspectRatio(float val) { _aspectRatio = val; }
float orthoNearPlane() const { return _orthNearVal; }
float orthoFarPlane() const { return _orthFarVal; }
void setOrthoNear(float f) { _orthNearVal = f; }
void setOrthoFar(float f) { _orthFarVal = f; }
float getViewportHeight() const { return _viewportH; }
float getViewportWidth() const { return _viewportW; }
private:
void updateProjectionMatrix();
int _projectionMatrixType; // TODO: Should be an enum.
float _orthNearVal;
float _orthFarVal;
float _fov;
float _aspectRatio;
int _viewportX;
int _viewportY;
uint _viewportW;
uint _viewportH;
int _transformA;
float _orthogonalParamL;
float _orthogonalParamR;
float _orthogonalParamT;
float _orthogonalParamB;
TeMatrix4x4 _projectionMatrix;
TeSignal0Param _onViewportChangedSignal;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_CAMERA_H

View File

@@ -0,0 +1,68 @@
/* 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 "tetraedge/te/te_camera_xml_parser.h"
namespace Tetraedge {
bool TeCameraXmlParser::parserCallback_position(ParserNode *node) {
_cam->setPosition(parsePoint(node));
return true;
}
bool TeCameraXmlParser::parserCallback_rotation(ParserNode *node) {
float x = atof(node->values["x"].c_str());
float y = atof(node->values["y"].c_str());
float z = atof(node->values["z"].c_str());
float w = atof(node->values["w"].c_str());
_cam->setRotation(TeQuaternion(x, y, z, w));
return true;
}
bool TeCameraXmlParser::parserCallback_scale(ParserNode *node) {
_cam->setScale(parsePoint(node));
return true;
}
bool TeCameraXmlParser::parserCallback_fov(ParserNode *node) {
float fov = parseDouble(node);
fov = atanf(1.0f / (1.333333f / tanf(fov / 2)));
_cam->setFov(fov * 2);
return true;
}
bool TeCameraXmlParser::parserCallback_aspect(ParserNode *node) {
_cam->setAspectRatio(parseDouble(node));
return true;
}
bool TeCameraXmlParser::parserCallback_near(ParserNode *node) {
_cam->setOrthoNear(parseDouble(node));
return true;
}
bool TeCameraXmlParser::parserCallback_far(ParserNode *node) {
_cam->setOrthoFar(parseDouble(node));
return true;
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,81 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_CAMERA_XML_PARSER_H
#define TETRAEDGE_TE_TE_CAMERA_XML_PARSER_H
#include "tetraedge/te/te_xml_parser.h"
#include "tetraedge/te/te_camera.h"
namespace Tetraedge {
class TeCameraXmlParser : public TeXmlParser {
public:
// Parser
CUSTOM_XML_PARSER(TeCameraXmlParser) {
XML_KEY(camera)
XML_KEY(position)
XML_PROP(x, true)
XML_PROP(y, true)
XML_PROP(z, true)
KEY_END()
XML_KEY(rotation)
XML_PROP(x, true)
XML_PROP(y, true)
XML_PROP(z, true)
XML_PROP(w, true)
KEY_END()
XML_KEY(scale)
XML_PROP(x, true)
XML_PROP(y, true)
XML_PROP(z, true)
KEY_END()
XML_KEY(fov)
XML_PROP(value, true)
KEY_END()
XML_KEY(aspect)
XML_PROP(value, true)
KEY_END()
XML_KEY(near)
XML_PROP(value, true)
KEY_END()
XML_KEY(far)
XML_PROP(value, true)
KEY_END()
KEY_END()
} PARSER_END()
public:
bool parserCallback_camera(ParserNode *node) { return true; }
bool parserCallback_position(ParserNode *node);
bool parserCallback_rotation(ParserNode *node);
bool parserCallback_scale(ParserNode *node);
bool parserCallback_fov(ParserNode *node);
bool parserCallback_aspect(ParserNode *node);
bool parserCallback_near(ParserNode *node);
bool parserCallback_far(ParserNode *node);
TeCamera *_cam;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_CAMERA_XML_PARSER_H

View File

@@ -0,0 +1,258 @@
/* 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 "tetraedge/tetraedge.h"
#include "tetraedge/te/te_checkbox_layout.h"
#include "tetraedge/te/te_color.h"
#include "tetraedge/te/te_callback.h"
#include "tetraedge/te/te_input_mgr.h"
namespace Tetraedge {
TeCheckboxLayout::TeCheckboxLayout() : _activeLayout(nullptr), _unactiveLayout(nullptr),
_activeDisabledLayout(nullptr), _unactiveDisabledLayout(nullptr),
_activeRollOverLayout(nullptr), _unactiveRollOverLayout(nullptr), _hitZone(nullptr),
_clickPassThrough(false), _state(CheckboxState6)
{
_onMouseLeftUpCallback.reset(new TeCallback1Param<TeCheckboxLayout, const Common::Point &>(this, &TeCheckboxLayout::onMouseLeftUp));
_onMouseLeftUpMaxPriorityCallback.reset(new TeCallback1Param<TeCheckboxLayout, const Common::Point &>(this, &TeCheckboxLayout::onMouseLeftUpMaxPriority));
_onMouseLeftDownCallback.reset(new TeCallback1Param<TeCheckboxLayout, const Common::Point &>(this, &TeCheckboxLayout::onMouseLeftDown));
_onMousePositionChangedCallback.reset(new TeCallback1Param<TeCheckboxLayout, const Common::Point &>(this, &TeCheckboxLayout::onMousePositionChanged));
TeInputMgr *inputmgr = g_engine->getInputMgr();
inputmgr->_mouseMoveSignal.push_back(_onMousePositionChangedCallback);
inputmgr->_mouseLDownSignal.push_back(_onMouseLeftDownCallback);
inputmgr->_mouseLUpSignal.push_back(_onMouseLeftUpCallback);
inputmgr->_mouseLUpSignal.push_back(_onMouseLeftUpMaxPriorityCallback);
}
TeCheckboxLayout::~TeCheckboxLayout() {
TeInputMgr *inputmgr = g_engine->getInputMgr();
inputmgr->_mouseMoveSignal.remove(_onMousePositionChangedCallback);
inputmgr->_mouseLDownSignal.remove(_onMouseLeftDownCallback);
inputmgr->_mouseLUpSignal.remove(_onMouseLeftUpCallback);
inputmgr->_mouseLUpSignal.remove(_onMouseLeftUpMaxPriorityCallback);
}
void TeCheckboxLayout::setActiveLayout(TeLayout *layout) {
if (_activeLayout)
removeChild(_activeLayout);
_activeLayout = layout;
if (layout) {
addChild(layout);
layout->setColor(TeColor(0, 0, 0, 0));
}
setState(_state);
}
void TeCheckboxLayout::setUnactiveLayout(TeLayout *layout) {
if (_unactiveLayout)
removeChild(_unactiveLayout);
_unactiveLayout = layout;
warning("TODO: Add extra code in TeCheckboxLayout::setUnactiveLayout.");
if (layout) {
addChild(layout);
//layout->setColor(TeColor(0, 0, 0, 0));
}
setState(_state);
}
void TeCheckboxLayout::setActiveDisabledLayout(TeLayout *layout) {
if (_activeDisabledLayout)
removeChild(_activeDisabledLayout);
_activeDisabledLayout = layout;
if (layout) {
addChild(layout);
//layout->setColor(TeColor(0, 0, 0, 0));
}
setState(_state);
}
void TeCheckboxLayout::setUnactiveDisabledLayout(TeLayout *layout) {
if (_unactiveDisabledLayout)
removeChild(_unactiveDisabledLayout);
_unactiveDisabledLayout = layout;
if (layout) {
addChild(layout);
//layout->setColor(TeColor(0, 0, 0, 0));
}
setState(_state);
}
void TeCheckboxLayout::setActiveRollOverLayout(TeLayout *layout) {
if (_activeRollOverLayout)
removeChild(_activeRollOverLayout);
_activeRollOverLayout = layout;
if (layout) {
addChild(layout);
//layout->setColor(TeColor(0, 0, 0, 0));
}
setState(_state);
}
void TeCheckboxLayout::setUnactiveRollOverLayout(TeLayout *layout) {
if (_unactiveRollOverLayout)
removeChild(_unactiveRollOverLayout);
_unactiveRollOverLayout = layout;
if (layout) {
addChild(layout);
//layout->setColor(TeColor(0, 0, 0, 0));
}
setState(_state);
}
void TeCheckboxLayout::setHitZone(TeLayout *layout) {
if (_hitZone)
removeChild(_hitZone);
_hitZone = layout;
if (layout) {
addChild(layout);
//layout->setColor(TeColor(0, 0, 0xff, 0xff));
}
}
void TeCheckboxLayout::setClickPassThrough(bool val) {
_clickPassThrough = val;
}
void TeCheckboxLayout::setActivationSound(const Common::String &sound) {
_activationSound = sound;
}
void TeCheckboxLayout::setUnactivationSound(const Common::String &sound) {
_unactivationSound = sound;
}
bool TeCheckboxLayout::isMouseIn(const TeVector2s32 &pt) {
if (_hitZone) {
return _hitZone->isMouseIn(pt);
} else {
return TeLayout::isMouseIn(pt);
}
}
void TeCheckboxLayout::setState(enum State state) {
if (_state == state)
return;
_state = state;
if (_activeLayout)
_activeLayout->setVisible(state == CheckboxStateActive);
if (_unactiveLayout)
_unactiveLayout->setVisible(state == CheckboxStateUnactive);
if (_activeRollOverLayout)
_activeRollOverLayout->setVisible(state == CheckboxStateActiveRollover);
if (_unactiveRollOverLayout)
_unactiveRollOverLayout->setVisible(state == CheckboxStateUnactiveRollover);
if (_activeDisabledLayout)
_activeDisabledLayout->setVisible(state == CheckboxStateActiveDisabled);
if (_unactiveDisabledLayout)
_unactiveDisabledLayout->setVisible(state == CheckboxStateUnactiveDisabled);
_onStateChangedSignal.call(state);
}
bool TeCheckboxLayout::onMouseLeftUp(const Common::Point &pt) {
if (!worldVisible())
return false;
bool mouseIn = isMouseIn(pt);
State newState = _state;
switch (_state) {
case CheckboxStateActive:
if (mouseIn)
newState = CheckboxStateUnactive;
break;
case CheckboxStateUnactive:
if (mouseIn)
newState = CheckboxStateActive;
break;
case CheckboxStateActiveRollover:
if (mouseIn)
newState = CheckboxStateUnactiveRollover;
else
newState = CheckboxStateActive;
break;
case CheckboxStateUnactiveRollover:
if (mouseIn)
newState = CheckboxStateActiveRollover;
else
newState = CheckboxStateUnactive;
break;
case CheckboxStateActiveDisabled:
case CheckboxStateUnactiveDisabled:
default:
break;
}
setState(newState);
return !_clickPassThrough;
}
bool TeCheckboxLayout::onMouseLeftUpMaxPriority(const Common::Point &pt) {
if (!worldVisible())
return false;
//bool mouseIn = isMouseIn(pt);
//error("TODO: Implement TeCheckboxLayout::onMouseLeftUpMaxPriority");
return false;
}
bool TeCheckboxLayout::onMouseLeftDown(const Common::Point &pt) {
if (!worldVisible())
return false;
//bool mouseIn = isMouseIn(pt);
//error("TODO: Implement TeCheckboxLayout::onMouseLeftDown");
return false;
}
bool TeCheckboxLayout::onMousePositionChanged(const Common::Point &pt) {
if (!worldVisible())
return false;
State newState = _state;
bool mouseIn = isMouseIn(pt);
if (!mouseIn) {
if (_state == CheckboxStateActiveRollover)
newState = CheckboxStateActive;
else if (_state == CheckboxStateUnactiveRollover)
newState = CheckboxStateUnactive;
} else {
if (_state == CheckboxStateActive)
newState = CheckboxStateActiveRollover;
else if (_state == CheckboxStateUnactive)
newState = CheckboxStateUnactiveRollover;
}
setState(newState);
return false;
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,89 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_CHECKBOX_LAYOUT_H
#define TETRAEDGE_TE_TE_CHECKBOX_LAYOUT_H
#include "tetraedge/te/te_layout.h"
#include "tetraedge/te/te_vector2s32.h"
namespace Tetraedge {
class TeCheckboxLayout : public TeLayout {
public:
TeCheckboxLayout();
virtual ~TeCheckboxLayout();
enum State {
CheckboxStateActive,
CheckboxStateUnactive,
CheckboxStateActiveDisabled,
CheckboxStateUnactiveDisabled,
CheckboxStateActiveRollover,
CheckboxStateUnactiveRollover,
CheckboxState6
};
void setActiveLayout(TeLayout *layout);
void setUnactiveLayout(TeLayout *layout);
void setActiveDisabledLayout(TeLayout *layout);
void setUnactiveDisabledLayout(TeLayout *layout);
void setActiveRollOverLayout(TeLayout *layout);
void setUnactiveRollOverLayout(TeLayout *layout);
void setHitZone(TeLayout *layout);
void setClickPassThrough(bool val);
void setActivationSound(const Common::String &sound);
void setUnactivationSound(const Common::String &sound);
bool isMouseIn(const TeVector2s32 &pt) override;
void setState(State state);
TeSignal1Param<State> &onStateChangedSignal() { return _onStateChangedSignal; }
bool onMouseLeftUp(const Common::Point &pt);
bool onMouseLeftUpMaxPriority(const Common::Point &pt);
bool onMouseLeftDown(const Common::Point &pt);
bool onMousePositionChanged(const Common::Point &pt);
private:
TeLayout *_activeLayout;
TeLayout *_unactiveLayout;
TeLayout *_activeDisabledLayout;
TeLayout *_unactiveDisabledLayout;
TeLayout *_activeRollOverLayout;
TeLayout *_unactiveRollOverLayout;
TeLayout *_hitZone;
bool _clickPassThrough;
Common::String _activationSound;
Common::String _unactivationSound;
State _state;
TeSignal1Param<State> _onStateChangedSignal;
TeICallback1ParamPtr<const Common::Point &> _onMouseLeftUpCallback;
TeICallback1ParamPtr<const Common::Point &> _onMouseLeftUpMaxPriorityCallback;
TeICallback1ParamPtr<const Common::Point &> _onMouseLeftDownCallback;
TeICallback1ParamPtr<const Common::Point &> _onMousePositionChangedCallback;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_CHECKBOX_LAYOUT_H

View File

@@ -0,0 +1,65 @@
/* 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 "tetraedge/te/te_clip_layout.h"
#include "tetraedge/tetraedge.h"
#include "tetraedge/game/application.h"
#include "tetraedge/te/te_renderer.h"
namespace Tetraedge {
TeClipLayout::TeClipLayout() {
}
void TeClipLayout::draw() {
if (!worldVisible())
return;
TeRenderer *renderer = g_engine->getRenderer();
bool prevScissorEnabled = renderer->scissorEnabled();
const TeVector2f32 prevScissorPos(renderer->scissorX(), renderer->scissorY());
const TeVector2f32 prevScissorSize(renderer->scissorWidth(), renderer->scissorHeight());
const TeMatrix4x4 worldTransform = worldTransformationMatrix();
const TeVector3f32 v1 = worldTransform * TeVector3f32(0, 0, 0);
const TeVector3f32 v2 = worldTransform * TeVector3f32(1, 0, 0);
const TeVector3f32 v3 = worldTransform * TeVector3f32(0, 1, 0);
const TeVector3f32 offset((v2 - v1).length(), (v3 - v1).length(), 1);
const TeVector3f32 thisSize(xSize(), ySize(), 0);
const TeVector3f32 newScissorSize = thisSize * offset;
const TeVector3f32 transformedSize(v1.x() - newScissorSize.x() / 2, v1.y() + newScissorSize.y() / 2, 0);
const TeVector3f32 winSize = g_engine->getApplication()->getMainWindow().size();
const TeVector3f32 newScissorOff(transformedSize.x() + winSize.x() / 2, winSize.y() - (transformedSize.y() + winSize.y() / 2), 0);
renderer->setScissorEnabled(true);
renderer->setScissor(newScissorOff.x(), newScissorOff.y(), newScissorSize.x(), newScissorSize.y());
TeLayout::draw();
renderer->setScissor(prevScissorPos.getX(), prevScissorPos.getY(), prevScissorSize.getX(), prevScissorSize.getY());
renderer->setScissorEnabled(prevScissorEnabled);
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,39 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_CLIP_LAYOUT_H
#define TETRAEDGE_TE_TE_CLIP_LAYOUT_H
#include "tetraedge/te/te_layout.h"
namespace Tetraedge {
// Not used in Syberia1
class TeClipLayout : public TeLayout {
public:
TeClipLayout();
virtual void draw() override;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_CLIP_LAYOUT_H

View File

@@ -0,0 +1,81 @@
/* 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 "tetraedge/te/te_color.h"
namespace Tetraedge {
TeColor::TeColor() : _c{0, 0, 0, 0xff} {
}
TeColor::TeColor(uint32 rgba) {
_c[0] = (byte)(rgba >> 24);
_c[1] = (byte)(rgba >> 16);
_c[2] = (byte)(rgba >> 8);
_c[3] = (byte)rgba;
}
TeColor::TeColor(uint16 shortcol) {
_c[0] = (byte)(shortcol >> 7) & 0xf8;
_c[1] = (byte)(shortcol >> 2) & 0xf8;
_c[2] = (byte)shortcol << 3;
_c[3] = 0;
}
TeColor::TeColor(byte r, byte g, byte b, byte a) : _c{r, g, b, a} {
}
uint32 TeColor::getPacked() const {
return (g() & 0xf8) << 2 | (r() & 0xf8) << 7 | (b() >> 3);
}
uint32 TeColor::getPacked32() const {
return (r() << 24) | (g() << 16) | (b() << 8) | a();
}
bool TeColor::serialize(Common::WriteStream &stream) const {
for (int i = 0; i < 4; i++)
stream.writeByte(_c[i]);
return true;
}
bool TeColor::deserialize(Common::ReadStream &stream) {
for (int i = 0; i < 4; i++)
_c[i] = stream.readByte();
return true;
}
TeColor operator*(const TeColor &c1, const TeColor &c2) {
return TeColor(
((c2.r() * (c1.r() / 255.0)) / 255.0) * 255.0,
((c2.g() * (c1.g() / 255.0)) / 255.0) * 255.0,
((c2.b() * (c1.b() / 255.0)) / 255.0) * 255.0,
((c2.a() * (c1.a() / 255.0)) / 255.0) * 255.0);
}
TeColor operator*(const TeColor &c, double amount) {
return TeColor(c.r() * amount, c.g() * amount, c.b() * amount, c.a() * amount);
}
TeColor operator+(const TeColor &c1, const TeColor &c2) {
return TeColor(c1.r() + c2.r(), c1.g() + c2.g(), c1.b() + c2.b(), c1.a() + c2.a());
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,76 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_COLOR_H
#define TETRAEDGE_TE_TE_COLOR_H
#include "common/types.h"
#include "common/stream.h"
namespace Tetraedge {
class TeColor {
public:
TeColor();
TeColor(uint32 rgba);
TeColor(uint16 shortcol);
TeColor(byte r, byte g, byte b, byte a);
byte &r() { return _c[0]; };
byte &g() { return _c[1]; };
byte &b() { return _c[2]; };
byte &a() { return _c[3]; };
const byte &r() const { return _c[0]; };
const byte &g() const { return _c[1]; };
const byte &b() const { return _c[2]; };
const byte &a() const { return _c[3]; };
uint32 getPacked() const;
uint32 getPacked32() const;
bool serialize(Common::WriteStream &stream) const;
bool deserialize(Common::ReadStream &stream);
bool operator==(const TeColor &c) const {
return (_c[0] == c._c[0] && _c[1] == c._c[1] &&
_c[2] == c._c[2] && _c[3] == c._c[3]);
}
bool operator!=(const TeColor &c) {
return !operator==(c);
}
Common::String dump() const {
return Common::String::format("TeColor(%d %d %d %d)",
_c[0], _c[1], _c[2], _c[3]);
}
private:
byte _c[4];
};
TeColor operator*(const TeColor &c1, const TeColor &c2);
TeColor operator*(const TeColor &c1, double amount);
TeColor operator+(const TeColor &c1, const TeColor &c2);
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_COLOR_H

View File

@@ -0,0 +1,245 @@
/* 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 "common/file.h"
#include "common/fs.h"
#include "common/debug.h"
#include "common/config-manager.h"
#include "common/language.h"
#include "common/tokenizer.h"
#include "tetraedge/te/te_core.h"
#include "tetraedge/tetraedge.h"
#include "tetraedge/te/te_png.h"
#include "tetraedge/te/te_images_sequence.h"
#include "tetraedge/te/te_jpeg.h"
#include "tetraedge/te/te_zlib_jpeg.h"
#include "tetraedge/te/te_theora.h"
#include "tetraedge/te/te_tga.h"
namespace Tetraedge {
TeCore::TeCore() : _loc(nullptr), _coreNotReady(true), _resourcesRoot("") {
create();
}
void TeCore::addLoc(TeILoc *loc) {
if (_loc) {
warning("TeCore::addLoc: There is already a loc");
}
_loc = loc;
}
void TeCore::create() {
const char *langCode = getLanguageCode(g_engine->getGameLanguage());
const Common::String confLang = ConfMan.get("language");
Common::String useLang = "en";
if (langCode)
useLang = langCode;
if (!confLang.empty())
useLang = confLang;
language(useLang);
_coreNotReady = false;
_activityTrackingTimer.alarmSignal().add(this, &TeCore::onActivityTrackingAlarm);
warning("TODO: TeCore::create: Finish implementing me.");
const Common::FSNode gameRoot(ConfMan.getPath("path"));
if (!gameRoot.isDirectory())
error("Game directory should be a directory");
const Common::FSNode resNode = (g_engine->getGamePlatform() == Common::kPlatformMacintosh
? gameRoot.getChild("Resources")
: gameRoot);
if (!resNode.isDirectory())
error("Resources directory should exist in game");
_resourcesRoot = Common::FSDirectory(resNode, 5, false, false, true);
}
TeICodec *TeCore::createVideoCodec(const Common::String &extn) {
// The original engine has more formats and even checks for alpha maps,
// but it never uses them.
if (TePng::matchExtension(extn)) {
// png codec needs to know extension
return new TePng(extn);
} else if (TeJpeg::matchExtension(extn)) {
return new TeJpeg();
} else if (TeZlibJpeg::matchExtension(extn)) {
return new TeZlibJpeg();
} else if (TeTheora::matchExtension(extn)) {
return new TeTheora();
} else if (TeTga::matchExtension(extn)) {
return new TeTga();
} else if (TeImagesSequence::matchExtension(extn)) {
return new TeImagesSequence();
}
return nullptr;
}
TeICodec *TeCore::createVideoCodec(const TetraedgeFSNode &node, const Common::Path &origPath) {
//
// Need to use the original requested path (not the node path) as
// it might include the #anim directive for animated pngs.
//
const Common::String filename = origPath.baseName();
if (!filename.contains('.'))
return nullptr;
Common::String extn = filename.substr(filename.findLastOf('.') + 1);
extn.toLowercase();
TeICodec *codec = createVideoCodec(extn);
if (!codec)
error("TTeCore::createVideoCodec: Unrecognised format %s", filename.c_str());
return codec;
}
const Common::String &TeCore::fileFlagSystemFlag(const Common::String &name) const {
return _fileSystemFlags.find(name)->_value;
}
void TeCore::fileFlagSystemSetFlag(const Common::String &name, const Common::String &val) {
// TODO: Impmenent this fully to check possible values
_fileSystemFlags.setVal(name, val);
}
bool TeCore::fileFlagSystemFlagsContains(const Common::String &name) const {
error("TODO: Implement TeCore::fileFlagSystemFlagsContains");
return false;
}
Common::Array<Common::String> TeCore::fileFlagSystemPossibleFlags() {
error("TODO: Implement TeCore::fileFlagSystemPossibleFlags");
return Common::Array<Common::String>();
}
bool TeCore::fileFlagSystemPossibleFlagsContains(const Common::String &name) const {
error("TODO: Implement TeCore::fileFlagSystemPossibleFlagsContains");
return false;
}
const Common::String &TeCore::language() const {
return fileFlagSystemFlag("language");
}
void TeCore::language(const Common::String &val) {
return fileFlagSystemSetFlag("language", val);
}
bool TeCore::onActivityTrackingAlarm() {
error("TODO: Implement TeCore::onActivityTrackingAlarm");
}
static bool _checkFileFlag(const Common::String &fname, const Common::HashMap<Common::String, bool, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> &activeTags) {
Common::StringTokenizer tokenizer(fname, "-");
while(!tokenizer.empty())
if (activeTags.getValOrDefault(tokenizer.nextToken(), false))
return true;
return false;
}
static void _findFileRecursively(const TetraedgeFSNode &parent,
const Common::HashMap<Common::String, bool, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> &activeTags,
const Common::String &fname,
Common::Array<TetraedgeFSNode> &foundFiles,
int maxDepth) {
TetraedgeFSNode child = parent.getChild(Common::Path(fname, '/'));
if (child.exists())
foundFiles.push_back(child);
if (maxDepth <= 0)
return;
TetraedgeFSList list;
if (!parent.getChildren(list))
return;
for (TetraedgeFSList::const_iterator it = list.begin(); it != list.end(); it++)
if (_checkFileFlag(it->getName(), activeTags))
_findFileRecursively(*it, activeTags, fname, foundFiles, maxDepth - 1);
}
TetraedgeFSNode TeCore::findFile(const Common::Path &path, bool quiet) const {
Common::Array<TetraedgeFSNode> dirNodes;
const Common::Path dir = path.getParent();
TetraedgeFSNode node;
const Common::Array<Common::Archive *> &roots = g_engine->getRootArchives();
for (Common::Archive *const archive : roots) {
TetraedgeFSNode archiveNode(archive);
node = archiveNode.getChild(path);
if (node.exists())
return node;
dirNodes.push_back(archiveNode.getChild(dir));
}
Common::String fname = path.getLastComponent().toString();
// Slight HACK: Remove 'comments' used to specify animated pngs
if (fname.contains('#'))
fname = fname.substr(0, fname.find('#'));
Common::HashMap<Common::String, bool, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> activeFlags;
for (Common::HashMap<Common::String, Common::String, Common::CaseSensitiveString_Hash, Common::CaseSensitiveString_EqualTo>::const_iterator it = _fileSystemFlags.begin();
it != _fileSystemFlags.end(); it++)
activeFlags[it->_value] = true;
// This is to minimize functionality changes from the previous implementation.
// I'm not sure if it's needed
// TODO: Figure out what to do with this. Right now we set the flag
// to "SD" but use assets from "HD". This seems to give the best
// results, but is fundamentally wrong.
activeFlags.erase("SD");
activeFlags["HD"] = true;
for (int attempt = 0; attempt < 2; attempt++) {
if (attempt == 1)
activeFlags["en"] = true;
for (uint dirNode = 0; dirNode < dirNodes.size(); dirNode++) {
Common::Array<TetraedgeFSNode> foundFiles;
_findFileRecursively(dirNodes[dirNode], activeFlags, fname, foundFiles, 5);
if (foundFiles.empty())
continue;
TetraedgeFSNode best = foundFiles[0];
int bestDepth = best.getDepth();
for (uint i = 1; i < foundFiles.size(); i++) {
int depth = foundFiles[i].getDepth();
if (depth > bestDepth) {
bestDepth = depth;
best = foundFiles[i];
}
}
if (attempt == 1 && !quiet)
debug("TeCore::findFile Falled back to English for %s", path.toString().c_str());
return best;
}
}
// Didn't find it at all..
if (!quiet)
debug("TeCore::findFile Searched but didn't find %s", path.toString().c_str());
return TetraedgeFSNode(nullptr, path);
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,77 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_CORE_H
#define TETRAEDGE_TE_TE_CORE_H
#include "common/array.h"
#include "common/str.h"
#include "common/path.h"
#include "common/hashmap.h"
#include "common/hash-str.h"
#include "tetraedge/te/te_i_loc.h"
#include "tetraedge/te/te_i_codec.h"
#include "tetraedge/te/te_timer.h"
namespace Tetraedge {
class TeCore {
public:
TeCore();
void addLoc(TeILoc *loc);
void create();
TeICodec *createVideoCodec(const TetraedgeFSNode &node, const Common::Path &origPath);
TeICodec *createVideoCodec(const Common::String &extn);
const Common::String &fileFlagSystemFlag(const Common::String &name) const;
bool fileFlagSystemFlagsContains(const Common::String &name) const;
Common::Array<Common::String> fileFlagSystemPossibleFlags();
bool fileFlagSystemPossibleFlagsContains(const Common::String &name) const;
void fileFlagSystemSetFlag(const Common::String &name, const Common::String &val);
const Common::String &language() const;
void language(const Common::String &val);
TeILoc *loc() { return _loc; }
bool onActivityTrackingAlarm();
// Note: this is not in the original, but it's not clear how the original
// adds things like "PC-MacOSX" to the path, and there is not clear logic
// to them, so here we are.
TetraedgeFSNode findFile(const Common::Path &path, bool quiet = false) const;
TetraedgeFSNode getFSNode(const Common::Path &path) const;
bool _coreNotReady;
private:
TeILoc *_loc;
Common::HashMap<Common::String, Common::String, Common::CaseSensitiveString_Hash, Common::CaseSensitiveString_EqualTo> _fileSystemFlags;
Common::FSDirectory _resourcesRoot;
TeTimer _activityTrackingTimer;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_CORE_H

View File

@@ -0,0 +1,80 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_CURVE_ANIM2_H
#define TETRAEDGE_TE_TE_CURVE_ANIM2_H
#include "tetraedge/te/te_animation.h"
#include "tetraedge/te/te_interpolation.h"
namespace Tetraedge {
template<class T> static T linearInterpolation(T &obj1, T &obj2, double amount) {
amount = CLIP<double>(amount, 0.0, 1.0);
return (obj1 * (1.0 - amount)) + (obj2 * amount);
}
template<class T, class S>
class TeCurveAnim2 : public TeAnimation {
public:
typedef void(T::*TMethod)(const S &);
TeCurveAnim2() : _callbackObj(nullptr), _callbackMethod(nullptr), _duration(0), _lastUpdateTime(0) {}
virtual ~TeCurveAnim2() {}
void setCurve(const Common::Array<float> &curve) {
// The original writes the curve to a stream to load it back in in
// the interpolation.. we just skip that with a direct array copy.
_interp.load(curve);
}
void update(double millis) {
_lastUpdateTime = millis;
double amount = _interp.interpole(millis, _duration);
const S interpVal = linearInterpolation<S>(_startVal, _endVal, amount);
//debug("CurveAnim %.02f/%.02f (%.02f) -> %s", time, _maxTime, amount, interpVal.toString().c_str());
(_callbackObj->*_callbackMethod)(interpVal);
if (_lastUpdateTime >= _duration) {
if (_repeatCount == -1) {
seekToStart();
} else {
stop();
onFinished().call();
}
}
}
S _startVal;
S _endVal;
T *_callbackObj;
TMethod _callbackMethod;
double _duration;
private:
TeInterpolation _interp;
double _lastUpdateTime;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_CURVE_ANIM2_H

View File

@@ -0,0 +1,92 @@
/* 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 "tetraedge/te/te_extended_text_layout.h"
namespace Tetraedge {
TeExtendedTextLayout::TeExtendedTextLayout() {
_textLayout.setSizeType(RELATIVE_TO_PARENT);
_textLayout.setAnchor(TeVector3f32(0.5, 0.0, 0.0));
_textLayout.setPosition(TeVector3f32(0.5, 0.0, 0.0));
const TeVector3f32 usersz = userSize();
_textLayout.setSize(TeVector3f32(1.0, 1.0, usersz.z()));
_scrollingLayout.setContentLayout(&_textLayout);
_scrollingLayout.setSizeType(RELATIVE_TO_PARENT);
_scrollingLayout.setSize(TeVector3f32(1.0, 1.0, usersz.z()));
_scrollingLayout.setDirection(TeVector3f32(0.0, 1.0, 0.0));
_scrollingLayout.setMouseControl(false);
_scrollingLayout.setEnclose(true);
_scrollingLayout.setAutoScrollLoop(1);
_scrollingLayout.setAutoScrollDelay(4000);
_scrollingLayout.setAutoScrollAnimation1Enabled(true);
_scrollingLayout.setAutoScrollAnimation1Delay(0);
_scrollingLayout.setAutoScrollAnimation1Speed(0.1f);
_scrollingLayout.setAutoScrollAnimation2Enabled(false);
_scrollingLayout.setAutoScrollAnimation2Delay(0);
_scrollingLayout.setAutoScrollAnimation2Speed(0.1f);
addChild(&_scrollingLayout);
}
void TeExtendedTextLayout::setAutoScrollDelay(int val) {
_scrollingLayout.setAutoScrollDelay(val);
}
void TeExtendedTextLayout::setAutoScrollSpeed(float val) {
_scrollingLayout.setAutoScrollAnimation1Speed(val);
_scrollingLayout.setAutoScrollAnimation2Speed(val);
}
void TeExtendedTextLayout::setText(const Common::String &val) {
_textLayout.setText(val);
_scrollingLayout.resetScrollPosition();
_scrollingLayout.playAutoScroll();
}
void TeExtendedTextLayout::setInterLine(float val) {
_textLayout.setInterLine(val);
}
void TeExtendedTextLayout::setWrapMode(TeTextBase2::WrapMode mode) {
if (mode == TeTextBase2::WrapModeFixed) {
_textLayout.setAnchor(TeVector3f32(0.5f, 0.0f, 0.0f));
_textLayout.setPosition(TeVector3f32(0.5f, 0.0f, 0.0f));
_scrollingLayout.setDirection(TeVector3f32(0.0, 1.0, 0.0));
} else {
_textLayout.setAnchor(TeVector3f32(0.0f, 0.5f, 0.0f));
_textLayout.setPosition(TeVector3f32(0.0f, 0.5f, 0.0f));
_scrollingLayout.setDirection(TeVector3f32(1.0, 0.0, 0.0));
}
_scrollingLayout.setContentLayout(nullptr);
_scrollingLayout.setContentLayout(&_textLayout);
_textLayout.setWrapMode(mode);
}
void TeExtendedTextLayout::setTextSizeType(int type) {
_textLayout.setTextSizeType(type);
}
void TeExtendedTextLayout::setTextSizeProportionalToWidth(int val) {
_textLayout.setTextSizeProportionalToWidth(val);
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,52 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_EXTENDED_TEXT_LAYOUT_H
#define TETRAEDGE_TE_TE_EXTENDED_TEXT_LAYOUT_H
#include "tetraedge/te/te_i_text_layout.h"
#include "tetraedge/te/te_text_layout.h"
#include "tetraedge/te/te_scrolling_layout.h"
#include "tetraedge/te/te_clip_layout.h"
namespace Tetraedge {
class TeExtendedTextLayout : public TeClipLayout, public TeITextLayout {
public:
TeExtendedTextLayout();
void setAutoScrollDelay(int val);
void setAutoScrollSpeed(float val);
void setText(const Common::String &val) override;
void setInterLine(float val) override;
void setWrapMode(TeTextBase2::WrapMode mode) override;
void setTextSizeType(int type) override;
void setTextSizeProportionalToWidth(int val) override;
private:
TeScrollingLayout _scrollingLayout;
TeTextLayout _textLayout;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_EXTENDED_TEXT_LAYOUT_H

View File

@@ -0,0 +1,231 @@
/* 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 "tetraedge/te/te_font2.h"
#include "tetraedge/tetraedge.h"
#include "tetraedge/te/te_3d_object2.h"
#include "tetraedge/te/te_core.h"
namespace Tetraedge {
bool operator==(const KernChars &l, const KernChars &r) {
return l._c1 == r._c1 && l._c2 == r._c2;
}
TeFont2::TeFont2() : _numChars(0), _hasKernData(false), _maxHeight(0) {
}
TeFont2::~TeFont2() {
}
bool TeFont2::load(const Common::Path &path) {
if (_loadedPath == path)
return true; // already open
TeCore *core = g_engine->getCore();
TetraedgeFSNode node = core->findFile(path);
return load(node);
}
bool TeFont2::load(const TetraedgeFSNode &node) {
const Common::Path path = node.getPath();
unload();
setAccessName(path);
_loadedPath = path;
if (!node.exists()) {
warning("TeFont2::load: Can't read from %s", node.toString().c_str());
return false;
}
Common::ScopedPtr<Common::SeekableReadStream> file(node.createReadStream());
if (!Te3DObject2::loadAndCheckFourCC(*file, "TESF")) {
warning("TeFont2::load: Invalid magic in %s", node.toString().c_str());
return false;
}
_numChars = file->readUint32LE();
if (_numChars > 65535)
error("TeFont2::load: improbable number of char points %d", _numChars);
TeVector2s32::deserialize(*file, _somePt);
TeVector3f32::deserialize(*file, _someVec);
_hasKernData = (file->readByte() != 0);
if (_hasKernData) {
uint32 numKernData = file->readUint32LE();
if (numKernData > 10000)
error("TeFont2::load: improbable number of kerning points %d", numKernData);
for (uint32 i = 0; i < numKernData; i++) {
KernChars kc;
TeVector3f32 vec;
kc._c1 = file->readUint32LE();
kc._c2 = file->readUint32LE();
vec.x() = file->readFloatLE();
vec.y() = file->readFloatLE();
_kernData[kc] = vec;
//debug("KernChars: '%c'-'%c' (%.2f, %.2f)", (char)kc._c1, (char)kc._c2, vec.x(), vec.y());
}
}
for (uint32 i = 0; i < _numChars; i++) {
GlyphData2 g;
g._xSz = file->readFloatLE();
g._ySz = file->readFloatLE();
_maxHeight = MAX(_maxHeight, g._ySz);
g._xOff = file->readFloatLE();
g._yOff = file->readFloatLE();
g._xAdvance = file->readFloatLE();
// TODO: What are these other floats?
for (uint j = 0; j < 3; j++)
g._floats[j] = file->readFloatLE();
g._vec.x() = file->readFloatLE();
g._vec.y() = file->readFloatLE();
_glyphs.push_back(g);
uint32 charNo = file->readUint32LE();
_uintArray.push_back(charNo);
/*
if (i >= 35 && i <= 127)
debug("Char data %c: sz (%.1f %.1f) off (%.1f %.1f) xadv %.1f %.1f %.1f %.1f texloc (%.1f, %.1f) %d", (char)i,
g._xSz, g._ySz, g._xOff, g._yOff, g._xAdvance, g._floats[0], g._floats[1], g._floats[2],
g._vec.x(), g._vec.y(), charNo);
*/
}
if (!_texture.load(*file, "png")) {
warning("Invalid png data in %s", node.toString().c_str());
return false;
}
return true;
}
void TeFont2::unload() {
_texture.free();
_uintArray.clear();
_glyphs.clear();
_kernData.clear();
_numChars = 0;
}
int TeFont2::getFontHeight() const {
return _maxHeight;
}
int TeFont2::getMaxCharWidth() const {
int maxWidth = 0;
for (auto &glyph : _glyphs) {
maxWidth = MAX(maxWidth, (int)glyph._xAdvance);
}
return maxWidth;
}
int TeFont2::getCharWidth(uint32 chr) const {
if (chr >= _glyphs.size())
return 0;
return (int)_glyphs[chr]._xAdvance;
}
void TeFont2::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const {
if (chr >= _glyphs.size())
return;
if (_texture.empty())
error("Call to TeFont2::drawChar but no texture loaded");
const GlyphData2 g = _glyphs[chr];
if (!g._xSz || !g._ySz)
return;
Common::Rect srcRect;
srcRect.left = (int)g._vec.x();
srcRect.top = _texture.h - (int)g._vec.y() - g._ySz;
srcRect.right = srcRect.left + g._xSz;
srcRect.bottom = srcRect.top + g._ySz;
int dstX = x + g._xOff;
int dstY = _maxHeight - g._yOff;
if (dstX + srcRect.width() > dst->w)
srcRect.right = srcRect.left + (dst->w - dstX);
if (dstY + srcRect.height() > dst->h)
srcRect.bottom = srcRect.top + (dst->h - dstY);
debug("TeFont2::drawChar %c (%d, %d) from (%d,%d-%d,%d)", chr, x, y,
srcRect.left, srcRect.top, srcRect.right, srcRect.bottom);
dst->copyRectToSurface(_texture, dstX, dstY, srcRect);
}
int TeFont2::getKerningOffset(uint32 left, uint32 right) const {
KernChars kc { left, right };
if (_kernData.contains(kc))
return (int)_kernData[kc].x();
return 0;
}
TeVector3f32 TeFont2::kerning(uint pxSize, uint isocode1, uint isocode2) {
KernChars kc { isocode1, isocode2 };
if (_kernData.contains(kc))
return _kernData[kc];
return TeVector3f32();
}
Common::Rect TeFont2::getBBox(const Common::String &str, int fontSize) {
Common::Rect rect;
for (uint i = 0; i < str.size(); i++) {
uint c = str[i];
if (c >= _glyphs.size())
continue;
const GlyphData2 &g = _glyphs[c];
rect.top = MIN(rect.top, (int16)-g._yOff);
rect.bottom = MAX(rect.bottom, (int16)(-g._yOff + g._ySz));
rect.right += g._xAdvance;
if (i < str.size() - 1) {
rect.right += kerning(fontSize, c, str[i+1]).x();
}
}
return rect;
}
Common::Rect TeFont2::getBoundingBox(uint32 chr) const {
if (chr > _glyphs.size())
return Common::Rect();
Common::Rect rect;
rect.left = (int)_glyphs[chr]._xOff;
rect.right = rect.left + _glyphs[chr]._xSz;
rect.top = _maxHeight - _glyphs[chr]._yOff;
rect.bottom = _maxHeight;
return rect;
}
float TeFont2::height(uint pxSize) {
return _maxHeight;
}
Graphics::Font *TeFont2::getAtSize(uint size) {
return this;
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,107 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_FONT2_H
#define TETRAEDGE_TE_TE_FONT2_H
#include "common/str.h"
#include "common/file.h"
#include "common/hashmap.h"
#include "graphics/font.h"
#include "tetraedge/te/te_resource.h"
#include "tetraedge/te/te_vector2s32.h"
#include "tetraedge/te/te_vector3f32.h"
#include "tetraedge/te/te_3d_texture.h"
#include "tetraedge/te/te_intrusive_ptr.h"
#include "tetraedge/te/te_i_font.h"
namespace Tetraedge {
struct KernChars {
uint32 _c1;
uint32 _c2;
};
bool operator==(const KernChars &l, const KernChars &r);
}
namespace Common {
template<> struct Hash<Tetraedge::KernChars> : public UnaryFunction<Tetraedge::KernChars, uint> {
uint operator()(Tetraedge::KernChars val) const { return val._c1 * 7333 + val._c2; }
};
}
namespace Tetraedge {
/**
* A pre-rendered font format with positioning data used in Amerzone
* ('tef' format)
*/
class TeFont2 : public TeIFont, public Graphics::Font {
public:
struct GlyphData2 {
float _xSz;
float _ySz;
float _xOff; // from nominal location
float _yOff; // top location, from baseline
float _xAdvance;
float _floats[3];
TeVector3f32 _vec; // location in texture - offset from bottom left
};
TeFont2();
virtual ~TeFont2();
bool load(const Common::Path &path);
bool load(const TetraedgeFSNode &node);
void unload();
Graphics::Font *getAtSize(uint size) override;
virtual int getFontHeight() const override;
virtual int getMaxCharWidth() const override;
virtual int getCharWidth(uint32 chr) const override;
virtual void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override;
virtual int getKerningOffset(uint32 left, uint32 right) const override;
virtual Common::Rect getBBox(const Common::String &str, int fontSize) override;
virtual Common::Rect getBoundingBox(uint32 chr) const override;
virtual TeVector3f32 kerning(uint pxSize, uint isocode1, uint isocode2) override;
virtual float height(uint pxSize) override;
private:
Common::Path _loadedPath;
uint32 _numChars;
TeVector2s32 _somePt;
TeVector3f32 _someVec;
bool _hasKernData;
float _maxHeight;
// Records a map of character pairs to kerning offsets
Common::HashMap<KernChars, TeVector3f32> _kernData;
Common::Array<uint32> _uintArray;
Common::Array<GlyphData2> _glyphs;
TeImage _texture;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_FONT2_H

View File

@@ -0,0 +1,95 @@
/* 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 "tetraedge/tetraedge.h"
#include "tetraedge/te/te_font3.h"
#include "tetraedge/te/te_core.h"
#include "graphics/font.h"
#include "graphics/fonts/ttf.h"
#include "common/unicode-bidi.h"
namespace Tetraedge {
TeFont3::TeFont3() {
}
TeFont3::~TeFont3() {
unload();
}
Graphics::Font *TeFont3::getAtSize(uint size) {
if (_fonts.contains(size))
return _fonts.getVal(size);
if (!_fontFile)
load(getAccessName());
if (!_fontFile)
error("TeFont3::: Couldn't open font file %s.", getAccessName().toString(Common::Path::kNativeSeparator).c_str());
_fontFile->seek(0);
Graphics::Font *newFont = Graphics::loadTTFFont(_fontFile.get(), DisposeAfterUse::NO, size, Graphics::kTTFSizeModeCharacter, 0, 0, Graphics::kTTFRenderModeNormal);
if (!newFont) {
error("TeFont3::: Couldn't load font %s at size %d.", _loadedPath.toString(Common::Path::kNativeSeparator).c_str(), size);
}
_fonts.setVal(size, newFont);
return newFont;
}
bool TeFont3::load(const Common::Path &path) {
if (_loadedPath == path && _fontFile)
return true; // already open
TeCore *core = g_engine->getCore();
TetraedgeFSNode node = core->findFile(path);
return load(node);
}
bool TeFont3::load(const TetraedgeFSNode &node) {
const Common::Path fontPath = node.getPath();
if (_loadedPath == fontPath && _fontFile)
return true; // already open
setAccessName(fontPath);
_loadedPath = fontPath;
if (!node.exists()) {
warning("TeFont3::load: Can't find %s", node.toString().c_str());
return false;
}
_fontFile.reset(node.createReadStream());
if (!_fontFile) {
warning("TeFont3::load: can't open %s", node.toString().c_str());
return false;
}
return true;
}
void TeFont3::unload() {
for (auto &entry : _fonts) {
delete entry._value;
}
_fonts.clear();
_fontFile.reset();
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,73 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_FONT3_H
#define TETRAEDGE_TE_TE_FONT3_H
#include "common/file.h"
#include "common/str.h"
#include "common/path.h"
#include "common/types.h"
#include "common/hashmap.h"
#include "common/rect.h"
#include "tetraedge/te/te_resource.h"
#include "tetraedge/te/te_vector3f32.h"
#include "tetraedge/te/te_image.h"
#include "tetraedge/te/te_intrusive_ptr.h"
#include "tetraedge/te/te_3d_texture.h"
#include "tetraedge/te/te_i_font.h"
namespace Graphics {
class Font;
}
namespace Tetraedge {
/**
* TeFont3 is a minimal wrapper on Graphics::Font for TTF files, supporting
* multiple sizes and matching the original TeFont api a bit closer.
*/
class TeFont3 : public TeIFont {
public:
TeFont3();
virtual ~TeFont3();
bool load(const Common::Path &path);
bool load(const TetraedgeFSNode &node);
void unload();
private:
TeIntrusivePtr<Te3DTexture> getFontSizeData(int size) const {
return _fontSizeData[size];
}
Graphics::Font *getAtSize(uint size) override;
Common::ScopedPtr<Common::SeekableReadStream> _fontFile;
Common::HashMap<uint, Graphics::Font *> _fonts;
Common::Path _loadedPath;
Common::HashMap<uint, TeIntrusivePtr<Te3DTexture>> _fontSizeData;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_FONT3_H

View File

@@ -0,0 +1,75 @@
/* 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 "common/util.h"
#include "math/utils.h"
#include "tetraedge/te/te_frame_anim.h"
namespace Tetraedge {
TeFrameAnim::TeFrameAnim() : _nbFrames(0), _frameRate(25.0f), _reversed(false), _minFrame(0),
_numFramesToShow(-1), _startTime(0), _endTime(FLT_MAX), _loopCount(0), _lastFrameShown(-1) {
}
void TeFrameAnim::update(double millis) {
int minFrame = MIN(_minFrame, _nbFrames);
int maxFrame = MIN(_minFrame + _numFramesToShow, _nbFrames);
double frameNo = _frameRate * millis / 1000.0;
int loopsDone;
int framesToPlay = maxFrame - minFrame;
if (framesToPlay <= 0 && _nbFrames > 0)
framesToPlay = _nbFrames;
int frameToShow;
if (framesToPlay == 0) {
frameToShow = 0;
loopsDone = -1;
} else if (framesToPlay > 0) {
loopsDone = (int)((int)frameNo / framesToPlay);
if (!_reversed) {
frameToShow = (int)frameNo % framesToPlay + minFrame;
} else {
frameToShow = (maxFrame - 1) - (int)frameNo % framesToPlay;
}
} else {
// else, we don't know the total frames.. just keep asking for higher.
loopsDone = -1;
frameToShow = (int)frameNo;
}
if (_loopCount == -1 || loopsDone < _loopCount) {
if (frameToShow == _lastFrameShown)
return;
_lastFrameShown = frameToShow;
if (_frameChangedSignal.call()) {
// got signal that we'd finished.
if (_nbFrames == 0)
_nbFrames = frameToShow;
}
} else {
stop();
_onFinishedSignal.call();
}
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,69 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_FRAME_ANIM_H
#define TETRAEDGE_TE_TE_FRAME_ANIM_H
#include "tetraedge/te/te_signal.h"
#include "tetraedge/te/te_animation.h"
namespace Tetraedge {
class TeFrameAnim : public TeAnimation {
public:
TeFrameAnim();
virtual ~TeFrameAnim() {}
void update(double millis) override;
TeSignal0Param &frameChangedSignal() { return _frameChangedSignal; };
void setFrameRate(float rate) { _frameRate = rate; }
void setNbFrames(int frames) { _nbFrames = frames; }
void setLoopCount(int count) { _loopCount = count; }
void setReversed(bool reverse) { _reversed = reverse; }
void setStartTime(double start) { _startTime = start; }
void setEndTime(double end) { _endTime = end; }
int lastFrameShown() const { return _lastFrameShown; }
private:
float _frameRate;
// TODO: Isn't this the same as TeAnimation::_repeatCount??
int _loopCount;
int _nbFrames;
int _numFramesToShow;
bool _reversed;
int _lastFrameShown;
int _minFrame;
double _startTime;
double _endTime;
TeSignal0Param _frameChangedSignal;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_FRAME_ANIM_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,174 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_FREE_MOVE_ZONE_H
#define TETRAEDGE_TE_TE_FREE_MOVE_ZONE_H
#include "common/array.h"
#include "tetraedge/te/te_bezier_curve.h"
#include "tetraedge/te/te_camera.h"
#include "tetraedge/te/te_intrusive_ptr.h"
#include "tetraedge/te/te_obp.h"
#include "tetraedge/te/te_pick_mesh2.h"
#include "tetraedge/te/te_vector3f32.h"
#include "tetraedge/te/te_act_zone.h"
#include "tetraedge/te/te_timer.h"
namespace Tetraedge {
namespace micropather {
class MicroPather;
}
// TODO: should these structs be moved to their own headers?
struct TeBlocker {
Common::String _s;
TeVector2f32 _pts[2];
bool _enabled;
};
struct TeRectBlocker {
Common::String _s;
TeVector2f32 _pts[4];
bool _enabled;
};
class TeFreeMoveZoneGraph;
class TeFreeMoveZone : public TePickMesh2 {
public:
struct CollidePoint {
TeVector3f32 _point;
float _distance;
};
TeFreeMoveZone();
~TeFreeMoveZone();
float bordersDistance() const;
void buildAStar();
void calcGridMatrix();
void clear();
Common::Array<TeVector3f32> collisions(const TeVector3f32 &v1, const TeVector3f32 &v2);
TeVector3f32 correctCharacterPosition(const TeVector3f32 &pos, bool *flagout, bool f);
TeIntrusivePtr<TeBezierCurve> curve(const TeVector3f32 &startpt, const TeVector2s32 &endpt, float param_5, bool findMeshFlag);
TeIntrusivePtr<TeBezierCurve> curve(const TeVector3f32 &startpt, const TeVector3f32 &endpt);
void draw() override;
TeVector3f32 findNearestPointOnBorder(const TeVector2f32 &pt);
byte hasBlockerIntersection(const TeVector2s32 &pt);
bool hasCellBorderIntersection(const TeVector2s32 &pt);
TeActZone *isInZone(const TeVector3f32 &pt);
bool loadAStar(const Common::Path &path, const TeVector2s32 &size);
bool loadBin(const Common::Path &path, const Common::Array<TeBlocker> *blockers,
const Common::Array<TeRectBlocker> *rectblockers, const Common::Array<TeActZone> *actzones,
const TeVector2f32 &gridSize);
bool loadBin(Common::ReadStream &stream, const Common::Array<TeBlocker> *blockers,
const Common::Array<TeRectBlocker> *rectblockers, const Common::Array<TeActZone> *actzones,
const TeVector2f32 &gridSize);
// loadBin() 2 versions, seem unused
// name(), onPositionChanged(), position(), rotate(), rotation(), scale(),
// setName(), setPosition(), setRotation(), setScale(), setVisible(),
// translate(), and visible() are all implemented in original, but all
// just do the same as super.
bool onViewportChanged();
void preUpdateGrid();
TeVector2s32 projectOnAStarGrid(const TeVector3f32 &pt);
Common::Array<TeVector3f32> removeInsignificantPoints(const Common::Array<TeVector3f32> &points);
void setBordersDistance(float dist);
void setCamera(TeIntrusivePtr<TeCamera> &cam, bool noRecalcProjPoints);
void setNbTriangles(uint len);
void setPathFindingOccluder(const TeOBP &occluder);
void setVertex(uint offset, const TeVector3f32 &vertex);
TeVector3f32 transformAStarGridInWorldSpace(const TeVector2s32 &gridpt);
float transformHeightMin(float minval);
TeVector3f32 transformVectorInWorldSpace(float param_3, float param_4);
void updateBorders();
void updateGrid(bool force);
void updatePickMesh();
void updateProjectedPoints();
void updateTransformedVertices();
static float normalizeAngle(float angle);
static void deserialize(Common::ReadStream &stream, TeFreeMoveZone &dest, const Common::Array<TeBlocker> *blockers,
const Common::Array<TeRectBlocker> *rectblockers, const Common::Array<TeActZone> *actzones);
static void serialize(Common::WriteStream &stream, const TeFreeMoveZone &src, bool updateFirst);
static TePickMesh2 *findNearestMesh(TeIntrusivePtr<TeCamera> &camera, const TeVector2s32 &frompt,
Common::Array<TePickMesh2*> &pickMeshes, TeVector3f32 *outloc, bool lastHitFirst);
const Common::Array<TeVector3f32> freeMoveZoneVerticies() const { return _freeMoveZoneVerticies; }
static void setCollisionSlide(bool val) { _collisionSlide = val; }
private:
TeVector2s32 aStarResolution() const;
const Common::Array<TeActZone> *_actzones;
const Common::Array<TeBlocker> *_blockers;
const Common::Array<TeRectBlocker> *_rectBlockers;
Common::Array<TeVector3f32> _freeMoveZoneVerticies;
Common::Array<uint> _pickMesh;
Common::Array<TeVector3f32> _transformedVerticies;
Common::Array<uint> _borders;
Common::Array<TeVector2f32> _projectedPoints;
TeVector2f32 _gridSquareSize;
TeVector2f32 _gridTopLeft;
TeVector2f32 _gridBottomRight;
TeVector2f32 _loadGridSize; // At least, it seems unused?
TeMatrix4x4 _gridMatrix;
TeMatrix4x4 _inverseWorldTransform;
float _gridWorldY;
TeOBP _obp;
TeIntrusivePtr<TeCamera> _camera;
//static TeIntrusivePtr<TeCamera> _globalCamera;
TeFreeMoveZoneGraph *_graph;
bool _loadedFromBin;
bool _gridDirty;
bool _transformedVerticiesDirty;
bool _bordersDirty;
bool _pickMeshDirty;
bool _projectedPointsDirty;
micropather::MicroPather *_micropather;
TeTimer _updateTimer;
Common::Path _aszGridPath;
static bool _collisionSlide;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_FREE_MOVE_ZONE_H

View File

@@ -0,0 +1,38 @@
/* 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 "tetraedge/te/te_frustum.h"
namespace Tetraedge {
TeFrustum::TeFrustum() {
}
void TeFrustum::update(TeCamera &cam) {
const TeMatrix4x4 camProjMatrix = cam.projectionMatrix();
TeMatrix4x4 camWorldMatrix = cam.worldTransformationMatrix();
camWorldMatrix.inverse();
const TeMatrix4x4 camProjWorld = camProjMatrix * camWorldMatrix;
setup(camProjWorld.toScummVMMatrix());
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,47 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_FRUSTUM_H
#define TETRAEDGE_TE_TE_FRUSTUM_H
#include "math/frustum.h"
#include "tetraedge/te/te_camera.h"
#include "tetraedge/te/te_vector3f32.h"
#include "tetraedge/te/te_matrix4x4.h"
namespace Tetraedge {
class TeFrustum : public Math::Frustum {
public:
TeFrustum();
// unused..
//void computeNormal(unsigned int val);
//bool pointIsIn(const TeVector3f32 &pt) const;
//bool sphereIsIn(const TeVector3f32 &vec, float f) const;
void update(TeCamera &camera);
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_FRUSTUM_H

View File

@@ -0,0 +1,29 @@
/* 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 "tetraedge/te/te_i_3d_object2.h"
namespace Tetraedge {
TeI3DObject2::TeI3DObject2() {
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,36 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_I_3D_OBJECT2_H
#define TETRAEDGE_TE_TE_I_3D_OBJECT2_H
namespace Tetraedge {
class TeI3DObject2 {
public:
TeI3DObject2();
virtual ~TeI3DObject2() {}
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_I_3D_OBJECT2_H

View File

@@ -0,0 +1,67 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_I_CODEC_H
#define TETRAEDGE_TE_TE_I_CODEC_H
#include "common/path.h"
#include "common/stream.h"
#include "tetraedge/te/te_color.h"
#include "tetraedge/te/te_image.h"
#include "tetraedge/te/te_signal.h"
namespace Tetraedge {
class TeICodec {
public:
TeICodec() {};
virtual ~TeICodec() {};
virtual bool load(const TetraedgeFSNode &node) = 0;
virtual uint width() = 0;
virtual uint height() = 0;
virtual int nbFrames() = 0;
virtual Graphics::PixelFormat pixelFormat() = 0;
virtual void setLeftBorderSize(uint val) = 0;
virtual uint leftBorderSize() = 0;
virtual void setRightBorderSize(uint val) = 0;
virtual uint rightBorderSize() = 0;
virtual void setBottomBorderSize(uint val) = 0;
virtual uint bottomBorderSize() = 0;
virtual void setTopBorderSize(uint val) = 0;
virtual uint topBorderSize() = 0;
virtual float frameRate() = 0;
virtual bool update(uint i, TeImage &imgout) = 0;
virtual bool isAtEnd() = 0;
virtual TeSignal0Param &onVideoFinished() { return _finishedSignal; };
virtual void setColorKeyActivated(bool val) = 0;
virtual void setColorKey(const TeColor &col) = 0;
virtual void setColorKeyTolerence(float val) = 0;
private:
TeSignal0Param _finishedSignal;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_I_CODEC_H

View File

@@ -0,0 +1,133 @@
/* 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 "tetraedge/tetraedge.h"
#include "tetraedge/te/te_font3.h"
#include "tetraedge/te/te_core.h"
#include "graphics/font.h"
#include "graphics/fonts/ttf.h"
#include "common/unicode-bidi.h"
namespace Tetraedge {
TeIFont::TeIFont() {
_codePage = codePage();
}
TeIFont::~TeIFont() {
}
TeIFont::GlyphData TeIFont::glyph(uint pxSize, uint charcode) {
Graphics::Font *font = getAtSize(pxSize);
Common::Rect bbox = font->getBoundingBox(charcode);
TeImage *img = new TeImage();
Common::SharedPtr<TePalette> nullpal;
img->createImg(bbox.width(), bbox.height(), nullpal, Graphics::PixelFormat::createFormatRGBA32());
font->drawChar(img, charcode, 0, 0, 0xffffffff);
GlyphData retval;
retval._charcode = charcode;
retval._bitmapSize = bbox;
retval._img = img;
return retval;
}
Common::CodePage TeIFont::codePage() const {
Common::String lang = g_engine->getCore()->language();
if (g_engine->isUtf8Release())
return Common::CodePage::kUtf8;
if (lang == "ru")
return Common::kISO8859_5;
if (g_engine->getGamePlatform() == Common::Platform::kPlatformAndroid)
return Common::CodePage::kUtf8;
if (lang == "he")
return Common::kWindows1255;
return Common::kLatin1;
}
int TeIFont::wordWrapText(const Common::String &str, int fontSize, int maxWidth, Common::Array<Common::String> &lines) {
Graphics::Font *font = getAtSize(fontSize);
Common::Array<Common::U32String> u32lines;
int retval = font->wordWrapText(str.decode(_codePage), maxWidth, u32lines);
for (auto &line: u32lines) {
lines.push_back(line.encode(_codePage));
}
return retval;
}
Common::Rect TeIFont::getBBox(const Common::String &str, int fontSize) {
Graphics::Font *font = getAtSize(fontSize);
return font->getBoundingBox(str.decode(_codePage));
}
int TeIFont::getHeight(int fontSize) {
Graphics::Font *font = getAtSize(fontSize);
return font->getFontHeight();
}
void TeIFont::draw(TeImage &destImage, const Common::String &str, int fontSize, int yoff, const TeColor &col, TeIFont::AlignStyle align) {
Graphics::Font *font = getAtSize(fontSize);
Graphics::TextAlign talign;
switch (align) {
case AlignLeft:
talign = Graphics::kTextAlignLeft;
break;
case AlignRight:
talign = Graphics::kTextAlignRight;
break;
// Note: we don't support justify.. just center. (justify is not used anyway)
case AlignJustify:
case AlignCenter:
default:
talign = Graphics::kTextAlignCenter;
break;
}
const Graphics::PixelFormat &fmt = destImage.format;
uint32 uintcol = ((uint32)col.a() << fmt.aShift) | ((uint32)(col.r()) << fmt.rShift)
| ((uint32)(col.g()) << fmt.gShift) | ((uint32)(col.b()) << fmt.bShift);
Common::U32String line = str.decode(_codePage);
if (g_engine->getCore()->language() == "he")
line = Common::convertBiDiU32String(line).visual;
font->drawString(&destImage, line, 0, yoff, destImage.w, uintcol, talign);
}
float TeIFont::ascender(uint pxSize) {
Graphics::Font *font = getAtSize(pxSize);
return font->getFontAscent();
}
float TeIFont::descender(uint pxSize) {
error("TODO: Implement TeFont3::descender");
}
float TeIFont::height(uint pxSize) {
Graphics::Font *font = getAtSize(pxSize);
return font->getFontHeight();
}
TeVector3f32 TeIFont::kerning(uint pxSize, uint charcode1, uint charcode2) {
Graphics::Font *font = getAtSize(pxSize);
int offset = font->getKerningOffset(charcode1, charcode2);
// note: not perfect because we have no Y, but it's ok..
return TeVector3f32(offset, 0.0f, 0.0f);
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,78 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_I_FONT_H
#define TETRAEDGE_TE_TE_I_FONT_H
#include "common/str.h"
#include "graphics/font.h"
#include "tetraedge/te/te_color.h"
#include "tetraedge/te/te_image.h"
#include "tetraedge/te/te_resource.h"
#include "tetraedge/te/te_vector3f32.h"
namespace Tetraedge {
/**
* A wrapper to provide a TeFont-like interface using ScummVM'S font class.
*/
class TeIFont : public TeResource {
public:
enum AlignStyle {
AlignLeft,
AlignRight,
AlignJustify,
AlignCenter
};
struct GlyphData {
uint32 _charcode;
Common::Rect _bitmapSize;
TeIntrusivePtr<TeImage> _img;
};
TeIFont();
virtual ~TeIFont();
virtual Graphics::Font *getAtSize(uint size) = 0;
virtual float ascender(uint pxSize);
virtual float descender(uint pxSize);
virtual float height(uint pxSize);
virtual TeVector3f32 kerning(uint pxSize, uint isocode1, uint isocode2);
virtual void draw(TeImage &destImage, const Common::String &str, int fontSize, int yoff, const TeColor &col, AlignStyle alignMode);
virtual Common::Rect getBBox(const Common::String &str, int fontSize);
virtual int getHeight(int fontSize);
virtual int wordWrapText(const Common::String &str, int fontSize, int maxWidth, Common::Array<Common::String> &lines);
virtual TeIFont::GlyphData glyph(uint pxSize, uint charcode);
protected:
Common::CodePage _codePage;
private:
Common::CodePage codePage() const;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_I_FONT_H

View File

@@ -0,0 +1,31 @@
/* 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 "tetraedge/te/te_i_layout.h"
namespace Tetraedge {
TeILayout::TeILayout() {
}
// TODO: Add more functions here.
} // end namespace Tetraedge

View File

@@ -0,0 +1,52 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_I_LAYOUT_H
#define TETRAEDGE_TE_TE_I_LAYOUT_H
#include "tetraedge/te/te_vector3f32.h"
namespace Tetraedge {
class TeILayout {
public:
TeILayout();
enum CoordinatesType {
ABSOLUTE, // use User Position?
RELATIVE_TO_PARENT // scale based on parent size
};
enum DrawMode {
DrawMode0
};
enum RatioMode {
RATIO_MODE_NONE = 0,
RATIO_MODE_LETTERBOX = 1,
RATIO_MODE_PAN_SCAN = 2
};
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_I_LAYOUT_H

View File

@@ -0,0 +1,36 @@
/* 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 "tetraedge/te/te_i_loc.h"
namespace Tetraedge {
TeILoc::TeILoc() {
}
const Common::String *TeILoc::text(const Common::String &key) const {
if (!_map.contains(key)) {
return nullptr;
}
return &_map.find(key)->_value;
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,44 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_I_LOC_H
#define TETRAEDGE_TE_TE_I_LOC_H
#include "common/str.h"
#include "common/hash-str.h"
namespace Tetraedge {
class TeILoc {
public:
TeILoc();
virtual ~TeILoc() {};
virtual const Common::String *text(const Common::String &key) const;
protected:
Common::StringMap _map;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_I_LOC_H

View File

@@ -0,0 +1,31 @@
/* 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 "tetraedge/te/te_i_text_layout.h"
namespace Tetraedge {
TeITextLayout::TeITextLayout() {
}
// TODO: Add more functions here.
} // end namespace Tetraedge

View File

@@ -0,0 +1,45 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_I_TEXT_LAYOUT_H
#define TETRAEDGE_TE_TE_I_TEXT_LAYOUT_H
#include "tetraedge/te/te_layout.h"
#include "tetraedge/te/te_text_base2.h"
namespace Tetraedge {
class TeITextLayout {
public:
TeITextLayout();
virtual ~TeITextLayout() {}
virtual void setText(const Common::String &val) = 0;
virtual void setInterLine(float val) = 0;
virtual void setWrapMode(TeTextBase2::WrapMode mode) = 0;
virtual void setTextSizeType(int type) = 0;
virtual void setTextSizeProportionalToWidth(int val) = 0;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_I_TEXT_LAYOUT_H

View File

@@ -0,0 +1,140 @@
/* 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 "tetraedge/tetraedge.h"
#include "common/endian.h"
#include "common/file.h"
#include "common/rect.h"
#include "tetraedge/te/te_core.h"
#include "tetraedge/te/te_image.h"
#include "tetraedge/te/te_i_codec.h"
#include "tetraedge/te/te_scummvm_codec.h"
namespace Tetraedge {
TeImage::TeImage() : ManagedSurface() {
}
TeImage::TeImage(const TeImage &other) : ManagedSurface() {
copyFrom(other);
error("TODO: Implement TeImage::TeImage copy constructor");
}
void TeImage::copy(TeImage &dest, const TeVector2s32 &vec1, const TeVector2s32 &vec2, const TeVector2s32 &vec3) const {
error("TODO: Implement TeImage::copy");
}
uint64 TeImage::countPixelsOfColor(const TeColor &col) const {
error("TODO: Implement TeImage::countPixelsOfColor");
}
/*
void TeImage::create() {
// Never used, but in original seems to do the same as destroy??
destroy();
}*/
void TeImage::createImg(uint xsize, uint ysize, Common::SharedPtr<TePalette> &pal,
const Graphics::PixelFormat &pxformat, uint bufxsize, uint bufysize) {
Graphics::ManagedSurface::create(xsize, ysize, pxformat);
if (pxformat.aBits() > 0)
Graphics::ManagedSurface::fillRect(Common::Rect(0, 0, xsize, ysize), 0);
}
void TeImage::deserialize(Common::ReadStream &stream) {
error("TODO: Implement TeImage::deserialize");
}
void TeImage::destroy() {
Graphics::ManagedSurface::free();
}
void TeImage::drawPlot(void *outbuf, int x, int y, const TeVector2s32 &bufsize, const TeColor &col) {
error("TODO: Implement TeImage::drawPlot");
}
void TeImage::fill(byte val) {
error("TODO: Implement TeImage::fill");
}
void TeImage::fill(byte r, byte g, byte b, byte a) {
Common::Rect wholeSurf(0, 0, w, h);
uint32 col = ((uint32)r << format.rShift) | ((uint32)g << format.gShift) | ((uint32)b << format.bShift) | ((uint32)a << format.aShift);
Graphics::ManagedSurface::fillRect(wholeSurf, col);
}
void TeImage::getBuff(uint x, uint y, byte *pout, uint w_, uint h_) {
error("TODO: Implement TeImage::getBuff");
}
bool TeImage::isExtensionSupported(const Common::Path &path) {
error("TODO: Implement TeImage::isExtensionSupported");
}
bool TeImage::load(const TetraedgeFSNode &node) {
TeCore *core = g_engine->getCore();
TeICodec *codec = core->createVideoCodec(node, node.getPath());
if (!node.exists() || !codec->load(node)) {
warning("TeImage::load: Failed to load %s.", node.toString().c_str());
delete codec;
return false;
}
Common::SharedPtr<TePalette> nullpal;
createImg(codec->width(), codec->height(), nullpal, codec->pixelFormat(), codec->width(), codec->height());
if (!codec->update(0, *this)) {
error("TeImage::load: Failed to update from %s.", node.toString().c_str());
}
delete codec;
return true;
}
bool TeImage::load(Common::SeekableReadStream &stream, const Common::String &type) {
TeCore *core = g_engine->getCore();
TeScummvmCodec *codec = dynamic_cast<TeScummvmCodec *>(core->createVideoCodec(type));
if (!codec || !codec->load(stream)) {
warning("TeImage::load: Failed to load stream");
delete codec;
return false;
}
Common::SharedPtr<TePalette> nullpal;
createImg(codec->width(), codec->height(), nullpal, codec->pixelFormat(), codec->width(), codec->height());
if (!codec->update(0, *this)) {
error("TeImage::load: Failed to update from stream");
}
delete codec;
return true;
}
bool TeImage::save(const Common::Path &path, enum SaveType type) {
error("TODO: Implement TeImage::save");
}
int TeImage::serialize(Common::WriteStream &stream) {
error("TODO: Implement TeImage::serialize");
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,85 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_IMAGE_H
#define TETRAEDGE_TE_TE_IMAGE_H
#include "common/fs.h"
#include "common/ptr.h"
#include "common/stream.h"
#include "common/types.h"
#include "common/path.h"
#include "graphics/managed_surface.h"
#include "tetraedge/te/te_color.h"
#include "tetraedge/te/te_palette.h"
#include "tetraedge/te/te_vector2s32.h"
#include "tetraedge/te/te_resource.h"
#include "tetraedge/tetraedge.h"
namespace Tetraedge {
class TeImage : public TeResource, public Graphics::ManagedSurface {
public:
TeImage();
TeImage(const TeImage &other);
virtual ~TeImage() {
destroy();
};
enum SaveType {
PNG
};
void copy(TeImage &dest, const TeVector2s32 &vec1, const TeVector2s32 &vec2,
const TeVector2s32 &vec3) const;
uint64 countPixelsOfColor(const TeColor &col) const;
// void create(); // never used?
void createImg(uint xsize, uint ysize, Common::SharedPtr<TePalette> &palette, const Graphics::PixelFormat &newformat) {
createImg(xsize, ysize, palette, newformat, xsize, ysize);
}
void createImg(uint xsize, uint ysize, Common::SharedPtr<TePalette> &pal,
const Graphics::PixelFormat &format, uint bufxsize, uint bufysize);
void deserialize(Common::ReadStream &stream);
void destroy();
void drawPlot(int x, int y, const TeColor &col) {
drawPlot(getPixels(), x, y, bufSize(), col);
}
void drawPlot(void *outbuf, int x, int y, const TeVector2s32 &bufsize, const TeColor &col);
void fill(byte val);
void fill(byte r, byte g, byte b, byte a);
void getBuff(uint x, uint y, byte *pout, uint w, uint h);
bool isExtensionSupported(const Common::Path &path);
bool load(const TetraedgeFSNode &node);
bool load(Common::SeekableReadStream &stream, const Common::String &type);
bool save(const Common::Path &path, enum SaveType type);
int serialize(Common::WriteStream &stream);
TeVector2s32 bufSize() const {
return TeVector2s32(pitch / format.bytesPerPixel, h);
}
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_IMAGE_H

View File

@@ -0,0 +1,169 @@
/* 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 "common/file.h"
#include "image/png.h"
#include "graphics/surface.h"
#include "graphics/managed_surface.h"
#include "tetraedge/tetraedge.h"
#include "tetraedge/te/te_core.h"
#include "tetraedge/te/te_images_sequence.h"
namespace Tetraedge {
TeImagesSequence::TeImagesSequence() : _width(0), _height(0), _curFrame(0), _frameRate(0) {
}
TeImagesSequence::~TeImagesSequence() {
for (auto surf : _cachedSurfaces) {
if (surf)
delete surf;
}
}
/*static*/
bool TeImagesSequence::matchExtension(const Common::String &extn) {
return extn == "anim" || extn == "animcached";
}
static bool compareNodes(const TetraedgeFSNode &left, const TetraedgeFSNode &right) {
return left.getPath().toString('/') < right.getPath().toString('/');
}
bool TeImagesSequence::load(const TetraedgeFSNode &dir) {
if (!dir.isDirectory()) {
warning("TeImagesSequence::load:: not a directory %s", dir.toString().c_str());
return false;
}
TetraedgeFSList children;
if (!dir.getChildren(children, Common::FSNode::kListFilesOnly) || children.empty()) {
warning("TeImagesSequence::load:: couldn't get children of %s", dir.toString().c_str());
return false;
}
Common::sort(children.begin(), children.end(), compareNodes);
dir.maybeAddToSearchMan();
for (TetraedgeFSNode &child : children) {
const Common::String fileName = child.getName();
if (fileName.size() <= 10 || fileName.substr(fileName.size() - 7) != "fps.png")
continue;
Common::String fstart = fileName.substr(0, fileName.size() - 7);
int frameno = 0;
int fps = 0;
if (sscanf(fstart.c_str(), "%d-%d", &frameno, &fps) != 2) {
warning("TeImagesSequence::load can't match %s", fileName.c_str());
continue;
}
Common::SeekableReadStream *stream = child.createReadStream();
if (!stream) {
warning("TeImagesSequence::load can't open %s", child.toString().c_str());
continue;
}
// Only do the deep check for the first file to get dimensions.
// If the images are small then cache them to avoid reloading each frame each time.
if (!_width || (_width < 100 && _height < 100)) {
Image::PNGDecoder png;
if (!png.loadStream(*stream)) {
warning("Image sequence failed to load png %s", child.toString().c_str());
delete stream;
return false;
}
_frameRate = fps;
const Graphics::Surface *pngsurf = png.getSurface();
assert(pngsurf);
_width = pngsurf->w;
_height = pngsurf->h;
if (_width < 100 && _height < 100) {
Graphics::ManagedSurface *surf = new Graphics::ManagedSurface();
surf->copyFrom(*pngsurf);
_cachedSurfaces.push_back(surf);
} else {
_cachedSurfaces.push_back(nullptr);
}
} else {
_cachedSurfaces.push_back(nullptr);
}
_files.push_back(child);
delete stream;
}
return true;
}
bool TeImagesSequence::update(uint i, TeImage &imgout) {
_curFrame = i;
if (i >= _files.size())
return false;
if (_cachedSurfaces[i] == nullptr) {
Common::SeekableReadStream *stream = _files[i].createReadStream();
if (!stream)
error("Open %s failed.. it was ok before?", _files[i].getName().c_str());
Image::PNGDecoder png;
if (!png.loadStream(*stream)) {
warning("Image sequence failed to load png %s", _files[i].getName().c_str());
delete stream;
return false;
}
const Graphics::Surface *surf = png.getSurface();
assert(surf);
imgout.setAccessName(_files[i].getPath());
if (imgout.w == surf->w && imgout.h == surf->h && imgout.format == surf->format) {
imgout.copyFrom(*surf);
delete stream;
return true;
}
} else {
const Graphics::ManagedSurface *surf = _cachedSurfaces[i];
if (imgout.w == surf->w && imgout.h == surf->h && imgout.format == surf->format) {
imgout.setAccessName(_files[i].getPath());
imgout.copyFrom(*surf);
return true;
}
}
error("TODO: Implement TeImagesSequence::update for different sizes");
}
bool TeImagesSequence::isAtEnd() {
return _curFrame >= _files.size();
}
Graphics::PixelFormat TeImagesSequence::pixelFormat() {
return Graphics::PixelFormat::createFormatRGBA32();
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,73 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_IMAGES_SEQUENCE_H
#define TETRAEDGE_TE_TE_IMAGES_SEQUENCE_H
#include "common/str.h"
#include "tetraedge/te/te_i_codec.h"
namespace Graphics {
struct Surface;
class ManagedSurface;
}
namespace Tetraedge {
class TeImagesSequence : public TeICodec {
public:
TeImagesSequence();
virtual ~TeImagesSequence();
virtual bool load(const TetraedgeFSNode &node) override;
virtual uint width() override { return _width; }
virtual uint height() override { return _height; }
virtual int nbFrames() override { return _files.size(); }
virtual void setLeftBorderSize(uint val) override { }
virtual uint leftBorderSize() override { return 0; }
virtual void setRightBorderSize(uint val) override { }
virtual uint rightBorderSize() override { return 0; }
virtual void setBottomBorderSize(uint val) override { }
virtual uint bottomBorderSize() override { return 0; }
virtual void setTopBorderSize(uint val) override { }
virtual uint topBorderSize() override { return 0; }
virtual Graphics::PixelFormat pixelFormat() override;
virtual float frameRate() override { return _frameRate; }
virtual bool update(uint i, TeImage &imgout) override;
virtual bool isAtEnd() override;
virtual void setColorKeyActivated(bool val) override { }
virtual void setColorKey(const TeColor &col) override { }
virtual void setColorKeyTolerence(float val) override { }
static bool matchExtension(const Common::String &extn);
private:
float _frameRate;
uint _width;
uint _height;
Common::Array<TetraedgeFSNode> _files;
Common::Array<Graphics::ManagedSurface *> _cachedSurfaces;
uint _curFrame;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_IMAGES_SEQUENCE_H

View File

@@ -0,0 +1,73 @@
/* 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 "tetraedge/tetraedge.h"
#include "tetraedge/game/game.h"
#include "tetraedge/te/te_input_mgr.h"
namespace Tetraedge {
TeInputMgr::TeInputMgr() {
}
void TeInputMgr::handleEvent(const Common::Event &e) {
switch (e.type) {
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
_customActionStartSignal.call(e.customType);
break;
case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
_customActionEndSignal.call(e.customType);
break;
case Common::EVENT_KEYDOWN:
_keyDownSignal.call(e.kbd);
break;
case Common::EVENT_KEYUP:
_keyUpSignal.call(e.kbd);
break;
case Common::EVENT_MOUSEMOVE:
_mouseMoveSignal.call(e.mouse);
_lastMousePos = e.mouse;
break;
case Common::EVENT_LBUTTONDOWN:
_mouseLDownSignal.call(e.mouse);
_lastMousePos = e.mouse;
break;
case Common::EVENT_LBUTTONUP:
_mouseLUpSignal.call(e.mouse);
_lastMousePos = e.mouse;
break;
case Common::EVENT_RBUTTONDOWN:
_mouseRDownSignal.call(e.mouse);
_lastMousePos = e.mouse;
break;
case Common::EVENT_RBUTTONUP:
_mouseRUpSignal.call(e.mouse);
_lastMousePos = e.mouse;
break;
case Common::EVENT_MAINMENU:
g_engine->getGame()->_returnToMainMenu = true;
break;
default:
break;
}
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,57 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_INPUT_MGR_H
#define TETRAEDGE_TE_TE_INPUT_MGR_H
#include "common/events.h"
#include "tetraedge/te/te_signal.h"
namespace Tetraedge {
class TeInputMgr {
public:
TeInputMgr();
void handleEvent(const Common::Event &e);
TeSignal1Param<const Common::KeyState &> _keyDownSignal;
TeSignal1Param<const Common::KeyState &> _keyUpSignal;
TeSignal1Param<const Common::Point &> _mouseMoveSignal;
TeSignal1Param<const Common::Point &> _mouseLDownSignal;
TeSignal1Param<const Common::Point &> _mouseLUpSignal;
TeSignal1Param<const Common::Point &> _mouseRDownSignal;
TeSignal1Param<const Common::Point &> _mouseRUpSignal;
TeSignal1Param<const Common::CustomEventType &> _customActionStartSignal;
TeSignal1Param<const Common::CustomEventType &> _customActionEndSignal;
const Common::Point &lastMousePos() {
return _lastMousePos;
}
private:
Common::Point _lastMousePos;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_INPUT_MGR_H

View File

@@ -0,0 +1,82 @@
/* 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 "common/file.h"
#include "tetraedge/te/te_interpolation.h"
namespace Tetraedge {
TeInterpolation::TeInterpolation() {
}
void TeInterpolation::load(Common::ReadStream &stream) {
uint32 len = stream.readUint32LE();
if (len > 1000000)
error("TeInterpolation: Unexpected interpolation length %d", len);
_array.resize(len);
for (uint32 i = 0; i < len && !stream.err(); i++)
_array[i] = stream.readFloatLE();
}
void TeInterpolation::load(TetraedgeFSNode &node) {
Common::ScopedPtr<Common::SeekableReadStream> f(node.createReadStream());
if (!f)
error("Couldn't open %s", node.toString().c_str());
load(*f);
}
// Note: this function is not in the original but simplifies
// the code for TeCurveAnim2 a lot.
void TeInterpolation::load(const Common::Array<double> &array) {
_array = array;
}
void TeInterpolation::load(const Common::Array<float> &array) {
_array.clear();
for (auto f : array) {
_array.push_back(f);
}
}
double TeInterpolation::interpole(double where, double max) const {
const uint arrayLen = _array.size();
if (!arrayLen)
return 0.0;
double elemNum = (arrayLen - 1) * where / max;
int leftElemNum = (int)floor(elemNum);
if (leftElemNum >= (int)arrayLen - 1)
return _array[arrayLen - 1];
else if (leftElemNum < 0)
return _array[0];
double left = _array[leftElemNum];
double right = _array[leftElemNum + 1];
return left + (right - left) * (elemNum - leftElemNum);
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,54 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_INTERPOLATION_H
#define TETRAEDGE_TE_TE_INTERPOLATION_H
#include "common/array.h"
#include "common/stream.h"
#include "common/fs.h"
#include "tetraedge/tetraedge.h"
namespace Tetraedge {
class TeInterpolation {
public:
TeInterpolation();
void load(Common::ReadStream &stream);
void load(TetraedgeFSNode &node);
// Note: this function is not in the original but simplifies
// the code for TeCurveAnim2 a lot.
void load(const Common::Array<double> &array);
void load(const Common::Array<float> &array);
double interpole(double amount, double max) const;
private:
Common::Array<double> _array;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_INTERPOLATION_H

View File

@@ -0,0 +1,133 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_INTRUSIVE_PTR_H
#define TETRAEDGE_TE_TE_INTRUSIVE_PTR_H
namespace Tetraedge {
/**
Like the boost intrusive pointer. To be used with an
object inheriting from TeReferencesCounter
*/
template<class T> class TeIntrusivePtr {
public:
// NOTE: The original uses a member function for this, which is cleaner, but
// MSVC compiles member functions for different class types (forward
// declaration, multi-inheritance, etc) as different sizes which causes all
// sorts of issues. Only accept a static function to avoid such problems.
typedef void(*Tdestructor)(T *obj);
TeIntrusivePtr() : _p(nullptr), _deleteFn(nullptr) {}
TeIntrusivePtr(const TeIntrusivePtr<T> &other) : _deleteFn(nullptr) {
_p = other._p;
if (_p)
_p->incrementCounter();
}
TeIntrusivePtr(T *obj) : _deleteFn(nullptr) {
_p = obj;
if (_p)
_p->incrementCounter();
}
virtual ~TeIntrusivePtr() {
release();
}
TeIntrusivePtr<T> &operator=(T *obj) {
if (_p != obj) {
release();
_p = obj;
if (_p)
_p->incrementCounter();
}
return *this;
}
TeIntrusivePtr<T> &operator=(const TeIntrusivePtr<T> &other) {
if (this != &other) {
release();
_p = other._p;
_deleteFn = other._deleteFn;
if (_p)
_p->incrementCounter();
}
return *this;
}
void release() {
if (_p) {
if (_p->decrementCounter()) {
if (_deleteFn)
(_deleteFn)(_p);
else
delete _p;
}
}
_p = nullptr;
}
bool operator==(const TeIntrusivePtr<T> &other) const {
return (this == &other || _p == other._p);
}
T *get() {
return _p;
}
const T *get() const {
return _p;
}
T &operator*() {
return *_p;
}
const T &operator*() const {
return *_p;
}
operator bool() const {
return _p != nullptr;
}
T *operator->() {
return _p;
}
const T *operator->() const {
return _p;
}
void setDeleteFn(Tdestructor destructor) {
_deleteFn = destructor;
}
private:
T *_p;
Tdestructor _deleteFn;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_INTRUSIVE_PTR_H

View File

@@ -0,0 +1,57 @@
/* 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 "tetraedge/te/te_jpeg.h"
#include "common/file.h"
#include "common/path.h"
#include "graphics/surface.h"
#include "image/jpeg.h"
namespace Tetraedge {
TeJpeg::TeJpeg() {
}
TeJpeg::~TeJpeg() {
}
/*static*/
bool TeJpeg::matchExtension(const Common::String &extn) {
return extn == "jpg" || extn == "jpeg";
}
bool TeJpeg::load(Common::SeekableReadStream &stream) {
Image::JPEGDecoder jpg;
if (_loadedSurface)
delete _loadedSurface;
_loadedSurface = nullptr;
jpg.setOutputPixelFormat(Graphics::PixelFormat::createFormatRGBA32());
if (!jpg.loadStream(stream))
return false;
_loadedSurface = jpg.getSurface()->convertTo(Graphics::PixelFormat::createFormatRGBA32());
return true;
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,53 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_JPEG_H
#define TETRAEDGE_TE_TE_JPEG_H
#include "common/str.h"
#include "tetraedge/te/te_scummvm_codec.h"
namespace Graphics {
struct Surface;
}
namespace Tetraedge {
class TeJpeg : public TeScummvmCodec {
public:
TeJpeg();
virtual ~TeJpeg();
virtual bool load(Common::SeekableReadStream &stream) override;
virtual int nbFrames() override { return 1; }
virtual float frameRate() override { return 0.0f; }
virtual bool isAtEnd() override { return true; }
virtual void setColorKeyActivated(bool val) override { }
virtual void setColorKey(const TeColor &col) override { }
virtual void setColorKeyTolerence(float val) override { }
static bool matchExtension(const Common::String &extn);
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_JPEG_H

View File

@@ -0,0 +1,519 @@
/* 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 "common/textconsole.h"
#include "tetraedge/tetraedge.h"
#include "tetraedge/game/application.h"
#include "tetraedge/te/te_layout.h"
#include "tetraedge/te/te_i_3d_object2.h"
namespace Tetraedge {
TeLayout::TeLayout() : Te3DObject2(), _autoz(true), _needZUpdate(true), _updatingZ(false),
_needZSizeUpdate(true), _updatingZSize(false), _sizeChanged(true), _updatingSize(false),
_positionChanged(true), _updatingPosition(false), _worldMatrixChanged(true),
_updatingWorldMatrix(false), _drawMode(TeILayout::DrawMode0),
_sizeType(CoordinatesType::ABSOLUTE), _userSize(1.0f, 1.0f, 1.0f),
_anchor(0.5f, 0.5f, 0.5f), _ratio(1.0f), _safeAreaRatio(1.333333f),
_ratioMode(RATIO_MODE_NONE), _positionType(CoordinatesType::RELATIVE_TO_PARENT)
{
_userPosition = _position = TeVector3f32(0.5f, 0.5f, 0.5f);
_size = TeVector3f32(1.0f, 1.0f, 1.0f);
_onChildSizeChangedCallback.reset(
new TeCallback0Param<TeLayout>(this, &TeLayout::onChildSizeChanged));
_onParentSizeChangedCallback.reset(
new TeCallback0Param<TeLayout>(this, &TeLayout::onParentSizeChanged));
_onParentWorldTransformationMatrixChangedCallback.reset(
new TeCallback0Param<TeLayout>(this, &TeLayout::onParentWorldTransformationMatrixChanged));
updateSize();
updateMesh();
}
TeLayout::~TeLayout() {
if (parent() && _onParentSizeChangedCallback) {
parent()->onSizeChanged().remove(_onParentSizeChangedCallback);
_onParentSizeChangedCallback.reset();
parent()->onWorldTransformationMatrixChanged().remove(_onParentWorldTransformationMatrixChangedCallback);
_onParentWorldTransformationMatrixChangedCallback.reset();
}
if (_onChildSizeChangedCallback) {
for (auto &child : childList()) {
child->onSizeChanged().remove(_onChildSizeChangedCallback);
}
}
}
void TeLayout::addChild(Te3DObject2 *child) {
Te3DObject2::addChild(child);
if (_onChildSizeChangedCallback) {
child->onSizeChanged().push_back(_onChildSizeChangedCallback);
}
_needZSizeUpdate = true;
_needZUpdate = true;
updateZSize();
updateZ();
}
void TeLayout::addChildBefore(Te3DObject2 *child, const Te3DObject2 *ref) {
Te3DObject2::addChildBefore(child, ref);
if (_onChildSizeChangedCallback) {
child->onSizeChanged().push_back(_onChildSizeChangedCallback);
}
_needZSizeUpdate = true;
_needZUpdate = true;
updateZSize();
updateZ();
}
void TeLayout::removeChild(Te3DObject2 *child) {
if (_onChildSizeChangedCallback) {
child->onSizeChanged().remove(_onChildSizeChangedCallback);
}
Te3DObject2::removeChild(child);
_needZSizeUpdate = true;
_needZUpdate = true;
updateZSize();
updateZ();
}
const TeVector3f32 &TeLayout::anchor() {
return _anchor;
}
void TeLayout::disableAutoZ() {
_autoz = false;
}
void TeLayout::enableAutoZ() {
_autoz = true;
}
bool TeLayout::isAutoZEnabled() {
return _autoz;
}
void TeLayout::draw() {
if (visible() && worldVisible()) {
// Ensure world transform is up-to-date.
worldTransformationMatrix();
for (auto &child : childList()) {
child->draw();
}
}
}
static const float EPSILON = 1.192093e-07f;
bool TeLayout::isMouseIn(const TeVector2s32 &mouseloc) {
const TeVector3f32 transformedPos = transformMousePosition(mouseloc);
const TeVector3f32 halfSize = size() / 2.0;
return ( (transformedPos.x() >= -halfSize.x() - EPSILON)
&& (transformedPos.x() < halfSize.x() + EPSILON)
&& (transformedPos.y() >= -halfSize.y() - EPSILON)
&& (transformedPos.y() < halfSize.y() + EPSILON));
}
TeILayout::DrawMode TeLayout::mode() {
return _drawMode;
}
bool TeLayout::onChildSizeChanged() {
_needZSizeUpdate = true;
_needZUpdate = true;
updateSize();
if (!_updatingZSize)
updateZSize();
return false;
}
bool TeLayout::onParentSizeChanged() {
_sizeChanged = true;
_positionChanged = true;
_worldMatrixChanged = true;
return false;
}
bool TeLayout::onParentWorldTransformationMatrixChanged() {
_worldMatrixChanged = true;
return false;
}
TeVector3f32 TeLayout::position() {
updateZ();
updatePosition();
return _position;
}
TeLayout::CoordinatesType TeLayout::positionType() const {
return _positionType;
}
float TeLayout::ratio() const {
return _ratio;
}
TeLayout::RatioMode TeLayout::ratioMode() const {
return _ratioMode;
}
float TeLayout::safeAreaRatio() const {
return _safeAreaRatio;
}
void TeLayout::setAnchor(const TeVector3f32 &anchor) {
if (_anchor != anchor) {
_anchor = anchor;
_positionChanged = true;
_worldMatrixChanged = true;
updatePosition();
}
}
void TeLayout::setMode(DrawMode mode) {
_drawMode = mode;
}
void TeLayout::setParent(Te3DObject2 *parent) {
assert(parent != this);
Te3DObject2 *oldParent = Te3DObject2::parent();
if (oldParent) {
if (_onParentSizeChangedCallback)
oldParent->onSizeChanged().remove(_onParentSizeChangedCallback);
if (_onParentWorldTransformationMatrixChangedCallback)
oldParent->onWorldTransformationMatrixChanged().remove(_onParentWorldTransformationMatrixChangedCallback);
}
//
TeLayout &mainWindowLayout = g_engine->getApplication()->getMainWindow();
mainWindowLayout.onSizeChanged().remove(_onMainWindowChangedCallback);
Te3DObject2::setParent(parent);
if (parent) {
if (_onParentSizeChangedCallback)
parent->onSizeChanged().push_back(_onParentSizeChangedCallback);
if (_onParentWorldTransformationMatrixChangedCallback)
parent->onWorldTransformationMatrixChanged().push_back(_onParentWorldTransformationMatrixChangedCallback);
if (_onMainWindowChangedCallback)
mainWindowLayout.onSizeChanged().push_back(_onMainWindowChangedCallback);
}
_needZUpdate = true;
_sizeChanged = true;
_positionChanged = true;
_worldMatrixChanged = true;
updateSize();
}
void TeLayout::setPosition(const TeVector3f32 &pos) {
TeVector3f32 pos3d(pos.x(), pos.y(), _userPosition.z());
if (_userPosition != pos3d) {
_userPosition.x() = pos.x();
_userPosition.y() = pos.y();
_positionChanged = true;
_worldMatrixChanged = true;
}
}
void TeLayout::setPositionType(CoordinatesType newtype) {
if (_positionType != newtype) {
_positionType = newtype;
_positionChanged = true;
_worldMatrixChanged = true;
}
}
void TeLayout::setRatio(float val) {
if (_ratio != val) {
_ratio = val;
_sizeChanged = true;
_worldMatrixChanged = true;
}
}
void TeLayout::setRatioMode(RatioMode mode) {
if (_ratioMode != mode) {
_ratioMode = mode;
_sizeChanged = true;
_worldMatrixChanged = true;
}
}
void TeLayout::setRotation(const TeQuaternion &rot) {
if (rot != _rotation) {
Te3DObject2::setRotation(rot);
_worldMatrixChanged = true;
}
}
void TeLayout::setSafeAreaRatio(float ratio) {
if (_safeAreaRatio != ratio) {
_safeAreaRatio = ratio;
_sizeChanged = true;
_worldMatrixChanged = true;
}
}
void TeLayout::setScale(const TeVector3f32 &scale) {
Te3DObject2::setScale(scale);
_worldMatrixChanged = true;
}
void TeLayout::setSize(const TeVector3f32 &size) {
const TeVector3f32 size3d(size.x(), size.y(), _userSize.z());
if (_userSize != size3d) {
_userSize.x() = size.x();
_userSize.y() = size.y();
_sizeChanged = true;
_positionChanged = true;
_worldMatrixChanged = true;
}
}
void TeLayout::setSizeType(CoordinatesType coordtype) {
assert(coordtype == RELATIVE_TO_PARENT || coordtype == ABSOLUTE);
if (_sizeType != coordtype) {
_sizeType = coordtype;
_sizeChanged = true;
_worldMatrixChanged = true;
}
}
void TeLayout::setZPosition(float zpos) {
if (_userPosition.z() != zpos) {
_userPosition.z() = zpos;
_positionChanged = true;
_worldMatrixChanged = true;
}
}
TeVector3f32 TeLayout::size() {
updateSize();
updateZSize();
return _size;
}
TeLayout::CoordinatesType TeLayout::sizeType() const {
return _sizeType;
}
TeVector3f32 TeLayout::transformMousePosition(const TeVector2s32 &mousepos) {
TeVector3f32 relativeMouse(mousepos);
relativeMouse.x() -= g_system->getWidth() / 2;
relativeMouse.y() -= g_system->getHeight() / 2;
TeMatrix4x4 transform = worldTransformationMatrix();
transform.inverse();
TeVector3f32 transformpos = transform * relativeMouse;
//debug("transformMousePosition: %d %d -> %f %f", mousepos._x, mousepos._y, transformpos.x(), transformpos.y());
return transformpos;
}
void TeLayout::updatePosition() {
if (!_positionChanged)
return;
_positionChanged = false;
_updatingPosition = true;
TeVector3f32 oldpos = _position;
Te3DObject2 *parentObj = parent();
static const TeVector3f32 midPoint(0.5f, 0.5f, 0.5f);
if (_positionType == RELATIVE_TO_PARENT && parentObj) {
const TeVector3f32 offsetUserPos = _userPosition - midPoint;
const TeVector3f32 parentSize(parentObj->xSize(), parentObj->ySize(), 0.0);
const TeVector3f32 offsetAnchor = midPoint - _anchor;
const TeVector3f32 thisSize(xSize(), ySize(), 0.0);
const TeVector3f32 newpos = (offsetUserPos * parentSize) + (offsetAnchor * thisSize);
_position = newpos;
} else if (_positionType == RELATIVE_TO_PARENT && !parentObj) {
// Not in original, but no parent -> set midpoint.
const TeVector3f32 offsetAnchor = midPoint - _anchor;
const TeVector3f32 thisSize(xSize(), ySize(), 0.0);
_position = offsetAnchor * thisSize;
} else if (_positionType == ABSOLUTE) {
_position = _userPosition;
}
_position.z() = _userPosition.z();
_worldMatrixChanged = true;
_updatingPosition = false;
if (_position != oldpos) {
onPositionChanged().call();
}
}
void TeLayout::updateSize() {
if (!_sizeChanged)
return;
_sizeChanged = false;
_updatingSize = true;
const TeVector3f32 oldSize = _size;
if (_sizeType == ABSOLUTE) {
TeVector3f32 newSize = _userSize;
_size.x() = abs(newSize.x());
_size.y() = abs(newSize.y());
// don't set Z val.
} else if (_sizeType == RELATIVE_TO_PARENT) {
Te3DObject2 *parentObj = parent();
if (parentObj) {
const TeVector3f32 parentSize(parentObj->xSize(), parentObj->ySize(), 0.0);
TeVector3f32 newSize = _userSize * parentSize;
if (newSize.x() > 0.0f && newSize.y() > 0.0f && _ratio > 0.0f && _safeAreaRatio > 0.0f) {
float newSizeRatio = newSize.x() / newSize.y();
if (_ratioMode == RATIO_MODE_PAN_SCAN) {
if (_safeAreaRatio <= newSizeRatio) {
newSize.x() = _ratio * newSize.y();
} else {
newSize.x() =
(1.0f - (_safeAreaRatio - newSizeRatio) / _safeAreaRatio) *
_ratio * newSize.y();
}
} else if (_ratioMode == RATIO_MODE_LETTERBOX) {
if (_ratio < newSizeRatio)
newSize.x() = _ratio * newSize.y();
else
newSize.y() = newSize.x() / _ratio;
}
}
_size.x() = newSize.x();
_size.y() = newSize.y();
} else {
_size.x() = 0.0f;
_size.y() = 0.0f;
}
}
_updatingSize = false;
// TODO: check this, is it the right flag to set?
_positionChanged = true;
updateMesh();
if (_size != oldSize) {
onSizeChanged().call();
}
}
void TeLayout::updateWorldMatrix() {
if (!_worldMatrixChanged)
return;
_worldMatrixChanged = false;
_updatingWorldMatrix = true;
const TeMatrix4x4 oldMatrix = _worldMatrixCache;
_worldMatrixCache = Te3DObject2::worldTransformationMatrix();
_updatingWorldMatrix = false;
if (_worldMatrixCache != oldMatrix) {
onWorldTransformationMatrixChanged().call();
}
}
void TeLayout::updateZ() {
if (!_needZUpdate || !_autoz)
return;
_needZUpdate = false;
_updatingZ = true;
float ztotal = 0.1f;
for (auto &child : childList()) {
child->setZPosition(ztotal);
ztotal += child->zSize();
}
_updatingZ = false;
}
void TeLayout::updateZSize() {
if (!_needZSizeUpdate)
return;
_needZSizeUpdate = false;
_updatingZSize = true;
const TeVector3f32 oldSize = _size;
_size.z() = 0.1f;
for (auto &child : childList()) {
_size.z() += child->zSize();
}
_positionChanged = true;
_updatingZSize = false;
if (_size != oldSize) {
onSizeChanged().call();
}
}
TeVector3f32 TeLayout::userPosition() const {
return _userPosition;
}
TeVector3f32 TeLayout::userSize() {
updateZ();
return _userSize;
}
TeVector3f32 TeLayout::worldPosition() {
if (!parent()) {
return position();
} else {
return parent()->worldPosition() + position();
}
}
TeMatrix4x4 TeLayout::worldTransformationMatrix() {
updateZ();
updatePosition();
updateWorldMatrix();
return _worldMatrixCache;
}
bool TeLayout::worldVisible() {
bool visible = Te3DObject2::visible();
if (visible && parent()) {
return parent()->worldVisible();
}
return visible;
}
float TeLayout::xSize() {
updateSize();
return _size.x();
}
float TeLayout::ySize() {
updateSize();
return _size.y();
}
float TeLayout::zSize() {
updateZSize();
return _size.z();
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,133 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_LAYOUT_H
#define TETRAEDGE_TE_TE_LAYOUT_H
#include "tetraedge/te/te_3d_object2.h"
#include "tetraedge/te/te_i_layout.h"
#include "tetraedge/te/te_i_3d_object2.h"
#include "tetraedge/te/te_matrix4x4.h"
#include "tetraedge/te/te_quaternion.h"
#include "tetraedge/te/te_vector2s32.h"
#include "tetraedge/te/te_vector3f32.h"
namespace Tetraedge {
class TeLayout : public TeILayout, public Te3DObject2 {
public:
TeLayout();
virtual ~TeLayout();
void addChild(Te3DObject2 *child) override;
void addChildBefore(Te3DObject2 *newchild, const Te3DObject2 *ref) override;
const TeVector3f32 &anchor();
void disableAutoZ();
void enableAutoZ();
bool isAutoZEnabled();
void draw() override;
virtual bool isMouseIn(const TeVector2s32 &mouseloc);
DrawMode mode();
bool onChildSizeChanged();
bool onParentSizeChanged();
bool onParentWorldTransformationMatrixChanged();
TeVector3f32 position() override;
CoordinatesType positionType() const;
float ratio() const;
RatioMode ratioMode() const;
void removeChild(Te3DObject2 *child) override;
float safeAreaRatio() const;
void setAnchor(const TeVector3f32 &anchor);
virtual void setEditionColor(TeColor col) {};
void setMode(DrawMode mode);
void setParent(Te3DObject2 *parent) override;
void setPosition(const TeVector3f32 &pos) override;
void setPositionType(CoordinatesType newtype);
void setRatio(float val);
void setRatioMode(RatioMode mode);
void setRotation(const TeQuaternion &rot) override;
void setSafeAreaRatio(float ratio);
void setScale(const TeVector3f32 &scale) override;
void setSize(const TeVector3f32 &size) override;
void setSizeType(CoordinatesType coordtype);
void setZPosition(float zpos) override;
virtual TeVector3f32 size() override;
CoordinatesType sizeType() const;
TeVector3f32 transformMousePosition(const TeVector2s32 &mousepos);
virtual void updateMesh() {}; // override available for TeSpriteLayout
void updatePosition();
virtual void updateSize();
void updateWorldMatrix();
void updateZ() override;
void updateZSize();
TeVector3f32 userPosition() const;
TeVector3f32 userSize();
TeVector3f32 worldPosition() override;
TeMatrix4x4 worldTransformationMatrix() override;
bool worldVisible() override;
float xSize() override;
float ySize() override;
float zSize() override;
protected:
bool _sizeChanged;
private:
TeVector3f32 _anchor;
CoordinatesType _positionType;
TeVector3f32 _userPosition;
CoordinatesType _sizeType;
TeVector3f32 _userSize;
TeMatrix4x4 _worldMatrixCache;
DrawMode _drawMode;
bool _autoz;
bool _positionChanged;
bool _worldMatrixChanged;
bool _needZSizeUpdate;
bool _needZUpdate;
bool _updatingZ;
bool _updatingZSize;
bool _updatingSize;
bool _updatingPosition;
bool _updatingWorldMatrix;
float _ratio;
RatioMode _ratioMode;
float _safeAreaRatio;
TeICallback0ParamPtr _onChildSizeChangedCallback;
TeICallback0ParamPtr _onParentSizeChangedCallback;
TeICallback0ParamPtr _onParentWorldTransformationMatrixChangedCallback;
TeICallback0ParamPtr _onMainWindowChangedCallback;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_LAYOUT_H

View File

@@ -0,0 +1,112 @@
/* 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 "graphics/renderer.h"
#include "tetraedge/tetraedge.h"
#include "tetraedge/te/te_light.h"
#include "tetraedge/te/te_light_opengl.h"
#include "tetraedge/te/te_light_tinygl.h"
#include "tetraedge/te/te_color.h"
#include "tetraedge/te/te_quaternion.h"
#include "tetraedge/te/te_vector3f32.h"
namespace Tetraedge {
/*static*/
uint32 TeLight::_globalAmbientColor = 0xffffffff;
TeLight::TeLight() : _colAmbient(0, 0, 0, 0xff), _colDiffuse(0, 0, 0, 0xff), _colSpecular(0xff, 0xff, 0xff, 0xff),
_constAtten(1.0f), _linearAtten(0.0f), _quadraticAtten(0.0f), _cutoff(0.0f), _exponent(0.0f), _type(LightTypePoint),
_displaySize(3.0f)
{
}
TeVector3f32 TeLight::directionVector() const {
float cosx = cosf(_positionRadial.getX());
float cosy = cosf(_positionRadial.getY());
float sinx = sinf(_positionRadial.getX());
float siny = sinf(_positionRadial.getY());
return TeVector3f32(cosx * cosy, siny, sinx * cosy);
}
void TeLight::transformDirPoint(const TeVector3f32 &pt1, TeVector3f32 &pt2) {
const TeQuaternion q1 = TeQuaternion::fromAxisAndAngle(TeVector3f32(0, 1, 0), _positionRadial.getX() + M_PI);
const TeQuaternion q2 = TeQuaternion::fromAxisAndAngle(TeVector3f32(0, 0, -1), -_positionRadial.getY());
pt2.rotate(q2);
pt2.rotate(q1);
pt2 += pt1;
}
void TeLight::transformSpotPoint(TeVector3f32 &pt) {
const TeQuaternion q1 = TeQuaternion::fromAxisAndAngle(TeVector3f32(0, 1, 0), _positionRadial.getX());
const TeQuaternion q2 = TeQuaternion::fromAxisAndAngle(TeVector3f32(0, 0, -1), _positionRadial.getY());
pt.rotate(q2);
pt.rotate(q1);
pt += _position3d;
}
Common::String TeLight::dump() const {
const char *ltype;
switch (_type) {
case LightTypeSpot:
ltype = "Spot";
break;
case LightTypePoint:
ltype = "Point";
break;
case LightTypeDirectional:
ltype = "Directional";
break;
default:
error("Invalid light type %d", (int)_type);
}
return Common::String::format("%sLight(\n\tamb:%s diff:%s spec:%s\n\tpos:%s posRad:%s atten:%.02f %.02f %.02f\n\tcutoff:%.02f exp:%.02f dispSz:%.02f\n)",
ltype, _colAmbient.dump().c_str(), _colDiffuse.dump().c_str(),
_colSpecular.dump().c_str(), _position3d.dump().c_str(),
_positionRadial.dump().c_str(), _constAtten, _linearAtten,
_quadraticAtten, _cutoff, _exponent, _displaySize);
}
void TeLight::correctAttenuation() {
if (!_constAtten && !_linearAtten && !_quadraticAtten)
_constAtten = 1.0;
}
/*static*/
TeLight *TeLight::makeInstance() {
Graphics::RendererType r = g_engine->preferredRendererType();
#if defined(USE_OPENGL_GAME)
if (r == Graphics::kRendererTypeOpenGL)
return new TeLightOpenGL();
#endif
#if defined(USE_TINYGL)
if (r == Graphics::kRendererTypeTinyGL)
return new TeLightTinyGL();
#endif
error("Couldn't create TeLight for selected renderer");
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,101 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_LIGHT_H
#define TETRAEDGE_TE_TE_LIGHT_H
#include "tetraedge/te/te_vector3f32.h"
#include "tetraedge/te/te_vector2f32.h"
#include "tetraedge/te/te_color.h"
namespace Tetraedge {
enum TeLightType {
LightTypePoint = 0,
LightTypeDirectional = 1,
LightTypeSpot = 2
};
class TeCamera;
class TeLight {
public:
TeLight();
virtual ~TeLight() {};
TeVector3f32 directionVector() const;
virtual void disable(uint lightno) = 0;
virtual void enable(uint lightno) = 0;
virtual void draw(TeCamera &camera) = 0;
void transformDirPoint(const TeVector3f32 &pt1, TeVector3f32 &pt2);
void transformSpotPoint(TeVector3f32 &pt1);
virtual void update(uint lightno) = 0;
static void setGlobalAmbient(const TeColor &col) { _globalAmbientColor = col.getPacked32(); }
static TeColor globalAmbient() { return TeColor(_globalAmbientColor); }
void setSpecular(const TeColor &col) { _colSpecular = col; }
void setDiffuse(const TeColor &col) { _colDiffuse = col; }
void setAmbient(const TeColor &col) { _colAmbient = col; }
void setConstAtten(float val) { _constAtten = val; }
void setLinearAtten(float val) { _linearAtten = val; }
void setQuadraticAtten(float val) { _quadraticAtten = val; }
void setCutoff(float val) { _cutoff = val; }
void setExponent(float val) { _exponent = val; }
void setDisplaySize(float val) { _displaySize = val; }
void setPosition3d(const TeVector3f32 &pos) { _position3d = pos; }
void setPositionRadial(const TeVector2f32 &pos) { _positionRadial = pos; }
void setType(TeLightType ltype) { _type = ltype; }
const TeVector2f32 &positionRadial() const { return _positionRadial; }
const TeVector3f32 &position3d() const { return _position3d; }
Common::String dump() const;
void correctAttenuation();
static TeLight *makeInstance();
protected:
TeVector3f32 _position3d;
TeVector2f32 _positionRadial;
TeColor _colAmbient;
TeColor _colDiffuse;
TeColor _colSpecular;
enum TeLightType _type;
static uint32 _globalAmbientColor;
float _constAtten;
float _linearAtten;
float _quadraticAtten;
float _cutoff;
float _exponent;
float _displaySize;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_LIGHT_H

View File

@@ -0,0 +1,124 @@
/* 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 "tetraedge/te/te_light_opengl.h"
#include "tetraedge/tetraedge.h"
#include "tetraedge/te/te_color.h"
#include "tetraedge/te/te_quaternion.h"
#include "tetraedge/te/te_vector3f32.h"
#include "graphics/opengl/system_headers.h"
namespace Tetraedge {
static inline uint _toGlLight(uint lightno) {
return GL_LIGHT0 + lightno;
}
TeLightOpenGL::TeLightOpenGL() {
}
void TeLightOpenGL::disable(uint lightno) {
glDisable(_toGlLight(lightno));
}
void TeLightOpenGL::enable(uint lightno) {
// Note: original casts to float and compares to 0.01, but that's the same?
if (_colDiffuse.r() == 0 && _colDiffuse.g() == 0 && _colDiffuse.b() == 0)
glDisable(_toGlLight(lightno));
else
glEnable(_toGlLight(lightno));
}
/*static*/
void TeLightOpenGL::disableAll() {
glDisable(GL_LIGHTING);
}
/*static*/
void TeLightOpenGL::enableAll() {
glEnable(GL_LIGHTING);
}
void TeLightOpenGL::draw(TeCamera &camera) {
error("TODO: Finish TeLightOpenGL::draw");
}
void TeLightOpenGL::update(uint lightno) {
if (lightno > GL_MAX_LIGHTS)
error("Invalid light no %d", lightno);
const uint glLight = _toGlLight(lightno);
const float ambient[4] = {_colAmbient.r() / 255.0f, _colAmbient.g() / 255.0f,
_colAmbient.b() / 255.0f, 1.0f};
glLightfv(glLight, GL_AMBIENT, ambient);
const float diff[4] = {_colDiffuse.r() / 255.0f, _colDiffuse.g() / 255.0f,
_colDiffuse.b() / 255.0f, 1.0f};
glLightfv(glLight, GL_DIFFUSE, diff);
// WORKAROUND: Original game sets 0.01 as threshold here to avoid enabling
// the "shadow" light. However, Syberia CitStation/31130 has shadowlight with
// values (4, 0, 0) which means it gets enabled and everything is dark.
if (diff[0] < 0.02f && diff[1] < 0.02f && diff[2] < 0.02f)
glDisable(glLight);
const float spec[4] = {_colSpecular.r() / 255.0f, _colSpecular.g() / 255.0f,
_colSpecular.b() / 255.0f, 1.0f};
glLightfv(glLight, GL_SPECULAR, spec);
if (_type == LightTypeSpot || _type == LightTypePoint) {
const float pos[4] = {_position3d.x(), _position3d.y(), _position3d.z(), 1.0f};
glLightfv(glLight, GL_POSITION, pos);
glLightf(glLight, GL_CONSTANT_ATTENUATION, _constAtten);
glLightf(glLight, GL_LINEAR_ATTENUATION, _linearAtten);
glLightf(glLight, GL_QUADRATIC_ATTENUATION, _quadraticAtten);
}
if (_type == LightTypeDirectional) {
const TeVector3f32 dirv = directionVector();
const float dir[4] = {dirv.x(), dirv.y(), dirv.z(), 0.0f};
glLightfv(glLight, GL_POSITION, dir);
}
if (_type == LightTypeSpot) {
const TeVector3f32 dirv = directionVector();
const float dir[4] = {dirv.x(), dirv.y(), dirv.z(), 0.0f};
glLightfv(glLight, GL_SPOT_DIRECTION, dir);
glLightf(glLight, GL_SPOT_CUTOFF, (_cutoff * 180.0f) / M_PI);
// Exponent doesn't get set in Syberia 2
if (g_engine->gameType() == TetraedgeEngine::kSyberia)
glLightf(glLight, GL_SPOT_EXPONENT, _exponent);
} else {
glLightf(glLight, GL_SPOT_CUTOFF, 180.0f);
}
}
/*static*/
void TeLightOpenGL::updateGlobal() {
const TeColor globalAmbient(_globalAmbientColor);
const float col[4] = {globalAmbient.r() / 255.0f,
globalAmbient.g() / 255.0f, globalAmbient.b() / 255.0f, 1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,56 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_LIGHT_OPENGL_H
#define TETRAEDGE_TE_TE_LIGHT_OPENGL_H
#include "common/scummsys.h"
#if defined(USE_OPENGL_GAME)
#include "tetraedge/te/te_light.h"
namespace Tetraedge {
class TeCamera;
class TeLightOpenGL : public TeLight {
public:
TeLightOpenGL();
void disable(uint lightno) override;
void enable(uint lightno) override;
void draw(TeCamera &camera) override;
void update(uint lightno) override;
static void updateGlobal();
static void disableAll();
static void enableAll();
};
} // end namespace Tetraedge
#endif // USE_OPENGL
#endif // TETRAEDGE_TE_TE_LIGHT_OPENGL_H

View File

@@ -0,0 +1,123 @@
/* 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 "graphics/tinygl/tinygl.h"
#include "tetraedge/te/te_light_tinygl.h"
#include "tetraedge/tetraedge.h"
#include "tetraedge/te/te_color.h"
#include "tetraedge/te/te_quaternion.h"
#include "tetraedge/te/te_vector3f32.h"
namespace Tetraedge {
static inline uint _toGlLight(uint lightno) {
return TGL_LIGHT0 + lightno;
}
TeLightTinyGL::TeLightTinyGL() {
}
void TeLightTinyGL::disable(uint lightno) {
tglDisable(_toGlLight(lightno));
}
void TeLightTinyGL::enable(uint lightno) {
if (_colDiffuse.r() == 0 && _colDiffuse.g() == 0 && _colDiffuse.b() == 0)
tglDisable(_toGlLight(lightno));
else
tglEnable(_toGlLight(lightno));
}
/*static*/
void TeLightTinyGL::disableAll() {
tglDisable(TGL_LIGHTING);
}
/*static*/
void TeLightTinyGL::enableAll() {
tglEnable(TGL_LIGHTING);
}
void TeLightTinyGL::draw(TeCamera &camera) {
error("TODO: Finish TeLight::draw");
}
void TeLightTinyGL::update(uint lightno) {
if (lightno > TGL_MAX_LIGHTS)
error("Invalid light no %d", lightno);
const uint glLight = _toGlLight(lightno);
const float ambient[4] = {_colAmbient.r() / 255.0f, _colAmbient.g() / 255.0f,
_colAmbient.b() / 255.0f, 1.0f};
tglLightfv(glLight, TGL_AMBIENT, ambient);
const float diff[4] = {_colDiffuse.r() / 255.0f, _colDiffuse.g() / 255.0f,
_colDiffuse.b() / 255.0f, 1.0f};
tglLightfv(glLight, TGL_DIFFUSE, diff);
// WORKAROUND: Original game sets 0.01 as threshold here to avoid enabling
// the "shadow" light. However, Syberia CitStation/31130 has shadowlight with
// values (4, 0, 0) which means it gets enabled and everything is dark.
if (diff[0] < 0.02f && diff[1] < 0.02f && diff[2] < 0.02f)
tglDisable(glLight);
const float spec[4] = {_colSpecular.r() / 255.0f, _colSpecular.g() / 255.0f,
_colSpecular.b() / 255.0f, 1.0f};
tglLightfv(glLight, TGL_SPECULAR, spec);
if (_type == LightTypeSpot || _type == LightTypePoint) {
const float pos[4] = {_position3d.x(), _position3d.y(), _position3d.z(), 1.0f};
tglLightfv(glLight, TGL_POSITION, pos);
tglLightf(glLight, TGL_CONSTANT_ATTENUATION, _constAtten);
tglLightf(glLight, TGL_LINEAR_ATTENUATION, _linearAtten);
tglLightf(glLight, TGL_QUADRATIC_ATTENUATION, _quadraticAtten);
}
if (_type == LightTypeDirectional) {
const TeVector3f32 dirv = directionVector();
const float dir[4] = {dirv.x(), dirv.y(), dirv.z(), 0.0f};
tglLightfv(glLight, TGL_POSITION, dir);
}
if (_type == LightTypeSpot) {
const TeVector3f32 dirv = directionVector();
const float dir[4] = {dirv.x(), dirv.y(), dirv.z(), 0.0f};
tglLightfv(glLight, TGL_SPOT_DIRECTION, dir);
tglLightf(glLight, TGL_SPOT_CUTOFF, (_cutoff * 180.0f) / M_PI);
// Exponent doesn't get set in Syberia 2
if (g_engine->gameType() == TetraedgeEngine::kSyberia)
tglLightf(glLight, TGL_SPOT_EXPONENT, _exponent);
} else {
tglLightf(glLight, TGL_SPOT_CUTOFF, 180.0f);
}
}
/*static*/
void TeLightTinyGL::updateGlobal() {
const TeColor globalAmbient(_globalAmbientColor);
const float col[4] = {globalAmbient.r() / 255.0f,
globalAmbient.g() / 255.0f, globalAmbient.b() / 255.0f, 1.0f};
tglLightModelfv(TGL_LIGHT_MODEL_AMBIENT, col);
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,54 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_LIGHT_TINYGL_H
#define TETRAEDGE_TE_TE_LIGHT_TINYGL_H
#include "common/scummsys.h"
#if defined(USE_TINYGL)
#include "tetraedge/te/te_light.h"
namespace Tetraedge {
class TeLightTinyGL : public TeLight {
public:
TeLightTinyGL();
void disable(uint lightno) override;
void enable(uint lightno) override;
void draw(TeCamera &camera) override;
void update(uint lightno) override;
static void updateGlobal();
static void disableAll();
static void enableAll();
};
} // end namespace Tetraedge
#endif // USE_TINYGL
#endif // TETRAEDGE_TE_TE_LIGHT_TINYGL_H

View File

@@ -0,0 +1,29 @@
/* 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 "tetraedge/te/te_list_layout.h"
namespace Tetraedge {
TeListLayout::TeListLayout() {
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,50 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_LIST_LAYOUT_H
#define TETRAEDGE_TE_TE_LIST_LAYOUT_H
#include "tetraedge/te/te_layout.h"
namespace Tetraedge {
class TeListLayout : public TeLayout {
public:
TeListLayout();
void setMinimumMargin(const TeVector3f32 &val) { _minimumMargin = val; }
void setMaximumMargin(const TeVector3f32 &val) { _maximumMargin = val; }
void setDirection(const TeVector3f32 &val) { _direction = val; }
const TeVector3f32 &minimumMargin() { return _minimumMargin; }
const TeVector3f32 &maximumMargin() { return _maximumMargin; }
const TeVector3f32 &direction() { return _direction; }
private:
TeVector3f32 _minimumMargin;
TeVector3f32 _maximumMargin;
TeVector3f32 _direction;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_LIST_LAYOUT_H

View File

@@ -0,0 +1,252 @@
/* 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 "common/debug.h"
#include "common/textconsole.h"
#include "common/lua/lua.h"
#include "common/lua/lualib.h"
#include "common/lua/lauxlib.h"
#include "tetraedge/te/te_lua_context.h"
namespace Tetraedge {
//#define TETRAEDGE_LUA_DEBUG 1
//static lua_State *globalState = nullptr;
static int luaPanicFunction(lua_State *state) {
const char *msg = lua_tolstring(state, -1, nullptr);
warning("Lua: %s", msg);
lua_settop(state, -2);
return 1;
}
#ifdef TETRAEDGE_LUA_DEBUG
static void luaDebugHook(lua_State *L, lua_Debug *ar) {
if (!lua_getinfo(L, "Sn", ar))
return;
debug("LUA: %s %d", ar->source, ar->currentline);
}
#endif
TeLuaContext::TeLuaContext() : _luaState(nullptr) {
_luaState = lua_open();
luaL_openlibs(_luaState);
lua_atpanic(_luaState, luaPanicFunction);
}
TeLuaContext::~TeLuaContext() {
destroy();
}
void TeLuaContext::addBindings(void(*fn)(lua_State *)) {
fn(_luaState);
}
void TeLuaContext::create() {
_luaState = lua_open();
luaL_openlibs(_luaState);
lua_atpanic(_luaState, luaPanicFunction);
#ifdef TETRAEDGE_LUA_DEBUG
lua_sethook(_luaState, luaDebugHook, LUA_MASKCALL | LUA_MASKLINE, 0);
#endif
}
void TeLuaContext::destroy() {
if (_luaState)
lua_close(_luaState);
_luaState = nullptr;
}
TeVariant TeLuaContext::global(const Common::String &name) {
lua_getglobal(_luaState, name.c_str());
TeVariant retval;
int type = lua_type(_luaState, -1);
if (type == LUA_TBOOLEAN) {
int result = lua_toboolean(_luaState, -1);
lua_settop(_luaState, -2);
return TeVariant(result > 0);
} else if (type == LUA_TNUMBER) {
double result = lua_tonumber(_luaState, -1);
lua_settop(_luaState, -2);
return TeVariant(result);
} else if (type == LUA_TSTRING) {
const char *str = lua_tolstring(_luaState, -1, nullptr);
lua_settop(_luaState, -2);
return TeVariant(str);
}
if (type != LUA_TNIL)
warning("TeLuaContext::global: Unexpected type %d for global %s", type, name.c_str());
else
debug("TeLuaContext::global: Request for nil global %s", name.c_str());
return TeVariant();
}
void TeLuaContext::setGlobal(const Common::String &name, int val) {
lua_pushinteger(_luaState, val);
lua_setglobal(_luaState, name.c_str());
}
void TeLuaContext::setGlobal(const Common::String &name, bool val) {
lua_pushboolean(_luaState, val);
lua_setglobal(_luaState, name.c_str());
}
void TeLuaContext::setGlobal(const Common::String &name, const Common::String &val) {
lua_pushstring(_luaState, val.c_str());
lua_setglobal(_luaState, name.c_str());
}
void TeLuaContext::removeGlobal(const Common::String &name) {
lua_pushnil(_luaState);
lua_setglobal(_luaState, name.c_str());
}
void TeLuaContext::registerCFunction(const Common::String &name, int(*fn)(lua_State *)) {
lua_pushcclosure(_luaState, fn, 0);
lua_setglobal(_luaState, name.c_str());
}
void TeLuaContext::setInRegistry(const Common::String &name, TeLuaGUI *gui) {
lua_pushstring(_luaState, name.c_str());
lua_pushlightuserdata(_luaState, gui);
lua_settable(_luaState, LUA_REGISTRYINDEX);
}
// Types for save file. Aligned with the Lua types at type of
// writing, but don't save them just in case they could change.
enum TeLuaSaveVarType {
None = 0,
Boolean = 1,
Number = 3,
String = 4
};
//#define TETRAEDGE_LUA_DEBUG_SAVELOAD
Common::Error TeLuaContext::syncState(Common::Serializer &s) {
// Save/Load globals. The format of saving is:
// [type][name][val] [type][name][val]...
// Vals can be string, number (uint32), or boolean (byte)
// The type of "None" (0) is the end of the list (and has no name/val).
if (s.isSaving()) {
#ifdef TETRAEDGE_LUA_DEBUG_SAVELOAD
debug("TeLuaContext::syncState: --- Saving globals: ---");
#endif
lua_pushvalue(_luaState, LUA_GLOBALSINDEX);
lua_pushnil(_luaState);
int nextresult = lua_next(_luaState, -2);
while (true) {
if (nextresult == 0) {
TeLuaSaveVarType stype = None;
s.syncAsUint32LE(stype);
lua_settop(_luaState, -2);
break;
}
uint vtype = lua_type(_luaState, -1);
Common::String name = lua_tolstring(_luaState, -2, nullptr);
if (vtype == LUA_TBOOLEAN) {
TeLuaSaveVarType stype = Boolean;
s.syncAsUint32LE(stype);
s.syncString(name);
bool val = lua_toboolean(_luaState, -1);
s.syncAsByte(val);
#ifdef TETRAEDGE_LUA_DEBUG_SAVELOAD
debug("TeLuaContext::syncState: bool %s = %s", name.c_str(), val ? "true" : "false");
#endif
} else if (vtype == LUA_TNUMBER) {
TeLuaSaveVarType stype = Number;
s.syncAsUint32LE(stype);
s.syncString(name);
double val = lua_tonumber(_luaState, -1);
s.syncAsDoubleLE(val);
#ifdef TETRAEDGE_LUA_DEBUG_SAVELOAD
debug("TeLuaContext::syncState: num %s = %f", name.c_str(), val);
#endif
} else if (vtype == LUA_TSTRING) {
TeLuaSaveVarType stype = String;
s.syncAsUint32LE(stype);
s.syncString(name);
Common::String val = lua_tostring(_luaState, -1);
s.syncString(val);
#ifdef TETRAEDGE_LUA_DEBUG_SAVELOAD
debug("TeLuaContext::syncState: str %s = '%s'", name.c_str(), val.c_str());
#endif
}
lua_settop(_luaState, -2);
nextresult = lua_next(_luaState, -2);
}
} else {
#ifdef TETRAEDGE_LUA_DEBUG_SAVELOAD
debug("TeLuaContext::syncState: --- Loading globals: --- ");
#endif
// loading
TeLuaSaveVarType vtype = None;
s.syncAsUint32LE(vtype);
while (vtype != None) {
Common::String name;
s.syncString(name);
switch (vtype) {
case Boolean: {
byte b = 0;
s.syncAsByte(b);
lua_pushboolean(_luaState, b);
#ifdef TETRAEDGE_LUA_DEBUG_SAVELOAD
debug("TeLuaContext::syncState: bool %s = %s", name.c_str(), b ? "true" : "false");
#endif
break;
}
case Number: {
float d = 0;
s.syncAsDoubleLE(d);
lua_pushnumber(_luaState, d);
#ifdef TETRAEDGE_LUA_DEBUG_SAVELOAD
debug("TeLuaContext::syncState: num %s = %f", name.c_str(), d);
#endif
break;
}
case String: {
Common::String str;
s.syncString(str);
lua_pushstring(_luaState, str.c_str());
#ifdef TETRAEDGE_LUA_DEBUG_SAVELOAD
debug("TeLuaContext::syncState: str %s = '%s'", name.c_str(), str.c_str());
#endif
break;
}
default:
error("Unexpected lua type on load %d", (int)vtype);
}
lua_setglobal(_luaState, name.c_str());
s.syncAsUint32LE(vtype);
}
}
#ifdef TETRAEDGE_LUA_DEBUG_SAVELOAD
debug("TeLuaContext::syncState: -------- end --------");
#endif
return Common::kNoError;
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,82 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_LUA_CONTEXT_H
#define TETRAEDGE_TE_TE_LUA_CONTEXT_H
#include "common/error.h"
#include "common/str.h"
#include "common/serializer.h"
#include "tetraedge/te/te_variant.h"
struct lua_State;
namespace Tetraedge {
class TeLuaGUI;
/*
* The lua state holder. In the original Te engine this is split into an
* interface and Impl class, but it just ends up being a 1-line wrapper in
* each function so there's very little point.
*/
class TeLuaContext {
public:
TeLuaContext();
~TeLuaContext();
void addBindings(void(*fn)(lua_State *));
void create();
void destroy();
TeVariant global(const Common::String &name);
void global(const Common::String &name, bool &outVal);
void global(const Common::String &name, Common::String &outVal);
void global(const Common::String &name, int &outVal);
void global(const Common::String &name, float &outVal);
bool isCreated() {
return _luaState != nullptr;
}
//void load(TiXmlNode *node);
//void save(TiXmlNode *node);
lua_State *luaState() { return _luaState; }
void registerCFunction(const Common::String &name, int(*fn)(lua_State *));
void removeGlobal(const Common::String &name);
void setGlobal(const Common::String &name, int val);
void setGlobal(const Common::String &name, bool val);
void setGlobal(const Common::String &name, const Common::String &val);
void setInRegistry(const Common::String &name, TeLuaGUI *gui);
Common::Error syncState(Common::Serializer &s);
private:
lua_State *_luaState;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_LUA_CONTEXT_H

View File

@@ -0,0 +1,302 @@
/* 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 "common/file.h"
#include "tetraedge/tetraedge.h"
#include "tetraedge/te/te_core.h"
#include "tetraedge/te/te_lua_gui.h"
#include "tetraedge/te/te_lua_gui_lua_callbacks.h"
namespace Tetraedge {
TeLuaGUI::TeLuaGUI() : _loaded(false) {
}
TeButtonLayout *TeLuaGUI::buttonLayout(const Common::String &name) {
StringMap<TeButtonLayout *>::iterator iter = _buttonLayouts.find(name);
if (iter != _buttonLayouts.end())
return iter->_value;
return nullptr;
}
TeCheckboxLayout *TeLuaGUI::checkboxLayout(const Common::String &name) {
StringMap<TeCheckboxLayout *>::iterator iter = _checkboxLayouts.find(name);
if (iter != _checkboxLayouts.end())
return iter->_value;
return nullptr;
}
TeClipLayout *TeLuaGUI::clipLayout(const Common::String &name) {
StringMap<TeClipLayout *>::iterator iter = _clipLayouts.find(name);
if (iter != _clipLayouts.end())
return iter->_value;
return nullptr;
}
TeCurveAnim2<Te3DObject2, TeColor> *TeLuaGUI::colorLinearAnimation(const Common::String &name) {
StringMap<TeCurveAnim2<Te3DObject2, TeColor> *>::iterator iter = _colorLinearAnimations.find(name);
if (iter != _colorLinearAnimations.end())
return iter->_value;
return nullptr;
}
TeExtendedTextLayout *TeLuaGUI::extendedTextLayout(const Common::String &name) {
StringMap<TeExtendedTextLayout *>::iterator iter = _extendedTextLayouts.find(name);
if (iter != _extendedTextLayouts.end())
return iter->_value;
return nullptr;
}
TeLayout *TeLuaGUI::layout(const Common::String &name) {
StringMap<TeLayout *>::iterator iter = _layouts.find(name);
if (iter != _layouts.end())
return iter->_value;
TeLayout *layout;
layout = buttonLayout(name);
if (layout)
return layout;
layout = spriteLayout(name);
if (layout)
return layout;
layout = dynamic_cast<TeLayout *>(textLayout(name));
if (layout)
return layout;
layout = checkboxLayout(name);
if (layout)
return layout;
layout = listLayout(name);
if (layout)
return layout;
layout = scrollingLayout(name);
if (layout)
return layout;
layout = clipLayout(name);
if (layout)
return layout;
layout = extendedTextLayout(name);
if (layout)
return layout;
return nullptr;
}
TeCurveAnim2<TeLayout, TeVector3f32> *TeLuaGUI::layoutAnchorLinearAnimation(const Common::String &name) {
return _layoutAnchorLinearAnimations.getVal(name);
}
TeCurveAnim2<TeLayout, TeVector3f32> *TeLuaGUI::layoutPositionLinearAnimation(const Common::String &name) {
return _layoutPositionLinearAnimations.getVal(name);
}
TeListLayout *TeLuaGUI::listLayout(const Common::String &name) {
StringMap<TeListLayout *>::iterator iter = _listLayouts.find(name);
if (iter != _listLayouts.end())
return iter->_value;
return nullptr;
}
TeCurveAnim2<TeI3DObject2, TeQuaternion> *TeLuaGUI::rotationLinearAnimation(const Common::String &name) {
error("TODO: Implement TeLuaGUI::rotationLinearAnimation.");
return nullptr;
}
TeScrollingLayout *TeLuaGUI::scrollingLayout(const Common::String &name) {
StringMap<TeScrollingLayout *>::iterator iter = _scrollingLayouts.find(name);
if (iter != _scrollingLayouts.end())
return iter->_value;
return nullptr;
}
TeSpriteLayout *TeLuaGUI::spriteLayout(const Common::String &name) {
StringMap<TeSpriteLayout *>::iterator iter = _spriteLayouts.find(name);
if (iter != _spriteLayouts.end())
return iter->_value;
return nullptr;
}
TeITextLayout *TeLuaGUI::textLayout(const Common::String &name) {
StringMap<TeTextLayout *>::iterator iter = _textLayouts.find(name);
if (iter != _textLayouts.end())
return iter->_value;
StringMap<TeExtendedTextLayout *>::iterator iter2 = _extendedTextLayouts.find(name);
if (iter2 != _extendedTextLayouts.end())
return iter2->_value;
return nullptr;
}
TeButtonLayout *TeLuaGUI::buttonLayoutChecked(const Common::String &name) {
TeButtonLayout *l = buttonLayout(name);
if (!l) {
error("No button '%s' in gui data '%s'", name.c_str(),
_scriptPath.toString(Common::Path::kNativeSeparator).c_str());
}
return l;
}
TeLayout *TeLuaGUI::layoutChecked(const Common::String &name) {
TeLayout *l = layout(name);
if (!l) {
error("No layout '%s' in gui data '%s'", name.c_str(),
_scriptPath.toString(Common::Path::kNativeSeparator).c_str());
}
return l;
}
TeSpriteLayout *TeLuaGUI::spriteLayoutChecked(const Common::String &name) {
TeSpriteLayout *l = spriteLayout(name);
if (!l) {
error("No sprite layout '%s' in gui data '%s'", name.c_str(),
_scriptPath.toString(Common::Path::kNativeSeparator).c_str());
}
return l;
}
bool TeLuaGUI::load(const Common::Path &subPath) {
TeCore *core = g_engine->getCore();
return load(core->findFile(subPath));
}
bool TeLuaGUI::load(const TetraedgeFSNode &node) {
unload();
_scriptPath = node.getPath();
// Not the same as original, we abstract the search logic a bit.
_luaContext.setGlobal("Pixel", 0);
_luaContext.setGlobal("Percent", 1);
_luaContext.setGlobal("None", 0);
_luaContext.setGlobal("LetterBox", 1);
_luaContext.setGlobal("PanScan", 2);
_luaContext.setGlobal("MultiLine", 0);
_luaContext.setGlobal("SingleLine", 1);
_luaContext.setGlobal("Fixed", 0);
_luaContext.setGlobal("Proportional", 1);
_luaContext.registerCFunction("TeLayout", layoutBindings);
_luaContext.registerCFunction("TeListLayout", listLayoutBindings);
_luaContext.registerCFunction("TeSpriteLayout", spriteLayoutBindings);
_luaContext.registerCFunction("TeButtonLayout", buttonLayoutBindings);
_luaContext.registerCFunction("TeCheckboxLayout", checkboxLayoutBindings);
_luaContext.registerCFunction("TeLayoutPositionLinearAnimation", layoutPositionLinearAnimationBindings);
_luaContext.registerCFunction("TeLayoutAnchorLinearAnimation", layoutAnchorLinearAnimationBindings);
_luaContext.registerCFunction("TeTextLayout", textLayoutBindings);
_luaContext.registerCFunction("TeClipLayout", clipLayoutBindings);
_luaContext.registerCFunction("TeColorLinearAnimation", colorLinearAnimationBindings);
_luaContext.registerCFunction("TeRotationLinearAnimation", rotationLinearAnimationBindings);
_luaContext.registerCFunction("TeScrollingLayout", scrollingLayoutBindings);
_luaContext.registerCFunction("TeExtendedTextLayout", extendedTextLayoutBindings);
// TODO: We replaced the video layout from Amerzone with a sprite layout. Probably
// works ok?
_luaContext.registerCFunction("TeVideoLayout", spriteLayoutBindings);
_luaContext.setInRegistry("__TeLuaGUIThis", this);
_luaScript.attachToContext(&_luaContext);
_luaScript.load(node);
_luaScript.execute();
_luaScript.unload();
_loaded = true;
return true;
}
void TeLuaGUI::unload() {
for (auto &iter : _layouts) {
iter._value->setVisible(false);
iter._value->deleteLater();
}
_layouts.clear();
for (auto &iter : _buttonLayouts) {
iter._value->setVisible(false);
iter._value->deleteLater();
}
_buttonLayouts.clear();
for (auto &iter : _checkboxLayouts) {
iter._value->setVisible(false);
iter._value->deleteLater();
}
_checkboxLayouts.clear();
for (auto &iter : _listLayouts) {
iter._value->setVisible(false);
iter._value->deleteLater();
}
_listLayouts.clear();
for (auto &iter : _spriteLayouts) {
iter._value->setVisible(false);
iter._value->deleteLater();
}
_spriteLayouts.clear();
for (auto &iter : _textLayouts) {
iter._value->setVisible(false);
iter._value->deleteLater();
}
_textLayouts.clear();
for (auto &iter : _scrollingLayouts) {
iter._value->setVisible(false);
iter._value->deleteLater();
}
_scrollingLayouts.clear();
for (auto &iter : _clipLayouts) {
iter._value->setVisible(false);
iter._value->deleteLater();
}
_clipLayouts.clear();
for (auto &iter : _extendedTextLayouts) {
iter._value->setVisible(false);
iter._value->deleteLater();
}
_extendedTextLayouts.clear();
for (auto &iter : _layoutAnchorLinearAnimations) {
iter._value->stop();
delete iter._value;
}
_layoutAnchorLinearAnimations.clear();
for (auto &iter : _layoutPositionLinearAnimations) {
iter._value->stop();
delete iter._value;
}
_layoutPositionLinearAnimations.clear();
for (auto &iter : _colorLinearAnimations) {
iter._value->stop();
delete iter._value;
}
_colorLinearAnimations.clear();
_loaded = false;
}
TeVariant TeLuaGUI::value(const Common::String &globalName) {
return _luaContext.global(globalName);
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,129 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_LUA_GUI_H
#define TETRAEDGE_TE_TE_LUA_GUI_H
#include "common/str.h"
#include "common/hashmap.h"
#include "common/hash-str.h"
#include "tetraedge/te/te_button_layout.h"
#include "tetraedge/te/te_checkbox_layout.h"
#include "tetraedge/te/te_clip_layout.h"
#include "tetraedge/te/te_color.h"
#include "tetraedge/te/te_curve_anim2.h"
#include "tetraedge/te/te_extended_text_layout.h"
#include "tetraedge/te/te_i_3d_object2.h"
#include "tetraedge/te/te_i_layout.h"
#include "tetraedge/te/te_i_text_layout.h"
#include "tetraedge/te/te_layout.h"
#include "tetraedge/te/te_list_layout.h"
#include "tetraedge/te/te_lua_context.h"
#include "tetraedge/te/te_lua_script.h"
#include "tetraedge/te/te_object.h"
#include "tetraedge/te/te_quaternion.h"
#include "tetraedge/te/te_scrolling_layout.h"
#include "tetraedge/te/te_sprite_layout.h"
#include "tetraedge/te/te_text_layout.h"
#include "tetraedge/te/te_vector3f32.h"
#include "tetraedge/te/te_variant.h"
namespace Tetraedge {
class TeLuaGUI : public TeObject {
public:
TeLuaGUI();
virtual ~TeLuaGUI() {
unload();
};
virtual void enter() {};
virtual void leave() {};
TeLayout *layout(const Common::String &name);
TeButtonLayout *buttonLayout(const Common::String &name);
TeCheckboxLayout *checkboxLayout(const Common::String &name);
TeClipLayout *clipLayout(const Common::String &name);
TeCurveAnim2<Te3DObject2, TeColor> *colorLinearAnimation(const Common::String &name);
TeExtendedTextLayout *extendedTextLayout(const Common::String &name);
TeCurveAnim2<TeLayout, TeVector3f32> *layoutAnchorLinearAnimation(const Common::String &name);
TeCurveAnim2<TeLayout, TeVector3f32> *layoutPositionLinearAnimation(const Common::String &name);
TeListLayout *listLayout(const Common::String &name);
TeCurveAnim2<TeI3DObject2, TeQuaternion> *rotationLinearAnimation(const Common::String &name);
TeScrollingLayout *scrollingLayout(const Common::String &name);
TeSpriteLayout *spriteLayout(const Common::String &name);
TeITextLayout *textLayout(const Common::String &name);
// Same as the above functions, but call error() if the result is null.
TeLayout *layoutChecked(const Common::String &name);
TeButtonLayout *buttonLayoutChecked(const Common::String &name);
TeSpriteLayout *spriteLayoutChecked(const Common::String &name);
bool load(const Common::Path &subPath);
bool load(const TetraedgeFSNode &node);
void unload();
TeVariant value(const Common::String &key);
template <typename T> using StringMap = Common::HashMap<Common::String, T>;
StringMap<TeLayout *> &layouts() { return _layouts; }
StringMap<TeButtonLayout *> &buttonLayouts() { return _buttonLayouts; }
StringMap<TeCheckboxLayout *> &checkboxLayouts() { return _checkboxLayouts; }
StringMap<TeListLayout *> &listLayouts() { return _listLayouts; }
StringMap<TeSpriteLayout *> &spriteLayouts() { return _spriteLayouts; }
StringMap<TeTextLayout *> &textLayouts() { return _textLayouts; }
StringMap<TeScrollingLayout *> &scrollingLayouts() { return _scrollingLayouts; }
StringMap<TeClipLayout *> &clipLayouts() { return _clipLayouts; }
StringMap<TeExtendedTextLayout *> &extendedTextLayouts() { return _extendedTextLayouts; }
StringMap<TeCurveAnim2<TeLayout, TeVector3f32> *> &layoutAnchorLinearAnimations() { return _layoutAnchorLinearAnimations; }
StringMap<TeCurveAnim2<TeLayout, TeVector3f32> *> &layoutPositionLinearAnimations() { return _layoutPositionLinearAnimations; }
StringMap<TeCurveAnim2<Te3DObject2, TeColor> *> &colorLinearAnimations() { return _colorLinearAnimations; }
bool loaded() const { return _loaded; }
const Common::Path &scriptPath() const { return _scriptPath; }
protected:
bool _loaded;
private:
Common::Path _scriptPath;
TeLuaContext _luaContext;
TeLuaScript _luaScript;
StringMap<TeLayout *> _layouts;
StringMap<TeButtonLayout *> _buttonLayouts;
StringMap<TeCheckboxLayout *> _checkboxLayouts;
StringMap<TeListLayout *> _listLayouts;
StringMap<TeSpriteLayout *> _spriteLayouts;
StringMap<TeTextLayout *> _textLayouts;
StringMap<TeScrollingLayout *> _scrollingLayouts;
StringMap<TeClipLayout *> _clipLayouts;
StringMap<TeExtendedTextLayout *> _extendedTextLayouts;
StringMap<TeCurveAnim2<TeLayout, TeVector3f32> *> _layoutAnchorLinearAnimations;
StringMap<TeCurveAnim2<TeLayout, TeVector3f32> *> _layoutPositionLinearAnimations;
StringMap<TeCurveAnim2<Te3DObject2, TeColor> *> _colorLinearAnimations;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_LUA_GUI_H

View File

@@ -0,0 +1,964 @@
/* 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 "common/lua/lua.h"
#include "common/textconsole.h"
#include "tetraedge/te/te_lua_gui_lua_callbacks.h"
#include "tetraedge/te/te_layout.h"
#include "tetraedge/te/te_lua_gui.h"
#include "tetraedge/te/te_3d_object2.h"
#include "tetraedge/te/te_object.h"
namespace Tetraedge {
template <typename T> static T TeLuaTo(lua_State *L, int index) {
void *ptr = lua_touserdata(L, index);
if (!ptr)
return nullptr;
T obj = reinterpret_cast<T>(ptr);
return dynamic_cast<T>(obj);
}
static Common::String TeLuaToTeString(lua_State *L, int index) {
if (!lua_isstring(L, index)) {
warning("TeLuaToTeString:: not a string");
return "";
} else {
return lua_tolstring(L, index, nullptr);
}
}
static long TeLuaToS32(lua_State *L, int index) {
if (!lua_isnumber(L, index)) {
warning("TeLuaToS32:: not a number");
return 0;
} else {
return lua_tointeger(L, index);
}
}
static long TeLuaToU32(lua_State *L, int index) {
if (!lua_isnumber(L, index)) {
warning("TeLuaToU32:: not a number");
return 0;
} else {
return lua_tointeger(L, index);
}
}
static float TeLuaToF32(lua_State *L, int index) {
if (!lua_isnumber(L, index)) {
warning("TeLuaToF32:: not a number");
return 0.0f;
} else {
return lua_tonumber(L, index);
}
}
static bool TeLuaToBool(lua_State *L, int index) {
if (lua_type(L, index) != LUA_TBOOLEAN) {
warning("TeLuaToBool:: not a bool");
return false;
} else {
return lua_toboolean(L, index);
}
}
static TeColor TeLuaToTeColor(lua_State *L, int index) {
TeColor retval(255, 255, 255, 255);
if (lua_type(L, index) != LUA_TTABLE) {
warning("TeLuaToTeColor:: not a table");
return retval;
}
lua_pushinteger(L, 1);
index--;
lua_gettable(L, index);
if (lua_isnumber(L, -1)) {
retval.r() = TeLuaToU32(L, -1);
}
lua_settop(L, -2);
lua_pushinteger(L, 2);
lua_gettable(L, index);
if (lua_isnumber(L, -1)) {
retval.g() = TeLuaToU32(L, -1);
}
lua_settop(L, -2);
lua_pushinteger(L, 3);
lua_gettable(L, index);
if (lua_isnumber(L, -1)) {
retval.b() = TeLuaToU32(L, -1);
}
lua_settop(L, -2);
lua_pushinteger(L, 4);
lua_gettable(L, index);
if (lua_isnumber(L, -1)) {
retval.a() = TeLuaToU32(L, -1);
}
lua_settop(L, -2);
return retval;
}
static TeVector3f32 TeLuaToTeVector3f32(lua_State *L, int index, TeVector3f32 defaultVal) {
TeVector3f32 retval = defaultVal;
if (lua_type(L, index) != LUA_TTABLE) {
warning("TeLuaToTeVector3f32:: not a table");
} else {
lua_pushinteger(L, 1);
index--;
lua_gettable(L, index);
if (lua_isnumber(L, -1)) {
retval.x() = TeLuaToF32(L, -1);
}
lua_settop(L, -2);
lua_pushinteger(L, 2);
lua_gettable(L, index);
if (lua_isnumber(L, -1)) {
retval.y() = TeLuaToF32(L, -1);
}
lua_settop(L, -2);
lua_pushinteger(L, 3);
lua_gettable(L, index);
if (lua_isnumber(L, -1)) {
retval.z() = TeLuaToF32(L, -1);
}
lua_settop(L, -2);
}
return retval;
}
static Common::Array<float> TeLuaToFloatArray(lua_State *L, int index) {
Common::Array<float> result;
int type = lua_type(L, index);
if (type == LUA_TTABLE) {
lua_pushnil(L);
while (true) {
int next = lua_next(L, index - 1);
if (next == 0)
break;
result.push_back(TeLuaToF32(L, -1));
lua_settop(L, -2);
}
} else {
warning("TeLuaToF32TeArray:: the lua value is not a table");
}
return result;
}
static bool loadCommonLayoutItems(lua_State *L, const char *s, TeLayout *layout) {
if (!strcmp(s, "name")) {
layout->setName(TeLuaToTeString(L, -1));
} else if (!strcmp(s, "sizeType")) {
layout->setSizeType(static_cast<TeILayout::CoordinatesType>(TeLuaToS32(L, -1)));
} else if (!strcmp(s, "size")) {
TeVector3f32 lastSize = layout->userSize();
TeVector3f32 size = TeLuaToTeVector3f32(L, -1, lastSize);
layout->setSize(size);
} else if (!strcmp(s, "ratio")) {
layout->setRatio(TeLuaToF32(L, -1));
} else if (!strcmp(s, "ratioMode")) {
layout->setRatioMode(static_cast<TeILayout::RatioMode>(TeLuaToS32(L, -1)));
} else if (!strcmp(s, "safeAreaRatio")) {
layout->setSafeAreaRatio(TeLuaToF32(L, -1));
} else if (!strcmp(s, "anchor")) {
TeVector3f32 lastAnchor = layout->anchor();
TeVector3f32 anchor = TeLuaToTeVector3f32(L, -1, lastAnchor);
layout->setAnchor(anchor);
} else if (!strcmp(s, "positionType")) {
layout->setPositionType(static_cast<TeILayout::CoordinatesType>(TeLuaToS32(L, -1)));
} else if (!strcmp(s, "position")) {
TeVector3f32 lastPos = layout->userPosition();
TeVector3f32 pos = TeLuaToTeVector3f32(L, -1, lastPos);
layout->setPosition(pos);
} else if (!strcmp(s, "visible")) {
layout->setVisible(TeLuaToBool(L, -1));
} else if (!strcmp(s, "color")) {
layout->setColor(TeLuaToTeColor(L, -1));
} else {
return false;
}
return true;
}
// TODO: Fix this widescreen flag
static bool _g_bWidescreen = false;
int layoutBindings(lua_State *L) {
if (lua_type(L, -1) != LUA_TTABLE) {
warning("layoutBindings:: the lua value is not a table");
return 0;
}
TeLayout *layout = new TeLayout();
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
int type = lua_type(L, -2);
if (type == LUA_TSTRING) {
const char *s = lua_tolstring(L, -2, nullptr);
if (loadCommonLayoutItems(L, s, layout)) {
// do nothing.
} else if (!strcmp(s, "consoleNoStretch")) {
warning("TODO: Handle _g_bWidescreen");
if (_g_bWidescreen) {
layout->setScale(TeVector3f32(0.75f, 1.0f, 1.0f));
}
} else {
warning("[TeLuaGUI.layoutBindings] Unreconized attribute : %s", s);
}
} else if (type == LUA_TNUMBER) {
Te3DObject2 *obj = TeLuaTo<Te3DObject2*>(L, -1);
layout->addChild(obj);
}
lua_settop(L, -2);
}
if (layout->name().empty()) {
layout->setName(Common::String::format("%p", (void *)layout));
}
lua_pushstring(L, "__TeLuaGUIThis");
lua_gettable(L, LUA_REGISTRYINDEX);
TeLuaGUI *gui = TeLuaTo<TeLuaGUI*>(L, -1);
TeLuaGUI::StringMap<TeLayout *> &layouts = gui->layouts();
if (!layouts.contains(layout->name())) {
layouts.setVal(layout->name(), layout);
lua_pushlightuserdata(L, static_cast<Te3DObject2*>(layout));
return true;
} else {
warning("layoutBindings:: multiple objects with name %s", layout->name().c_str());
delete layout;
return false;
}
}
int listLayoutBindings(lua_State *L) {
if (lua_type(L, -1) != LUA_TTABLE) {
warning("listLayoutBindings:: the lua value is not a table");
return 0;
}
TeListLayout *layout = new TeListLayout();
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
int type = lua_type(L, -2);
if (type == LUA_TSTRING) {
const char *s = lua_tolstring(L, -2, nullptr);
if (loadCommonLayoutItems(L, s, layout)) {
// do nothing.
} else if (!strcmp(s, "direction")) {
const TeVector3f32 lastDirection = layout->direction();
const TeVector3f32 direction = TeLuaToTeVector3f32(L, -1, lastDirection);
layout->setDirection(direction);
} else if (!strcmp(s, "minimumMargin")) {
const TeVector3f32 lastMinimumMargin = layout->minimumMargin();
const TeVector3f32 minimumMargin = TeLuaToTeVector3f32(L, -1, lastMinimumMargin);
layout->setMinimumMargin(minimumMargin);
} else if (!strcmp(s, "maximumMargin")) {
const TeVector3f32 lastMaximumMargin = layout->maximumMargin();
const TeVector3f32 maximumMargin = TeLuaToTeVector3f32(L, -1, lastMaximumMargin);
layout->setMaximumMargin(maximumMargin);
} else if (!strcmp(s, "consoleNoStretch")) {
warning("TODO: Handle _g_bWidescreen");
if (_g_bWidescreen) {
layout->setScale(TeVector3f32(0.75f, 1.0f, 1.0f));
}
} else {
warning("[TeLuaGUI.layoutBindings] Unreconized attribute : %s", s);
}
} else if (type == LUA_TNUMBER) {
Te3DObject2 *obj = TeLuaTo<Te3DObject2*>(L, -1);
layout->addChild(obj);
}
lua_settop(L, -2);
}
if (layout->name().empty()) {
layout->setName(Common::String::format("%p", (void *)layout));
}
lua_pushstring(L, "__TeLuaGUIThis");
lua_gettable(L, LUA_REGISTRYINDEX);
TeLuaGUI *gui = TeLuaTo<TeLuaGUI*>(L, -1);
TeLuaGUI::StringMap<TeListLayout *> &layouts = gui->listLayouts();
if (!layouts.contains(layout->name())) {
layouts.setVal(layout->name(), layout);
lua_pushlightuserdata(L, static_cast<Te3DObject2*>(layout));
return true;
} else {
warning("listLayoutBindings:: multiple objects with name %s", layout->name().c_str());
delete layout;
return false;
}
}
int spriteLayoutBindings(lua_State *L) {
if (lua_type(L, -1) != LUA_TTABLE) {
warning("spriteLayoutBindings:: the lua value is not a table");
return 0;
}
lua_pushstring(L, "__TeLuaGUIThis");
lua_gettable(L, LUA_REGISTRYINDEX);
TeLuaGUI *gui = TeLuaTo<TeLuaGUI*>(L, -1);
lua_settop(L, -2);
TeSpriteLayout *layout = new TeSpriteLayout();
lua_pushnil(L);
bool playNow = layout->_tiledSurfacePtr->_frameAnim._runTimer.running();
int startingFrame = 0;
int endingFrame = -1;
Common::Path imgFullPath;
while (lua_next(L, -2) != 0) {
int type = lua_type(L, -2);
if (type == LUA_TSTRING) {
const char *s = lua_tolstring(L, -2, 0);
if (loadCommonLayoutItems(L, s, layout)) {
// do nothing.
} else if (!strcmp(s, "image")) {
Common::String imgPath = TeLuaToTeString(L, -1);
// Slight hack.. fix double-slash that appears in some script files
uint32 loc = imgPath.find("//");
if (loc != Common::String::npos) {
imgPath.replace(loc, 2, "/");
}
if (imgPath.substr(0, 2) == "./") {
imgPath = imgPath.substr(0, 2);
// NOTE: This is bad.. the scriptPath is a system-local path so the
// separator may not be '/', we can't just make a Path from it like
// this. Fortunately it seems this is never actually used? No sprites
// use './' in their data.
warning("Taking non-portable code path to load image in spriteLayoutBindings");
imgFullPath = Common::Path(gui->scriptPath()).getParent().join(imgPath);
} else {
imgFullPath = imgPath;
}
} else if (!strcmp(s, "leftCropping")) {
layout->_tiledSurfacePtr->setLeftCropping(TeLuaToF32(L, -1));
} else if (!strcmp(s, "rightCropping")) {
layout->_tiledSurfacePtr->setRightCropping(TeLuaToF32(L, -1));
} else if (!strcmp(s, "topCropping")) {
layout->_tiledSurfacePtr->setTopCropping(TeLuaToF32(L, -1));
} else if (!strcmp(s, "bottomCropping")) {
layout->_tiledSurfacePtr->setBottomCropping(TeLuaToF32(L, -1));
} else if (!strcmp(s, "loopCount")) {
layout->_tiledSurfacePtr->_frameAnim.setLoopCount(TeLuaToS32(L, -1));
} else if (!strcmp(s, "play")) {
playNow = TeLuaToBool(L, -1);
} else if (!strcmp(s, "reversed")) {
layout->_tiledSurfacePtr->_frameAnim.setReversed(TeLuaToBool(L, -1));
} else if (!strcmp(s, "startingFrame")) {
startingFrame = TeLuaToU32(L, -1);
} else if (!strcmp(s, "endingFrame")) {
endingFrame = TeLuaToU32(L, -1);
} else if (!strcmp(s, "consoleNoStretch")) {
warning("TODO: Handle _g_bWidescreen");
if (_g_bWidescreen) {
layout->setScale(TeVector3f32(0.75f, 1.0f, 1.0f));
}
} else {
warning("[TeLuaGUI.layoutBindings] Unreconized attribute : %s", s);
}
}
lua_settop(L, -2);
}
if (!imgFullPath.empty())
layout->load(imgFullPath);
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
if (lua_type(L, -2) == LUA_TNUMBER) {
Te3DObject2 *object = TeLuaTo<Te3DObject2*>(L, -1);
layout->addChild(object);
}
lua_settop(L, -2);
}
if (layout->name().empty()) {
layout->setName(Common::String::format("%p", (void *)layout));
}
// WORKAROUND: ValStreet scene 11070 has a misnamed animation in the script.
// All references to it in script refer to it with the "ab".
// This scene is broken in the original game too.
if (layout->name() == "11070-1")
layout->setName("ab11070-1");
TeICodec *codec = layout->_tiledSurfacePtr->codec();
if (codec) {
float frameRate = codec->frameRate();
layout->_tiledSurfacePtr->_frameAnim.setStartTime((startingFrame / frameRate) * 1000.0 * 1000.0);
if (endingFrame == -1) {
layout->_tiledSurfacePtr->_frameAnim.setEndTime(FLT_MAX);
} else {
layout->_tiledSurfacePtr->_frameAnim.setEndTime((endingFrame / frameRate) * 1000.0 * 1000.0);
}
}
// Slight divergence from original.. start playing only after setting
// start/end values above as it makes more sense that way.
if (playNow) {
layout->play();
} else {
layout->stop();
}
if (!gui->spriteLayout(layout->name())) {
TeLuaGUI::StringMap<TeSpriteLayout *> &spriteLayouts = gui->spriteLayouts();
spriteLayouts.setVal(layout->name(), layout);
lua_pushlightuserdata(L, static_cast<Te3DObject2*>(layout));
return true;
} else {
warning("layoutBindings:: multiple objects with name %s", layout->name().c_str());
delete layout;
return false;
}
}
int buttonLayoutBindings(lua_State *L) {
if (lua_type(L, -1) != LUA_TTABLE) {
warning("buttonLayoutBindings:: the lua value is not a table");
return 0;
}
TeButtonLayout *layout = new TeButtonLayout();
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
int type = lua_type(L, -2);
if (type == LUA_TSTRING) {
const char *s = lua_tolstring(L, -2, nullptr);
if (loadCommonLayoutItems(L, s, layout)) {
// do nothing.
} else if (!strcmp(s, "upLayout")) {
layout->setUpLayout(TeLuaTo<TeLayout*>(L, -1));
} else if (!strcmp(s, "downLayout")) {
layout->setDownLayout(TeLuaTo<TeLayout*>(L, -1));
} else if (!strcmp(s, "disabledLayout")) {
layout->setDisabledLayout(TeLuaTo<TeLayout*>(L, -1));
} else if (!strcmp(s, "rollOverLayout")) {
layout->setRollOverLayout(TeLuaTo<TeLayout*>(L, -1));
} else if (!strcmp(s, "hitZone")) {
layout->setHitZone(TeLuaTo<TeLayout*>(L, -1));
} else if (!strcmp(s, "enable")) {
layout->setEnable(TeLuaToBool(L, -1));
} else if (!strcmp(s, "clickPassThrough")) {
layout->setClickPassThrough(TeLuaToBool(L, -1));
} else if (!strcmp(s, "validationSound")) {
layout->setValidationSound(Common::Path(TeLuaToTeString(L, -1)));
} else if (!strcmp(s, "validationSoundVolume")) {
layout->setValidationSoundVolume(TeLuaToF32(L, -1));
} else if (!strcmp(s, "consoleNoStretch")) {
warning("TODO: Handle _g_bWidescreen");
if (_g_bWidescreen) {
layout->setScale(TeVector3f32(0.75f, 1.0f, 1.0f));
}
} else {
warning("[TeLuaGUI.buttonLayoutBindings] Unreconized attribute : %s", s);
}
}
lua_settop(L, -2);
}
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
if (lua_type(L, -2) == LUA_TNUMBER) {
Te3DObject2 *object = TeLuaTo<Te3DObject2*>(L, -1);
layout->addChild(object);
}
lua_settop(L, -2);
}
lua_pushstring(L, "__TeLuaGUIThis");
lua_gettable(L, LUA_REGISTRYINDEX);
TeLuaGUI *gui = TeLuaTo<TeLuaGUI*>(L, -1);
TeLuaGUI::StringMap<TeButtonLayout *> &blayouts = gui->buttonLayouts();
if (!blayouts.contains(layout->name())) {
blayouts.setVal(layout->name(), layout);
lua_pushlightuserdata(L, static_cast<Te3DObject2*>(layout));
return true;
} else {
warning("buttonLayoutBindings:: multiple objects with name %s", layout->name().c_str());
delete layout;
return false;
}
}
int checkboxLayoutBindings(lua_State *L) {
if (lua_type(L, -1) != LUA_TTABLE) {
warning("checkboxLayoutBindings:: the lua value is not a table");
return 0;
}
TeCheckboxLayout *layout = new TeCheckboxLayout();
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
int type = lua_type(L, -2);
if (type == LUA_TSTRING) {
const char *s = lua_tolstring(L, -2, nullptr);
if (loadCommonLayoutItems(L, s, layout)) {
// do nothing.
} else if (!strcmp(s, "activeLayout")) {
layout->setActiveLayout(TeLuaTo<TeLayout*>(L, -1));
} else if (!strcmp(s, "unactiveLayout")) {
layout->setUnactiveLayout(TeLuaTo<TeLayout*>(L, -1));
} else if (!strcmp(s, "activeDisabledLayout")) {
layout->setActiveDisabledLayout(TeLuaTo<TeLayout*>(L, -1));
} else if (!strcmp(s, "unactiveDisabledLayout")) {
layout->setUnactiveDisabledLayout(TeLuaTo<TeLayout*>(L, -1));
} else if (!strcmp(s, "activeRollOverLayout")) {
layout->setActiveRollOverLayout(TeLuaTo<TeLayout*>(L, -1));
} else if (!strcmp(s, "unactiveRollOverLayout")) {
layout->setUnactiveRollOverLayout(TeLuaTo<TeLayout*>(L, -1));
} else if (!strcmp(s, "hitZone")) {
layout->setHitZone(TeLuaTo<TeLayout*>(L, -1));
} else if (!strcmp(s, "clickPassThrough")) {
layout->setClickPassThrough(TeLuaToBool(L, -1));
} else if (!strcmp(s, "activationSound")) {
layout->setActivationSound(TeLuaToTeString(L, -1));
} else if (!strcmp(s, "unactivationSound")) {
layout->setUnactivationSound(TeLuaToTeString(L, -1));
} else if (!strcmp(s, "consoleNoStretch")) {
warning("TODO: Handle _g_bWidescreen");
if (_g_bWidescreen) {
layout->setScale(TeVector3f32(0.75f, 1.0f, 1.0f));
}
} else {
warning("[TeLuaGUI.checkboxLayoutBindings] Unreconized attribute : %s", s);
}
}
lua_settop(L, -2);
}
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
if (lua_type(L, -2) == LUA_TNUMBER) {
Te3DObject2 *object = TeLuaTo<Te3DObject2*>(L, -1);
layout->addChild(object);
}
lua_settop(L, -2);
}
lua_pushstring(L, "__TeLuaGUIThis");
lua_gettable(L, LUA_REGISTRYINDEX);
TeLuaGUI *gui = TeLuaTo<TeLuaGUI*>(L, -1);
TeLuaGUI::StringMap<TeCheckboxLayout *> &blayouts = gui->checkboxLayouts();
if (!blayouts.contains(layout->name())) {
blayouts.setVal(layout->name(), layout);
lua_pushlightuserdata(L, static_cast<Te3DObject2*>(layout));
return true;
} else {
warning("checkboxLayoutBindings:: multiple objects with name %s", layout->name().c_str());
delete layout;
return false;
}
}
int layoutPositionLinearAnimationBindings(lua_State *L) {
if (lua_type(L, -1) != LUA_TTABLE) {
warning("layoutPositionLinearAnimationBindings:: the lua value is not a table");
return 0;
}
TeCurveAnim2<TeLayout, TeVector3f32> *anim = new TeCurveAnim2<TeLayout, TeVector3f32>();
lua_pushnil(L);
Common::String name;
while (lua_next(L, -2) != 0) {
int type = lua_type(L, -2);
if (type == LUA_TSTRING) {
const char *s = lua_tolstring(L, -2, nullptr);
if (!strcmp(s, "name")) {
name = TeLuaToTeString(L, -1);
} else if (!strcmp(s, "duration")) {
anim->_duration = TeLuaToF32(L, -1);
} else if (!strcmp(s, "startValue")) {
static const TeVector3f32 defaultStart(0.0f, 0.0f, 0.0f);
anim->_startVal = TeLuaToTeVector3f32(L, -1, defaultStart);
} else if (!strcmp(s, "endValue")) {
static const TeVector3f32 defaultEnd(0.0f, 0.0f, 0.0f);
anim->_endVal = TeLuaToTeVector3f32(L, -1, defaultEnd);
} else if (!strcmp(s, "layout") || !strcmp(s, "pausable")) {
// skip.
// TODO: What should we do with "pausable" attribute?
} else if (!strcmp(s, "curve")) {
const Common::Array<float> curve = TeLuaToFloatArray(L, -1);
anim->setCurve(curve);
} else {
error("[TeLuaGUI.layoutPositionLinearAnimationBindings] Unreconized attribute : %s", s);
}
lua_settop(L, -2);
}
}
if (name.empty()) {
name = Common::String::format("%p", (void *)anim);
}
anim->_callbackMethod = &TeLayout::setPosition;
lua_pushstring(L, "__TeLuaGUIThis");
lua_gettable(L, LUA_REGISTRYINDEX);
TeLuaGUI *gui = TeLuaTo<TeLuaGUI*>(L, -1);
TeLuaGUI::StringMap<TeCurveAnim2<TeLayout, TeVector3f32> *> &anims = gui->layoutPositionLinearAnimations();
if (!anims.contains(name)) {
anims.setVal(name, anim);
lua_pushlightuserdata(L, (void *)(anim));
return true;
} else {
warning("layoutPositionLinearAnimationBindings:: multiple objects with name %s", name.c_str());
delete anim;
return false;
}
return true;
}
int layoutAnchorLinearAnimationBindings(lua_State *L) {
if (lua_type(L, -1) != LUA_TTABLE) {
warning("layoutAnchorLinearAnimationBindings:: the lua value is not a table");
return 0;
}
TeCurveAnim2<TeLayout, TeVector3f32> *anim = new TeCurveAnim2<TeLayout, TeVector3f32>();
lua_pushnil(L);
Common::String name;
while (lua_next(L, -2) != 0) {
int type = lua_type(L, -2);
if (type == LUA_TSTRING) {
const char *s = lua_tolstring(L, -2, nullptr);
if (!strcmp(s, "name")) {
name = TeLuaToTeString(L, -1);
} else if (!strcmp(s, "duration")) {
anim->_duration = TeLuaToF32(L, -1);
} else if (!strcmp(s, "startValue")) {
static const TeVector3f32 defaultStart(0.0f, 0.0f, 0.0f);
anim->_startVal = TeLuaToTeVector3f32(L, -1, defaultStart);
} else if (!strcmp(s, "endValue")) {
static const TeVector3f32 defaultEnd(0.0f, 0.0f, 0.0f);
anim->_endVal = TeLuaToTeVector3f32(L, -1, defaultEnd);
} else if (!strcmp(s, "layout")) {
// skip.
} else if (!strcmp(s, "curve")) {
const Common::Array<float> curve = TeLuaToFloatArray(L, -1);
anim->setCurve(curve);
} else {
error("[TeLuaGUI.layoutAnchorLinearAnimationBindings] Unreconized attribute : %s", s);
}
lua_settop(L, -2);
}
}
if (name.empty()) {
name = Common::String::format("%p", (void *)anim);
}
anim->_callbackMethod = &TeLayout::setAnchor;
lua_pushstring(L, "__TeLuaGUIThis");
lua_gettable(L, LUA_REGISTRYINDEX);
TeLuaGUI *gui = TeLuaTo<TeLuaGUI*>(L, -1);
TeLuaGUI::StringMap<TeCurveAnim2<TeLayout, TeVector3f32> *> &anims = gui->layoutAnchorLinearAnimations();
if (!anims.contains(name)) {
anims.setVal(name, anim);
lua_pushlightuserdata(L, (void *)(anim));
return true;
} else {
warning("layoutAnchorLinearAnimationBindings:: multiple objects with name %s", name.c_str());
delete anim;
return false;
}
return true;
}
int textLayoutBindings(lua_State *L) {
if (lua_type(L, -1) != LUA_TTABLE) {
warning("textLayoutBindings:: the lua value is not a table");
return 0;
}
TeTextLayout *layout = new TeTextLayout();
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
int type = lua_type(L, -2);
if (type == LUA_TSTRING) {
const char *s = lua_tolstring(L, -2, nullptr);
if (loadCommonLayoutItems(L, s, layout)) {
// do nothing.
} else if (!strcmp(s, "text")) {
layout->setText(TeLuaToTeString(L, -1));
} else if (!strcmp(s, "interLine") || !strcmp(s, "interline")) {
layout->setInterLine(TeLuaToF32(L, -1));
} else if (!strcmp(s, "wrapMode")) {
layout->setWrapMode(static_cast<TeTextBase2::WrapMode>(TeLuaToS32(L, -1)));
} else if (!strcmp(s, "textSizeType")) {
layout->setTextSizeType(TeLuaToS32(L, -1));
} else if (!strcmp(s, "textSizeProportionalToWidth")) {
layout->setTextSizeProportionalToWidth(TeLuaToS32(L, -1));
} else if (!strcmp(s, "consoleNoStretch")) {
warning("TODO: Handle _g_bWidescreen");
if (_g_bWidescreen) {
layout->setScale(TeVector3f32(0.75f, 1.0f, 1.0f));
}
} else {
warning("[TeLuaGUI.textLayoutBindings] Unreconized attribute : %s", s);
}
} else if (type == LUA_TNUMBER) {
Te3DObject2 *obj = TeLuaTo<Te3DObject2*>(L, -1);
layout->addChild(obj);
}
lua_settop(L, -2);
}
if (layout->name().empty()) {
layout->setName(Common::String::format("%p", (void *)layout));
}
lua_pushstring(L, "__TeLuaGUIThis");
lua_gettable(L, LUA_REGISTRYINDEX);
TeLuaGUI *gui = TeLuaTo<TeLuaGUI*>(L, -1);
TeLuaGUI::StringMap<TeTextLayout *> &layouts = gui->textLayouts();
if (!layouts.contains(layout->name())) {
layouts.setVal(layout->name(), layout);
lua_pushlightuserdata(L, static_cast<Te3DObject2*>(layout));
return true;
} else {
warning("textLayoutBindings:: multiple objects with name %s", layout->name().c_str());
delete layout;
return false;
}
}
int clipLayoutBindings(lua_State *L) {
if (lua_type(L, -1) != LUA_TTABLE) {
warning("clipLayoutBindings:: the lua value is not a table");
return 0;
}
error("TODO: Implement clipLayoutBindings.");
}
int colorLinearAnimationBindings(lua_State *L) {
if (lua_type(L, -1) != LUA_TTABLE) {
warning("colorLinearAnimationBindings:: the lua value is not a table");
return 0;
}
TeCurveAnim2<Te3DObject2, TeColor> *anim = new TeCurveAnim2<Te3DObject2, TeColor>();
lua_pushnil(L);
Common::String name;
while (lua_next(L, -2) != 0) {
int type = lua_type(L, -2);
if (type == LUA_TSTRING) {
const char *s = lua_tolstring(L, -2, nullptr);
if (!strcmp(s, "name")) {
name = TeLuaToTeString(L, -1);
} else if (!strcmp(s, "duration")) {
anim->_duration = TeLuaToF32(L, -1);
} else if (!strcmp(s, "startValue")) {
anim->_startVal = TeLuaToTeColor(L, -1);
} else if (!strcmp(s, "endValue")) {
anim->_endVal = TeLuaToTeColor(L, -1);
} else if (!strcmp(s, "layout")) {
} else if (!strcmp(s, "curve")) {
const Common::Array<float> curve = TeLuaToFloatArray(L, -1);
anim->setCurve(curve);
} else {
error("[TeLuaGUI.colorLinearAnimationBindings] Unreconized attribute : %s", s);
}
lua_settop(L, -2);
}
}
if (name.empty()) {
name = Common::String::format("%p", (void *)anim);
}
anim->_callbackMethod = &Te3DObject2::setColor;
lua_pushstring(L, "__TeLuaGUIThis");
lua_gettable(L, LUA_REGISTRYINDEX);
TeLuaGUI *gui = TeLuaTo<TeLuaGUI*>(L, -1);
TeLuaGUI::StringMap<TeCurveAnim2<Te3DObject2, TeColor> *> &anims = gui->colorLinearAnimations();
if (!anims.contains(name)) {
anims.setVal(name, anim);
lua_pushlightuserdata(L, (void *)(anim));
return true;
} else {
warning("colorLinearAnimationBindings:: multiple objects with name %s", name.c_str());
delete anim;
return false;
}
return true;
}
int rotationLinearAnimationBindings(lua_State *L) {
if (lua_type(L, -1) != LUA_TTABLE) {
warning("rotationLinearAnimationBindings:: the lua value is not a table");
return 0;
}
error("TODO: Implement rotationLinearAnimationBindings.");
}
int scrollingLayoutBindings(lua_State *L) {
if (lua_type(L, -1) != LUA_TTABLE) {
warning("scrollingLayoutBindings:: the lua value is not a table");
return 0;
}
TeScrollingLayout *layout = new TeScrollingLayout();
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
int type = lua_type(L, -2);
if (type == LUA_TSTRING) {
const char *s = lua_tolstring(L, -2, nullptr);
if (loadCommonLayoutItems(L, s, layout)) {
// do nothing.
} else if (!strcmp(s, "inertiaAnimationDuration")) {
layout->setInertiaAnimationDuration(TeLuaToU32(L, -1));
} else if (!strcmp(s, "inertiaAnimationCurve")) {
layout->setInertiaAnimationCurve(TeLuaToFloatArray(L, -1));
} else if (!strcmp(s, "direction")) {
TeVector3f32 newdir = TeLuaToTeVector3f32(L, -1, layout->direction());
layout->setDirection(newdir);
} else if (!strcmp(s, "contentLayout")) {
layout->setContentLayout(TeLuaTo<TeLayout*>(L, -1));
} else if (!strcmp(s, "enclose")) {
layout->setEnclose(TeLuaToBool(L, -1));
} else if (!strcmp(s, "mouseControl")) {
layout->setMouseControl(TeLuaToBool(L, -1));
} else if (!strcmp(s, "autoScrollLoop")) {
layout->setAutoScrollLoop(TeLuaToS32(L, -1));
} else if (!strcmp(s, "autoScrollDelay")) {
layout->setAutoScrollDelay(TeLuaToS32(L, -1));
} else if (!strcmp(s, "autoScrollAnimation1Enabled")) {
layout->setAutoScrollAnimation1Enabled(TeLuaToBool(L, -1));
} else if (!strcmp(s, "autoScrollAnimation1Delay")) {
layout->setAutoScrollAnimation1Delay(TeLuaToS32(L, -1));
} else if (!strcmp(s, "autoScrollAnimation1Speed")) {
layout->setAutoScrollAnimation1Speed(TeLuaToF32(L, -1));
} else if (!strcmp(s, "autoScrollAnimation1Curve")) {
layout->setAutoScrollAnimation1Curve(TeLuaToFloatArray(L, -1));
} else if (!strcmp(s, "autoScrollAnimation2Enabled")) {
layout->setAutoScrollAnimation2Enabled(TeLuaToBool(L, -1));
} else if (!strcmp(s, "autoScrollAnimation2Delay")) {
layout->setAutoScrollAnimation2Delay(TeLuaToS32(L, -1));
} else if (!strcmp(s, "autoScrollAnimation2Speed")) {
layout->setAutoScrollAnimation2Speed(TeLuaToF32(L, -1));
} else if (!strcmp(s, "autoScrollAnimation2Curve")) {
layout->setAutoScrollAnimation2Curve(TeLuaToFloatArray(L, -1));
} else if (!strcmp(s, "consoleNoStretch")) {
warning("TODO: Handle _g_bWidescreen");
if (_g_bWidescreen) {
layout->setScale(TeVector3f32(0.75f, 1.0f, 1.0f));
}
} else {
warning("[TeLuaGUI.scrollingLayoutBindings] Unreconized attribute : %s", s);
}
} else if (type == LUA_TNUMBER) {
Te3DObject2 *obj = TeLuaTo<Te3DObject2*>(L, -1);
layout->addChild(obj);
}
lua_settop(L, -2);
}
if (layout->name().empty()) {
layout->setName(Common::String::format("%p", (void *)layout));
}
lua_pushstring(L, "__TeLuaGUIThis");
lua_gettable(L, LUA_REGISTRYINDEX);
TeLuaGUI *gui = TeLuaTo<TeLuaGUI*>(L, -1);
TeLuaGUI::StringMap<TeScrollingLayout *> &layouts = gui->scrollingLayouts();
if (!layouts.contains(layout->name())) {
layouts.setVal(layout->name(), layout);
lua_pushlightuserdata(L, static_cast<Te3DObject2*>(layout));
return true;
} else {
warning("scrollingLayoutBindings:: multiple objects with name %s", layout->name().c_str());
delete layout;
return false;
}
}
int extendedTextLayoutBindings(lua_State *L) {
if (lua_type(L, -1) != LUA_TTABLE) {
warning("extendedTextLayoutBindings:: the lua value is not a table");
return 0;
}
TeExtendedTextLayout *layout = new TeExtendedTextLayout();
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
int type = lua_type(L, -2);
if (type == LUA_TSTRING) {
const char *s = lua_tolstring(L, -2, nullptr);
if (loadCommonLayoutItems(L, s, layout)) {
// do nothing.
} else if (!strcmp(s, "text")) {
layout->setText(TeLuaToTeString(L, -1));
} else if (!strcmp(s, "interLine") || !strcmp(s, "interline")) {
layout->setInterLine(TeLuaToF32(L, -1));
} else if (!strcmp(s, "wrapMode")) {
layout->setWrapMode(static_cast<TeTextBase2::WrapMode>(TeLuaToS32(L, -1)));
} else if (!strcmp(s, "autoScrollDelay")) {
layout->setAutoScrollDelay(TeLuaToS32(L, -1));
} else if (!strcmp(s, "autoScrollSpeed")) {
layout->setAutoScrollSpeed(TeLuaToF32(L, -1));
} else if (!strcmp(s, "textSizeType")) {
layout->setTextSizeType(TeLuaToS32(L, -1));
} else if (!strcmp(s, "textSizeProportionalToWidth")) {
layout->setTextSizeProportionalToWidth(TeLuaToS32(L, -1));
} else if (!strcmp(s, "consoleNoStretch")) {
warning("TODO: Handle _g_bWidescreen");
if (_g_bWidescreen) {
layout->setScale(TeVector3f32(0.75f, 1.0f, 1.0f));
}
} else {
warning("[TeLuaGUI.textLayoutBindings] Unreconized attribute : %s", s);
}
} else if (type == LUA_TNUMBER) {
Te3DObject2 *obj = TeLuaTo<Te3DObject2*>(L, -1);
layout->addChild(obj);
}
lua_settop(L, -2);
}
if (layout->name().empty()) {
layout->setName(Common::String::format("%p", (void *)layout));
}
lua_pushstring(L, "__TeLuaGUIThis");
lua_gettable(L, LUA_REGISTRYINDEX);
TeLuaGUI *gui = TeLuaTo<TeLuaGUI*>(L, -1);
TeLuaGUI::StringMap<TeExtendedTextLayout *> &layouts = gui->extendedTextLayouts();
if (!layouts.contains(layout->name())) {
layouts.setVal(layout->name(), layout);
lua_pushlightuserdata(L, static_cast<Te3DObject2*>(layout));
return true;
} else {
warning("extendedTextLayoutBindings:: multiple objects with name %s", layout->name().c_str());
delete layout;
return false;
}
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,46 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_LUA_GUI_LUA_CALLBACKS_H
#define TETRAEDGE_TE_TE_LUA_GUI_LUA_CALLBACKS_H
struct lua_State;
namespace Tetraedge {
int layoutBindings(lua_State *state);
int listLayoutBindings(lua_State *state);
int spriteLayoutBindings(lua_State *state);
int buttonLayoutBindings(lua_State *state);
int checkboxLayoutBindings(lua_State *state);
int layoutPositionLinearAnimationBindings(lua_State *state);
int layoutAnchorLinearAnimationBindings(lua_State *state);
int textLayoutBindings(lua_State *state);
int clipLayoutBindings(lua_State *state);
int colorLinearAnimationBindings(lua_State *state);
int rotationLinearAnimationBindings(lua_State *state);
int scrollingLayoutBindings(lua_State *state);
int extendedTextLayoutBindings(lua_State *state);
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_LUA_GUI_LUA_CALLBACKS_H

View File

@@ -0,0 +1,95 @@
/* 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 "common/debug.h"
#include "common/textconsole.h"
#include "common/file.h"
#include "tetraedge/te/te_lua_script.h"
#include "tetraedge/te/te_lua_thread.h"
#include "tetraedge/te/te_lua_context.h"
namespace Tetraedge {
TeLuaScript::TeLuaScript() : _started(false), _luaContext(nullptr) {
}
void TeLuaScript::attachToContext(TeLuaContext *context) {
_luaContext = context;
}
void TeLuaScript::execute() {
if (_luaContext) {
//debug("TeLuaScript::execute %s", _scriptNode.toString().c_str());
lua_State *state = _luaContext->luaState();
if (state) {
TeLuaThread *thread = TeLuaThread::create(_luaContext);
thread->executeFile(_scriptNode);
thread->release();
_started = true;
}
}
}
void TeLuaScript::execute(const Common::String &fname) {
if (_luaContext) {
//debug("TeLuaScript::execute %s %s", _scriptNode.toString().c_str(), fname.c_str());
TeLuaThread *thread = TeLuaThread::create(_luaContext);
thread->execute(fname);
thread->release();
}
}
void TeLuaScript::execute(const Common::String &fname, const TeVariant &p1) {
if (_luaContext) {
//debug("TeLuaScript::execute %s %s(%s)", _scriptNode.toString().c_str(), fname.c_str(), p1.toString().c_str());
TeLuaThread *thread = TeLuaThread::create(_luaContext);
thread->execute(fname, p1);
thread->release();
}
}
void TeLuaScript::execute(const Common::String &fname, const TeVariant &p1, const TeVariant &p2) {
if (_luaContext) {
TeLuaThread *thread = TeLuaThread::create(_luaContext);
thread->execute(fname, p1, p2);
thread->release();
}
}
void TeLuaScript::execute(const Common::String &fname, const TeVariant &p1, const TeVariant &p2, const TeVariant &p3) {
if (_luaContext) {
TeLuaThread *thread = TeLuaThread::create(_luaContext);
thread->execute(fname, p1, p2, p3);
thread->release();
}
}
void TeLuaScript::load(const TetraedgeFSNode &node) {
_started = false;
_scriptNode = node;
}
void TeLuaScript::unload() {
_scriptNode = TetraedgeFSNode();
_started = false;
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,58 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_LUA_SCRIPT_H
#define TETRAEDGE_TE_TE_LUA_SCRIPT_H
#include "common/str.h"
#include "common/path.h"
#include "tetraedge/te/te_variant.h"
#include "tetraedge/tetraedge.h"
namespace Tetraedge {
class TeLuaContext;
class TeLuaScript {
public:
TeLuaScript();
void attachToContext(TeLuaContext *context);
void execute();
void execute(const Common::String &fname);
void execute(const Common::String &fname, const TeVariant &p1);
void execute(const Common::String &fname, const TeVariant &p1, const TeVariant &p2);
void execute(const Common::String &fname, const TeVariant &p1, const TeVariant &p2, const TeVariant &p3);
void load(const TetraedgeFSNode &node);
void unload();
private:
TeLuaContext *_luaContext;
TetraedgeFSNode _scriptNode;
bool _started;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_LUA_SCRIPT_H

View File

@@ -0,0 +1,406 @@
/* 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 "tetraedge/tetraedge.h"
#include "tetraedge/te/te_lua_thread.h"
#include "tetraedge/te/te_lua_context.h"
#include "tetraedge/te/te_variant.h"
#include "common/config-manager.h"
#include "common/str.h"
#include "common/debug.h"
#include "common/file.h"
#include "common/lua/lua.h"
#include "common/lua/lauxlib.h"
#include "common/lua/lualib.h"
//#define TETRAEDGE_LUA_DEBUG 1
//#define TETRAEDGE_RESTORE_EXPERIMENTAL 1
namespace Tetraedge {
/*static*/
Common::Array<TeLuaThread *> *TeLuaThread::_threadList = nullptr;
TeLuaThread::TeLuaThread(TeLuaContext *context) : _resumeCount(0), _lastResumeResult(0), _released(false) {
_luaThread = lua_newthread(context->luaState());
_bottomRef = luaL_ref(context->luaState(), LUA_REGISTRYINDEX);
threadList()->push_back(this);
}
TeLuaThread::~TeLuaThread() {
luaL_unref(_luaThread, LUA_REGISTRYINDEX, _bottomRef);
uint i;
Common::Array<TeLuaThread *> *threads = threadList();
for (i = 0; i < threads->size(); i++)
if ((*threads)[i] == this)
break;
if (i < threads->size())
threads->remove_at(i);
}
/*static*/ TeLuaThread *TeLuaThread::create(TeLuaContext *context) {
return new TeLuaThread(context);
}
void TeLuaThread::_resume(int nargs) {
_resumeCount++;
_lastResumeResult = lua_resume(_luaThread, nargs);
if (_lastResumeResult > 1) {
const char *msg = lua_tolstring(_luaThread, -1, nullptr);
warning("TeLuaThread::_resume: %s", msg);
}
if (_lastResumeResult != 1 && _released) {
//debug("TeLuaThread:: deleting this?");
delete this;
}
}
void TeLuaThread::execute(const Common::String &fname) {
if (!_luaThread)
return;
#ifdef TETRAEDGE_LUA_DEBUG
if (fname != "Update" && fname != "UpdateHelp")
debug("TeLuaThread::execute: %s()", fname.c_str());
#endif
lua_getglobal(_luaThread, fname.c_str());
if (lua_type(_luaThread, -1) == LUA_TFUNCTION) {
_resume(0);
} else {
if (!fname.contains("Update"))
debug("[TeLuaThread::Execute0] Function: \"%s\" does not exist", fname.c_str());
lua_settop(_luaThread, -2);
}
}
void TeLuaThread::execute(const Common::String &fname, const TeVariant &p1) {
if (!_luaThread)
return;
#ifdef TETRAEDGE_LUA_DEBUG
debug("TeLuaThread::execute: %s(%s)", fname.c_str(), p1.dumpStr().c_str());
#endif
lua_getglobal(_luaThread, fname.c_str());
if (lua_type(_luaThread, -1) == LUA_TFUNCTION) {
pushValue(p1);
_resume(1);
} else {
// Don't report Update (as original) or some other functions which are not
// implemented in both games
if (!fname.contains("Update") && !fname.equals("OnCellCharacterAnimationPlayerFinished")
&& !fname.equals("OnCharacterAnimationFinished") && !fname.equals("OnCellDialogFinished")
&& !fname.equals("OnCellFreeSoundFinished"))
debug("[TeLuaThread::Execute1] Function: \"%s\" does not exist", fname.c_str());
lua_settop(_luaThread, -2);
}
}
void TeLuaThread::execute(const Common::String &fname, const TeVariant &p1, const TeVariant &p2) {
if (!_luaThread)
return;
#ifdef TETRAEDGE_LUA_DEBUG
debug("TeLuaThread::execute: %s(%s, %s)", fname.c_str(), p1.dumpStr().c_str(),
p2.dumpStr().c_str());
#endif
lua_getglobal(_luaThread, fname.c_str());
if (lua_type(_luaThread, -1) == LUA_TFUNCTION) {
pushValue(p1);
pushValue(p2);
_resume(2);
} else {
if (!fname.contains("Update"))
debug("[TeLuaThread::Execute2] Function: \"%s\" does not exist.", fname.c_str());
lua_settop(_luaThread, -2);
}
}
void TeLuaThread::execute(const Common::String &fname, const TeVariant &p1, const TeVariant &p2, const TeVariant &p3) {
if (!_luaThread)
return;
#ifdef TETRAEDGE_LUA_DEBUG
debug("TeLuaThread::execute: %s(%s, %s, %s)", fname.c_str(), p1.dumpStr().c_str(),
p2.dumpStr().c_str(), p3.dumpStr().c_str());
#endif
lua_getglobal(_luaThread, fname.c_str());
if (lua_type(_luaThread, -1) == LUA_TFUNCTION) {
pushValue(p1);
pushValue(p2);
pushValue(p3);
_resume(3);
} else {
if (!fname.contains("Update"))
debug("[TeLuaThread::Execute3] Function: \"%s\" does not exist.", fname.c_str());
lua_settop(_luaThread, -4);
}
}
void TeLuaThread::applyScriptWorkarounds(char *buf, const Common::String &fileNameIn) {
char *fixline;
Common::String fileName(fileNameIn);
if (fileName.hasSuffix(".data")) {
fileName = fileName.substr(0, fileName.size() - 5) + ".lua";
}
//
// WORKAROUND: Some script files have rogue ";" lines in them with nothing
// else, and ScummVM common lua version doesn't like them. Clean those up.
//
fixline = strstr(buf, "\n\t;");
if (fixline)
fixline[2] = '\t';
//
// Restore Syberia 1 scenes by patching up the scripts
//
if (g_engine->gameType() == TetraedgeEngine::kSyberia && ConfMan.getBool("restore_scenes")) {
if (fileName.contains("Logic11070.lua")) {
// Allow Kate to enter scene 11100
fixline = strstr(buf, "\"11110\"");
if (fixline) // 11110 -> 11100
fixline[4] = '0';
fixline = strstr(buf, "\"11110\"");
if (fixline)
fixline[4] = '0';
} else if (fileName.contains("Logic11110.lua")) {
// Allow Kate to enter scene 11100
fixline = strstr(buf, "\"11070\"");
if (fixline) // 11070 -> 11100
memcpy(fixline + 3, "10 ", 2);
fixline = strstr(buf, "\"11070\"");
if (fixline)
memcpy(fixline + 3, "10 ", 2);
#ifdef TETRAEDGE_RESTORE_EXPERIMENTAL
// The 11170 scene is not usable yet - it seems
// to not have any free move zone data?
} else if (fileName.contains("Logic11160.lua")) {
fixline = strstr(buf, "\"11180\"");
if (fixline) // 11180 -> 11170
fixline[4] = '7';
fixline = strstr(buf, "\"11180\"");
if (fixline)
fixline[4] = '7';
} else if (fileName.contains("Logic11180.lua")) {
fixline = strstr(buf, "\"11160\"");
if (fixline) // 11160 -> 11170
fixline[4] = '7';
fixline = strstr(buf, "\"11160\"");
if (fixline)
fixline[4] = '7';
#endif
} else if (fileName.contains("Logic11100.lua")) {
fixline = strstr(buf, " , 55 ,70, ");
if (fixline) // 70 -> 65 to fix speech marker location
memcpy(fixline + 7, "65 ", 2);
} else if (fileName.contains("Int11100.lua") || fileName.contains("Int11170.lua")) {
fixline = strstr(buf, "ratio = 16/9,");
if (fixline) // 16/9 -> 4/3
memcpy(fixline + 8, "4/3 ", 4);
fixline = strstr(buf, "ratioMode = PanScan,");
if (fixline)
memcpy(fixline + 9, "=LetterBox", 10);
} else if (fileName.contains("For11100.lua") || fileName.contains("For11170.lua")) {
fixline = strstr(buf, "size = {1.0");
if (fixline) // 1.0 -> 1.5
fixline[10] = '5';
}
}
//
// WORKAROUND: Syberia 2 constantly re-seeds the random number generator.
// This fails on ScummVM Lua because os.time() returns a large Number and
// math.randomseed() clamps the number to an int, so it always seeds on the
// same value. It's also kind of pointless, so just patch it out.
//
static const char RESEED_PATTERN[] = "math.randomseed( os.time() )";
fixline = strstr(buf, RESEED_PATTERN);
while (fixline != nullptr) {
for (int i = 0; i < ARRAYSIZE(RESEED_PATTERN); i++) {
fixline[i] = ' ';
}
fixline = strstr(fixline, RESEED_PATTERN);
}
//
// WORKAROUND: Syberia 2 A1_Cabaret/11420/Logic11420.lua has a typo on a
// variable name that causes the game to lock up
//
fixline = strstr(buf, "OBJECT_10050_Inventory_obj_coeurmec_Taketoun ");
if (fixline) {
// Taketoun -> Taken
memcpy(fixline + 40, "n ", 4);
}
}
void TeLuaThread::executeFile(const TetraedgeFSNode &node) {
Common::ScopedPtr<Common::SeekableReadStream> scriptFile(node.createReadStream());
if (!scriptFile) {
warning("TeLuaThread::executeFile: File %s can't be opened", node.getName().c_str());
return;
}
#ifdef TETRAEDGE_LUA_DEBUG
debug("TeLuaThread::executeFile: %s", node.getName().c_str());
#endif
int64 fileLen = scriptFile->size();
char *buf = new char[fileLen + 1];
scriptFile->read(buf, fileLen);
buf[fileLen] = 0;
scriptFile.reset();
applyScriptWorkarounds(buf, node.getPath().baseName());
_lastResumeResult = luaL_loadbuffer(_luaThread, buf, fileLen, node.toString().c_str());
if (_lastResumeResult) {
const char *msg = lua_tostring(_luaThread, -1);
warning("TeLuaThread::executeFile: %s", msg);
}
delete [] buf;
_resume(0);
}
void TeLuaThread::pushValue(const TeVariant &val) {
TeVariant::VariantType valType = val.type();
switch(valType) {
case TeVariant::TypeBoolean:
lua_pushboolean(_luaThread, val.toBoolean());
break;
case TeVariant::TypeInt32:
lua_pushinteger(_luaThread, val.toSigned32());
break;
case TeVariant::TypeUInt32:
lua_pushinteger(_luaThread, val.toUnsigned32());
break;
case TeVariant::TypeInt64:
lua_pushinteger(_luaThread, val.toSigned64());
break;
case TeVariant::TypeUInt64:
lua_pushinteger(_luaThread, val.toUnsigned64());
break;
case TeVariant::TypeFloat32:
lua_pushnumber(_luaThread, val.toFloat32());
break;
case TeVariant::TypeFloat64:
lua_pushnumber(_luaThread, val.toFloat64());
break;
case TeVariant::TypeString:
lua_pushstring(_luaThread, val.toString().c_str());
break;
default:
warning("TeLuaThread::pushValue: Unknown type");
return;
}
}
void TeLuaThread::release() {
_released = true;
if (_lastResumeResult != 1) {
//debug("TeLuaThread:: deleting this?");
delete this;
}
}
void TeLuaThread::resume() {
#ifdef TETRAEDGE_LUA_DEBUG
debug("TeLuaThread::resume");
#endif
if (_luaThread)
_resume(0);
}
void TeLuaThread::resume(const TeVariant &p1) {
#ifdef TETRAEDGE_LUA_DEBUG
debug("TeLuaThread::resume(%s)", p1.dumpStr().c_str());
#endif
if (_luaThread) {
pushValue(p1);
_resume(1);
}
}
void TeLuaThread::resume(const TeVariant &p1, const TeVariant &p2) {
#ifdef TETRAEDGE_LUA_DEBUG
debug("TeLuaThread::resume(%s, %s)", p1.dumpStr().c_str(), p2.dumpStr().c_str());
#endif
if (_luaThread) {
pushValue(p1);
pushValue(p2);
_resume(2);
}
}
void TeLuaThread::resume(const TeVariant &p1, const TeVariant &p2, const TeVariant &p3) {
#ifdef TETRAEDGE_LUA_DEBUG
debug("TeLuaThread::resume(%s, %s, %s)", p1.dumpStr().c_str(), p2.dumpStr().c_str(),
p3.dumpStr().c_str());
#endif
if (_luaThread) {
pushValue(p1);
pushValue(p2);
pushValue(p3);
_resume(3);
}
}
/*static*/
TeLuaThread *TeLuaThread::threadFromState(lua_State *state) {
Common::Array<TeLuaThread *> *threads = threadList();
for (auto &thread : *threads) {
if (thread->_luaThread == state)
return thread;
}
return nullptr;
}
/*static*/
Common::Array<TeLuaThread *> *TeLuaThread::threadList() {
if (!_threadList)
_threadList = new Common::Array<TeLuaThread *>();
return _threadList;
}
/*static*/
void TeLuaThread::cleanup() {
delete _threadList;
_threadList = nullptr;
}
int TeLuaThread::yield() {
return lua_yield(_luaThread, 0);
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,82 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_LUA_THREAD_H
#define TETRAEDGE_TE_TE_LUA_THREAD_H
#include "common/array.h"
#include "common/str.h"
#include "common/fs.h"
struct lua_State;
namespace Tetraedge {
class TeLuaContext;
class TeVariant;
class TeLuaThread {
public:
TeLuaThread(TeLuaContext *context);
~TeLuaThread();
static TeLuaThread *create(TeLuaContext *context);
void execute(const Common::String &str);
void execute(const Common::String &str, const TeVariant &p1);
void execute(const Common::String &str, const TeVariant &p1, const TeVariant &p2);
void execute(const Common::String &str, const TeVariant &p1, const TeVariant &p2, const TeVariant &p3);
void executeFile(const TetraedgeFSNode &node);
void pushValue(const TeVariant &val);
void release();
void resume();
void resume(const TeVariant &p1);
void resume(const TeVariant &p1, const TeVariant &p2);
void resume(const TeVariant &p1, const TeVariant &p2, const TeVariant &p3);
static TeLuaThread *threadFromState(lua_State *state);
int yield();
static void cleanup();
private:
void _resume(int nargs);
void applyScriptWorkarounds(char *buf, const Common::String &fileName);
lua_State *_luaThread;
uint64 _resumeCount;
int _bottomRef;
int _lastResumeResult;
bool _released;
static Common::Array<TeLuaThread *> *threadList();
static Common::Array<TeLuaThread *> *_threadList;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_LUA_THREAD_H

View File

@@ -0,0 +1,64 @@
/* 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 "tetraedge/te/te_marker.h"
namespace Tetraedge {
TeMarker::TeMarker() : _visible(true), _isActive(false), _zLoc(0) {
}
void TeMarker::active(bool val) {
_isActive = val;
_button.setVisible(_visible && val);
}
void TeMarker::update(TeCamera &camera) {
_button.setVisible(true);
if (!_visible)
return;
const TeVector3f32 transformLoc = camera.projectPoint3f32(_loc);
const TeVector3f32 btnSize = _button.size();
_button.setPositionType(TeILayout::ABSOLUTE);
float vpWidth = camera.getViewportWidth();
float vpHeight = camera.getViewportHeight();
if (transformLoc.z() < 1.0f) {
// Behind the camera, move off-screen.
_button.setPosition(TeVector3f32(-btnSize.x() - vpWidth / 2, -btnSize.y() - vpHeight / 2, _zLoc));
} else {
TeVector3f32 buttonMiddle(transformLoc.x() - btnSize.x() / 2 - vpWidth / 2, transformLoc.y() - btnSize.y() / 2 - vpHeight / 2, _zLoc);
// Note: device rotation is taken account of here in original, skip that.
// Original also uses scales 480 and 320, but that makes it too small
// in HD.
//TeVector3f32 newScale(480.0f / vpWidth, 320.0f / vpHeight, 1.0);
//_button.setScale(newScale);
_button.setPosition(TeVector3f32(buttonMiddle.x(), buttonMiddle.y(), buttonMiddle.z()));
/*debug("Updated button pos to %s (transformed %s middle %s)", _button.position().dump().c_str(), transformLoc.dump().c_str(), buttonMiddle.dump().c_str());*/
}
}
void TeMarker::visible(bool vis) {
_visible = vis;
bool buttonVis = (vis && _isActive);
_button.setVisible(buttonVis);
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,57 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_MARKER_H
#define TETRAEDGE_TE_TE_MARKER_H
#include "tetraedge/te/te_camera.h"
#include "tetraedge/te/te_button_layout.h"
#include "tetraedge/te/te_vector3f32.h"
namespace Tetraedge {
// Note: Only used in Amerzone
class TeMarker : public TeObject {
public:
TeMarker();
void active(bool val);
void update(TeCamera &camera);
void visible(bool val);
TeButtonLayout &button() { return _button; }
TeVector3f32 &loc() { return _loc; }
void setZLoc(float f) { _zLoc = f; }
private:
bool _visible;
bool _isActive;
float _zLoc;
TeVector3f32 _loc;
// Note: this is a TeSpriteButton in the original, updated
// to use the newer ButtonLayout
TeButtonLayout _button;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_MARKER_H

View File

@@ -0,0 +1,143 @@
/* 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 "common/textconsole.h"
#include "tetraedge/tetraedge.h"
#include "tetraedge/te/te_core.h"
#include "tetraedge/te/te_light.h"
#include "tetraedge/te/te_material.h"
#include "tetraedge/te/te_model.h"
#include "tetraedge/te/te_renderer.h"
namespace Tetraedge {
TeMaterial::TeMaterial() {
defaultValues();
_mode = MaterialMode1;
}
TeMaterial::TeMaterial(TeIntrusivePtr<Te3DTexture> texture, Mode mode) {
defaultValues();
_texture = texture;
_mode = mode;
}
void TeMaterial::defaultValues() {
_ambientColor = TeColor(0, 0, 0, 255);
_diffuseColor = TeColor(255, 255, 255, 255);
_specularColor = TeColor(0, 0, 0, 255);
_emissionColor = TeColor(0, 0, 0, 255);
_shininess = 0.0;
_enableLights = false;
_isShadowTexture = false;
}
Common::String TeMaterial::dump() const {
return Common::String::format
("amb:%s dif:%s spe:%s emi:%s mode:%d tex:%s shin:%.02f lights:%s",
_ambientColor.dump().c_str(),
_diffuseColor.dump().c_str(),
_specularColor.dump().c_str(),
_emissionColor.dump().c_str(),
(int)_mode,
_texture ? _texture->getAccessName().toString('/').c_str() : "None",
_shininess, _enableLights ? "on" : "off");
}
bool TeMaterial::operator==(const TeMaterial &other) const {
return (_texture == other._texture) && (_ambientColor == other._ambientColor)
&& (_diffuseColor == other._diffuseColor) && (_specularColor == other._specularColor)
&& (_emissionColor == other._emissionColor) && (_enableLights == other._enableLights)
&& (_shininess == other._shininess) && (_mode == other._mode);
}
TeMaterial &TeMaterial::operator=(const TeMaterial &other) {
if (&other == this)
return *this;
_texture = other._texture;
_ambientColor = other._ambientColor;
_diffuseColor = other._diffuseColor;
_specularColor = other._specularColor;
_emissionColor = other._emissionColor;
_enableLights = other._enableLights;
_shininess = other._shininess;
_mode = other._mode;
_isShadowTexture = other._isShadowTexture;
return *this;
}
/*static*/
void TeMaterial::deserialize(Common::SeekableReadStream &stream, TeMaterial &material, const Common::Path &texPath) {
const Common::String nameStr = Te3DObject2::deserializeString(stream);
TeModel::loadAlign(stream);
material._mode = static_cast<TeMaterial::Mode>(stream.readUint32LE());
if (nameStr.size()) {
TeCore *core = g_engine->getCore();
TetraedgeFSNode matPath = core->findFile(Common::Path(texPath).join(nameStr));
material._texture = Te3DTexture::load2(matPath, false);
if (!material._texture)
warning("failed to load texture %s (texpath %s)", nameStr.c_str(), matPath.toString().c_str());
}
material._ambientColor.deserialize(stream);
material._diffuseColor.deserialize(stream);
material._specularColor.deserialize(stream);
// TODO: Confirm this - Surely this should be emission color,
// but the original doesn't assign the result
// to _emissionColor. It does read though.
TeColor c;
c.deserialize(stream);
material._shininess = stream.readFloatLE();
}
/*static*/ void TeMaterial::serialize(Common::SeekableWriteStream &stream, TeMaterial &material) {
Te3DTexture *tex = material._texture.get();
Common::String texName;
if (tex) {
texName = tex->getAccessName().toString('/');
// "Remove extension" twice for some reason..
size_t offset = texName.rfind('.');
if (offset != Common::String::npos) {
texName.substr(0, offset);
}
offset = texName.rfind('.');
if (offset != Common::String::npos) {
texName.substr(0, offset);
}
}
stream.writeUint32LE(texName.size());
stream.write(texName.c_str(), texName.size());
TeModel::saveAlign(stream);
stream.writeUint32LE(static_cast<uint32>(material._mode));
material._ambientColor.serialize(stream);
material._diffuseColor.serialize(stream);
material._specularColor.serialize(stream);
material._emissionColor.serialize(stream);
stream.writeFloatLE(material._shininess);
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,74 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_MATERIAL_H
#define TETRAEDGE_TE_TE_MATERIAL_H
#include "common/ptr.h"
#include "common/path.h"
#include "common/stream.h"
#include "tetraedge/te/te_color.h"
#include "tetraedge/te/te_3d_texture.h"
#include "tetraedge/te/te_intrusive_ptr.h"
namespace Tetraedge {
class TeMaterial {
public:
enum Mode {
MaterialMode0,
MaterialMode1,
MaterialMode2 // alpha only?
};
TeMaterial();
TeMaterial(const TeMaterial &other) = default;
TeMaterial(TeIntrusivePtr<Te3DTexture> texture, Mode mode);
// Note: apply() function from original moved to TeRenderer to remove OGL specific code from here
void defaultValues();
static void deserialize(Common::SeekableReadStream &stream, TeMaterial &material, const Common::Path &path);
static void serialize(Common::SeekableWriteStream &stream, TeMaterial &material);
bool operator==(const TeMaterial &other) const;
bool operator!=(const TeMaterial &other) const {
return !operator==(other);
}
TeMaterial &operator=(const TeMaterial &other);
Common::String dump() const;
TeIntrusivePtr<Te3DTexture> _texture;
Mode _mode;
TeColor _ambientColor;
TeColor _diffuseColor;
TeColor _specularColor;
TeColor _emissionColor;
float _shininess;
bool _isShadowTexture;
bool _enableLights;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_MATERIAL_H

View File

@@ -0,0 +1,79 @@
/* 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 "tetraedge/te/te_matricies_stack.h"
namespace Tetraedge {
TeMatriciesStack::TeMatriciesStack() {
_stack.push(TeMatrix4x4());
}
const TeMatrix4x4 &TeMatriciesStack::currentMatrix() const {
return _stack.top();
}
bool TeMatriciesStack::isEmpty() const {
return _stack.empty();
}
void TeMatriciesStack::loadIdentity() {
_stack.top() = TeMatrix4x4();
}
void TeMatriciesStack::loadMatrix(const TeMatrix4x4 &matrix) {
_stack.top() = matrix;
}
void TeMatriciesStack::multiplyMatrix(const TeMatrix4x4 &matrix) {
_stack.top() = _stack.top() * matrix;
}
void TeMatriciesStack::popMatrix() {
if (_stack.size() > 1)
_stack.pop();
}
void TeMatriciesStack::pushMatrix() {
_stack.push(_stack.top());
}
void TeMatriciesStack::rotate(const TeQuaternion &rot) {
_stack.top() = _stack.top() * rot.toTeMatrix();
}
void TeMatriciesStack::rotate(float angle, const TeVector3f32 &axis) {
rotate(TeQuaternion::fromAxisAndAngle(axis, angle));
}
void TeMatriciesStack::scale(const TeVector3f32 &scale) {
_stack.top().scale(scale);
}
uint TeMatriciesStack::size() {
return _stack.size();
}
void TeMatriciesStack::translate(const TeVector3f32 &trans) {
_stack.top().translate(trans);
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,56 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_MATRICIES_STACK_H
#define TETRAEDGE_TE_TE_MATRICIES_STACK_H
#include "common/stack.h"
#include "tetraedge/te/te_matrix4x4.h"
#include "tetraedge/te/te_quaternion.h"
namespace Tetraedge {
class TeMatriciesStack {
public:
TeMatriciesStack();
const TeMatrix4x4 &currentMatrix() const;
bool isEmpty() const;
void loadIdentity();
void loadMatrix(const TeMatrix4x4 &matrix);
void multiplyMatrix(const TeMatrix4x4 &matrix);
void popMatrix();
void pushMatrix();
void rotate(const TeQuaternion &rot);
void rotate(float f, const TeVector3f32 &rot);
void scale(const TeVector3f32 &scale);
uint size();
void translate(const TeVector3f32 &trans);
private:
Common::Stack<TeMatrix4x4> _stack;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_MATRICIES_STACK_H

View File

@@ -0,0 +1,360 @@
/* 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 "tetraedge/te/te_matrix4x4.h"
#include "tetraedge/te/te_trs.h"
namespace Tetraedge {
TeMatrix4x4::TeMatrix4x4() {
setToIdentity();
}
void TeMatrix4x4::setToIdentity() {
_data[0] = _data[5] = _data[10] = _data[15] = 1.0f;
_data[1] = _data[2] = _data[3] = _data[4] = 0.0f;
_data[6] = _data[7] = _data[8] = _data[9] = 0.0f;
_data[11] = _data[12] = _data[13] = _data[14] = 0.0f;
}
TeMatrix4x4::TeMatrix4x4(const Math::Matrix<4, 4> &matrix) {
// Transpose - row-major to column-major.
float *d = getData();
const float *s = matrix.getData();
for (int c = 0; c < 4; c++) {
for (int r = 0; r < 4; r++) {
d[c * 4 + r] = s[r * 4 + c];
}
}
}
TeMatrix4x4 operator*(const TeMatrix4x4 &left, const TeMatrix4x4 &right) {
TeMatrix4x4 retval;
const float *d1 = left.getData();
const float *d2 = right.getData();
float *res = retval.getData();
res[0] = res[5] = res[10] = res[15] = 0.0f;
for (int r = 0; r < 4; r++) {
for (int c = 0; c < 16; c += 4) {
res[c + r] = (d1[r + 0] * d2[c + 0]) +
(d1[r + 4] * d2[c + 1]) +
(d1[r + 8] * d2[c + 2]) +
(d1[r + 12] * d2[c + 3]);
}
}
return retval;
}
/*
TeMatrix4x4 &TeMatrix4x4::operator*=(const TeMatrix4x4 &mul) {
TeMatrix4x4 result = operator*(*this, mul);
*this = result;
return *this;
}*/
bool TeMatrix4x4::operator==(const TeMatrix4x4 &other) const {
for (int i = 0; i < 16; i++) {
if (_data[i] != other._data[i])
return false;
}
return true;
}
void TeMatrix4x4::scale(const TeVector3f32 &vec) {
TeMatrix4x4 scaleMatrix;
scaleMatrix(0, 0) = vec.x();
scaleMatrix(1, 1) = vec.y();
scaleMatrix(2, 2) = vec.z();
//scaleMatrix(3, 3) = 1.0; // default.
*this = (*this * scaleMatrix);
}
void TeMatrix4x4::translate(const TeVector3f32 &vec) {
TeMatrix4x4 translMatrix;
translMatrix(0, 3) = vec.x();
translMatrix(1, 3) = vec.y();
translMatrix(2, 3) = vec.z();
*this = (*this * translMatrix);
}
void TeMatrix4x4::rotate(const TeQuaternion &rot) {
const TeMatrix4x4 rotMatrix = rot.toTeMatrix();
*this = (*this * rotMatrix);
}
TeVector3f32 TeMatrix4x4::translation() const {
return TeVector3f32(_data[12], _data[13], _data[14]);
}
TeVector3f32 TeMatrix4x4::mult4x3(const TeVector3f32 &vec) const {
const float f1 = vec.x();
const float f2 = vec.y();
const float f3 = vec.z();
const float *data = getData();
return TeVector3f32(data[0] * f1 + data[4] * f2 + data[8] * f3 + data[12],
data[1] * f1 + data[5] * f2 + data[9] * f3 + data[13],
data[2] * f1 + data[6] * f2 + data[10] * f3 + data[14]);
}
TeVector3f32 TeMatrix4x4::mult3x3(const TeVector3f32 &vec) const {
const float f1 = vec.x();
const float f2 = vec.y();
const float f3 = vec.z();
const float *data = getData();
return TeVector3f32(data[0] * f1 + data[4] * f2 + data[8] * f3,
data[1] * f1 + data[5] * f2 + data[9] * f3,
data[2] * f1 + data[6] * f2 + data[10] * f3);
}
TeMatrix4x4 TeMatrix4x4::meshScale(float factor) const {
TeMatrix4x4 result;
for (int i = 0; i < 16; i++) {
result._data[i] = _data[i] * factor;
}
return result;
}
void TeMatrix4x4::meshAdd(const TeMatrix4x4 &other) {
for (int i = 0; i < 16; i++) {
_data[i] += other._data[i];
}
}
TeVector3f32 TeMatrix4x4::operator*(const TeVector3f32 &mul) const {
float x = mul.x();
float y = mul.y();
float z = mul.z();
const float *d = getData();
float w = d[3] * x + d[7] * y + d[11] * z + d[15];
if (w == 0.0)
w = 1e-09f;
return TeVector3f32
((d[0] * x + d[4] * y + d[8] * z + d[12]) / w,
(d[1] * x + d[5] * y + d[9] * z + d[13]) / w,
(d[2] * x + d[6] * y + d[10] * z + d[14]) / w);
}
Common::String TeMatrix4x4::toString() const {
const float *data = getData();
return Common::String::format("[[%.03f %.03f %.03f %.03f] [%.03f %.03f %.03f %.03f] [%.03f %.03f %.03f %.03f] [%.03f %.03f %.03f %.03f]]",
data[0], data[4], data[8], data[12],
data[1], data[5], data[9], data[13],
data[2], data[6], data[10], data[14],
data[3], data[7], data[11], data[15]);
}
Math::Matrix<4, 4> TeMatrix4x4::toScummVMMatrix() const {
const TeMatrix4x4 trans = transpose();
Math::Matrix<4, 4> retval;
retval.setData(trans.getData());
return retval;
}
TeMatrix4x4 TeMatrix4x4::transpose() const {
TeMatrix4x4 ret;
const float *s = getData();
float *d = ret.getData();
for (int c = 0; c < 4; c++) {
for (int r = 0; r < 4; r++) {
d[c * 4 + r] = s[r * 4 + c];
}
}
return ret;
}
bool TeMatrix4x4::inverse() {
TeMatrix4x4 invMatrix;
float *inv = invMatrix.getData();
TeMatrix4x4 temp = transpose();
float *m = temp.getData();
inv[0] = m[5] * m[10] * m[15] -
m[5] * m[11] * m[14] -
m[9] * m[6] * m[15] +
m[9] * m[7] * m[14] +
m[13] * m[6] * m[11] -
m[13] * m[7] * m[10];
inv[4] = -m[4] * m[10] * m[15] +
m[4] * m[11] * m[14] +
m[8] * m[6] * m[15] -
m[8] * m[7] * m[14] -
m[12] * m[6] * m[11] +
m[12] * m[7] * m[10];
inv[8] = m[4] * m[9] * m[15] -
m[4] * m[11] * m[13] -
m[8] * m[5] * m[15] +
m[8] * m[7] * m[13] +
m[12] * m[5] * m[11] -
m[12] * m[7] * m[9];
inv[12] = -m[4] * m[9] * m[14] +
m[4] * m[10] * m[13] +
m[8] * m[5] * m[14] -
m[8] * m[6] * m[13] -
m[12] * m[5] * m[10] +
m[12] * m[6] * m[9];
inv[1] = -m[1] * m[10] * m[15] +
m[1] * m[11] * m[14] +
m[9] * m[2] * m[15] -
m[9] * m[3] * m[14] -
m[13] * m[2] * m[11] +
m[13] * m[3] * m[10];
inv[5] = m[0] * m[10] * m[15] -
m[0] * m[11] * m[14] -
m[8] * m[2] * m[15] +
m[8] * m[3] * m[14] +
m[12] * m[2] * m[11] -
m[12] * m[3] * m[10];
inv[9] = -m[0] * m[9] * m[15] +
m[0] * m[11] * m[13] +
m[8] * m[1] * m[15] -
m[8] * m[3] * m[13] -
m[12] * m[1] * m[11] +
m[12] * m[3] * m[9];
inv[13] = m[0] * m[9] * m[14] -
m[0] * m[10] * m[13] -
m[8] * m[1] * m[14] +
m[8] * m[2] * m[13] +
m[12] * m[1] * m[10] -
m[12] * m[2] * m[9];
inv[2] = m[1] * m[6] * m[15] -
m[1] * m[7] * m[14] -
m[5] * m[2] * m[15] +
m[5] * m[3] * m[14] +
m[13] * m[2] * m[7] -
m[13] * m[3] * m[6];
inv[6] = -m[0] * m[6] * m[15] +
m[0] * m[7] * m[14] +
m[4] * m[2] * m[15] -
m[4] * m[3] * m[14] -
m[12] * m[2] * m[7] +
m[12] * m[3] * m[6];
inv[10] = m[0] * m[5] * m[15] -
m[0] * m[7] * m[13] -
m[4] * m[1] * m[15] +
m[4] * m[3] * m[13] +
m[12] * m[1] * m[7] -
m[12] * m[3] * m[5];
inv[14] = -m[0] * m[5] * m[14] +
m[0] * m[6] * m[13] +
m[4] * m[1] * m[14] -
m[4] * m[2] * m[13] -
m[12] * m[1] * m[6] +
m[12] * m[2] * m[5];
inv[3] = -m[1] * m[6] * m[11] +
m[1] * m[7] * m[10] +
m[5] * m[2] * m[11] -
m[5] * m[3] * m[10] -
m[9] * m[2] * m[7] +
m[9] * m[3] * m[6];
inv[7] = m[0] * m[6] * m[11] -
m[0] * m[7] * m[10] -
m[4] * m[2] * m[11] +
m[4] * m[3] * m[10] +
m[8] * m[2] * m[7] -
m[8] * m[3] * m[6];
inv[11] = -m[0] * m[5] * m[11] +
m[0] * m[7] * m[9] +
m[4] * m[1] * m[11] -
m[4] * m[3] * m[9] -
m[8] * m[1] * m[7] +
m[8] * m[3] * m[5];
inv[15] = m[0] * m[5] * m[10] -
m[0] * m[6] * m[9] -
m[4] * m[1] * m[10] +
m[4] * m[2] * m[9] +
m[8] * m[1] * m[6] -
m[8] * m[2] * m[5];
float det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
if (det == 0)
return false;
det = 1.0 / det;
for (int i = 0; i < 16; i++) {
m[i] = inv[i] * det;
}
*this = temp.transpose();
return true;
}
void TeMatrix4x4::deserialize(Common::ReadStream &stream) {
for (int i = 0; i < 16; i++) {
_data[i] = stream.readFloatLE();
}
}
void TeMatrix4x4::serialize(Common::WriteStream &stream) const {
for (int i = 0; i < 16; i++) {
stream.writeFloatLE(_data[i]);
}
}
/*static*/
TeMatrix4x4 TeMatrix4x4::fromTRS(const TeTRS &trs) {
TeMatrix4x4 result;
const TeVector3f32 trans = trs.getTranslation();
TeMatrix4x4 transm;
transm(0, 3) = trans.x();
transm(1, 3) = trans.y();
transm(2, 3) = trans.z();
result = result * transm;
const TeMatrix4x4 rotm = trs.getRotation().toTeMatrix();
result = result * rotm;
const TeVector3f32 scle = trs.getScale();
TeMatrix4x4 scalem;
scalem(0, 0) = scle.x();
scalem(1, 1) = scle.y();
scalem(2, 2) = scle.z();
result = result * scalem;
return result;
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,98 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_MATRIX4X4_H
#define TETRAEDGE_TE_TE_MATRIX4X4_H
#include "math/matrix4.h"
#include "tetraedge/te/te_vector3f32.h"
namespace Tetraedge {
class TeTRS;
/**
* A 4x4 matrix, but stored in *column-major* order to match
* OpenGL (and the original engine)
*/
class TeMatrix4x4 {
public:
TeMatrix4x4();
TeMatrix4x4(const Math::Matrix<4, 4> &matrix);
void setToIdentity();
float &operator()(int row, int col) {
return *(_data + col * 4 + row);
}
const float &operator()(int row, int col) const {
return *(_data + col * 4 + row);
}
bool operator==(const TeMatrix4x4 &other) const;
bool operator!=(const TeMatrix4x4 &other) const {
return !operator==(other);
}
//TeMatrix4x4 &operator*=(const TeMatrix4x4 &mul);
TeVector3f32 operator*(const TeVector3f32 &mul) const;
void scale(const TeVector3f32 &vec);
void translate(const TeVector3f32 &vec);
void rotate(const TeQuaternion &rot);
TeVector3f32 translation() const;
TeVector3f32 mult3x3(const TeVector3f32 &vec) const;
TeVector3f32 mult4x3(const TeVector3f32 &vec) const;
Common::String toString() const;
Math::Matrix<4, 4> toScummVMMatrix() const;
void setValue(int row, int col, float val) {
operator()(row, col) = val;
}
TeMatrix4x4 transpose() const;
TeMatrix4x4 meshScale(float factor) const;
void meshAdd(const TeMatrix4x4 &other);
bool inverse();
static TeMatrix4x4 fromTRS(const TeTRS &trs);
const float *getData() const { return _data; }
float *getData() { return _data; }
void deserialize(Common::ReadStream &stream);
void serialize(Common::WriteStream &stream) const;
private:
float _data[16];
};
TeMatrix4x4 operator*(const TeMatrix4x4 &left, const TeMatrix4x4 &right);
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_MATRIX4X4_H

View File

@@ -0,0 +1,251 @@
/* 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 "tetraedge/tetraedge.h"
#include "tetraedge/te/te_renderer.h"
#include "tetraedge/te/te_light.h"
#include "tetraedge/te/te_mesh.h"
#include "tetraedge/te/te_mesh_opengl.h"
#include "tetraedge/te/te_mesh_tinygl.h"
#include "tetraedge/te/te_material.h"
namespace Tetraedge {
TeMesh::TeMesh() : _matrixForced(false), _hasAlpha(false), _initialMaterialIndexCount(0),
_drawWires(false), _shouldDraw(true) {
}
void TeMesh::defaultMaterial(const TeIntrusivePtr<Te3DTexture> &texture) {
TeMaterial::Mode mode = TeMaterial::MaterialMode1;
if (texture && !texture->hasAlpha())
mode = TeMaterial::MaterialMode0;
_materials.resize(1);
_materials[0] = TeMaterial(texture, mode);
}
TeMaterial *TeMesh::material(uint index) {
assert(!_materials.empty());
if (index < _materials.size()) {
return &_materials[index];
} else {
return &_materials[0];
}
}
const TeMaterial *TeMesh::material(uint index) const {
assert(!_materials.empty());
if (index < _materials.size()) {
return &_materials[index];
} else {
return &_materials[0];
}
}
void TeMesh::destroy() {
_hasAlpha = false;
_updatedVerticies.clear();
_updatedNormals.clear();
_verticies.clear();
_normals.clear();
_uvs.clear();
_colors.clear();
_indexes.clear();
_materialIndexes.clear();
_faceCounts.clear();
_matricies.clear();
}
bool TeMesh::hasAlpha(uint idx) {
// Note: I don't understand this logic, but it's what the game does..
bool hasGlobalAlpha = _hasAlpha && !_colors.empty();
bool retval = hasGlobalAlpha;
if (idx < _materials.size()) {
const TeMaterial &material = _materials[idx];
if (material._isShadowTexture) {
retval = false;
} else {
retval = true;
if (!hasGlobalAlpha && material._mode != TeMaterial::MaterialMode1 && material._ambientColor.a() == 255)
retval = (material._diffuseColor.a() != 255);
}
}
return retval;
}
TeVector3f32 TeMesh::normal(uint idx) const {
if (!_updatedNormals.empty())
return _updatedNormals[idx];
else
return _normals[idx];
}
void TeMesh::resizeUpdatedTables(uint newSize) {
_updatedVerticies.resize(newSize);
_updatedNormals.resize(newSize);
}
void TeMesh::setColor(const TeColor &col) {
Te3DObject2::setColor(col);
if (!_verticies.empty()) {
const TeColor colnow = Te3DObject2::color();
_colors.resize(_verticies.size());
if (colnow.a() != 255)
_hasAlpha = true;
for (uint i = 0; i < _verticies.size(); i++) {
_colors[i] = colnow;
}
}
}
void TeMesh::setColor(uint idx, const TeColor &col) {
if (col.a() != 255) {
_hasAlpha = true;
}
_colors.resize(_verticies.size());
_colors[idx] = col;
}
void TeMesh::setConf(uint vertexCount, uint indexCount, enum Mode mode, uint materialCount, uint materialIndexCount) {
destroy();
_initialMaterialIndexCount = materialIndexCount;
_verticies.resize(vertexCount);
_indexes.resize(indexCount);
_materials.resize(materialCount);
_matricies.resize(vertexCount);
setMode(mode);
}
void TeMesh::setIndex(uint idx, uint val) {
_indexes[idx] = val;
}
void TeMesh::setNormal(uint idx, const TeVector3f32 &val) {
_normals.resize(_verticies.size());
_normals[idx] = val;
}
void TeMesh::setTextureUV(uint idx, const TeVector2f32 &val) {
_uvs.resize(_verticies.size());
_uvs[idx] = val;
}
void TeMesh::setVertex(uint idx, const TeVector3f32 &val) {
_verticies[idx] = val;
}
TeVector3f32 TeMesh::vertex(uint idx) const {
if (!_updatedVerticies.empty())
return _updatedVerticies[idx];
else
return _verticies[idx];
}
void TeMesh::attachMaterial(uint idx, const TeMaterial &src) {
TeMaterial &dest = _materials[idx];
dest._texture = src._texture;
dest._enableLights = src._enableLights;
dest._isShadowTexture = src._isShadowTexture;
dest._emissionColor = src._emissionColor;
dest._shininess = src._shininess;
dest._diffuseColor = src._diffuseColor;
dest._specularColor = src._specularColor;
dest._mode = src._mode;
dest._ambientColor = src._ambientColor;
}
void TeMesh::facesPerMaterial(uint idx, unsigned short value) {
_faceCounts.resize(_materials.size());
_faceCounts[idx] = value;
}
void TeMesh::matrixIndex(uint num, unsigned short val) {
_matricies[num] = val;
}
void TeMesh::update(const Common::Array<TeMatrix4x4> *matricies1, const Common::Array<TeMatrix4x4> *matricies2) {
if (visible()) {
if (matricies1) {
_updatedVerticies.resize(_verticies.size());
_updatedNormals.resize(_normals.size());
updateTo(matricies1, matricies2, _updatedVerticies, _updatedNormals);
} else {
_updatedVerticies.clear();
_updatedNormals.clear();
}
}
}
void TeMesh::update(TeIntrusivePtr<TeModelVertexAnimation> vertexanim) {
_updatedVerticies.resize(_verticies.size());
_updatedNormals.resize(_normals.size());
const Common::Array<TeVector3f32> animverts = vertexanim->getVertices();
assert(animverts.size() >= _verticies.size());
for (uint i = 0; i < _verticies.size(); i++) {
_updatedVerticies[i] = animverts[i];
}
for (uint i = 0; i < _normals.size(); i++) {
_updatedNormals[i] = _normals[i];
}
}
void TeMesh::updateTo(const Common::Array<TeMatrix4x4> *matricies1, const Common::Array<TeMatrix4x4> *matricies2,
Common::Array<TeVector3f32> &verts, Common::Array<TeVector3f32> &normals) {
static const TeMatrix4x4 emptyMatrix;
for (uint i = 0; i < _verticies.size(); i++) {
uint m = _matricies[i];
const TeMatrix4x4 *mat;
if (m < matricies1->size()) {
mat = &((*matricies1)[m]);
} else {
m -= matricies1->size();
if (m < matricies2->size())
mat = &((*matricies2)[m]);
else
mat = &emptyMatrix;
}
verts[i] = mat->mult4x3(_verticies[i]);
normals[i] = mat->mult3x3(_normals[i]);
}
}
/*static*/
TeMesh *TeMesh::makeInstance() {
Graphics::RendererType r = g_engine->preferredRendererType();
#if defined(USE_OPENGL_GAME)
if (r == Graphics::kRendererTypeOpenGL)
return new TeMeshOpenGL();
#endif
#if defined(USE_TINYGL)
if (r == Graphics::kRendererTypeTinyGL)
return new TeMeshTinyGL();
#endif
error("Couldn't create TeMesh for selected renderer");
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,149 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_MESH_H
#define TETRAEDGE_TE_TE_MESH_H
#include "common/array.h"
#include "common/ptr.h"
#include "tetraedge/te/te_3d_object2.h"
#include "tetraedge/te/te_3d_texture.h"
#include "tetraedge/te/te_color.h"
#include "tetraedge/te/te_intrusive_ptr.h"
#include "tetraedge/te/te_vector2f32.h"
#include "tetraedge/te/te_vector3f32.h"
#include "tetraedge/te/te_matrix4x4.h"
#include "tetraedge/te/te_material.h"
#include "tetraedge/te/te_model_vertex_animation.h"
namespace Tetraedge {
class TeModel;
class TeModelVertexAnimation;
class TeMesh : public Te3DObject2 {
public:
TeMesh();
virtual ~TeMesh() {};
enum Mode {
MeshMode_None = 0,
MeshMode_Points,
MeshMode_Lines,
MeshMode_LineLoop,
MeshMode_LineStrip,
MeshMode_Triangles,
MeshMode_TriangleStrip,
MeshMode_TriangleFan
};
void attachMaterial(uint idx, const TeMaterial &material);
void boundingBox(TeVector3f32 &boxmin, TeVector3f32 boxmax);
void checkArrays() {};
void clearColors() { _colors.clear(); }
TeColor color(uint idx) const { return _colors[idx]; }
void copy(const TeMesh &other);
void create();
void defaultMaterial(const TeIntrusivePtr<Te3DTexture> &texture);
void destroy();
void facesPerMaterial(uint idx, unsigned short value);
unsigned short facesPerMaterial(uint idx) const { return _faceCounts[idx]; }
void forceMatrix(const TeMatrix4x4 &matrix);
byte getFaceMaterial(uint idx);
virtual uint32 getTexEnvMode() const = 0;
virtual TeMesh::Mode getMode() const = 0;
virtual void setMode(enum Mode mode) = 0;
bool hasAlpha(uint idx);
bool hasColor() const { return !_colors.empty(); }
bool hasUvs() const { return !_uvs.empty(); }
unsigned short index(uint num) const { return _indexes[num]; }
TeMaterial *material(uint idx);
const TeMaterial *material(uint idx) const;
void materialIndex(uint idx, byte val);
byte materialIndex(uint idx) const { return _materialIndexes[idx]; }
void matrixIndex(uint num, unsigned short val);
unsigned short matrixIndex(uint num) const { return _matricies[num]; }
TeVector3f32 normal(uint idx) const;
void optimizeVerticies();
void resizeUpdatedTables(uint newSize);
void setColor(const TeColor &col) override;
void setColor(uint idx, const TeColor &col);
void setConf(uint vertexCount, uint indexCount, enum Mode mode, uint materialCount, uint materialIndexCount);
void setIndex(uint idx, uint val);
void setNormal(uint idx, const TeVector3f32 &val);
void setTextureUV(uint idx, const TeVector2f32 &val);
void setVertex(uint idx, const TeVector3f32 &val);
void sortFaces();
void update(const Common::Array<TeMatrix4x4> *matricies1, const Common::Array<TeMatrix4x4> *matricies2);
void update(TeIntrusivePtr<TeModelVertexAnimation> vertexanim);
void updateTo(const Common::Array<TeMatrix4x4> *matricies1, const Common::Array<TeMatrix4x4> *matricies2,
Common::Array<TeVector3f32> &verts, Common::Array<TeVector3f32> &normals);
TeVector2f32 textureUV(uint idx) const { return _uvs[idx]; }
TeVector3f32 vertex(uint idx) const;
uint numIndexes() const { return _indexes.size(); }
uint numVerticies() const { return _verticies.size(); }
bool shouldDrawMaybe() const { return _shouldDraw; }
void setShouldDraw(bool val) { _shouldDraw = val; }
virtual void setglTexEnvBlend() = 0;
void setHasAlpha(bool val) { _hasAlpha = val; }
Common::Array<TeMaterial> &materials() { return _materials; }
void setUpdatedVertex(uint idx, const TeVector3f32 &val) { _updatedVerticies[idx] = val; }
void setUpdatedNormal(uint idx, const TeVector3f32 &val) { _updatedNormals[idx] = val; }
const TeVector3f32 &preUpdatedVertex(uint idx) const { return _verticies[idx]; }
const TeVector3f32 &preUpdatedNormal(uint idx) const { return _normals[idx]; }
static TeMesh *makeInstance();
protected:
Common::Array<unsigned char> _materialIndexes;
Common::Array<TeVector3f32> _verticies;
Common::Array<TeVector3f32> _normals;
Common::Array<TeVector3f32> _updatedVerticies;
Common::Array<TeVector3f32> _updatedNormals;
Common::Array<TeVector2f32> _uvs;
Common::Array<unsigned short> _indexes;
Common::Array<unsigned short> _faceCounts;
Common::Array<unsigned short> _matricies;
Common::Array<TeColor> _colors;
Common::Array<TeMaterial> _materials;
bool _matrixForced;
TeMatrix4x4 _forcedMatrix;
bool _hasAlpha;
uint _initialMaterialIndexCount;
bool _drawWires;
bool _shouldDraw;
};
} // end namespace Tetraedge
#endif // TETRAEDGE_TE_TE_MESH_H

View File

@@ -0,0 +1,262 @@
/* 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 "graphics/opengl/system_headers.h"
#include "tetraedge/tetraedge.h"
#include "tetraedge/te/te_renderer.h"
#include "tetraedge/te/te_light.h"
#include "tetraedge/te/te_mesh_opengl.h"
#include "tetraedge/te/te_material.h"
namespace Tetraedge {
TeMeshOpenGL::TeMeshOpenGL() : _glMeshMode(GL_POINTS), _gltexEnvMode(GL_MODULATE) {
}
void TeMeshOpenGL::draw() {
if (!worldVisible())
return;
TeRenderer *renderer = g_engine->getRenderer();
renderer->pushMatrix();
if (_matrixForced)
renderer->multiplyMatrix(_forcedMatrix);
else
renderer->multiplyMatrix(worldTransformationMatrix());
/*
debug("Draw mesh %p (%s, %d verts %d norms %d indexes %d materials %d updated)", this, name().empty() ? "no name" : name().c_str(), _verticies.size(), _normals.size(), _indexes.size(), _materials.size(), _updatedVerticies.size());
debug(" renderMatrix %s", renderer->currentMatrix().toString().c_str());
if (!_materials.empty())
debug(" material %s", _materials[0].dump().c_str());
debug(" position %s", position().dump().c_str());
debug(" worldPos %s", worldPosition().dump().c_str());
debug(" scale %s", scale().dump().c_str());
debug(" worldScale %s", worldScale().dump().c_str());
debug(" rotation %s", rotation().dump().c_str());
debug(" worldRot %s", worldRotation().dump().c_str());
*/
if (renderer->shadowMode() != TeRenderer::ShadowModeCreating) {
if (_faceCounts.empty()) {
if (hasAlpha(0) && _shouldDraw) {
renderer->addTransparentMesh(*this, 0, 0, 0);
renderer->popMatrix();
return;
}
} else {
assert(_faceCounts.size() == _materials.size());
int totalFaceCount = 0;
for (uint i = 0; i < _faceCounts.size(); i++) {
if (!_faceCounts[i])
continue;
if (hasAlpha(i)) {
renderer->addTransparentMesh(*this, totalFaceCount, _faceCounts[i], i);
}
totalFaceCount += _faceCounts[i];
}
}
}
renderer->setMatrixMode(TeRenderer::MM_GL_MODELVIEW);
renderer->pushMatrix();
renderer->loadCurrentMatrixToGL();
const Common::Array<TeVector3f32> &normals = (_updatedVerticies.empty() ? _normals : _updatedNormals);
const Common::Array<TeVector3f32> &verticies = (_updatedVerticies.empty() ? _verticies : _updatedVerticies);
glEnableClientState(GL_VERTEX_ARRAY);
if (!normals.empty())
glEnableClientState(GL_NORMAL_ARRAY);
if (!_colors.empty())
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(TeVector3f32), verticies.data());
if (!normals.empty())
glNormalPointer(GL_FLOAT, sizeof(TeVector3f32), normals.data());
if (!_uvs.empty() && renderer->shadowMode() != TeRenderer::ShadowModeDrawing)
glTexCoordPointer(2, GL_FLOAT, sizeof(TeVector2f32), _uvs.data());
if (!_colors.empty())
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(TeColor), _colors.data());
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, _gltexEnvMode);
if (renderer->scissorEnabled()) {
glEnable(GL_SCISSOR_TEST);
uint scissorx = renderer->scissorX();
uint scissory = renderer->scissorY();
uint scissorwidth = renderer->scissorWidth();
uint scissorheight = renderer->scissorHeight();
glScissor(scissorx, scissory, scissorwidth, scissorheight);
}
if (_faceCounts.empty()) {
if (!_materials.empty())
renderer->applyMaterial(_materials[0]);
glDrawElements(_glMeshMode, _indexes.size(), GL_UNSIGNED_SHORT, _indexes.data());
if (!_materials.empty()) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
renderer->disableTexture();
}
} else {
int totalFaceCount = 0;
assert(_faceCounts.size() == _materials.size());
for (uint i = 0; i < _materials.size(); i++) {
if (!_faceCounts[i])
continue;
if (!hasAlpha(i) || renderer->shadowMode() == TeRenderer::ShadowModeCreating || !_shouldDraw) {
renderer->applyMaterial(_materials[i]);
glDrawElements(_glMeshMode, _faceCounts[i] * 3, GL_UNSIGNED_SHORT, _indexes.data() + totalFaceCount * 3);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
renderer->disableTexture();
}
totalFaceCount += _faceCounts[i];
}
}
if (!renderer->scissorEnabled())
glDisable(GL_SCISSOR_TEST);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
//renderer->setCurrentColor(renderer->currentColor()); // pointless?
if (_drawWires && !normals.empty()) {
renderer->disableAllLights();
error("TODO: Properly implement _drawWires case in TeMesh::draw");
/*
// TODO: Reimplement without glBegin/glEnd
glBegin(GL_LINES);
renderer->setCurrentColor(TeColor(255, 255, 255, 255));
for (uint i = 0; i < verticies.size(); i++) {
glVertex3f(verticies[i].x(), verticies[i].y(), verticies[i].z());
glVertex3f(verticies[i].x() + normals[i].x(),
verticies[i].y() + normals[i].y(),
verticies[i].z() + normals[i].z());
}
glEnd();
*/
}
renderer->setMatrixMode(TeRenderer::MM_GL_MODELVIEW);
renderer->popMatrix();
renderer->popMatrix();
}
TeMesh::Mode TeMeshOpenGL::getMode() const {
// Do the reverse translation of setConf... why? I dunno.. the game does that..
switch(_glMeshMode) {
case GL_POINTS:
return MeshMode_Points;
case GL_LINES:
return MeshMode_Lines;
case GL_LINE_LOOP:
return MeshMode_LineLoop;
case GL_LINE_STRIP:
return MeshMode_LineStrip;
case GL_TRIANGLES:
return MeshMode_Triangles;
case GL_TRIANGLE_STRIP:
return MeshMode_TriangleStrip;
case GL_TRIANGLE_FAN:
return MeshMode_TriangleFan;
default:
return MeshMode_None;
}
}
void TeMeshOpenGL::setMode(enum Mode mode) {
switch(mode) {
case MeshMode_Points:
_glMeshMode = GL_POINTS;
break;
case MeshMode_Lines:
_glMeshMode = GL_LINES;
break;
case MeshMode_LineLoop:
_glMeshMode = GL_LINE_LOOP;
break;
case MeshMode_LineStrip:
_glMeshMode = GL_LINE_STRIP;
break;
case MeshMode_Triangles:
_glMeshMode = GL_TRIANGLES;
break;
case MeshMode_TriangleStrip:
_glMeshMode = GL_TRIANGLE_STRIP;
break;
case MeshMode_TriangleFan:
_glMeshMode = GL_TRIANGLE_FAN;
break;
default:
error("Invalid mesh mode %d", (int)mode);
}
}
void TeMeshOpenGL::setglTexEnvBlend() {
_gltexEnvMode = GL_BLEND;
}
uint32 TeMeshOpenGL::getTexEnvMode() const {
return _gltexEnvMode;
}
void TeMeshOpenGL::setConf(uint vertexCount, uint indexCount, enum Mode mode, uint materialCount, uint materialIndexCount) {
destroy();
_initialMaterialIndexCount = materialIndexCount;
_verticies.resize(vertexCount);
_indexes.resize(indexCount);
_materials.resize(materialCount);
_matricies.resize(vertexCount);
switch(mode) {
case MeshMode_Points:
_glMeshMode = GL_POINTS;
break;
case MeshMode_Lines:
_glMeshMode = GL_LINES;
break;
case MeshMode_LineLoop:
_glMeshMode = GL_LINE_LOOP;
break;
case MeshMode_LineStrip:
_glMeshMode = GL_LINE_STRIP;
break;
case MeshMode_Triangles:
_glMeshMode = GL_TRIANGLES;
break;
case MeshMode_TriangleStrip:
_glMeshMode = GL_TRIANGLE_STRIP;
break;
case MeshMode_TriangleFan:
_glMeshMode = GL_TRIANGLE_FAN;
break;
default:
error("Setting invalid mesh mode.");
}
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,55 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_MESH_OPENGL_H
#define TETRAEDGE_TE_TE_MESH_OPENGL_H
#if defined(USE_OPENGL_GAME)
#include "tetraedge/te/te_mesh.h"
namespace Tetraedge {
class TeMeshOpenGL : public TeMesh {
public:
TeMeshOpenGL();
void copy(const TeMesh &other);
void draw() override;
TeMesh::Mode getMode() const override;
void setMode(enum Mode mode) override;
void setConf(uint vertexCount, uint indexCount, enum Mode mode, uint materialCount, uint materialIndexCount);
void setglTexEnvBlend() override;
uint32 getTexEnvMode() const override;
private:
uint _glMeshMode;
uint32 _gltexEnvMode;
};
} // end namespace Tetraedge
#endif // USE_OPENGL
#endif // TETRAEDGE_TE_TE_MESH_H

View File

@@ -0,0 +1,230 @@
/* 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 "graphics/tinygl/tinygl.h"
#include "tetraedge/tetraedge.h"
#include "tetraedge/te/te_renderer.h"
#include "tetraedge/te/te_light.h"
#include "tetraedge/te/te_mesh_tinygl.h"
namespace Tetraedge {
TeMeshTinyGL::TeMeshTinyGL() : _glMeshMode(TGL_POINTS), _gltexEnvMode(TGL_MODULATE) {
}
void TeMeshTinyGL::draw() {
if (!worldVisible())
return;
TeRenderer *renderer = g_engine->getRenderer();
renderer->pushMatrix();
if (_matrixForced)
renderer->multiplyMatrix(_forcedMatrix);
else
renderer->multiplyMatrix(worldTransformationMatrix());
/*
debug("Draw mesh %p (%s, %d verts %d norms %d indexes %d materials %d updated)", this, name().empty() ? "no name" : name().c_str(), _verticies.size(), _normals.size(), _indexes.size(), _materials.size(), _updatedVerticies.size());
debug(" renderMatrix %s", renderer->currentMatrix().toString().c_str());
if (!_materials.empty())
debug(" material %s", _materials[0].dump().c_str());
debug(" position %s", position().dump().c_str());
debug(" worldPos %s", worldPosition().dump().c_str());
debug(" scale %s", scale().dump().c_str());
debug(" worldScale %s", worldScale().dump().c_str());
debug(" rotation %s", rotation().dump().c_str());
debug(" worldRot %s", worldRotation().dump().c_str());
*/
if (renderer->shadowMode() != TeRenderer::ShadowModeCreating) {
if (_faceCounts.empty()) {
if (hasAlpha(0) && _shouldDraw) {
renderer->addTransparentMesh(*this, 0, 0, 0);
renderer->popMatrix();
return;
}
} else {
assert(_faceCounts.size() == _materials.size());
int totalFaceCount = 0;
for (uint i = 0; i < _faceCounts.size(); i++) {
if (!_faceCounts[i])
continue;
if (hasAlpha(i)) {
renderer->addTransparentMesh(*this, totalFaceCount, _faceCounts[i], i);
}
totalFaceCount += _faceCounts[i];
}
}
}
const Common::Array<TeVector3f32> &normals = (_updatedVerticies.empty() ? _normals : _updatedNormals);
const Common::Array<TeVector3f32> &verticies = (_updatedVerticies.empty() ? _verticies : _updatedVerticies);
renderer->setMatrixMode(TeRenderer::MM_GL_MODELVIEW);
renderer->pushMatrix();
renderer->loadCurrentMatrixToGL();
tglEnableClientState(TGL_VERTEX_ARRAY);
if (!normals.empty())
tglEnableClientState(TGL_NORMAL_ARRAY);
if (!_colors.empty())
tglEnableClientState(TGL_COLOR_ARRAY);
tglVertexPointer(3, TGL_FLOAT, sizeof(TeVector3f32), verticies.data());
if (!normals.empty())
tglNormalPointer(TGL_FLOAT, sizeof(TeVector3f32), normals.data());
if (!_uvs.empty() && renderer->shadowMode() != TeRenderer::ShadowModeDrawing)
tglTexCoordPointer(2, TGL_FLOAT, sizeof(TeVector2f32), _uvs.data());
if (!_colors.empty())
tglColorPointer(4, TGL_UNSIGNED_BYTE, sizeof(TeColor), _colors.data());
tglTexEnvi(TGL_TEXTURE_ENV, TGL_TEXTURE_ENV_MODE, _gltexEnvMode);
if (renderer->scissorEnabled()) {
tglEnable(TGL_SCISSOR_TEST);
// TODO: Scissor not supported by TGL
/*
uint scissorx = renderer->scissorX();
uint scissory = renderer->scissorY();
uint scissorwidth = renderer->scissorWidth();
uint scissorheight = renderer->scissorHeight();
//tglScissor(scissorx, scissory, scissorwidth, scissorheight);
*/
}
if (_faceCounts.empty()) {
if (!_materials.empty())
renderer->applyMaterial(_materials[0]);
tglDrawElements(_glMeshMode, _indexes.size(), TGL_UNSIGNED_SHORT, _indexes.data());
if (!_materials.empty()) {
tglDisableClientState(TGL_TEXTURE_COORD_ARRAY);
renderer->disableTexture();
}
} else {
int totalFaceCount = 0;
assert(_faceCounts.size() == _materials.size());
for (uint i = 0; i < _materials.size(); i++) {
if (!_faceCounts[i])
continue;
if (!hasAlpha(i) || renderer->shadowMode() == TeRenderer::ShadowModeCreating || !_shouldDraw) {
renderer->applyMaterial(_materials[i]);
tglDrawElements(_glMeshMode, _faceCounts[i] * 3, TGL_UNSIGNED_SHORT, _indexes.data() + totalFaceCount * 3);
tglDisableClientState(TGL_TEXTURE_COORD_ARRAY);
renderer->disableTexture();
}
totalFaceCount += _faceCounts[i];
}
}
if (!renderer->scissorEnabled())
tglDisable(TGL_SCISSOR_TEST);
tglTexEnvi(TGL_TEXTURE_ENV, TGL_TEXTURE_ENV_MODE, TGL_MODULATE);
tglDisableClientState(TGL_VERTEX_ARRAY);
tglDisableClientState(TGL_NORMAL_ARRAY);
tglDisableClientState(TGL_COLOR_ARRAY);
//renderer->setCurrentColor(renderer->currentColor()); // pointless?
if (_drawWires && !normals.empty()) {
renderer->disableAllLights();
//error("TODO: Properly implement _drawWires case in TeMesh::draw");
///*
// TODO: Reimplement without glBegin/glEnd
tglBegin(TGL_LINES);
renderer->setCurrentColor(TeColor(255, 255, 255, 255));
for (uint i = 0; i < verticies.size(); i++) {
tglVertex3f(verticies[i].x(), verticies[i].y(), verticies[i].z());
tglVertex3f(verticies[i].x() + normals[i].x(),
verticies[i].y() + normals[i].y(),
verticies[i].z() + normals[i].z());
}
tglEnd();
//*/
}
renderer->setMatrixMode(TeRenderer::MM_GL_MODELVIEW);
renderer->popMatrix();
renderer->popMatrix();
}
TeMesh::Mode TeMeshTinyGL::getMode() const {
switch(_glMeshMode) {
case TGL_POINTS:
return MeshMode_Points;
case TGL_LINES:
return MeshMode_Lines;
case TGL_LINE_LOOP:
return MeshMode_LineLoop;
case TGL_LINE_STRIP:
return MeshMode_LineStrip;
case TGL_TRIANGLES:
return MeshMode_Triangles;
case TGL_TRIANGLE_STRIP:
return MeshMode_TriangleStrip;
case TGL_TRIANGLE_FAN:
return MeshMode_TriangleFan;
default:
return MeshMode_None;
}
}
void TeMeshTinyGL::setMode(enum Mode mode) {
switch(mode) {
case MeshMode_Points:
_glMeshMode = TGL_POINTS;
break;
case MeshMode_Lines:
_glMeshMode = TGL_LINES;
break;
case MeshMode_LineLoop:
_glMeshMode = TGL_LINE_LOOP;
break;
case MeshMode_LineStrip:
_glMeshMode = TGL_LINE_STRIP;
break;
case MeshMode_Triangles:
_glMeshMode = TGL_TRIANGLES;
break;
case MeshMode_TriangleStrip:
_glMeshMode = TGL_TRIANGLE_STRIP;
break;
case MeshMode_TriangleFan:
_glMeshMode = TGL_TRIANGLE_FAN;
break;
default:
error("Invalid mesh mode %d", (int)mode);
}
}
void TeMeshTinyGL::setglTexEnvBlend() {
_gltexEnvMode = TGL_BLEND;
}
uint32 TeMeshTinyGL::getTexEnvMode() const {
return _gltexEnvMode;
}
} // end namespace Tetraedge

View File

@@ -0,0 +1,54 @@
/* 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/>.
*
*/
#ifndef TETRAEDGE_TE_TE_MESH_TINYGL_H
#define TETRAEDGE_TE_TE_MESH_TINYGL_H
#if defined(USE_TINYGL)
#include "tetraedge/te/te_mesh.h"
namespace Tetraedge {
class TeMeshTinyGL : public TeMesh {
public:
TeMeshTinyGL();
void copy(const TeMesh &other);
void draw() override;
TeMesh::Mode getMode() const override;
void setMode(enum Mode mode) override;
void setConf(uint vertexCount, uint indexCount, enum Mode mode, uint materialCount, uint materialIndexCount);
void setglTexEnvBlend() override;
uint32 getTexEnvMode() const override;
private:
uint _glMeshMode;
uint32 _gltexEnvMode;
};
} // end namespace Tetraedge
#endif // USE_TINYGL
#endif // TETRAEDGE_TE_TE_MESH_H

Some files were not shown because too many files have changed in this diff Show More