From ecab9761d46754cd8d7a513a8ac16a8b88499d55 Mon Sep 17 00:00:00 2001 From: erihel Date: Wed, 4 Jul 2012 19:38:18 +0200 Subject: * Added OpenAL sound plugin Plugin needs some more work and tests. It doesn't support playing music yet as sound interface is propably going to change a bit. --- src/plugins/sound/oalsound/CMakeLists.txt | 25 ++ src/plugins/sound/oalsound/alsound.cpp | 534 ++++++++++++++++++++++++++++++ src/plugins/sound/oalsound/alsound.h | 94 ++++++ src/plugins/sound/oalsound/buffer.cpp | 80 +++++ src/plugins/sound/oalsound/buffer.h | 48 +++ src/plugins/sound/oalsound/channel.cpp | 304 +++++++++++++++++ src/plugins/sound/oalsound/channel.h | 99 ++++++ src/plugins/sound/oalsound/check.h | 39 +++ 8 files changed, 1223 insertions(+) create mode 100644 src/plugins/sound/oalsound/CMakeLists.txt create mode 100644 src/plugins/sound/oalsound/alsound.cpp create mode 100644 src/plugins/sound/oalsound/alsound.h create mode 100644 src/plugins/sound/oalsound/buffer.cpp create mode 100644 src/plugins/sound/oalsound/buffer.h create mode 100644 src/plugins/sound/oalsound/channel.cpp create mode 100644 src/plugins/sound/oalsound/channel.h create mode 100644 src/plugins/sound/oalsound/check.h (limited to 'src') diff --git a/src/plugins/sound/oalsound/CMakeLists.txt b/src/plugins/sound/oalsound/CMakeLists.txt new file mode 100644 index 0000000..6056590 --- /dev/null +++ b/src/plugins/sound/oalsound/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 2.8) + +set(SOURCES + alsound.cpp + buffer.cpp + channel.cpp + ../../../common/logger.cpp +) + +SET (CMAKE_CXX_FLAGS "-Wall -g -std=c++0x") + +include(FindPkgConfig) +include(FindOpenAL) +pkg_check_modules(OPENAL_LIB REQUIRED openal) + +set(OPENAL_LIBRARIES + openal + alut +) + + +include_directories(../../..) +include_directories(.) +add_library(openalsound SHARED ${SOURCES}) +target_link_libraries(openalsound ${OPENAL_LIBRARIES}) diff --git a/src/plugins/sound/oalsound/alsound.cpp b/src/plugins/sound/oalsound/alsound.cpp new file mode 100644 index 0000000..87baabd --- /dev/null +++ b/src/plugins/sound/oalsound/alsound.cpp @@ -0,0 +1,534 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// alsound.cpp + + +#include "alsound.h" + + +#define MIN(a, b) (a > b ? b : a) + + +PLUGIN_INTERFACE(ALSound, CSoundInterface) + + +char* ALSound::pluginName() +{ + return const_cast("Sound plugin using OpenAL library to play sounds."); +} + + +int ALSound::pluginVersion() +{ + return 1; +} + + +ALSound::ALSound() +{ + mEnabled = false; + m3D = false; + mAudioVolume = MAXVOLUME; + mMute = false; +} + + +ALSound::~ALSound() +{ + CleanUp(); +} + + +void ALSound::CleanUp() +{ + if (mEnabled) { + GetLogger()->Info("Unloading files and closing device...\n"); + mEnabled = false; + + for (auto item : mSounds) + delete item.second; + + alutExit(); + } +} + + +bool ALSound::Create(bool b3D) +{ + CleanUp(); + + if (mEnabled) + return true; + + GetLogger()->Info("Opening audio device...\n"); + if (!alutInit(NULL, NULL)) { + ALenum error = alutGetError(); + GetLogger()->Error("Could not open audio device! Reason: %s\n", alutGetErrorString(error)); + return false; + } + GetLogger()->Info("Done.\n"); + + mEnabled = true; + return true; +} + + +void ALSound::SetSound3D(bool bMode) +{ + // TODO stub! need to be implemented + m3D = bMode; +} + + +bool ALSound::RetSound3D() +{ + // TODO stub! need to be implemented + return true; +} + + +bool ALSound::RetSound3DCap() +{ + // TODO stub! need to be implemented + return true; +} + + +bool ALSound::RetEnable() +{ + return mEnabled; +} + + +void ALSound::SetAudioVolume(int volume) +{ + alListenerf(AL_GAIN, MIN(volume, MAXVOLUME) * 0.01f); + mAudioVolume = MIN(volume, MAXVOLUME); +} + + +int ALSound::RetAudioVolume() +{ + float volume; + if ( !mEnabled ) + return 0; + + alGetListenerf(AL_GAIN, &volume); + return volume * MAXVOLUME; +} + + +void ALSound::SetMusicVolume(int volume) +{ + // TODO stub! Add music support +} + + +int ALSound::RetMusicVolume() +{ + // TODO stub! Add music support + if ( !mEnabled ) + return 0; + + return 0; +} + + +bool ALSound::Cache(Sound sound, std::string filename) +{ + Buffer *buffer = new Buffer(); + if (buffer->LoadFromFile(filename, sound)) { + mSounds[sound] = buffer; + return true; + } + return false; +} + + +void ALSound::CacheAll() +{ + char filename[100]; + for ( int i = 1; i < 69; i++ ) + { + sprintf(filename, "high/sound%.3d.wav", i); + if ( !Cache((Sound) i, std::string(filename)) ) + { + fprintf(stderr, "Unable to load audio: %s\n", filename); + } + } +} + + +int ALSound::RetPriority(Sound sound) +{ + if ( sound == SOUND_FLYh || + sound == SOUND_FLY || + sound == SOUND_MOTORw || + sound == SOUND_MOTORt || + sound == SOUND_MOTORr || + sound == SOUND_MOTORs || + sound == SOUND_SLIDE || + sound == SOUND_ERROR ) + { + return 30; + } + + if ( sound == SOUND_CONVERT || + sound == SOUND_ENERGY || + sound == SOUND_DERRICK || + sound == SOUND_STATION || + sound == SOUND_REPAIR || + sound == SOUND_RESEARCH || + sound == SOUND_BURN || + sound == SOUND_BUILD || + sound == SOUND_TREMBLE || + sound == SOUND_NUCLEAR || + sound == SOUND_EXPLO || + sound == SOUND_EXPLOl || + sound == SOUND_EXPLOlp || + sound == SOUND_EXPLOp || + sound == SOUND_EXPLOi ) + { + return 20; + } + + if ( sound == SOUND_BLUP || + sound == SOUND_INSECTs || + sound == SOUND_INSECTa || + sound == SOUND_INSECTb || + sound == SOUND_INSECTw || + sound == SOUND_INSECTm || + sound == SOUND_PSHHH || + sound == SOUND_EGG ) + { + return 0; + } + + return 10; +} + + +bool ALSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded) +{ + int priority = RetPriority(sound); + + // Seeks a channel used which sound is stopped. + for (auto it : mChannels) { + if (it.second->IsPlaying()) + continue; + if (it.second->GetSoundType() != sound) + continue; + + it.second->SetPriority(priority); + channel = it.first; + bAlreadyLoaded = true; + return true; + } + + // just add a new channel if we dont have any + if (mChannels.size() == 0) { + Channel *chn = new Channel(); + // check if we channel ready to play music, if not report error + if (chn->IsReady()) { + chn->SetPriority(priority); + mChannels[1] = chn; + channel = 1; + bAlreadyLoaded = false; + return true; + } + delete chn; + GetLogger()->Error("Could not open channel to play sound!"); + return false; + } + + // Seeks a channel completely free. + auto it = mChannels.end(); + it--; + int i = (*it).first; + while (++i) + { + if (mChannels.find(i) == mChannels.end()) { + Channel *chn = new Channel(); + // check if we channel ready to play music, if not destroy it and seek free one + if (chn->IsReady()) { + chn->SetPriority(priority); + mChannels[1] = chn; + channel = 1; + bAlreadyLoaded = false; + return true; + } + delete chn; + GetLogger()->Warn("Could not open additional channel to play sound!"); + } + } + + int lowerOrEqual = -1; + for (auto it : mChannels) { + if (it.second->GetPriority() < priority) { + GetLogger()->Info("Sound channel with lower priority will be reused."); + channel = it.first; + return true; + } + if (it.second->GetPriority() <= priority) + lowerOrEqual = it.first; + } + + if (lowerOrEqual != -1) { + channel = lowerOrEqual; + GetLogger()->Info("Sound channel with lower or equal priority will be reused."); + return true; + } + + GetLogger()->Warn("Could not find free buffer to use.\n"); + return false; +} + + +int ALSound::Play(Sound sound, float amplitude, float frequency, bool bLoop) +{ + return Play(sound, Math::Vector(), amplitude, frequency, bLoop); +} + + +int ALSound::Play(Sound sound, Math::Vector pos, float amplitude, float frequency, bool bLoop) +{ + if (!mEnabled) + return -1; + + if (mAudioVolume <= 0.0f) + return -1; + + if (mSounds.find(sound) == mSounds.end()) { + GetLogger()->Warn("Sound %d was not loaded!\n", sound); + return -1; + } + + int channel; + bool bAlreadyLoaded; + if (!SearchFreeBuffer(sound, channel, bAlreadyLoaded)) + return -1; + if ( !bAlreadyLoaded ) { + mChannels[channel]->SetBuffer(mSounds[sound]); + } + + Position(channel, pos); + + // setting initial values + mChannels[channel]->SetStartAmplitude(amplitude); + mChannels[channel]->SetStartFrequency(frequency); + mChannels[channel]->SetChangeFrequency(1.0f); + mChannels[channel]->ResetOper(); + mChannels[channel]->AdjustFrequency(frequency); + mChannels[channel]->AdjustVolume(mAudioVolume); + mChannels[channel]->Play(); + return channel; +} + + +bool ALSound::FlushEnvelope(int channel) +{ + if (mChannels.find(channel) == mChannels.end()) { + return false; + } + + mChannels[channel]->ResetOper(); + return true; +} + + +bool ALSound::AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper) +{ + if (!mEnabled) + return false; + + if (mChannels.find(channel) == mChannels.end()) { + return false; + } + + SoundOper op; + op.finalAmplitude = amplitude; + op.finalFrequency = frequency; + op.totalTime = time; + op.nextOper = oper; + mChannels[channel]->AddOper(op); + + return false; +} + + +bool ALSound::Position(int channel, Math::Vector pos) +{ + if (!mEnabled) + return false; + + if (mChannels.find(channel) == mChannels.end()) { + return false; + } + + mChannels[channel]->SetPosition(pos); + return true; +} + + +bool ALSound::Frequency(int channel, float frequency) +{ + if (!mEnabled) + return false; + + if (mChannels.find(channel) == mChannels.end()) { + return false; + } + + mChannels[channel]->SetFrequency(frequency); + return true; +} + +bool ALSound::Stop(int channel) +{ + if (!mEnabled) + return false; + + if (mChannels.find(channel) == mChannels.end()) { + return false; + } + + mChannels[channel]->Stop(); + mChannels[channel]->ResetOper(); + + return true; +} + + +bool ALSound::StopAll() +{ + if (!mEnabled) + return false; + + for (auto channel : mChannels) { + channel.second->Stop(); + channel.second->ResetOper(); + } + + return true; +} + + +bool ALSound::MuteAll(bool bMute) +{ + if (!mEnabled) + return false; + + float volume; + mMute = bMute; + if (mMute) + volume = 0; + else + volume = mAudioVolume; + + for (auto channel : mChannels) { + channel.second->SetVolume(volume); + } + + return true; +} + + +void ALSound::FrameMove(float delta) +{ + if (!mEnabled) + return; + + float progress; + float volume, frequency; + for (auto it : mChannels) { + if (!it.second->IsPlaying()) + continue; + + if (!it.second->HasEnvelope()) + continue; + + //it.second->GetEnvelope().currentTime += delta; + SoundOper oper = it.second->GetEnvelope(); + progress = it.second->GetCurrentTime() / oper.totalTime; + progress = MIN(progress, 1.0f); + + // setting volume + volume = progress * abs(oper.finalAmplitude - it.second->GetStartAmplitude()); + it.second->AdjustVolume(volume * mAudioVolume); + + // setting frequency + frequency = progress * (oper.finalFrequency - it.second->GetStartFrequency()) * it.second->GetStartFrequency() * it.second->GetChangeFrequency(); + it.second->AdjustFrequency(frequency); + + if (it.second->GetEnvelope().totalTime <= it.second->GetCurrentTime()) { + + if (oper.nextOper == SOPER_LOOP) { + GetLogger()->Info("Replay.\n"); + it.second->SetCurrentTime(0.0f); + it.second->Play(); + } else { + GetLogger()->Info("Next.\n"); + it.second->SetStartAmplitude(oper.finalAmplitude); + it.second->SetStartFrequency(oper.finalFrequency); + it.second->PopEnvelope(); + } + } + } +} + + +void ALSound::SetListener(Math::Vector eye, Math::Vector lookat) +{ + GetLogger()->Info("Setting listener position.\n"); + float orientation[] = {lookat.x, lookat.y, lookat.z, 0.f, 1.f, 0.f}; + alListener3f(AL_POSITION, eye.x, eye.y, eye.z); + alListenerfv(AL_ORIENTATION, orientation); +} + + +bool ALSound::PlayMusic(int rank, bool bRepeat) +{ + // TODO stub! Add music support + return true; +} + + +bool ALSound::RestartMusic() +{ + // TODO stub! Add music support + return true; +} + +void ALSound::StopMusic() +{ + // TODO stub! Add music support + SuspendMusic(); +} + + +bool ALSound::IsPlayingMusic() +{ + // TODO stub! Add music support + return true; +} + + +void ALSound::SuspendMusic() +{ + // TODO stub! Add music support +} diff --git a/src/plugins/sound/oalsound/alsound.h b/src/plugins/sound/oalsound/alsound.h new file mode 100644 index 0000000..d41f6bf --- /dev/null +++ b/src/plugins/sound/oalsound/alsound.h @@ -0,0 +1,94 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// alsound.h + +#pragma once + +#include +#include + +#include + +#include +#include +#include + +#include "buffer.h" +#include "channel.h" +#include "check.h" + + +class ALSound : public CSoundInterface +{ + public: + ALSound(); + ~ALSound(); + + bool Create(bool b3D); + void CacheAll(); + bool Cache(Sound, std::string); + + bool RetEnable(); + + void SetSound3D(bool bMode); + bool RetSound3D(); + bool RetSound3DCap(); + + void SetAudioVolume(int volume); + int RetAudioVolume(); + void SetMusicVolume(int volume); + int RetMusicVolume(); + + void SetListener(Math::Vector eye, Math::Vector lookat); + void FrameMove(float rTime); + + int Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false); + int Play(Sound sound, Math::Vector pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false); + bool FlushEnvelope(int channel); + bool AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper); + bool Position(int channel, Math::Vector pos); + bool Frequency(int channel, float frequency); + bool Stop(int channel); + bool StopAll(); + bool MuteAll(bool bMute); + + bool PlayMusic(int rank, bool bRepeat); + bool RestartMusic(); + void SuspendMusic(); + void StopMusic(); + bool IsPlayingMusic(); + + // plugin interface + char* pluginName(); + int pluginVersion(); + void pluginInit(); + + private: + void CleanUp(); + int RetPriority(Sound); + bool SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded); + + bool mEnabled; + bool m3D; + bool mMute; + int mAudioVolume; + ALCdevice* audioDevice; + ALCcontext* audioContext; + std::map mSounds; + std::map mChannels; +}; diff --git a/src/plugins/sound/oalsound/buffer.cpp b/src/plugins/sound/oalsound/buffer.cpp new file mode 100644 index 0000000..37211e9 --- /dev/null +++ b/src/plugins/sound/oalsound/buffer.cpp @@ -0,0 +1,80 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// buffer.cpp + +#include "buffer.h" + +Buffer::Buffer() { + mLoaded = false; + mDuration = 0; +} + + +Buffer::~Buffer() { + if (mLoaded) { + alDeleteBuffers(1, &mBuffer); + if (alCheck()) + GetLogger()->Warn("Failed to unload buffer. Code %d\n", alGetCode()); + } +} + + +bool Buffer::LoadFromFile(std::string filename, Sound sound) { + mSound = sound; + + GetLogger()->Info("Loading audio file: %s\n", filename.c_str()); + mBuffer = alutCreateBufferFromFile(filename.c_str()); + + ALenum error = alutGetError(); + if (error) { + GetLogger()->Warn("Failed to load file. Reason: %s\n", alutGetErrorString(error)); + mLoaded = false; + return false; + } + + ALint size, bits, channels, freq; + + alGetBufferi(mBuffer, AL_SIZE, &size); + alGetBufferi(mBuffer, AL_BITS, &bits); + alGetBufferi(mBuffer, AL_CHANNELS, &channels); + alGetBufferi(mBuffer, AL_FREQUENCY, &freq); + + mDuration = (ALfloat)size / channels / bits / 8 / (ALfloat)freq; + + mLoaded = true; + return true; +} + + +Sound Buffer::GetSoundType() { + return mSound; +} + + +ALuint Buffer::GetBuffer() { + return mBuffer; +} + + +bool Buffer::IsLoaded() { + return mLoaded; +} + + +float Buffer::GetDuration() { + return mDuration; +} diff --git a/src/plugins/sound/oalsound/buffer.h b/src/plugins/sound/oalsound/buffer.h new file mode 100644 index 0000000..6eefe72 --- /dev/null +++ b/src/plugins/sound/oalsound/buffer.h @@ -0,0 +1,48 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// buffer.h + +#pragma once + +#include + +#include + +#include +#include + +#include "check.h" + +class Buffer +{ + public: + Buffer(); + ~Buffer(); + + bool LoadFromFile(std::string, Sound); + bool IsLoaded(); + + Sound GetSoundType(); + ALuint GetBuffer(); + float GetDuration(); + + private: + ALuint mBuffer; + Sound mSound; + bool mLoaded; + float mDuration; +}; diff --git a/src/plugins/sound/oalsound/channel.cpp b/src/plugins/sound/oalsound/channel.cpp new file mode 100644 index 0000000..4476dee --- /dev/null +++ b/src/plugins/sound/oalsound/channel.cpp @@ -0,0 +1,304 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// channel.cpp + +#include "channel.h" + + +Channel::Channel() { + alGenSources(1, &mSource); + + if (alCheck()) { + GetLogger()->Warn("Failed to create sound source. Code: %d\n", alGetCode()); + mReady = false; + } else { + mReady = true; + } + + mPriority = 0; + mBuffer = nullptr; +} + + +Channel::~Channel() { + if (mReady) { + alSourcei(mSource, AL_BUFFER, 0); + alDeleteSources(1, &mSource); + if (alCheck()) + GetLogger()->Warn("Failed to delete sound source. Code: %s\n", alGetCode()); + } +} + + +bool Channel::Play() { + if (!mReady) + return false; + + alSourcePlay(mSource); + if (alCheck()) + GetLogger()->Warn("Could not play audio sound source. Code: %s\n", alGetCode()); + return true; +} + + +bool Channel::SetPosition(Math::Vector pos) { + if (!mReady) + return false; + + alSource3f(mSource, AL_POSITION, pos.x, pos.y, pos.z); + if (alCheck()) { + GetLogger()->Warn("Could not set sound position. Code: %s\n", alGetCode()); + return false; + } + return true; +} + + +bool Channel::SetFrequency(float freq) +{ + if (!mReady) + return false; + + alSourcef(mSource, AL_PITCH, freq); + if (alCheck()) { + GetLogger()->Warn("Could not set sound pitch. Code: %s\n", alGetCode()); + return false; + } + return true; +} + + +float Channel::GetFrequency() +{ + ALfloat freq; + if (!mReady) + return 0; + + alGetSourcef(mSource, AL_PITCH, &freq); + if (alCheck()) { + GetLogger()->Warn("Could not get sound pitch. Code: %s\n", alGetCode()); + return 0; + } + + return freq; +} + + +bool Channel::SetVolume(float vol) +{ + if (!mReady || vol < 0) + return false; + + alSourcef(mSource, AL_GAIN, vol / MAXVOLUME); + if (alCheck()) { + GetLogger()->Warn("Could not set sound volume. Code: %s\n", alGetCode()); + return false; + } + return true; +} + + +float Channel::GetVolume() +{ + ALfloat vol; + if (!mReady) + return 0; + + alGetSourcef(mSource, AL_GAIN, &vol); + if (alCheck()) { + GetLogger()->Warn("Could not get sound volume. Code: %s\n", alGetCode()); + return 0; + } + + return vol * MAXVOLUME; +} + + +int Channel::GetPriority() +{ + return mPriority; +} + + +void Channel::SetPriority(int pri) +{ + mPriority = pri; +} + + +void Channel::SetStartAmplitude(float gain) +{ + mStartAmplitude = gain; +} + + +void Channel::SetStartFrequency(float freq) +{ + mStartFrequency = freq; +} + + +void Channel::SetChangeFrequency(float freq) +{ + mChangeFrequency = freq; +} + + +void Channel::SetInitFrequency(float freq) +{ + mInitFrequency = freq; +} + + +float Channel::GetStartAmplitude() +{ + return mStartAmplitude; +} + + +float Channel::GetStartFrequency() +{ + return mStartFrequency; +} + + +float Channel::GetChangeFrequency() +{ + return mChangeFrequency; +} + + +float Channel::GetInitFrequency() +{ + return mInitFrequency; +} + + +void Channel::AddOper(SoundOper oper) +{ + mOper.push_back(oper); +} + + +void Channel::ResetOper() +{ + mOper.clear(); +} + + +Sound Channel::GetSoundType() { + return mBuffer->GetSoundType(); +} + + +bool Channel::SetBuffer(Buffer *buffer) { + if (!mReady) + return false; + + assert(buffer); + mBuffer = buffer; + alSourcei(mSource, AL_BUFFER, buffer->GetBuffer()); + if (alCheck()) { + GetLogger()->Warn("Could not set sound buffer. Code: %s\n", alGetCode()); + return false; + } + mInitFrequency = GetFrequency(); + return true; +} + + +void Channel::AdjustFrequency(float freq) { + SetFrequency(freq * mInitFrequency); +} + + +void Channel::AdjustVolume(float volume) { + SetVolume(mStartAmplitude * (float) volume); +} + + +bool Channel::IsPlaying() { + ALint status; + if (!mReady) return false; + + alGetSourcei(mSource, AL_SOURCE_STATE, &status); + if (alCheck()) { + GetLogger()->Warn("Could not get sound status. Code: %s\n", alGetCode()); + return false; + } + + return status == AL_PLAYING; +} + + +bool Channel::IsReady() { + return mReady; +} + + +bool Channel::Stop() { + alSourceStop(mSource); + if (alCheck()) { + GetLogger()->Warn("Could not stop sound. Code: %s\n", alGetCode()); + return false; + } + return true; +} + + +float Channel::GetCurrentTime() +{ + ALfloat current; + alGetSourcef(mSource, AL_SEC_OFFSET, ¤t); + if (alCheck()) { + GetLogger()->Warn("Could not get source current play time. Code: %s\n", alGetCode()); + return 0.0f; + } + return current; +} + + +void Channel::SetCurrentTime(float current) +{ + alSourcef(mSource, AL_SEC_OFFSET, current); + if (alCheck()) + GetLogger()->Warn("Could not get source current play time. Code: %s\n", alGetCode()); +} + + +float Channel::GetDuration() +{ + return mBuffer->GetDuration(); +} + + +bool Channel::HasEnvelope() +{ + return mOper.size() > 0; +} + + +SoundOper& Channel::GetEnvelope() +{ + return mOper.front(); +} + + +void Channel::PopEnvelope() +{ + mOper.pop_front(); +} diff --git a/src/plugins/sound/oalsound/channel.h b/src/plugins/sound/oalsound/channel.h new file mode 100644 index 0000000..3099931 --- /dev/null +++ b/src/plugins/sound/oalsound/channel.h @@ -0,0 +1,99 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// channel.h + +#pragma once + +#include +#include +#include + +#include +#include + +#include + +#include "buffer.h" +#include "check.h" + +struct SoundOper +{ + float finalAmplitude; + float finalFrequency; + float totalTime; + SoundNext nextOper; +}; + + +class Channel +{ + public: + Channel(); + ~Channel(); + + bool Play(); + bool Stop(); + bool SetPosition(Math::Vector); + + bool SetFrequency(float); + float GetFrequency(); + + float GetCurrentTime(); + void SetCurrentTime(float); + float GetDuration(); + + bool SetVolume(float); + float GetVolume(); + bool IsPlaying(); + bool IsReady(); + + bool SetBuffer(Buffer *); + bool HasEnvelope(); + SoundOper& GetEnvelope(); + void PopEnvelope(); + + int GetPriority(); + void SetPriority(int); + + void SetStartAmplitude(float); + void SetStartFrequency(float); + void SetChangeFrequency(float); + void SetInitFrequency(float); + + float GetStartAmplitude(); + float GetStartFrequency(); + float GetChangeFrequency(); + float GetInitFrequency(); + + void AddOper(SoundOper); + void ResetOper(); + Sound GetSoundType(); + void AdjustFrequency(float); + void AdjustVolume(float); + + private: + Buffer *mBuffer; + ALuint mSource; + + int mPriority; + float mStartAmplitude; + float mStartFrequency; + float mChangeFrequency; + float mInitFrequency; + std::deque mOper; + bool mReady; +}; diff --git a/src/plugins/sound/oalsound/check.h b/src/plugins/sound/oalsound/check.h new file mode 100644 index 0000000..cb6b4a1 --- /dev/null +++ b/src/plugins/sound/oalsound/check.h @@ -0,0 +1,39 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// check.h + +#pragma once + +#include +#include + +#include + +static ALenum CODE = AL_NO_ERROR; + +inline bool alCheck() +{ + CODE = alGetError(); + return CODE != AL_NO_ERROR; +} + +inline ALenum alGetCode() +{ + ALenum ret = CODE; + CODE = AL_NO_ERROR; + return ret; +} -- cgit v1.2.3-1-g7c22 From 0e4b070b5f10c0004cfbfa234e3634357b070cba Mon Sep 17 00:00:00 2001 From: erihel Date: Wed, 4 Jul 2012 20:03:17 +0200 Subject: just some fixes --- src/common/logger.h | 1 + src/plugins/sound/oalsound/alsound.cpp | 4 ++-- src/plugins/sound/oalsound/alsound.h | 5 ++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/common/logger.h b/src/common/logger.h index 1b3829c..3a48210 100644 --- a/src/common/logger.h +++ b/src/common/logger.h @@ -21,6 +21,7 @@ #include #include +#include #include diff --git a/src/plugins/sound/oalsound/alsound.cpp b/src/plugins/sound/oalsound/alsound.cpp index 87baabd..0e15a40 100644 --- a/src/plugins/sound/oalsound/alsound.cpp +++ b/src/plugins/sound/oalsound/alsound.cpp @@ -27,13 +27,13 @@ PLUGIN_INTERFACE(ALSound, CSoundInterface) -char* ALSound::pluginName() +char* ALSound::PluginName() { return const_cast("Sound plugin using OpenAL library to play sounds."); } -int ALSound::pluginVersion() +int ALSound::PluginVersion() { return 1; } diff --git a/src/plugins/sound/oalsound/alsound.h b/src/plugins/sound/oalsound/alsound.h index d41f6bf..982d3a3 100644 --- a/src/plugins/sound/oalsound/alsound.h +++ b/src/plugins/sound/oalsound/alsound.h @@ -74,9 +74,8 @@ class ALSound : public CSoundInterface bool IsPlayingMusic(); // plugin interface - char* pluginName(); - int pluginVersion(); - void pluginInit(); + char* PluginName(); + int PluginVersion(); private: void CleanUp(); -- cgit v1.2.3-1-g7c22 From d56db5f4e4a8e0d572bf3d682619bb25aebe4120 Mon Sep 17 00:00:00 2001 From: erihel Date: Thu, 19 Jul 2012 19:19:21 +0200 Subject: * Chaned plugin interface * Added plugin class for plugin loading * Added plugin loading test --- src/common/iman.cpp | 15 +++++ src/common/iman.h | 6 +- src/plugins/plugin.cpp | 97 +++++++++++++++++++++++++++++++ src/plugins/plugin.h | 25 ++++++-- src/plugins/plugininterface.h | 37 ++++++++++++ src/plugins/sound/oalsound/CMakeLists.txt | 3 +- src/plugins/sound/oalsound/alsound.cpp | 20 ++++++- src/plugins/sound/oalsound/alsound.h | 2 + src/plugins/test/CMakeLists.txt | 11 ++++ src/plugins/test/plugin_test.cpp | 40 +++++++++++++ src/sound/sound.h | 9 +-- 11 files changed, 246 insertions(+), 19 deletions(-) create mode 100644 src/plugins/plugin.cpp create mode 100644 src/plugins/plugininterface.h create mode 100644 src/plugins/test/CMakeLists.txt create mode 100644 src/plugins/test/plugin_test.cpp (limited to 'src') diff --git a/src/common/iman.cpp b/src/common/iman.cpp index 28ee3d3..9e94f24 100644 --- a/src/common/iman.cpp +++ b/src/common/iman.cpp @@ -23,6 +23,21 @@ #include "common/iman.h" +template<> CInstanceManager* CSingleton::mInstance = 0; + + +CInstanceManager& CInstanceManager::GetInstance() +{ + assert(mInstance); + return *mInstance; +} + + +CInstanceManager* CInstanceManager::GetInstancePointer() +{ + assert(mInstance); + return mInstance; +} // Object's constructor. diff --git a/src/common/iman.h b/src/common/iman.h index 7a7b499..38e5f37 100644 --- a/src/common/iman.h +++ b/src/common/iman.h @@ -18,7 +18,7 @@ #pragma once - +#include "common/singleton.h" #include "common/misc.h" @@ -32,7 +32,7 @@ struct BaseClass -class CInstanceManager +class CInstanceManager : public CSingleton { public: CInstanceManager(); @@ -44,6 +44,8 @@ public: bool DeleteInstance(ClassType classType, void* pointer); void* SearchInstance(ClassType classType, int rank=0); + static CInstanceManager& GetInstance(); + static CInstanceManager* GetInstancePointer(); protected: void Compress(ClassType classType); diff --git a/src/plugins/plugin.cpp b/src/plugins/plugin.cpp new file mode 100644 index 0000000..ca0fe0e --- /dev/null +++ b/src/plugins/plugin.cpp @@ -0,0 +1,97 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012 Polish Portal of Colobot (PPC) +// * +// * 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/. + +// plugin.cpp + + +#include "plugin.h" + + +CPlugin::CPlugin(std::string filename) +{ + mInterface = nullptr; + mFilename = filename; + mLoaded = false; +} + + +char* CPlugin::GetName() +{ + if (mLoaded) + return mInterface->PluginName(); + return nullptr; +} + + +int CPlugin::GetVersion() +{ + if (mLoaded) + return mInterface->PluginVersion(); + return 0; +} + + +bool CPlugin::IsLoaded() +{ + return mLoaded; +} + + +bool CPlugin::UnloadPlugin() +{ + if (!mLoaded) { + GetLogger()->Warn("Plugin %s is not loaded.\n"); + return true; + } + + void (*uninstall)() = (void (*)()) lt_dlsym(mHandle, "UninstallPluginEntry"); + if (!uninstall) { + GetLogger()->Error("Error getting UninstallPluginEntry for plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); + return false; + } + + lt_dlclose(mHandle); + mLoaded = false; + return true; +} + + +bool CPlugin::LoadPlugin() +{ + mHandle = lt_dlopenext(mFilename.c_str()); + if (!mHandle) { + GetLogger()->Error("Error loading plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); + return false; + } + + void (*install)() = (void (*)()) lt_dlsym(mHandle, "InstallPluginEntry"); + if (!install) { + GetLogger()->Error("Error getting InstallPluginEntry for plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); + return false; + } + + CPluginInterface* (*getInterface)() = (CPluginInterface* (*)()) lt_dlsym(mHandle, "GetPluginInterfaceEntry"); + + if (!getInterface) { + GetLogger()->Error("Error getting GetPluginInterfaceEntry for plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); + return false; + } + + install(); + mInterface = getInterface(); + mLoaded = true; + return true; +} diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h index f238122..e7d4b12 100644 --- a/src/plugins/plugin.h +++ b/src/plugins/plugin.h @@ -19,15 +19,28 @@ #pragma once +#include +#include -#define PLUGIN_INTERFACE(class_type, interface_type) \ - extern "C" interface_type* installPlugin() { return (interface_type *)new class_type(); } \ - extern "C" void uninstallPlugin(class_type *_class) { delete _class; } +#include + +#include "plugininterface.h" class CPlugin { public: - virtual char* PluginName() = 0; - virtual int PluginVersion() = 0; + CPlugin(std::string filename); + + char* GetName(); + int GetVersion(); + bool UnloadPlugin(); + bool LoadPlugin(); + bool IsLoaded(); + + + private: + CPluginInterface* mInterface; + std::string mFilename; + lt_dlhandle mHandle; + bool mLoaded; }; - diff --git a/src/plugins/plugininterface.h b/src/plugins/plugininterface.h new file mode 100644 index 0000000..bf4e040 --- /dev/null +++ b/src/plugins/plugininterface.h @@ -0,0 +1,37 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// plugininterface.h + + +#pragma once + + +#define PLUGIN_INTERFACE(class_type) \ + static class_type* Plugin##class_type; \ + extern "C" void InstallPluginEntry() { Plugin##class_type = new class_type(); Plugin##class_type->InstallPlugin(); } \ + extern "C" void UninstallPluginEntry() { Plugin##class_type->UninstallPlugin(); delete Plugin##class_type; } \ + extern "C" CPluginInterface* GetPluginInterfaceEntry() { return static_cast(Plugin##class_type); } + + +class CPluginInterface { + public: + virtual char* PluginName() = 0; + virtual int PluginVersion() = 0; + virtual void InstallPlugin() = 0; + virtual void UninstallPlugin() = 0; +}; + diff --git a/src/plugins/sound/oalsound/CMakeLists.txt b/src/plugins/sound/oalsound/CMakeLists.txt index 6056590..e36f3ac 100644 --- a/src/plugins/sound/oalsound/CMakeLists.txt +++ b/src/plugins/sound/oalsound/CMakeLists.txt @@ -4,10 +4,9 @@ set(SOURCES alsound.cpp buffer.cpp channel.cpp - ../../../common/logger.cpp ) -SET (CMAKE_CXX_FLAGS "-Wall -g -std=c++0x") +SET (CMAKE_CXX_FLAGS "-Wall -g -std=c++0x -fPIC") include(FindPkgConfig) include(FindOpenAL) diff --git a/src/plugins/sound/oalsound/alsound.cpp b/src/plugins/sound/oalsound/alsound.cpp index 0e15a40..19da66a 100644 --- a/src/plugins/sound/oalsound/alsound.cpp +++ b/src/plugins/sound/oalsound/alsound.cpp @@ -1,6 +1,6 @@ // * This file is part of the COLOBOT source code // * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch -// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * Copyright (C) 2012 Polish Portal of Colobot (PPC) // * // * 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 @@ -24,7 +24,7 @@ #define MIN(a, b) (a > b ? b : a) -PLUGIN_INTERFACE(ALSound, CSoundInterface) +PLUGIN_INTERFACE(ALSound) char* ALSound::PluginName() @@ -39,6 +39,19 @@ int ALSound::PluginVersion() } +void ALSound::InstallPlugin() +{ + CInstanceManager::GetInstancePointer()->AddInstance(CLASS_SOUND, this); +} + + +void ALSound::UninstallPlugin() +{ + CInstanceManager::GetInstancePointer()->DeleteInstance(CLASS_SOUND, this); + CleanUp(); +} + + ALSound::ALSound() { mEnabled = false; @@ -58,11 +71,12 @@ void ALSound::CleanUp() { if (mEnabled) { GetLogger()->Info("Unloading files and closing device...\n"); - mEnabled = false; + StopAll(); for (auto item : mSounds) delete item.second; + mEnabled = false; alutExit(); } } diff --git a/src/plugins/sound/oalsound/alsound.h b/src/plugins/sound/oalsound/alsound.h index 982d3a3..6d4e5b6 100644 --- a/src/plugins/sound/oalsound/alsound.h +++ b/src/plugins/sound/oalsound/alsound.h @@ -76,6 +76,8 @@ class ALSound : public CSoundInterface // plugin interface char* PluginName(); int PluginVersion(); + void InstallPlugin(); + void UninstallPlugin(); private: void CleanUp(); diff --git a/src/plugins/test/CMakeLists.txt b/src/plugins/test/CMakeLists.txt new file mode 100644 index 0000000..551daeb --- /dev/null +++ b/src/plugins/test/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 2.8) + +set(CMAKE_BUILD_TYPE debug) +set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0 -std=c++11 -rdynamic") + +add_executable(plugin_test plugin_test.cpp ../../common/iman.cpp ../../common/logger.cpp ../plugin.cpp) + +# Change to DirectX SDK directory +include_directories("../../") + +target_link_libraries(plugin_test ltdl) \ No newline at end of file diff --git a/src/plugins/test/plugin_test.cpp b/src/plugins/test/plugin_test.cpp new file mode 100644 index 0000000..7175773 --- /dev/null +++ b/src/plugins/test/plugin_test.cpp @@ -0,0 +1,40 @@ +#include +#include +#include + +#include +#include +#include +#include + + +int main() { + new CLogger(); + new CInstanceManager(); + + lt_dlinit(); + + CPlugin *plugin = new CPlugin("libopenalsound"); + if (plugin->LoadPlugin()) { + CSoundInterface *sound = static_cast(CInstanceManager::GetInstancePointer()->SearchInstance(CLASS_SOUND)); + + sound->Create(true); + sound->CacheAll(); + sound->Play((Sound)8); + sound->Play((Sound)18); + + sleep(10); + /* + while (1) + { + // just a test, very slow + plugin->FrameMove(0); + //if ('n' == getchar()) + // break; + }*/ + plugin->UnloadPlugin(); + } + + lt_dlexit(); + return 0; +} diff --git a/src/sound/sound.h b/src/sound/sound.h index 598ffe3..1bf9ae5 100644 --- a/src/sound/sound.h +++ b/src/sound/sound.h @@ -26,7 +26,7 @@ #include -#include +#include /*! * Maximum possible audio volume @@ -145,13 +145,10 @@ enum SoundNext * @brief Sound plugin interface * */ -class CSoundInterface : public CPlugin +class CSoundInterface : public CPluginInterface { public: - CSoundInterface() { - //CInstanceManager::getInstance().AddInstance(CLASS_SOUND, this); - //m_iMan->AddInstance(CLASS_SOUND, this); - }; + CSoundInterface() {}; virtual ~CSoundInterface() = 0; /** Function to initialize sound device -- cgit v1.2.3-1-g7c22 From 61bfb22f27f5216f989c023a5e39fad7e356d2d6 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Fri, 3 Aug 2012 23:23:13 +0200 Subject: Basic font rendering - added basic font rendering - minor refactoring & fixes --- src/CMakeLists.txt | 1 + src/app/app.cpp | 54 ++--- src/app/app.h | 6 - src/graphics/core/device.h | 9 +- src/graphics/engine/engine.cpp | 148 +++++++----- src/graphics/engine/engine.h | 31 ++- src/graphics/engine/text.cpp | 477 ++++++++++++++++++++++++++++++++++++++- src/graphics/engine/text.h | 267 ++++++++++++++++++---- src/graphics/opengl/gldevice.cpp | 39 ++-- src/graphics/opengl/gldevice.h | 5 +- src/math/const.h | 11 +- src/math/func.h | 8 + src/math/geometry.h | 4 +- src/math/intsize.h | 15 +- src/math/size.h | 9 + 15 files changed, 895 insertions(+), 189 deletions(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9bcd288..25a576e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -176,6 +176,7 @@ graphics/opengl/gldevice.cpp set(LIBS ${SDL_LIBRARY} ${SDLIMAGE_LIBRARY} +${SDLTTF_LIBRARY} ${OPENGL_LIBRARY} ${PNG_LIBRARIES} ${OPTIONAL_LIBS} diff --git a/src/app/app.cpp b/src/app/app.cpp index d20232d..3681172 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -122,6 +122,7 @@ bool CApplication::ParseArguments(int argc, char *argv[]) { waitDataDir = false; m_dataPath = arg; + continue; } if (arg == "-debug") @@ -153,10 +154,6 @@ bool CApplication::Create() // Temporarily -- only in windowed mode m_deviceConfig.fullScreen = false; - // Create the 3D engine - m_engine = new Gfx::CEngine(m_iMan, this); - - /* // Create the sound instance. m_sound = new CSound(m_iMan); @@ -224,20 +221,15 @@ bool CApplication::Create() return false; } + // Create the 3D engine + m_engine = new Gfx::CEngine(m_iMan, this); + m_engine->SetDevice(m_device); - if (! m_engine->Create() ) - { - SystemDialog( SDT_ERROR, "COLOBT - Fatal Error", - std::string("Error in CEngine::Create() :\n") + - std::string(m_engine->GetError()) ); - m_exitCode = 1; - return false; - } - if (! m_engine->AfterDeviceSetInit() ) + if (! m_engine->Create() ) { SystemDialog( SDT_ERROR, "COLOBT - Fatal Error", - std::string("Error in CEngine::AfterDeviceSetInit() :\n") + + std::string("Error in CEngine::Init() :\n") + std::string(m_engine->GetError()) ); m_exitCode = 1; return false; @@ -315,8 +307,7 @@ void CApplication::Destroy() if (m_engine != NULL) { - if (m_engine->GetWasInit()) - m_engine->Destroy(); + m_engine->Destroy(); delete m_engine; m_engine = NULL; @@ -324,8 +315,7 @@ void CApplication::Destroy() if (m_device != NULL) { - if (m_device->GetWasInit()) - m_device->Destroy(); + m_device->Destroy(); delete m_device; m_device = NULL; @@ -616,21 +606,6 @@ PressState TranslatePressState(unsigned char state) return STATE_RELEASED; } -/** Conversion of the position of the mouse from window coords to interface coords: - - x: 0=left, 1=right - - y: 0=down, 1=up */ -Math::Point CApplication::WindowToInterfaceCoords(Math::IntPoint pos) -{ - return Math::Point( static_cast(pos.x) / static_cast(m_deviceConfig.size.w), - 1.0f - static_cast(pos.y) / static_cast(m_deviceConfig.size.h) ); -} - -Math::IntPoint CApplication::InterfaceToWindowCoords(Math::Point pos) -{ - return Math::IntPoint(static_cast(pos.x * m_deviceConfig.size.w), - static_cast((1.0f - pos.y) * m_deviceConfig.size.h)); -} - /** The SDL event parsed is stored internally. If event is not available or is not understood, returned event is of type EVENT_NULL. */ Event CApplication::ParseEvent() @@ -666,14 +641,16 @@ Event CApplication::ParseEvent() event.mouseButton.button = m_private->currentEvent.button.button; event.mouseButton.state = TranslatePressState(m_private->currentEvent.button.state); - event.mouseButton.pos = WindowToInterfaceCoords(Math::IntPoint(m_private->currentEvent.button.x, m_private->currentEvent.button.y)); + event.mouseButton.pos = m_engine->WindowToInterfaceCoords( + Math::IntPoint(m_private->currentEvent.button.x, m_private->currentEvent.button.y)); } else if (m_private->currentEvent.type == SDL_MOUSEMOTION) { event.type = EVENT_MOUSE_MOVE; event.mouseMove.state = TranslatePressState(m_private->currentEvent.button.state); - event.mouseMove.pos = WindowToInterfaceCoords(Math::IntPoint(m_private->currentEvent.button.x, m_private->currentEvent.button.y)); + event.mouseMove.pos = m_engine->WindowToInterfaceCoords( + Math::IntPoint(m_private->currentEvent.button.x, m_private->currentEvent.button.y)); } else if (m_private->currentEvent.type == SDL_JOYAXISMOTION) { @@ -792,6 +769,11 @@ void CApplication::StepSimulation(float rTime) // TODO } +Gfx::GLDeviceConfig CApplication::GetVideoConfig() +{ + return m_deviceConfig; +} + VideoQueryResult CApplication::GetVideoResolutionList(std::vector &resolutions, bool fullScreen, bool resizeable) { @@ -891,7 +873,7 @@ bool CApplication::GetSystemMouseVisibile() void CApplication::SetSystemMousePos(Math::Point pos) { - Math::IntPoint windowPos = InterfaceToWindowCoords(pos); + Math::IntPoint windowPos = m_engine->InterfaceToWindowCoords(pos); SDL_WarpMouse(windowPos.x, windowPos.y); m_systemMousePos = pos; } diff --git a/src/app/app.h b/src/app/app.h index 483aa55..bba55b2 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -25,7 +25,6 @@ #include "graphics/core/device.h" #include "graphics/engine/engine.h" #include "graphics/opengl/gldevice.h" -#include "math/intsize.h" #include #include @@ -206,11 +205,6 @@ protected: //! Closes the joystick device void CloseJoystick(); - //! Converts window coords to interface coords - Math::Point WindowToInterfaceCoords(Math::IntPoint pos); - //! Converts the interface coords to window coords - Math::IntPoint InterfaceToWindowCoords(Math::Point pos); - protected: //! Instance manager CInstanceManager* m_iMan; diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h index c10b853..3ab86dd 100644 --- a/src/graphics/core/device.h +++ b/src/graphics/core/device.h @@ -32,6 +32,7 @@ class CImage; +struct ImageData; namespace Gfx { @@ -279,8 +280,6 @@ public: //! Destroys the device, releasing every acquired resource virtual void Destroy() = 0; - //! Returns whether the device has been initialized - virtual bool GetWasInit() = 0; //! Returns the last encountered error virtual std::string GetError() = 0; @@ -317,6 +316,8 @@ public: //! Creates a texture from image; the image can be safely removed after that virtual Gfx::Texture CreateTexture(CImage *image, const Gfx::TextureCreateParams ¶ms) = 0; + //! Creates a texture from raw image data; image data can be freed after that + virtual Gfx::Texture CreateTexture(ImageData *data, const Gfx::TextureCreateParams ¶ms) = 0; //! Deletes a given texture, freeing it from video memory virtual void DestroyTexture(const Gfx::Texture &texture) = 0; //! Deletes all textures created so far @@ -324,8 +325,10 @@ public: //! Returns the maximum number of multitexture stages virtual int GetMaxTextureCount() = 0; - //! Sets the (multi)texture at given index + //! Sets the texture at given texture stage virtual void SetTexture(int index, const Gfx::Texture &texture) = 0; + //! Sets the texture image by ID at given texture stage + virtual void SetTexture(int index, unsigned int textureId) = 0; //! Returns the (multi)texture at given index virtual Gfx::Texture GetTexture(int index) = 0; //! Enables/disables the given texture stage diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index e544ee3..345a15c 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -25,6 +25,8 @@ #include "common/key.h" #include "common/logger.h" #include "graphics/core/device.h" +#include "graphics/engine/lightman.h" +#include "graphics/engine/text.h" #include "math/geometry.h" // Initial size of various vectors @@ -44,23 +46,21 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) { m_iMan = iMan; m_app = app; - m_device = NULL; - - m_wasInit = false; + m_device = nullptr; m_iMan = iMan; m_iMan->AddInstance(CLASS_ENGINE, this); m_app = app; - m_lightMan = NULL; - m_text = NULL; - m_particle = NULL; - m_water = NULL; - m_cloud = NULL; - m_lightning = NULL; - m_planet = NULL; - m_sound = NULL; - m_terrain = NULL; + m_lightMan = nullptr; + m_text = nullptr; + m_particle = nullptr; + m_water = nullptr; + m_cloud = nullptr; + m_lightning = nullptr; + m_planet = nullptr; + m_sound = nullptr; + m_terrain = nullptr; m_focus = 0.75f; m_baseTime = 0; @@ -178,95 +178,93 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) Gfx::CEngine::~CEngine() { - m_iMan = NULL; - m_app = NULL; - m_device = NULL; + m_iMan = nullptr; + m_app = nullptr; + m_device = nullptr; - m_sound = NULL; - m_terrain = NULL; + m_sound = nullptr; + m_terrain = nullptr; } -bool Gfx::CEngine::GetWasInit() +std::string Gfx::CEngine::GetError() { - return m_wasInit; + return m_error; } -std::string Gfx::CEngine::GetError() +void Gfx::CEngine::SetDevice(Gfx::CDevice *device) { - return m_error; + m_device = device; +} + +Gfx::CDevice* Gfx::CEngine::GetDevice() +{ + return m_device; } bool Gfx::CEngine::Create() { - m_wasInit = true; + m_size = m_lastSize = m_app->GetVideoConfig().size; - /*m_lightMan = new Gfx::CLight(m_iMan, this); + m_lightMan = new Gfx::CLightManager(m_iMan, this); m_text = new Gfx::CText(m_iMan, this); + /* TODO: m_particle = new Gfx::CParticle(m_iMan, this); m_water = new Gfx::CWater(m_iMan, this); m_cloud = new Gfx::CCloud(m_iMan, this); m_lightning = new Gfx::CLightning(m_iMan, this); m_planet = new Gfx::CPlanet(m_iMan, this);*/ + m_text->SetDevice(m_device); + if (! m_text->Create()) + { + m_error = std::string("Error creating CText: ") + m_text->GetError(); + return false; + } + + m_matWorldInterface.LoadIdentity(); m_matViewInterface.LoadIdentity(); Math::LoadOrthoProjectionMatrix(m_matProjInterface, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); + m_device->SetClearColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)); + + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); + + Gfx::TextureCreateParams params; + params.format = Gfx::TEX_IMG_RGB; + params.minFilter = Gfx::TEX_MIN_FILTER_NEAREST; + params.magFilter = Gfx::TEX_MAG_FILTER_NEAREST; + params.mipmap = false; + m_miceTexture = CreateTexture("mouse.png", params); + return true; } void Gfx::CEngine::Destroy() { - // TODO + m_text->Destroy(); - /*delete m_lightMan; - m_lightMan = NULL; + delete m_lightMan; + m_lightMan = nullptr; delete m_text; - m_text = NULL; + m_text = nullptr; + /* TODO: delete m_particle; - m_particle = NULL; + m_particle = nullptr; delete m_water; - m_water = NULL; + m_water = nullptr; delete m_cloud; - m_cloud = NULL; + m_cloud = nullptr; delete m_lightning; - m_lightning = NULL; + m_lightning = nullptr; delete m_planet; - m_planet = NULL;*/ - - m_wasInit = false; -} - -void Gfx::CEngine::SetDevice(Gfx::CDevice *device) -{ - m_device = device; -} - -Gfx::CDevice* Gfx::CEngine::GetDevice() -{ - return m_device; -} - -bool Gfx::CEngine::AfterDeviceSetInit() -{ - m_device->SetClearColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)); - - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); - - Gfx::TextureCreateParams params; - params.format = Gfx::TEX_IMG_RGB; - params.minFilter = Gfx::TEX_MIN_FILTER_NEAREST; - params.magFilter = Gfx::TEX_MAG_FILTER_NEAREST; - params.mipmap = false; - m_miceTexture = CreateTexture("mouse.png", params); - - return true; + m_planet = nullptr;*/ } void Gfx::CEngine::ResetAfterDeviceChanged() @@ -274,7 +272,6 @@ void Gfx::CEngine::ResetAfterDeviceChanged() // TODO } - Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName, const Gfx::TextureCreateParams ¶ms) { CImage img; @@ -610,9 +607,38 @@ bool Gfx::CEngine::DrawInterface() DrawMouse(); + m_text->DrawString("abcdefghijklmnopqrstuvwxyz ąęśćółńż", Gfx::FONT_COLOBOT, 15.0f, Math::Point(0.25f, 0.2f), 1.0f, 0); + return true; } +/** Conversion of the position of the mouse from window coords to interface coords: + - x: 0=left, 1=right + - y: 0=down, 1=up */ +Math::Point Gfx::CEngine::WindowToInterfaceCoords(Math::IntPoint pos) +{ + return Math::Point( static_cast(pos.x) / static_cast(m_size.w), + 1.0f - static_cast(pos.y) / static_cast(m_size.h) ); +} + +Math::IntPoint Gfx::CEngine::InterfaceToWindowCoords(Math::Point pos) +{ + return Math::IntPoint(static_cast(pos.x * m_size.w), + static_cast((1.0f - pos.y) * m_size.h)); +} + +Math::Size Gfx::CEngine::WindowToInterfaceSize(Math::IntSize size) +{ + return Math::Size( static_cast(size.w) / static_cast(m_size.w), + static_cast(size.h) / static_cast(m_size.h) ); +} + +Math::IntSize Gfx::CEngine::InterfaceToWindowSize(Math::Size size) +{ + return Math::IntSize(static_cast(size.w * m_size.w), + static_cast(size.h * m_size.h)); +} + void Gfx::CEngine::DrawMouse() { if (! m_mouseVisible) diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 25c5e5d..79844c6 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -29,6 +29,7 @@ #include "math/intsize.h" #include "math/matrix.h" #include "math/point.h" +#include "math/size.h" #include "math/vector.h" @@ -514,23 +515,18 @@ public: CEngine(CInstanceManager *iMan, CApplication *app); ~CEngine(); - //! Returns whether the device was initialized - bool GetWasInit(); //! Returns the last error encountered std::string GetError(); - //! Performs the first initialization, before a device was set - bool Create(); - //! Frees all resources before exit - void Destroy(); - //! Sets the device to be used void SetDevice(Gfx::CDevice *device); //! Returns the current device Gfx::CDevice* GetDevice(); - //! Performs initialization after a device was created and set - bool AfterDeviceSetInit(); + //! Performs the initialization; must be called after device was set + bool Create(); + //! Frees all resources before exit + void Destroy(); //! Resets some states and flushes textures after device was changed (e.g. resoulution changed) void ResetAfterDeviceChanged(); @@ -544,6 +540,17 @@ public: bool Render(); + //! Converts window coords to interface coords + Math::Point WindowToInterfaceCoords(Math::IntPoint pos); + //! Converts interface coords to window coords + Math::IntPoint InterfaceToWindowCoords(Math::Point pos); + + //! Converts window size to interface size + Math::Size WindowToInterfaceSize(Math::IntSize size); + //! Converts interface size to window size + Math::IntSize InterfaceToWindowSize(Math::Size size); + + bool WriteProfile(); void SetPause(bool pause); @@ -769,7 +776,8 @@ public: Math::Vector GetLookatPt(); float GetEyeDirH(); float GetEyeDirV(); - Math::Point GetDim(); + Math::IntPoint GetViewportSize(); + Math::IntPoint GetLastViewportSize(); void UpdateMatProj(); void ApplyChange(); @@ -903,8 +911,9 @@ protected: bool m_render; bool m_movieLock; - //! Current size of window + //! Current size of viewport Math::IntSize m_size; + //! Previous size of viewport Math::IntSize m_lastSize; std::vector m_objectTree; diff --git a/src/graphics/engine/text.cpp b/src/graphics/engine/text.cpp index 2a9543c..eea9fdb 100644 --- a/src/graphics/engine/text.cpp +++ b/src/graphics/engine/text.cpp @@ -19,5 +19,480 @@ #include "graphics/engine/text.h" +#include "app/app.h" +#include "common/image.h" +#include "common/iman.h" +#include "common/logger.h" +#include "common/stringutils.h" +#include "math/func.h" -// TODO implementation +#include +#include + + +namespace Gfx +{ + +/** + \struct CachedFont + \brief Base TTF font with UTF-8 char cache */ +struct CachedFont +{ + TTF_Font* font; + std::map cache; + + CachedFont() : font(nullptr) {} +}; + +}; + + + +Gfx::CText::CText(CInstanceManager *iMan, Gfx::CEngine* engine) +{ + m_iMan = iMan; + m_iMan->AddInstance(CLASS_TEXT, this); + + m_device = nullptr; + m_engine = engine; + + m_defaultSize = 12.0f; + m_fontPath = "fonts"; + + m_lastFontType = Gfx::FONT_COLOBOT; + m_lastFontSize = 0; + m_lastCachedFont = nullptr; +} + +Gfx::CText::~CText() +{ + m_iMan->DeleteInstance(CLASS_TEXT, this); + + m_iMan = nullptr; + m_device = nullptr; + m_engine = nullptr; +} + +bool Gfx::CText::Create() +{ + if (TTF_Init() != 0) + { + m_error = std::string("TTF_Init error: ") + std::string(TTF_GetError()); + return false; + } + + m_fonts[Gfx::FONT_COLOBOT] = new MultisizeFont("dvu_sans.ttf"); + m_fonts[Gfx::FONT_COLOBOT_BOLD] = new MultisizeFont("dvu_sans_bold.ttf"); + m_fonts[Gfx::FONT_COLOBOT_ITALIC] = new MultisizeFont("dvu_sans_italic.ttf"); + + m_fonts[Gfx::FONT_COURIER] = new MultisizeFont("dvu_sans_mono.ttf"); + m_fonts[Gfx::FONT_COURIER_BOLD] = new MultisizeFont("dvu_sans_mono_bold.ttf"); + + for (auto it = m_fonts.begin(); it != m_fonts.end(); ++it) + { + Gfx::FontType type = (*it).first; + CachedFont* cf = GetOrOpenFont(type, m_defaultSize); + if (cf == nullptr || cf->font == nullptr) + return false; + } + + return true; +} + +void Gfx::CText::Destroy() +{ + for (auto it = m_fonts.begin(); it != m_fonts.end(); ++it) + { + MultisizeFont* mf = (*it).second; + + for (auto jt = mf->fonts.begin(); jt != mf->fonts.end(); ++jt) + { + CachedFont* cf = (*jt).second; + + TTF_CloseFont(cf->font); + + cf->font = nullptr; + delete cf; + } + + mf->fonts.clear(); + delete mf; + } + + m_fonts.clear(); + + m_lastCachedFont = nullptr; + + TTF_Quit(); +} + +void Gfx::CText::SetDevice(Gfx::CDevice* device) +{ + m_device = device; +} + +std::string Gfx::CText::GetError() +{ + return m_error; +} + +void Gfx::CText::FlushCache() +{ + for (auto it = m_fonts.begin(); it != m_fonts.end(); ++it) + { + MultisizeFont *mf = (*it).second; + for (auto jt = mf->fonts.begin(); jt != mf->fonts.end(); ++jt) + { + CachedFont *f = (*jt).second; + f->cache.clear(); + } + } +} + +void Gfx::CText::DrawText(const std::string &text, const std::vector &format, + Math::Point pos, float width, Gfx::JustifyType justify, float size, + float stretch, int eol) +{ + // TODO +} + +void Gfx::CText::DrawText(const std::string &text, Gfx::FontType font, + Math::Point pos, float width, Gfx::JustifyType justify, float size, + float stretch, int eol) +{ + // TODO +} + +void Gfx::CText::SizeText(const std::string &text, const std::vector &format, + Math::Point pos, Gfx::JustifyType justify, float size, + Math::Point &start, Math::Point &end) +{ + // TODO +} + +void Gfx::CText::SizeText(const std::string &text, Gfx::FontType font, + Math::Point pos, Gfx::JustifyType justify, float size, + Math::Point &start, Math::Point &end) +{ + // TODO +} + +float Gfx::CText::GetAscent(Gfx::FontType font, float size) +{ + // TODO + return 0.0f; +} + +float Gfx::CText::GetDescent(Gfx::FontType font, float size) +{ + // TODO + return 0.0f; +} + +float Gfx::CText::GetHeight(Gfx::FontType font, float size) +{ + // TODO + return 0.0f; +} + + +float Gfx::CText::GetStringWidth(const std::string &text, + const std::vector &format, float size) +{ + // TODO + return 0.0f; +} + +float Gfx::CText::GetStringWidth(const std::string &text, Gfx::FontType font, float size) +{ + // TODO + return 0.0f; +} + +float Gfx::CText::GetCharWidth(int character, Gfx::FontType font, float size, float offset) +{ + // TODO + return 0.0f; +} + + +int Gfx::CText::Justify(const std::string &text, const std::vector &format, + float size, float width) +{ + // TODO + return 0; +} + +int Gfx::CText::Justify(const std::string &text, Gfx::FontType font, float size, float width) +{ + // TODO + return 0; +} + +int Gfx::CText::Detect(const std::string &text, const std::vector &format, + float size, float offset) +{ + // TODO + return 0; +} + +int Gfx::CText::Detect(const std::string &text, Gfx::FontType font, float size, float offset) +{ + // TODO + return 0; +} + +void Gfx::CText::DrawString(const std::string &text, const std::vector &format, + float size, Math::Point pos, float width, int eol) +{ + // TODO +} + +void Gfx::CText::DrawString(const std::string &text, Gfx::FontType font, + float size, Math::Point pos, float width, int eol) +{ + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetTextureEnabled(0, true); + + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_INV_SRC_ALPHA); + + unsigned int index = 0; + Math::Point screenPos = pos; + while (index < text.length()) + { + UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + index += len; + + DrawChar(ch, font, size, screenPos); + } +} + +void Gfx::CText::DrawColor(int color, float size, Math::Point pos, float width) +{ + // TODO !!! + /* + float h, u1, u2, v1, v2, dp; + int icon; + + int icon = -1; + switch (color) + { + case Gfx::FONT_COLOR_LINK: + icon = 9; + break; + case Gfx::FONT_COLOR_TOKEN: + icon = 4; + break; + case Gfx::FONT_COLOR_TYPE: + icon = 5; + break; + } + icon = -1; + if ( color == COLOR_LINK ) icon = 9; // blue + if ( color == COLOR_TOKEN ) icon = 4; // orange + if ( color == COLOR_TYPE ) icon = 5; // green + if ( color == COLOR_CONST ) icon = 8; // red + if ( color == COLOR_REM ) icon = 6; // magenta + if ( color == COLOR_KEY ) icon = 10; // gray + + if ( icon == -1 ) return; + + if ( color == COLOR_LINK ) + { + m_engine->SetState(D3DSTATENORMAL); + } + + Math::IntSize vsize = m_engine->GetViewportSize(); + if (vsize.h <= 768.0f) // 1024x768 or less? + h = 1.01f / dim.y; // 1 pixel + else // more than 1024x768? + h = 2.0f / dim.y; // 2 pixels + + Math::Point p1, p2; + p1.x = pos.x; + p2.x = pos.x + width; + + if (color == Gfx::FONT_COLOR_LINK) + { + p1.y = pos.y; + p2.y = pos.y + h; // just emphasized + } + else + { + p1.y = pos.y; + p2.y = pos.y + (16.0f/256.0f)*(size/20.0f); + } + + u1 = (16.0f/256.0f)*(icon%16); + v1 = (240.0f/256.0f); + u2 = (16.0f/256.0f)+u1; + v2 = (16.0f/256.0f)+v1; + + dp = 0.5f/256.0f; + u1 += dp; + v1 += dp; + u2 -= dp; + v2 -= dp; + + Math::Vector n(0.0f, 0.0f, -1.0f); // normal + + Gfx::Vertex quad[] = + { + Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), n, Math::Point(u1, v2)), + Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), n, Math::Point(u1, v1)), + Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(u2, v2)), + Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(u2, v1)), + }; + + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); + m_engine->AddStatisticTriangle(2); + + if (color == Gfx::FONT_COLOR_LINK) + m_engine->SetState(Gfx::ENG_RSTATE_TTEXTURE_WHITE);*/ +} + +void Gfx::CText::DrawChar(UTF8Char character, Gfx::FontType font, float size, Math::Point &pos) +{ + CachedFont* cf = GetOrOpenFont(font, size); + + if (cf == nullptr) + return; + + auto it = cf->cache.find(character); + CharTexture tex; + if (it != cf->cache.end()) + { + tex = (*it).second; + } + else + { + char str[] = { character.c1, character.c2, character.c3, '\0' }; + tex = CreateCharTexture(str, cf); + + if (tex.id == 0) // invalid + return; + + cf->cache[character] = tex; + } + + Math::Vector n(0.0f, 0.0f, -1.0f); // normal + + Gfx::Vertex quad[4] = + { + Gfx::Vertex(Math::Vector(pos.x, pos.y + tex.charSize.h, 0.0f), + n, Math::Point(0.0f, 0.0f)), + Gfx::Vertex(Math::Vector(pos.x, pos.y + tex.charSize.h - tex.texSize.h, 0.0f), + n, Math::Point(0.0f, 1.0f)), + Gfx::Vertex(Math::Vector(pos.x + tex.texSize.w, pos.y + tex.charSize.h, 0.0f), + n, Math::Point(1.0f, 0.0f)), + Gfx::Vertex(Math::Vector(pos.x + tex.texSize.w, pos.y + tex.charSize.h - tex.texSize.h, 0.0f), + n, Math::Point(1.0f, 1.0f)) + }; + + m_device->SetTexture(0, tex.id); + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); + + pos.x += tex.charSize.w; +} + +Gfx::CachedFont* Gfx::CText::GetOrOpenFont(Gfx::FontType font, float size) +{ + // TODO: sizing + int pointSize = static_cast(size); + + if (m_lastCachedFont != nullptr) + { + if (m_lastFontType == font && m_lastFontSize == pointSize) + return m_lastCachedFont; + } + + auto it = m_fonts.find(font); + if (it == m_fonts.end()) + { + m_error = std::string("Invalid font type ") + StrUtils::ToString(static_cast(font)); + return nullptr; + } + + MultisizeFont* mf = (*it).second; + + auto jt = mf->fonts.find(pointSize); + if (jt != mf->fonts.end()) + { + m_lastCachedFont = (*jt).second; + m_lastFontType = font; + m_lastFontSize = pointSize; + return m_lastCachedFont; + } + + std::string path = CApplication::GetInstance().GetDataFilePath(m_fontPath, mf->fileName); + + m_lastCachedFont = new CachedFont(); + m_lastCachedFont->font = TTF_OpenFont(path.c_str(), pointSize); + if (m_lastCachedFont->font == nullptr) + m_error = std::string("TTF_OpenFont error ") + std::string(TTF_GetError()); + + mf->fonts[pointSize] = m_lastCachedFont; + + return m_lastCachedFont; +} + +Gfx::CharTexture Gfx::CText::CreateCharTexture(const char* str, Gfx::CachedFont* font) +{ + CharTexture texture; + + SDL_Surface* textSurface = nullptr; + SDL_Color white = {255, 255, 255, 0}; + textSurface = TTF_RenderUTF8_Blended(font->font, str, white); + + if (textSurface == nullptr) + { + m_error = "TTF_Render error"; + return texture; + } + + int w = Math::NextPowerOfTwo(textSurface->w); + int h = Math::NextPowerOfTwo(textSurface->h); + + textSurface->flags = textSurface->flags & (~SDL_SRCALPHA); + SDL_Surface* textureSurface = SDL_CreateRGBSurface(0, w, h, 32, 0x00ff0000, 0x0000ff00, + 0x000000ff, 0xff000000); + SDL_BlitSurface(textSurface, NULL, textureSurface, NULL); + + ImageData data; + data.surface = textureSurface; + + Gfx::TextureCreateParams createParams; + createParams.format = Gfx::TEX_IMG_RGBA; + createParams.minFilter = Gfx::TEX_MIN_FILTER_NEAREST; + createParams.magFilter = Gfx::TEX_MAG_FILTER_NEAREST; + createParams.mipmap = false; + + Gfx::Texture tex = m_device->CreateTexture(&data, createParams); + + data.surface = nullptr; + + SDL_FreeSurface(textSurface); + SDL_FreeSurface(textureSurface); + + if (! tex.valid) + { + m_error = "Texture create error"; + return texture; + } + + texture.id = tex.id; + texture.texSize = m_engine->WindowToInterfaceSize(Math::IntSize(textureSurface->w, textureSurface->h)); + texture.charSize = m_engine->WindowToInterfaceSize(Math::IntSize(textSurface->w, textSurface->h)); + + return texture; +} diff --git a/src/graphics/engine/text.h b/src/graphics/engine/text.h index c2de220..19d9882 100644 --- a/src/graphics/engine/text.h +++ b/src/graphics/engine/text.h @@ -19,95 +19,268 @@ #pragma once -#include "graphics/engine/engine.h" -#include "graphics/core/device.h" #include "math/point.h" +#include "math/size.h" +#include +#include class CInstanceManager; - namespace Gfx { -const float SMALLFONT = 10.0f; -const float BIGFONT = 15.0f; +class CEngine; +class CDevice; + +//! Standard small font size +const float FONT_SIZE_SMALL = 10.0f; +//! Standard big font size +const float FONT_SIZE_BIG = 15.0f; + +/** + \enum TextAlignType + \brief Type of text alignment */ +enum JustifyType +{ + TEXT_ALIGN_RIGHT, + TEXT_ALIGN_LEFT, + TEXT_ALIGN_CENTER +}; -const float NORMSTRETCH = 0.8f; +/* Font meta char constants */ +//! Type used for font character metainfo +typedef short FontMetaChar; +/** + \enum FontType + \brief Type of font + Bitmask in lower 4 bits (mask 0x00f) */ enum FontType { - FONT_COLOBOT = 0, - FONT_COURIER = 1, - FONT_BUTTON = 2, + //! Flag for bold font subtype + FONT_BOLD = 0x04, + //! Flag for italic font subtype + FONT_ITALIC = 0x08, + + //! Default colobot font used for interface + FONT_COLOBOT = 0x00, + //! Alias for bold colobot font + FONT_COLOBOT_BOLD = FONT_COLOBOT | FONT_BOLD, + //! Alias for italic colobot font + FONT_COLOBOT_ITALIC = FONT_COLOBOT | FONT_ITALIC, + + //! Courier (monospace) font used mainly in code editor (only regular & bold) + FONT_COURIER = 0x01, + //! Alias for bold courier font + FONT_COURIER_BOLD = FONT_COURIER | FONT_BOLD, + + // 0x02 left for possible another font + + //! Pseudo-font loaded from textures for buttons, icons, etc. + FONT_BUTTON = 0x03, }; +/** + \enum FontTitle + \brief Size of font title + + Bitmask in 2 bits left shifted 4 (mask 0x030) */ enum FontTitle { - TITLE_BIG = 0x04, - TITLE_NORM = 0x08, - TITLE_LITTLE = 0x0c, + FONT_TITLE_BIG = 0x01 << 4, + FONT_TITLE_NORM = 0x02 << 4, + FONT_TITLE_LITTLE = 0x03 << 4, }; +/** + \enum FontColor + \brief Font color type (?) + + Bitmask in 3 bits left shifted 6 (mask 0x1c0) */ enum FontColor { - COLOR_LINK = 0x10, - COLOR_TOKEN = 0x20, - COLOR_TYPE = 0x30, - COLOR_CONST = 0x40, - COLOR_REM = 0x50, - COLOR_KEY = 0x60, - COLOR_TABLE = 0x70, + FONT_COLOR_LINK = 0x01 << 6, + FONT_COLOR_TOKEN = 0x02 << 6, + FONT_COLOR_TYPE = 0x03 << 6, + FONT_COLOR_CONST = 0x04 << 6, + FONT_COLOR_REM = 0x05 << 6, + FONT_COLOR_KEY = 0x06 << 6, + FONT_COLOR_TABLE = 0x07 << 6, }; -const short FONT_MASK = 0x03; -const short TITLE_MASK = 0x0c; -const short COLOR_MASK = 0x70; -const short IMAGE_MASK = 0x80; +/** + \enum FontMask + \brief Masks in FontMetaChar for different attributes */ +enum FontMask +{ + //! Mask for FontType + FONT_MASK_FONT = 0x00f, + //! Mask for FontTitle + FONT_MASK_TITLE = 0x030, + //! Mask for FontColor + FONT_MASK_COLOR = 0x1c0, + //! Mask for image bit + FONT_MASK_IMAGE = 0x200 +}; + + +/** + \struct UTF8Char + \brief UTF-8 character in font cache + + Only 3-byte chars are supported */ +struct UTF8Char +{ + char c1, c2, c3; + + explicit UTF8Char(char ch1 = '\0', char ch2 = '\0', char ch3 = '\0') + : c1(ch1), c2(ch2), c3(ch3) {} + + inline bool operator<(const UTF8Char &other) const + { + if (c1 < other.c1) + return true; + else if (c1 > other.c1) + return false; + if (c2 < other.c2) + return true; + else if (c2 > other.c2) + return false; + return c3 < other.c3; + } + + inline bool operator==(const UTF8Char &other) const + { + return c1 == other.c1 && c2 == other.c2 && c3 == other.c3; + } +}; -class CText { +/** + \struct CharTexture + \brief Texture of font character */ +struct CharTexture +{ + unsigned int id; + Math::Size texSize; + Math::Size charSize; + + CharTexture() : id(0) {} +}; + +// Definition is private - in text.cpp +struct CachedFont; + +/** + \struct MultisizeFont + \brief Font with multiple possible sizes */ +struct MultisizeFont +{ + std::string fileName; + std::map fonts; + + MultisizeFont(const std::string &fn) + : fileName(fn) {} +}; + +/** + \class CText + \brief Text rendering engine + + ... */ +class CText +{ public: CText(CInstanceManager *iMan, Gfx::CEngine* engine); ~CText(); + //! Sets the device to be used void SetDevice(Gfx::CDevice *device); - void DrawText(char *string, char *format, int len, Math::Point pos, float width, int justif, float size, float stretch, int eol); - void DrawText(char *string, char *format, Math::Point pos, float width, int justif, float size, float stretch, int eol); - void DrawText(char *string, int len, Math::Point pos, float width, int justif, float size, float stretch, FontType font, int eol); - void DrawText(char *string, Math::Point pos, float width, int justif, float size, float stretch, FontType font, int eol); - void DimText(char *string, char *format, int len, Math::Point pos, int justif, float size, float stretch, Math::Point &start, Math::Point &end); - void DimText(char *string, char *format, Math::Point pos, int justif, float size, float stretch, Math::Point &start, Math::Point &end); - void DimText(char *string, int len, Math::Point pos, int justif, float size, float stretch, FontType font, Math::Point &start, Math::Point &end); - void DimText(char *string, Math::Point pos, int justif, float size, float stretch, FontType font, Math::Point &start, Math::Point &end); + //! Returns the last encountered error + std::string GetError(); - float RetAscent(float size, FontType font); - float RetDescent(float size, FontType font); - float RetHeight(float size, FontType font); + //! Initializes the font engine; must be called after SetDevice() + bool Create(); + //! Frees resources before exit + void Destroy(); - float RetStringWidth(char *string, char *format, int len, float size, float stretch); - float RetStringWidth(char *string, int len, float size, float stretch, FontType font); - float RetCharWidth(int character, float offset, float size, float stretch, FontType font); + //! Flushes cached textures + void FlushCache(); - int Justif(char *string, char *format, int len, float width, float size, float stretch); - int Justif(char *string, int len, float width, float size, float stretch, FontType font); - int Detect(char *string, char *format, int len, float offset, float size, float stretch); - int Detect(char *string, int len, float offset, float size, float stretch, FontType font); + //! Draws text (multi-format) + void DrawText(const std::string &text, const std::vector &format, + Math::Point pos, float width, Gfx::JustifyType justify, float size, + float stretch, int eol); + //! Draws text (one font) + void DrawText(const std::string &text, Gfx::FontType font, + Math::Point pos, float width, Gfx::JustifyType justify, float size, + float stretch, int eol); -protected: - void DrawString(char *string, char *format, int len, Math::Point pos, float width, float size, float stretch, int eol); - void DrawString(char *string, int len, Math::Point pos, float width, float size, float stretch, FontType font, int eol); - void DrawColor(Math::Point pos, float size, float width, int color); - void DrawChar(int character, Math::Point pos, float size, float stretch, FontType font); + //! Calculates dimensions for text (multi-format) + void SizeText(const std::string &text, const std::vector &format, + Math::Point pos, Gfx::JustifyType justify, float size, + Math::Point &start, Math::Point &end); + //! Calculates dimensions for text (one font) + void SizeText(const std::string &text, Gfx::FontType font, + Math::Point pos, Gfx::JustifyType justify, float size, + Math::Point &start, Math::Point &end); + + //! Returns the ascent font metric + float GetAscent(Gfx::FontType font, float size); + //! Returns the descent font metric + float GetDescent(Gfx::FontType font, float size); + //! Returns the height font metric + float GetHeight(Gfx::FontType font, float size); + + //! Returns width of string (multi-format) + float GetStringWidth(const std::string &text, + const std::vector &format, float size); + //! Returns width of string (single font) + float GetStringWidth(const std::string &text, Gfx::FontType font, float size); + //! Returns width of single character + float GetCharWidth(int character, Gfx::FontType font, float size, float offset); + + //! Justifies a line of text (multi-format) + int Justify(const std::string &text, const std::vector &format, + float size, float width); + //! Justifies a line of text (one font) + int Justify(const std::string &text, Gfx::FontType font, float size, float width); + + //! Returns the most suitable position to a given offset (multi-format) + int Detect(const std::string &text, const std::vector &format, + float size, float offset); + //! Returns the most suitable position to a given offset (one font) + int Detect(const std::string &text, Gfx::FontType font, float size, float offset); + +public: // for testing! + Gfx::CachedFont* GetOrOpenFont(Gfx::FontType type, float size); + Gfx::CharTexture CreateCharTexture(const char* utf8Char, Gfx::CachedFont* font); + + void DrawString(const std::string &text, const std::vector &format, + float size, Math::Point pos, float width, int eol); + void DrawString(const std::string &text, Gfx::FontType font, + float size, Math::Point pos, float width, int eol); + void DrawColor(int color, float size, Math::Point pos, float width); + void DrawChar(UTF8Char character, Gfx::FontType font, float size, Math::Point &pos); protected: CInstanceManager* m_iMan; Gfx::CEngine* m_engine; Gfx::CDevice* m_device; + std::string m_error; + float m_defaultSize; + std::string m_fontPath; + + std::map m_fonts; + + Gfx::FontType m_lastFontType; + int m_lastFontSize; + Gfx::CachedFont* m_lastCachedFont; }; }; // namespace Gfx diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index 3a255f4..cef372f 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -64,7 +64,6 @@ void Gfx::GLDeviceConfig::LoadDefault() Gfx::CGLDevice::CGLDevice(const Gfx::GLDeviceConfig &config) { m_config = config; - m_wasInit = false; m_lighting = false; m_texturing = false; } @@ -74,11 +73,6 @@ Gfx::CGLDevice::~CGLDevice() { } -bool Gfx::CGLDevice::GetWasInit() -{ - return m_wasInit; -} - std::string Gfx::CGLDevice::GetError() { return m_error; @@ -110,8 +104,6 @@ bool Gfx::CGLDevice::Create() /* NOTE: when not using GLEW, extension testing is not performed, as it is assumed that glext.h is up-to-date and the OpenGL shared library has the required functions present. */ - m_wasInit = true; - // This is mostly done in all modern hardware by default // DirectX doesn't even allow the option to turn off perspective correction anymore // So turn it on permanently @@ -158,8 +150,6 @@ void Gfx::CGLDevice::Destroy() m_currentTextures.clear(); m_texturesEnabled.clear(); m_textureStageParams.clear(); - - m_wasInit = false; } void Gfx::CGLDevice::ConfigChanged(const Gfx::GLDeviceConfig& newConfig) @@ -385,15 +375,20 @@ bool Gfx::CGLDevice::GetLightEnabled(int index) This struct must not be deleted in other way than through DeleteTexture() */ Gfx::Texture Gfx::CGLDevice::CreateTexture(CImage *image, const Gfx::TextureCreateParams ¶ms) { - Gfx::Texture result; - ImageData *data = image->GetData(); if (data == NULL) { m_error = "Invalid texture data"; - return result; // invalid texture + return Gfx::Texture(); // invalid texture } + return CreateTexture(data, params); +} + +Gfx::Texture Gfx::CGLDevice::CreateTexture(ImageData *data, const Gfx::TextureCreateParams ¶ms) +{ + Gfx::Texture result; + result.valid = true; result.size.w = data->surface->w; result.size.h = data->surface->h; @@ -531,6 +526,24 @@ void Gfx::CGLDevice::SetTexture(int index, const Gfx::Texture &texture) glDisable(GL_TEXTURE_2D); } +void Gfx::CGLDevice::SetTexture(int index, unsigned int textureId) +{ + assert(index >= 0); + assert(index < static_cast( m_currentTextures.size() )); + + // Enable the given texture stage + glActiveTexture(GL_TEXTURE0 + index); + glEnable(GL_TEXTURE_2D); + + m_currentTextures[index].id = textureId; + + glBindTexture(GL_TEXTURE_2D, textureId); + + // Disable the stage if it is set so + if ( (! m_texturing) || (! m_texturesEnabled[index]) ) + glDisable(GL_TEXTURE_2D); +} + /** Returns the previously assigned texture or invalid texture if the given stage is not enabled. */ Gfx::Texture Gfx::CGLDevice::GetTexture(int index) diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h index 1864000..a41c41c 100644 --- a/src/graphics/opengl/gldevice.h +++ b/src/graphics/opengl/gldevice.h @@ -73,7 +73,6 @@ public: CGLDevice(const Gfx::GLDeviceConfig &config); virtual ~CGLDevice(); - virtual bool GetWasInit(); virtual std::string GetError(); virtual bool Create(); @@ -100,11 +99,13 @@ public: virtual bool GetLightEnabled(int index); virtual Gfx::Texture CreateTexture(CImage *image, const Gfx::TextureCreateParams ¶ms); + virtual Gfx::Texture CreateTexture(ImageData *data, const Gfx::TextureCreateParams ¶ms); virtual void DestroyTexture(const Gfx::Texture &texture); virtual void DestroyAllTextures(); virtual int GetMaxTextureCount(); virtual void SetTexture(int index, const Gfx::Texture &texture); + virtual void SetTexture(int index, unsigned int textureId); virtual Gfx::Texture GetTexture(int index); virtual void SetTextureEnabled(int index, bool enabled); virtual bool GetTextureEnabled(int index); @@ -163,8 +164,6 @@ private: private: //! Current config Gfx::GLDeviceConfig m_config; - //! Was initialized? - bool m_wasInit; //! Last encountered error std::string m_error; diff --git a/src/math/const.h b/src/math/const.h index dd7ab0f..b08a400 100644 --- a/src/math/const.h +++ b/src/math/const.h @@ -20,6 +20,8 @@ #pragma once +#include + // Math module namespace namespace Math @@ -30,12 +32,12 @@ namespace Math const float TOLERANCE = 1e-6f; //! Very small number (used in testing/returning some values) -const float VERY_SMALL = 1e-6f; +const float VERY_SMALL_NUM = 1e-6f; //! Very big number (used in testing/returning some values) -const float VERY_BIG = 1e6f; +const float VERY_BIG_NUM = 1e6f; //! Huge number -const float HUGE = 1.0e+38f; +const float HUGE_NUM = 1.0e+38f; //! PI const float PI = 3.14159265358979323846f; @@ -45,6 +47,9 @@ const float DEG_TO_RAD = 0.01745329251994329547f; //! Radians to degrees multiplier const float RAD_TO_DEG = 57.29577951308232286465f; +//! Natural logarithm of 2 +const float LOG_2 = log(2.0f); + /* @} */ // end of group }; // namespace Math diff --git a/src/math/func.h b/src/math/func.h index 2127d1a..e97d990 100644 --- a/src/math/func.h +++ b/src/math/func.h @@ -127,6 +127,14 @@ inline float Rand() return static_cast(rand()) / static_cast(RAND_MAX); } +//! Returns the next nearest power of two to \a x +inline int NextPowerOfTwo(int x) +{ + double logbase2 = log(static_cast(x)) / Math::LOG_2; + return static_cast(pow(2, ceil(logbase2)) + 0.5); +} + + //! Returns a normalized angle, that is in other words between 0 and 2 * PI inline float NormAngle(float angle) { diff --git a/src/math/geometry.h b/src/math/geometry.h index 61d1868..3a31ad6 100644 --- a/src/math/geometry.h +++ b/src/math/geometry.h @@ -45,9 +45,9 @@ inline float MidPoint(const Math::Point &a, const Math::Point &b, float px) if (IsEqual(a.x, b.x)) { if (a.y < b.y) - return HUGE; + return Math::HUGE_NUM; else - return -HUGE; + return -Math::HUGE_NUM; } return (b.y-a.y) * (px-a.x) / (b.x-a.x) + a.y; } diff --git a/src/math/intsize.h b/src/math/intsize.h index f4b2431..d53de85 100644 --- a/src/math/intsize.h +++ b/src/math/intsize.h @@ -20,6 +20,9 @@ #pragma once +#include "math/intpoint.h" + + // Math module namespace namespace Math { @@ -31,9 +34,9 @@ namespace Math struct IntSize { //! Width - int w; + long w; //! Height - int h; + long h; //! Constructs a zero size: (0,0) inline IntSize() @@ -42,7 +45,7 @@ struct IntSize } //! Constructs a size from given dimensions: (w,h) - inline explicit IntSize(int w, int h) + inline explicit IntSize(long w, long h) { this->w = w; this->h = h; @@ -53,6 +56,12 @@ struct IntSize { w = h = 0; } + + //! Converts Point to Size + inline static Math::IntSize FromIntPoint(Math::IntPoint p) + { + return Math::IntSize(p.x, p.y); + } }; // struct Size diff --git a/src/math/size.h b/src/math/size.h index 781b9a4..03cffaa 100644 --- a/src/math/size.h +++ b/src/math/size.h @@ -20,6 +20,9 @@ #pragma once +#include "math/point.h" + + // Math module namespace namespace Math { @@ -58,6 +61,12 @@ struct Size { w = h = 0.0f; } + + //! Converts Point to Size + inline static Math::Size FromPoint(Math::Point p) + { + return Math::Size(p.x, p.y); + } }; // struct Size -- cgit v1.2.3-1-g7c22 From f7e78b21e9655604ba6fba1d068a9bf7f00b85a5 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Mon, 6 Aug 2012 20:20:50 +0200 Subject: Font rendering - implemented rest of CText interface excluding some minor features --- src/common/stringutils.cpp | 10 +- src/graphics/engine/engine.cpp | 37 ++- src/graphics/engine/engine.h | 8 +- src/graphics/engine/text.cpp | 516 ++++++++++++++++++++++++++++++++--------- src/graphics/engine/text.h | 67 +++--- src/math/intpoint.h | 6 +- src/math/intsize.h | 6 +- 7 files changed, 501 insertions(+), 149 deletions(-) (limited to 'src') diff --git a/src/common/stringutils.cpp b/src/common/stringutils.cpp index 585bb46..12a3179 100644 --- a/src/common/stringutils.cpp +++ b/src/common/stringutils.cpp @@ -135,15 +135,11 @@ int StrUtils::Utf8CharSizeAt(const std::string &str, unsigned int pos) size_t StrUtils::Utf8StringLength(const std::string &str) { size_t result = 0; - for (unsigned int i = 0; i < str.size(); ++i) + unsigned int i = 0; + while (i < str.size()) { - char ch = str[i]; - if ((ch & 0x80) == 0) + i += Utf8CharSizeAt(str, i); ++result; - else if ((ch & 0xC0) == 0xC0) - result += 2; - else - result += 3; } return result; } diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 345a15c..c5d2a1d 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -447,6 +447,19 @@ void Gfx::CEngine::SetState(int state, Gfx::Color color) m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); m_device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);*/ } + else if (state & Gfx::ENG_RSTATE_TEXT) + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + + m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_INV_SRC_ALPHA); + } else // normal ? { m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); @@ -607,11 +620,33 @@ bool Gfx::CEngine::DrawInterface() DrawMouse(); - m_text->DrawString("abcdefghijklmnopqrstuvwxyz ąęśćółńż", Gfx::FONT_COLOBOT, 15.0f, Math::Point(0.25f, 0.2f), 1.0f, 0); + std::vector format; + for (int i = 0; i < 10; ++i) + format.push_back(Gfx::FONT_COLOBOT_BOLD | Gfx::FONT_HIGHLIGHT_CONST); + for (int i = 0; i < 10; ++i) + format.push_back(Gfx::FONT_COLOBOT_ITALIC | Gfx::FONT_HIGHLIGHT_KEY); + for (int i = 0; i < 10; ++i) + format.push_back(Gfx::FONT_COURIER | Gfx::FONT_HIGHLIGHT_LINK); + for (int i = 0; i < 5; ++i) + format.push_back(Gfx::FONT_COURIER_BOLD | Gfx::FONT_HIGHLIGHT_REM); + + m_text->DrawText("abcdefghijklmnopqrstuvwxyz ąęśćółńż", Gfx::FONT_COLOBOT, 15.0f, Math::Point(0.25f, 0.2f), 1.0f, Gfx::TEXT_ALIGN_LEFT, 0); + float h = m_text->GetHeight(Gfx::FONT_COLOBOT, 15.0f); + m_text->DrawText("abcdefghijklmnopqrstuvwxyz ąęśćółńż", format, 13.0f, Math::Point(0.25f, 0.2f - h), 1.0f, Gfx::TEXT_ALIGN_LEFT, 0); return true; } +Math::IntSize Gfx::CEngine::GetWindowSize() +{ + return m_size; +} + +Math::IntSize Gfx::CEngine::GetLastWindowSize() +{ + return m_lastSize; +} + /** Conversion of the position of the mouse from window coords to interface coords: - x: 0=left, 1=right - y: 0=down, 1=up */ diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 79844c6..3f7f4f2 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -408,7 +408,9 @@ enum EngineRenderState //! The transparent color (black = no) ENG_RSTATE_TCOLOR_BLACK = (1<<16), //! The transparent color (white = no) - ENG_RSTATE_TCOLOR_WHITE = (1<<17) + ENG_RSTATE_TCOLOR_WHITE = (1<<17), + //! Mode for rendering text + ENG_RSTATE_TEXT = (1<<18) }; @@ -776,8 +778,8 @@ public: Math::Vector GetLookatPt(); float GetEyeDirH(); float GetEyeDirV(); - Math::IntPoint GetViewportSize(); - Math::IntPoint GetLastViewportSize(); + Math::IntSize GetWindowSize(); + Math::IntSize GetLastWindowSize(); void UpdateMatProj(); void ApplyChange(); diff --git a/src/graphics/engine/text.cpp b/src/graphics/engine/text.cpp index eea9fdb..77515ad 100644 --- a/src/graphics/engine/text.cpp +++ b/src/graphics/engine/text.cpp @@ -150,118 +150,421 @@ void Gfx::CText::FlushCache() } void Gfx::CText::DrawText(const std::string &text, const std::vector &format, - Math::Point pos, float width, Gfx::JustifyType justify, float size, - float stretch, int eol) + float size, Math::Point pos, float width, Gfx::TextAlign align, + int eol) { - // TODO + float sw = 0.0f; + + if (align == Gfx::TEXT_ALIGN_CENTER) + { + sw = GetStringWidth(text, format, size); + if (sw > width) sw = width; + pos.x -= sw / 2.0f; + } + else if (align == Gfx::TEXT_ALIGN_RIGHT) + { + sw = GetStringWidth(text, format, size); + if (sw > width) sw = width; + pos.x -= sw; + } + + DrawString(text, format, size, pos, width, eol); } void Gfx::CText::DrawText(const std::string &text, Gfx::FontType font, - Math::Point pos, float width, Gfx::JustifyType justify, float size, - float stretch, int eol) + float size, Math::Point pos, float width, Gfx::TextAlign align, + int eol) { - // TODO + float sw = 0.0f; + + if (align == Gfx::TEXT_ALIGN_CENTER) + { + sw = GetStringWidth(text, font, size); + if (sw > width) sw = width; + pos.x -= sw / 2.0f; + } + else if (align == Gfx::TEXT_ALIGN_RIGHT) + { + sw = GetStringWidth(text, font, size); + if (sw > width) sw = width; + pos.x -= sw; + } + + DrawString(text, font, size, pos, width, eol); } void Gfx::CText::SizeText(const std::string &text, const std::vector &format, - Math::Point pos, Gfx::JustifyType justify, float size, + float size, Math::Point pos, Gfx::TextAlign align, Math::Point &start, Math::Point &end) { - // TODO + start = end = pos; + + float sw = GetStringWidth(text, format, size); + end.x += sw; + if (align == Gfx::TEXT_ALIGN_CENTER) + { + start.x -= sw/2.0f; + end.x -= sw/2.0f; + } + else if (align == Gfx::TEXT_ALIGN_RIGHT) + { + start.x -= sw; + end.x -= sw; + } + + start.y -= GetDescent(Gfx::FONT_COLOBOT, size); + end.y += GetAscent(Gfx::FONT_COLOBOT, size); } void Gfx::CText::SizeText(const std::string &text, Gfx::FontType font, - Math::Point pos, Gfx::JustifyType justify, float size, + float size, Math::Point pos, Gfx::TextAlign align, Math::Point &start, Math::Point &end) { - // TODO + start = end = pos; + + float sw = GetStringWidth(text, font, size); + end.x += sw; + if (align == Gfx::TEXT_ALIGN_CENTER) + { + start.x -= sw/2.0f; + end.x -= sw/2.0f; + } + else if (align == Gfx::TEXT_ALIGN_RIGHT) + { + start.x -= sw; + end.x -= sw; + } + + start.y -= GetDescent(font, size); + end.y += GetAscent(font, size); } float Gfx::CText::GetAscent(Gfx::FontType font, float size) { - // TODO - return 0.0f; + assert(font != Gfx::FONT_BUTTON); + + Gfx::CachedFont* cf = GetOrOpenFont(font, size); + assert(cf != nullptr); + Math::IntSize wndSize; + wndSize.h = TTF_FontAscent(cf->font); + Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.h; } float Gfx::CText::GetDescent(Gfx::FontType font, float size) { - // TODO - return 0.0f; + assert(font != Gfx::FONT_BUTTON); + + Gfx::CachedFont* cf = GetOrOpenFont(font, size); + assert(cf != nullptr); + Math::IntSize wndSize; + wndSize.h = TTF_FontDescent(cf->font); + Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.h; } float Gfx::CText::GetHeight(Gfx::FontType font, float size) { - // TODO - return 0.0f; + assert(font != Gfx::FONT_BUTTON); + + Gfx::CachedFont* cf = GetOrOpenFont(font, size); + assert(cf != nullptr); + Math::IntSize wndSize; + wndSize.h = TTF_FontHeight(cf->font); + Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.h; } float Gfx::CText::GetStringWidth(const std::string &text, const std::vector &format, float size) { - // TODO - return 0.0f; + assert(StrUtils::Utf8StringLength(text) == format.size()); + + float width = 0.0f; + unsigned int index = 0; + unsigned int fmtIndex = 0; + while (index < text.length()) + { + Gfx::FontType font = static_cast(format[fmtIndex] & Gfx::FONT_MASK_FONT); + + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + width += GetCharWidth(ch, font, size, width); + + index += len; + fmtIndex++; + } + + return width; } float Gfx::CText::GetStringWidth(const std::string &text, Gfx::FontType font, float size) { - // TODO - return 0.0f; + assert(font != Gfx::FONT_BUTTON); + + // TODO: special chars? + + Gfx::CachedFont* cf = GetOrOpenFont(font, size); + assert(cf != nullptr); + Math::IntSize wndSize; + TTF_SizeUTF8(cf->font, text.c_str(), &wndSize.w, &wndSize.h); + Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.w; } -float Gfx::CText::GetCharWidth(int character, Gfx::FontType font, float size, float offset) +float Gfx::CText::GetCharWidth(Gfx::UTF8Char ch, Gfx::FontType font, float size, float offset) { - // TODO - return 0.0f; + // TODO: if (font == Gfx::FONT_BUTTON) + if (font == Gfx::FONT_BUTTON) return 0.0f; + + // TODO: special chars? + // TODO: tab sizing + + Gfx::CachedFont* cf = GetOrOpenFont(font, size); + assert(cf != nullptr); + + Gfx::CharTexture tex; + auto it = cf->cache.find(ch); + if (it != cf->cache.end()) + tex = (*it).second; + else + tex = CreateCharTexture(ch, cf); + + return tex.charSize.w; } int Gfx::CText::Justify(const std::string &text, const std::vector &format, float size, float width) { - // TODO - return 0; + assert(StrUtils::Utf8StringLength(text) == format.size()); + + float pos = 0.0f; + int cut = 0; + unsigned int index = 0; + unsigned int fmtIndex = 0; + while (index < text.length()) + { + Gfx::FontType font = static_cast(format[fmtIndex] & Gfx::FONT_MASK_FONT); + + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + if (font != Gfx::FONT_BUTTON) + { + if (ch.c1 == '\n') + return index+1; + if (ch.c1 == ' ') + cut = index+1; + } + + pos += GetCharWidth(ch, font, size, pos); + if (pos > width) + { + if (cut == 0) return index; + else return cut; + } + + index += len; + fmtIndex++; + } + + return index; } int Gfx::CText::Justify(const std::string &text, Gfx::FontType font, float size, float width) { - // TODO - return 0; + assert(font != Gfx::FONT_BUTTON); + + float pos = 0.0f; + int cut = 0; + unsigned int index = 0; + while (index < text.length()) + { + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + index += len; + + if (ch.c1 == '\n') + return index+1; + + if (ch.c1 == ' ' ) + cut = index+1; + + pos += GetCharWidth(ch, font, size, pos); + if (pos > width) + { + if (cut == 0) return index; + else return cut; + } + } + + return index; } int Gfx::CText::Detect(const std::string &text, const std::vector &format, float size, float offset) { - // TODO - return 0; + assert(StrUtils::Utf8StringLength(text) == format.size()); + + float pos = 0.0f; + unsigned int index = 0; + unsigned int fmtIndex = 0; + while (index < text.length()) + { + Gfx::FontType font = static_cast(format[fmtIndex] & Gfx::FONT_MASK_FONT); + + // TODO: if (font == Gfx::FONT_BUTTON) + if (font == Gfx::FONT_BUTTON) continue; + + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + if (ch.c1 == '\n') + return index; + + float width = GetCharWidth(ch, font, size, pos); + if (offset <= pos + width/2.0f) + return index; + + pos += width; + index += len; + fmtIndex++; + } + + return index; } int Gfx::CText::Detect(const std::string &text, Gfx::FontType font, float size, float offset) { - // TODO - return 0; + assert(font != Gfx::FONT_BUTTON); + + float pos = 0.0f; + unsigned int index = 0; + while (index < text.length()) + { + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + index += len; + + if (ch.c1 == '\n') + return index; + + float width = GetCharWidth(ch, font, size, pos); + if (offset <= pos + width/2.0f) + return index; + + pos += width; + } + + return index; } void Gfx::CText::DrawString(const std::string &text, const std::vector &format, float size, Math::Point pos, float width, int eol) { - // TODO + assert(StrUtils::Utf8StringLength(text) == format.size()); + + m_engine->SetState(Gfx::ENG_RSTATE_TEXT); + + Gfx::FontType font = Gfx::FONT_COLOBOT; + float start = pos.x; + + unsigned int index = 0; + unsigned int fmtIndex = 0; + while (index < text.length()) + { + font = static_cast(format[fmtIndex] & Gfx::FONT_MASK_FONT); + + // TODO: if (font == Gfx::FONT_BUTTON) + if (font == Gfx::FONT_BUTTON) continue; + + Gfx::UTF8Char ch; + + int len = StrUtils::Utf8CharSizeAt(text, index); + if (len >= 1) + ch.c1 = text[index]; + if (len >= 2) + ch.c2 = text[index+1]; + if (len >= 3) + ch.c3 = text[index+2]; + + float offset = pos.x - start; + float cw = GetCharWidth(ch, font, size, offset); + if (offset + cw > width) // exceeds the maximum width? + { + // TODO: special end-of-line char + break; + } + + Gfx::FontHighlight hl = static_cast(format[fmtIndex] & Gfx::FONT_MASK_HIGHLIGHT); + if (hl != Gfx::FONT_HIGHLIGHT_NONE) + { + Math::Size charSize; + charSize.w = GetCharWidth(ch, font, size, offset); + charSize.h = GetHeight(font, size); + DrawHighlight(hl, pos, charSize); + } + + DrawChar(ch, font, size, pos); + + index += len; + fmtIndex++; + } + + // TODO: eol } void Gfx::CText::DrawString(const std::string &text, Gfx::FontType font, float size, Math::Point pos, float width, int eol) { - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); - m_device->SetTextureEnabled(0, true); + assert(font != Gfx::FONT_BUTTON); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); - m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_INV_SRC_ALPHA); + m_engine->SetState(Gfx::ENG_RSTATE_TEXT); unsigned int index = 0; - Math::Point screenPos = pos; while (index < text.length()) { - UTF8Char ch; + Gfx::UTF8Char ch; int len = StrUtils::Utf8CharSizeAt(text, index); if (len >= 1) @@ -273,56 +576,64 @@ void Gfx::CText::DrawString(const std::string &text, Gfx::FontType font, index += len; - DrawChar(ch, font, size, screenPos); + DrawChar(ch, font, size, pos); } } -void Gfx::CText::DrawColor(int color, float size, Math::Point pos, float width) +void Gfx::CText::DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Size size) { - // TODO !!! - /* - float h, u1, u2, v1, v2, dp; - int icon; + // Gradient colors + Gfx::Color grad[4]; + + // TODO: switch to alpha factors - int icon = -1; - switch (color) + switch (hl) { - case Gfx::FONT_COLOR_LINK: - icon = 9; + case Gfx::FONT_HIGHLIGHT_LINK: + grad[0] = grad[1] = grad[2] = grad[3] = Gfx::Color(0.0f, 0.0f, 1.0f, 0.5f); break; - case Gfx::FONT_COLOR_TOKEN: - icon = 4; + + case Gfx::FONT_HIGHLIGHT_TOKEN: + grad[0] = grad[1] = Gfx::Color(248.0f / 256.0f, 248.0f / 256.0f, 248.0f / 256.0f, 0.5f); + grad[2] = grad[3] = Gfx::Color(248.0f / 256.0f, 220.0f / 256.0f, 188.0f / 256.0f, 0.5f); break; - case Gfx::FONT_COLOR_TYPE: - icon = 5; + + case Gfx::FONT_HIGHLIGHT_TYPE: + grad[0] = grad[1] = Gfx::Color(248.0f / 256.0f, 248.0f / 256.0f, 248.0f / 256.0f, 0.5f); + grad[2] = grad[3] = Gfx::Color(169.0f / 256.0f, 234.0f / 256.0f, 169.0f / 256.0f, 0.5f); break; - } - icon = -1; - if ( color == COLOR_LINK ) icon = 9; // blue - if ( color == COLOR_TOKEN ) icon = 4; // orange - if ( color == COLOR_TYPE ) icon = 5; // green - if ( color == COLOR_CONST ) icon = 8; // red - if ( color == COLOR_REM ) icon = 6; // magenta - if ( color == COLOR_KEY ) icon = 10; // gray - if ( icon == -1 ) return; + case Gfx::FONT_HIGHLIGHT_CONST: + grad[0] = grad[1] = Gfx::Color(248.0f / 256.0f, 248.0f / 256.0f, 248.0f / 256.0f, 0.5f); + grad[2] = grad[3] = Gfx::Color(248.0f / 256.0f, 176.0f / 256.0f, 169.0f / 256.0f, 0.5f); + break; - if ( color == COLOR_LINK ) - { - m_engine->SetState(D3DSTATENORMAL); + case Gfx::FONT_HIGHLIGHT_REM: + grad[0] = grad[1] = Gfx::Color(248.0f / 256.0f, 248.0f / 256.0f, 248.0f / 256.0f, 0.5f); + grad[2] = grad[3] = Gfx::Color(248.0f / 256.0f, 169.0f / 256.0f, 248.0f / 256.0f, 0.5f); + break; + + case Gfx::FONT_HIGHLIGHT_KEY: + grad[0] = grad[1] = grad[2] = grad[3] = + Gfx::Color(192.0f / 256.0f, 192.0f / 256.0f, 192.0f / 256.0f, 0.5f); + break; + + default: + return; } - Math::IntSize vsize = m_engine->GetViewportSize(); - if (vsize.h <= 768.0f) // 1024x768 or less? - h = 1.01f / dim.y; // 1 pixel - else // more than 1024x768? - h = 2.0f / dim.y; // 2 pixels + Math::IntSize vsize = m_engine->GetWindowSize(); + float h = 0.0f; + if (vsize.h <= 768.0f) // 1024x768 or less? + h = 1.01f / vsize.h; // 1 pixel + else // more than 1024x768? + h = 2.0f / vsize.h; // 2 pixels Math::Point p1, p2; p1.x = pos.x; - p2.x = pos.x + width; + p2.x = pos.x + size.w; - if (color == Gfx::FONT_COLOR_LINK) + if (hl == Gfx::FONT_HIGHLIGHT_LINK) { p1.y = pos.y; p2.y = pos.y + h; // just emphasized @@ -330,45 +641,38 @@ void Gfx::CText::DrawColor(int color, float size, Math::Point pos, float width) else { p1.y = pos.y; - p2.y = pos.y + (16.0f/256.0f)*(size/20.0f); + p2.y = pos.y + size.h; } - u1 = (16.0f/256.0f)*(icon%16); - v1 = (240.0f/256.0f); - u2 = (16.0f/256.0f)+u1; - v2 = (16.0f/256.0f)+v1; - - dp = 0.5f/256.0f; - u1 += dp; - v1 += dp; - u2 -= dp; - v2 -= dp; + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); - Math::Vector n(0.0f, 0.0f, -1.0f); // normal - - Gfx::Vertex quad[] = + Gfx::VertexCol quad[] = { - Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), n, Math::Point(u1, v2)), - Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), n, Math::Point(u1, v1)), - Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(u2, v2)), - Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(u2, v1)), + Gfx::VertexCol(Math::Vector(p1.x, p1.y, 0.0f), grad[3]), + Gfx::VertexCol(Math::Vector(p2.x, p1.y, 0.0f), grad[2]), + Gfx::VertexCol(Math::Vector(p1.x, p2.y, 0.0f), grad[0]), + Gfx::VertexCol(Math::Vector(p2.x, p2.y, 0.0f), grad[1]) }; m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); m_engine->AddStatisticTriangle(2); - if (color == Gfx::FONT_COLOR_LINK) - m_engine->SetState(Gfx::ENG_RSTATE_TTEXTURE_WHITE);*/ + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); } -void Gfx::CText::DrawChar(UTF8Char character, Gfx::FontType font, float size, Math::Point &pos) +void Gfx::CText::DrawChar(Gfx::UTF8Char ch, Gfx::FontType font, float size, Math::Point &pos) { + // TODO: if (font == Gfx::FONT_BUTTON) + if (font == Gfx::FONT_BUTTON) return; + + // TODO: special chars? + CachedFont* cf = GetOrOpenFont(font, size); if (cf == nullptr) return; - auto it = cf->cache.find(character); + auto it = cf->cache.find(ch); CharTexture tex; if (it != cf->cache.end()) { @@ -376,31 +680,32 @@ void Gfx::CText::DrawChar(UTF8Char character, Gfx::FontType font, float size, Ma } else { - char str[] = { character.c1, character.c2, character.c3, '\0' }; - tex = CreateCharTexture(str, cf); + tex = CreateCharTexture(ch, cf); if (tex.id == 0) // invalid return; - cf->cache[character] = tex; + cf->cache[ch] = tex; } + m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); + + Math::Point p1(pos.x, pos.y + tex.charSize.h - tex.texSize.h); + Math::Point p2(pos.x + tex.texSize.w, pos.y + tex.charSize.h); + Math::Vector n(0.0f, 0.0f, -1.0f); // normal Gfx::Vertex quad[4] = { - Gfx::Vertex(Math::Vector(pos.x, pos.y + tex.charSize.h, 0.0f), - n, Math::Point(0.0f, 0.0f)), - Gfx::Vertex(Math::Vector(pos.x, pos.y + tex.charSize.h - tex.texSize.h, 0.0f), - n, Math::Point(0.0f, 1.0f)), - Gfx::Vertex(Math::Vector(pos.x + tex.texSize.w, pos.y + tex.charSize.h, 0.0f), - n, Math::Point(1.0f, 0.0f)), - Gfx::Vertex(Math::Vector(pos.x + tex.texSize.w, pos.y + tex.charSize.h - tex.texSize.h, 0.0f), - n, Math::Point(1.0f, 1.0f)) + Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), n, Math::Point(0.0f, 1.0f)), + Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(1.0f, 1.0f)), + Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), n, Math::Point(0.0f, 0.0f)), + Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(1.0f, 0.0f)) }; m_device->SetTexture(0, tex.id); m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); + m_engine->AddStatisticTriangle(2); pos.x += tex.charSize.w; } @@ -446,12 +751,13 @@ Gfx::CachedFont* Gfx::CText::GetOrOpenFont(Gfx::FontType font, float size) return m_lastCachedFont; } -Gfx::CharTexture Gfx::CText::CreateCharTexture(const char* str, Gfx::CachedFont* font) +Gfx::CharTexture Gfx::CText::CreateCharTexture(Gfx::UTF8Char ch, Gfx::CachedFont* font) { CharTexture texture; SDL_Surface* textSurface = nullptr; SDL_Color white = {255, 255, 255, 0}; + char str[] = { ch.c1, ch.c2, ch.c3, '\0' }; textSurface = TTF_RenderUTF8_Blended(font->font, str, white); if (textSurface == nullptr) diff --git a/src/graphics/engine/text.h b/src/graphics/engine/text.h index 19d9882..6209c39 100644 --- a/src/graphics/engine/text.h +++ b/src/graphics/engine/text.h @@ -38,9 +38,9 @@ const float FONT_SIZE_SMALL = 10.0f; const float FONT_SIZE_BIG = 15.0f; /** - \enum TextAlignType + \enum TextAlign \brief Type of text alignment */ -enum JustifyType +enum TextAlign { TEXT_ALIGN_RIGHT, TEXT_ALIGN_LEFT, @@ -86,6 +86,8 @@ enum FontType \enum FontTitle \brief Size of font title + Used internally by CEdit + Bitmask in 2 bits left shifted 4 (mask 0x030) */ enum FontTitle { @@ -95,19 +97,20 @@ enum FontTitle }; /** - \enum FontColor - \brief Font color type (?) + \enum FontHighlight + \brief Type of color highlight for text Bitmask in 3 bits left shifted 6 (mask 0x1c0) */ -enum FontColor +enum FontHighlight { - FONT_COLOR_LINK = 0x01 << 6, - FONT_COLOR_TOKEN = 0x02 << 6, - FONT_COLOR_TYPE = 0x03 << 6, - FONT_COLOR_CONST = 0x04 << 6, - FONT_COLOR_REM = 0x05 << 6, - FONT_COLOR_KEY = 0x06 << 6, - FONT_COLOR_TABLE = 0x07 << 6, + FONT_HIGHLIGHT_NONE = 0x00 << 6, + FONT_HIGHLIGHT_LINK = 0x01 << 6, + FONT_HIGHLIGHT_TOKEN = 0x02 << 6, + FONT_HIGHLIGHT_TYPE = 0x03 << 6, + FONT_HIGHLIGHT_CONST = 0x04 << 6, + FONT_HIGHLIGHT_REM = 0x05 << 6, + FONT_HIGHLIGHT_KEY = 0x06 << 6, + FONT_HIGHLIGHT_TABLE = 0x07 << 6, }; /** @@ -119,9 +122,9 @@ enum FontMask FONT_MASK_FONT = 0x00f, //! Mask for FontTitle FONT_MASK_TITLE = 0x030, - //! Mask for FontColor - FONT_MASK_COLOR = 0x1c0, - //! Mask for image bit + //! Mask for FontHighlight + FONT_MASK_HIGHLIGHT = 0x1c0, + //! Mask for image bit (TODO: not used?) FONT_MASK_IMAGE = 0x200 }; @@ -190,7 +193,17 @@ struct MultisizeFont \class CText \brief Text rendering engine - ... */ + CText is responsible for drawing text in 2D interface. Font rendering is done using + textures generated by SDL_ttf from TTF font files. + + All functions rendering text are divided into two types: + - single font - function takes a single Gfx::FontType argument that (along with size) + determines the font to be used for all characters, + - multi-font - function takes the text as one argument and a std::vector of FontMetaChar + with per-character formatting information (font, highlights and some other info used by CEdit) + + All font rendering is done in UTF-8. +*/ class CText { public: @@ -213,20 +226,20 @@ public: //! Draws text (multi-format) void DrawText(const std::string &text, const std::vector &format, - Math::Point pos, float width, Gfx::JustifyType justify, float size, - float stretch, int eol); + float size, Math::Point pos, float width, Gfx::TextAlign align, + int eol); //! Draws text (one font) void DrawText(const std::string &text, Gfx::FontType font, - Math::Point pos, float width, Gfx::JustifyType justify, float size, - float stretch, int eol); + float size, Math::Point pos, float width, Gfx::TextAlign align, + int eol); //! Calculates dimensions for text (multi-format) void SizeText(const std::string &text, const std::vector &format, - Math::Point pos, Gfx::JustifyType justify, float size, + float size, Math::Point pos, Gfx::TextAlign align, Math::Point &start, Math::Point &end); //! Calculates dimensions for text (one font) void SizeText(const std::string &text, Gfx::FontType font, - Math::Point pos, Gfx::JustifyType justify, float size, + float size, Math::Point pos, Gfx::TextAlign align, Math::Point &start, Math::Point &end); //! Returns the ascent font metric @@ -242,7 +255,7 @@ public: //! Returns width of string (single font) float GetStringWidth(const std::string &text, Gfx::FontType font, float size); //! Returns width of single character - float GetCharWidth(int character, Gfx::FontType font, float size, float offset); + float GetCharWidth(Gfx::UTF8Char ch, Gfx::FontType font, float size, float offset); //! Justifies a line of text (multi-format) int Justify(const std::string &text, const std::vector &format, @@ -256,16 +269,16 @@ public: //! Returns the most suitable position to a given offset (one font) int Detect(const std::string &text, Gfx::FontType font, float size, float offset); -public: // for testing! +protected: Gfx::CachedFont* GetOrOpenFont(Gfx::FontType type, float size); - Gfx::CharTexture CreateCharTexture(const char* utf8Char, Gfx::CachedFont* font); + Gfx::CharTexture CreateCharTexture(Gfx::UTF8Char ch, Gfx::CachedFont* font); void DrawString(const std::string &text, const std::vector &format, float size, Math::Point pos, float width, int eol); void DrawString(const std::string &text, Gfx::FontType font, float size, Math::Point pos, float width, int eol); - void DrawColor(int color, float size, Math::Point pos, float width); - void DrawChar(UTF8Char character, Gfx::FontType font, float size, Math::Point &pos); + void DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Size size); + void DrawChar(Gfx::UTF8Char ch, Gfx::FontType font, float size, Math::Point &pos); protected: CInstanceManager* m_iMan; diff --git a/src/math/intpoint.h b/src/math/intpoint.h index a760bc2..476e67b 100644 --- a/src/math/intpoint.h +++ b/src/math/intpoint.h @@ -32,11 +32,11 @@ namespace Math { struct IntPoint { //! X coord - long x; + int x; //! Y coord - long y; + int y; - IntPoint(long aX = 0, long aY = 0) : x(aX), y(aY) {} + IntPoint(int aX = 0, int aY = 0) : x(aX), y(aY) {} }; /* @} */ // end of group diff --git a/src/math/intsize.h b/src/math/intsize.h index d53de85..c88f09b 100644 --- a/src/math/intsize.h +++ b/src/math/intsize.h @@ -34,9 +34,9 @@ namespace Math struct IntSize { //! Width - long w; + int w; //! Height - long h; + int h; //! Constructs a zero size: (0,0) inline IntSize() @@ -45,7 +45,7 @@ struct IntSize } //! Constructs a size from given dimensions: (w,h) - inline explicit IntSize(long w, long h) + inline explicit IntSize(int w, int h) { this->w = w; this->h = h; -- cgit v1.2.3-1-g7c22 From 878eec8eea26deedf3b1346df71bff391424c325 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Wed, 8 Aug 2012 21:32:44 +0200 Subject: CTerrain implementation Added rewritten CTerrain implementation Compiles OK, but functions are missing from other classes Also needs testing --- src/graphics/engine/cloud.h | 4 +- src/graphics/engine/engine.cpp | 5 + src/graphics/engine/engine.h | 3 +- src/graphics/engine/particle.h | 6 +- src/graphics/engine/terrain.cpp | 1802 ++++++++++++++++++++++++++++++++++++++- src/graphics/engine/terrain.h | 258 ++++-- src/graphics/engine/water.h | 14 +- 7 files changed, 1988 insertions(+), 104 deletions(-) (limited to 'src') diff --git a/src/graphics/engine/cloud.h b/src/graphics/engine/cloud.h index d2d29d7..562f651 100644 --- a/src/graphics/engine/cloud.h +++ b/src/graphics/engine/cloud.h @@ -56,10 +56,10 @@ public: void Draw(); bool SetLevel(float level); - float RetLevel(); + float GetLevel(); void SetEnable(bool bEnable); - bool RetEnable(); + bool GetEnable(); protected: bool EventFrame(const Event &event); diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index c5d2a1d..4bf80d2 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -674,6 +674,11 @@ Math::IntSize Gfx::CEngine::InterfaceToWindowSize(Math::Size size) static_cast(size.h * m_size.h)); } +std::string Gfx::CEngine::GetTextureDir() +{ + return m_texPath; +} + void Gfx::CEngine::DrawMouse() { if (! m_mouseVisible) diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 3f7f4f2..cd89a1c 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -552,6 +552,7 @@ public: //! Converts interface size to window size Math::IntSize InterfaceToWindowSize(Math::Size size); + std::string GetTextureDir(); bool WriteProfile(); @@ -606,7 +607,7 @@ public: bool AddSurface(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material &mat, int state, std::string texName1, std::string texName2, float min, float max, bool globalUpdate); - bool AddQuick(int objRank, Gfx::EngineObjLevel5* buffer, + bool AddQuick(int objRank, const Gfx::EngineObjLevel5& buffer, std::string texName1, std::string texName2, float min, float max, bool globalUpdate); Gfx::EngineObjLevel5* SearchTriangle(int objRank, const Gfx::Material &mat, diff --git a/src/graphics/engine/particle.h b/src/graphics/engine/particle.h index bd9741f..94aacfc 100644 --- a/src/graphics/engine/particle.h +++ b/src/graphics/engine/particle.h @@ -260,7 +260,7 @@ public: CParticle(CInstanceManager* iMan, CEngine* engine); ~CParticle(); - void SetGLDevice(CDevice device); + void SetDevice(CDevice* device); void FlushParticle(); void FlushParticle(int sheet); @@ -283,7 +283,7 @@ public: void SetPhase(int channel, ParticlePhase phase, float duration); bool GetPosition(int channel, Math::Vector &pos); - Gfx::Color RetFogColor(Math::Vector pos); + Gfx::Color GetFogColor(Math::Vector pos); void SetFrameUpdate(int sheet, bool bUpdate); void FrameParticle(float rTime); @@ -311,7 +311,7 @@ protected: protected: CInstanceManager* m_iMan; CEngine* m_engine; - CDevice* m_pDevice; + CDevice* m_device; CRobotMain* m_main; CTerrain* m_terrain; CWater* m_water; diff --git a/src/graphics/engine/terrain.cpp b/src/graphics/engine/terrain.cpp index c489321..6d4fcd3 100644 --- a/src/graphics/engine/terrain.cpp +++ b/src/graphics/engine/terrain.cpp @@ -19,5 +19,1805 @@ #include "graphics/engine/terrain.h" +#include "app/app.h" +#include "common/iman.h" +#include "common/image.h" +#include "common/logger.h" +#include "graphics/engine/engine.h" +#include "graphics/engine/water.h" +#include "math/geometry.h" -// TODO implementation +#include + +#include + +const int LEVEL_MAT_PREALLOCATE_COUNT = 101; +const int FLYING_LIMIT_PREALLOCATE_COUNT = 10; +const int BUILDING_LEVEL_PREALLOCATE_COUNT = 101; + + +Gfx::CTerrain::CTerrain(CInstanceManager* iMan) +{ + m_iMan = iMan; + m_iMan->AddInstance(CLASS_TERRAIN, this); + + m_engine = static_cast( m_iMan->SearchInstance(CLASS_ENGINE) ); + m_water = static_cast( m_iMan->SearchInstance(CLASS_WATER) ); + + m_mosaic = 20; + m_brick = 1 << 4; + m_size = 10.0f; + m_vision = 200.0f; + m_scaleMapping = 0.01f; + m_scaleRelief = 1.0f; + m_subdivMapping = 1; + m_depth = 2; + m_levelMatMax = 0; + m_multiText = true; + m_levelText = false; + m_wind = Math::Vector(0.0f, 0.0f, 0.0f); + m_defHardness = 0.5f; + + m_levelMat.reserve(LEVEL_MAT_PREALLOCATE_COUNT); + m_flyingLimits.reserve(FLYING_LIMIT_PREALLOCATE_COUNT); + m_buildingLevels.reserve(BUILDING_LEVEL_PREALLOCATE_COUNT); +} + +Gfx::CTerrain::~CTerrain() +{ +} + +/** + The terrain is composed of mosaics, themselves composed of bricks. + Each brick is composed of two triangles. + mosaic: number of mosaics along the axes X and Z + brick: number of bricks (power of 2) + size: size of a brick along the axes X and Z + vision: vision before a change of resolution + scaleMapping: scale textures for mapping + +\verbatim + ^ z + | <---> brick*size + +---+---+---+---+ + | | | |_|_| mosaic = 4 + | | | | | | brick = 2 (brickP2=1) + +---+---+---+---+ + |\ \| | | | + |\ \| | | | + +---+---o---+---+---> x + | | | | | + | | | | | + +---+---+---+---+ + | | | | | The land is viewed from above here. + | | | | | + +---+---+---+---+ + <---------------> mosaic*brick*size +\endverbatim */ +bool Gfx::CTerrain::Generate(int mosaic, int brickPow2, float size, float vision, + int depth, float hardness) +{ + m_mosaic = mosaic; + m_brick = 1 << brickPow2; + m_size = size; + m_vision = vision; + m_depth = depth; + m_defHardness = hardness; + + m_engine->SetTerrainVision(vision); + + m_multiText = true; + m_levelText = false; + m_scaleMapping = 1.0f / (m_brick*m_size); + m_subdivMapping = 1; + + int dim = 0; + + dim = (m_mosaic*m_brick+1)*(m_mosaic*m_brick+1); + std::vector(dim).swap(m_relief); + + dim = m_mosaic*m_subdivMapping*m_mosaic*m_subdivMapping; + std::vector(dim).swap(m_texture); + + dim = m_mosaic*m_mosaic; + std::vector(dim).swap(m_objRank); + + return true; +} + + +int Gfx::CTerrain::GetMosaic() +{ + return m_mosaic; +} + +int Gfx::CTerrain::GetBrick() +{ + return m_brick; +} + +float Gfx::CTerrain::GetSize() +{ + return m_size; +} + +float Gfx::CTerrain::GetScaleRelief() +{ + return m_scaleRelief; +} + +bool Gfx::CTerrain::InitTextures(const std::string& baseName, int* table, int dx, int dy) +{ + m_levelText = false; + m_texBaseName = baseName; + size_t pos = baseName.find('.'); + if (pos == baseName.npos) + { + m_texBaseExt = ".png"; + } + else + { + m_texBaseName = m_texBaseName.substr(0, pos); + m_texBaseExt = m_texBaseName.substr(pos); + } + + for (int y = 0; y < m_mosaic*m_subdivMapping; y++) + { + for (int x = 0; x < m_mosaic*m_subdivMapping; x++) + { + m_texture[x+y*m_mosaic] = table[(x%dx)+(y%dy)*dx]; + } + } + return true; +} + + +void Gfx::CTerrain::LevelFlush() +{ + m_levelMat.clear(); + m_levelMatMax = 0; + m_levelID = 1000; + LevelCloseTable(); +} + +void Gfx::CTerrain::LevelMaterial(int id, std::string& baseName, float u, float v, + int up, int right, int down, int left, + float hardness) +{ + LevelOpenTable(); + + if (id == 0) + id = m_levelID++; // puts an ID internal standard + + Gfx::TerrainMaterial tm; + tm.texName = baseName; + tm.id = id; + tm.u = u; + tm.v = v; + tm.mat[0] = up; + tm.mat[1] = right; + tm.mat[2] = down; + tm.mat[3] = left; + tm.hardness = hardness; + + m_levelMat.push_back(tm); + + if (m_levelMatMax < up+1 ) m_levelMatMax = up+1; + if (m_levelMatMax < right+1) m_levelMatMax = right+1; + if (m_levelMatMax < down+1 ) m_levelMatMax = down+1; + if (m_levelMatMax < left+1 ) m_levelMatMax = left+1; + + m_levelText = true; + m_subdivMapping = 4; +} + + +/** + The size of the image must be dimension dx and dy with dx=dy=(mosaic*brick)+1. + The image must be 24 bits/pixel + + Converts coordinated image (x;y) -> world (x;-;z) : + Wx = 5*Ix-400 + Wz = -(5*Iy-400) + + Converts coordinated world (x;-;z) -> image (x;y) : + Ix = (400+Wx)/5 + Iy = (400-Wz)/5 */ +bool Gfx::CTerrain::ResFromPNG(const std::string& fileName) +{ + CImage img; + if (! img.Load(CApplication::GetInstance().GetDataFilePath(m_engine->GetTextureDir(), fileName))) + return false; + + ImageData *data = img.GetData(); + + int size = (m_mosaic*m_brick)+1; + + m_resources.clear(); + + std::vector(3*size*size).swap(m_resources); + + if ( (data->surface->w != size) || (data->surface->h != size) || + (data->surface->format->BytesPerPixel != 3) ) + return false; + + // Assuming the data format is compatible + memcpy(&m_resources[0], data->surface->pixels, 3*size*size); + + return true; +} + +Gfx::TerrainRes Gfx::CTerrain::GetResource(const Math::Vector &p) +{ + if (m_resources.empty()) + return Gfx::TR_NULL; + + int x = static_cast((p.x + (m_mosaic*m_brick*m_size)/2.0f)/m_size); + int y = static_cast((p.z + (m_mosaic*m_brick*m_size)/2.0f)/m_size); + + if ( x < 0 || x > m_mosaic*m_brick || + y < 0 || y > m_mosaic*m_brick ) + return Gfx::TR_NULL; + + int size = (m_mosaic*m_brick)+1; + + int resR = m_resources[3*x+3*size*(size-y-1)]; + int resG = m_resources[3*x+3*size*(size-y-1)+1]; + int resB = m_resources[3*x+3*size*(size-y-1)+2]; + + if (resR == 255 && resG == 0 && resB == 0) return Gfx::TR_STONE; + if (resR == 255 && resG == 255 && resB == 0) return Gfx::TR_URANIUM; + if (resR == 0 && resG == 255 && resB == 0) return Gfx::TR_POWER; + + // TODO key res values + //if (ress == 24) return Gfx::TR_KEY_A; // ~green? + //if (ress == 25) return Gfx::TR_KEY_B; // ~green? + //if (ress == 26) return Gfx::TR_KEY_C; // ~green? + //if (ress == 27) return Gfx::TR_KEY_D; // ~green? + + return TR_NULL; +} + +void Gfx::CTerrain::FlushRelief() +{ + m_relief.clear(); +} + +/** + The size of the image must be dimension dx and dy with dx=dy=(mosaic*brick)+1. + The image must be 24 bits/pixel, but gray scale: + white = ground (y=0) + black = mountain (y=255*scaleRelief) + + Converts coordinated image(x;y) -> world (x;-;z) : + Wx = 5*Ix-400 + Wz = -(5*Iy-400) + + Converts coordinated world (x;-;z) -> image (x;y) : + Ix = (400+Wx)/5 + Iy = (400-Wz)/5 */ +bool Gfx::CTerrain::ReliefFromPNG(const std::string &fileName, float scaleRelief, + bool adjustBorder) +{ + m_scaleRelief = scaleRelief; + + CImage img; + if (! img.Load(CApplication::GetInstance().GetDataFilePath(m_engine->GetTextureDir(), fileName))) + return false; + + ImageData *data = img.GetData(); + + int size = (m_mosaic*m_brick)+1; + + if ( (data->surface->w != size) || (data->surface->h != size) || + (data->surface->format->BytesPerPixel != 3) ) + return false; + + unsigned char* pixels = static_cast(data->surface->pixels); + + float limit = 0.9f; + for (int y = 0; y < size; y++) + { + for (int x = 0; x < size; x++) + { + float level = (255 - pixels[3*x+3*size*(size-y-1)]) * scaleRelief; + + float dist = Math::Max(fabs(static_cast(x-size/2)), + fabs(static_cast(y-size/2))); + dist = dist/ static_cast(size / 2); + if (dist > limit && adjustBorder) + { + dist = (dist-limit)/(1.0f-limit); // 0..1 + if (dist > 1.0f) dist = 1.0f; + float border = 300.0f+Math::Rand()*20.0f; + level = level+dist*(border-level); + } + + m_relief[x+y*size] = level; + } + } + + return true; +} + +bool Gfx::CTerrain::ReliefAddDot(Math::Vector pos, float scaleRelief) +{ + float dim = (m_mosaic*m_brick*m_size)/2.0f; + int size = (m_mosaic*m_brick)+1; + + pos.x = (pos.x+dim)/m_size; + pos.z = (pos.z+dim)/m_size; + + int x = static_cast(pos.x); + int y = static_cast(pos.z); + + if ( x < 0 || x >= size || + y < 0 || y >= size ) return false; + + if (m_relief[x+y*size] < pos.y*scaleRelief) + m_relief[x+y*size] = pos.y*scaleRelief; + + return true; +} + +void Gfx::CTerrain::LimitPos(Math::Vector &pos) +{ +// TODO: #if _TEEN +// dim = (m_mosaic*m_brick*m_size)/2.0f*0.98f; + + float dim = (m_mosaic*m_brick*m_size)/2.0f*0.92f; + + if (pos.x < -dim) pos.x = -dim; + if (pos.x > dim) pos.x = dim; + if (pos.z < -dim) pos.z = -dim; + if (pos.z > dim) pos.z = dim; +} + +void Gfx::CTerrain::AdjustRelief() +{ + if (m_depth == 1) return; + + int ii = m_mosaic*m_brick+1; + int b = 1 << (m_depth-1); + + for (int y = 0; y < m_mosaic*m_brick; y += b) + { + for (int x = 0; x < m_mosaic*m_brick; x += b) + { + int xx = 0; + int yy = 0; + if ((y+yy)%m_brick == 0) + { + float level1 = m_relief[(x+0)+(y+yy)*ii]; + float level2 = m_relief[(x+b)+(y+yy)*ii]; + for (xx = 1; xx < b; xx++) + { + m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*xx+level1; + } + } + + yy = b; + if ((y+yy)%m_brick == 0) + { + float level1 = m_relief[(x+0)+(y+yy)*ii]; + float level2 = m_relief[(x+b)+(y+yy)*ii]; + for (xx = 1; xx < b; xx++) + { + m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*xx+level1; + } + } + + xx = 0; + if ((x+xx)%m_brick == 0) + { + float level1 = m_relief[(x+xx)+(y+0)*ii]; + float level2 = m_relief[(x+xx)+(y+b)*ii]; + for (yy = 1; yy < b; yy++) + { + m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*yy+level1; + } + } + + xx = b; + if ((x+xx)%m_brick == 0) + { + float level1 = m_relief[(x+xx)+(y+0)*ii]; + float level2 = m_relief[(x+xx)+(y+b)*ii]; + for (yy = 1; yy < b; yy++) + { + m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*yy+level1; + } + } + } + } +} + +Math::Vector Gfx::CTerrain::GetVector(int x, int y) +{ + Math::Vector p; + p.x = x*m_size - (m_mosaic*m_brick*m_size)/2; + p.z = y*m_size - (m_mosaic*m_brick*m_size)/2; + + if ( !m_relief.empty() && + x >= 0 && x <= m_mosaic*m_brick && + y >= 0 && y <= m_mosaic*m_brick ) + { + p.y = m_relief[x+y*(m_mosaic*m_brick+1)]; + } + else + { + p.y = 0.0f; + } + + return p; +} + +/** Calculates a normal soft, taking into account the six adjacent triangles: + +\verbatim + ^ y + | + b---c---+ + |\ |\ | + | \| \| + a---o---d + |\ |\ | + | \| \| + +---f---e--> x +\endverbatim */ +Gfx::VertexTex2 Gfx::CTerrain::GetVertex(int x, int y, int step) +{ + Gfx::VertexTex2 v; + + Math::Vector o = GetVector(x, y); + v.coord = o; + + Math::Vector a = GetVector(x-step, y ); + Math::Vector b = GetVector(x-step, y+step); + Math::Vector c = GetVector(x, y+step); + Math::Vector d = GetVector(x+step, y ); + Math::Vector e = GetVector(x+step, y-step); + Math::Vector f = GetVector(x, y-step); + + Math::Vector s(0.0f, 0.0f, 0.0f); + + if (x-step >= 0 && y+step <= m_mosaic*m_brick+1) + { + s += Math::NormalToPlane(b,a,o); + s += Math::NormalToPlane(c,b,o); + } + + if (x+step <= m_mosaic*m_brick+1 && y+step <= m_mosaic*m_brick+1) + s += Math::NormalToPlane(d,c,o); + + if (x+step <= m_mosaic*m_brick+1 && y-step >= 0) + { + s += Math::NormalToPlane(e,d,o); + s += Math::NormalToPlane(f,e,o); + } + + if (x-step >= 0 && y-step >= 0) + s += Math::NormalToPlane(a,f,o); + + s = Normalize(s); + v.normal = s; + + if (m_multiText) + { + int brick = m_brick/m_subdivMapping; + Math::Vector oo = GetVector((x/brick)*brick, (y/brick)*brick); + o = GetVector(x, y); + v.texCoord.x = (o.x-oo.x)*m_scaleMapping*m_subdivMapping; + v.texCoord.y = 1.0f - (o.z-oo.z)*m_scaleMapping*m_subdivMapping; + } + else + { + v.texCoord.x = o.x*m_scaleMapping; + v.texCoord.y = o.z*m_scaleMapping; + } + + return v; +} + +/** The origin of mosaic is its center. +\verbatim + ^ z + | + | 2---4---6-- + | |\ |\ |\ + | | \| \| + | 1---3---5--- ... + | + +-------------------> x +\endverbatim */ +bool Gfx::CTerrain::CreateMosaic(int ox, int oy, int step, int objRank, + const Gfx::Material &mat, + float min, float max) +{ + std::string texName1; + std::string texName2; + + if ( step == 1 && m_engine->GetGroundSpot() ) + { + int i = (ox/5) + (oy/5)*(m_mosaic/5); + std::stringstream s; + s << "shadow"; + s.width(2); + s.fill('0'); + s << i; + s << ".png"; + texName2 = s.str(); + } + + int brick = m_brick/m_subdivMapping; + + Gfx::VertexTex2 o = GetVertex(ox*m_brick+m_brick/2, oy*m_brick+m_brick/2, step); + int total = ((brick/step)+1)*2; + + float pixel = 1.0f/256.0f; // 1 pixel cover (*) + float dp = 1.0f/512.0f; + + Math::Point uv; + + for (int my = 0; my < m_subdivMapping; my++) + { + for (int mx = 0; mx < m_subdivMapping; mx++) + { + if (m_levelText) + { + int xx = ox*m_brick + mx*(m_brick/m_subdivMapping); + int yy = oy*m_brick + my*(m_brick/m_subdivMapping); + LevelTextureName(xx, yy, texName1, uv); + } + else + { + int i = (ox*m_subdivMapping+mx)+(oy*m_subdivMapping+my)*m_mosaic; + std::stringstream s; + s << m_texBaseName; + s.width(3); + s.fill('0'); + s << m_texture[i]; + s << m_texBaseExt; + texName1 = s.str(); + } + + for (int y = 0; y < brick; y += step) + { + Gfx::EngineObjLevel5 buffer; + buffer.vertices.reserve(total); + + buffer.type = Gfx::ENG_TRIANGLE_TYPE_6S; + buffer.material = mat; + + buffer.state = Gfx::ENG_RSTATE_WRAP; + + buffer.state |= Gfx::ENG_RSTATE_SECOND; + if (step == 1) + buffer.state |= Gfx::ENG_RSTATE_DUAL_BLACK; + + for (int x = 0; x <= brick; x += step) + { + Gfx::VertexTex2 p1 = GetVertex(ox*m_brick+mx*brick+x, oy*m_brick+my*brick+y+0 , step); + Gfx::VertexTex2 p2 = GetVertex(ox*m_brick+mx*brick+x, oy*m_brick+my*brick+y+step, step); + p1.coord.x -= o.coord.x; p1.coord.z -= o.coord.z; + p2.coord.x -= o.coord.x; p2.coord.z -= o.coord.z; + + if (m_multiText) + { + if (x == 0) + { + p1.texCoord.x = 0.0f+(0.5f/256.0f); + p2.texCoord.x = 0.0f+(0.5f/256.0f); + } + if (x == brick) + { + p1.texCoord.x = 1.0f-(0.5f/256.0f); + p2.texCoord.x = 1.0f-(0.5f/256.0f); + } + if (y == 0) + p1.texCoord.y = 1.0f-(0.5f/256.0f); + + if (y == brick - step) + p2.texCoord.y = 0.0f+(0.5f/256.0f); + } + + if (m_levelText) + { + p1.texCoord.x /= m_subdivMapping; // 0..1 -> 0..0.25 + p1.texCoord.y /= m_subdivMapping; + p2.texCoord.x /= m_subdivMapping; + p2.texCoord.y /= m_subdivMapping; + + if (x == 0) + { + p1.texCoord.x = 0.0f+dp; + p2.texCoord.x = 0.0f+dp; + } + if (x == brick) + { + p1.texCoord.x = (1.0f/m_subdivMapping)-dp; + p2.texCoord.x = (1.0f/m_subdivMapping)-dp; + } + if (y == 0) + p1.texCoord.y = (1.0f/m_subdivMapping)-dp; + + if (y == brick - step) + p2.texCoord.y = 0.0f+dp; + + p1.texCoord.x += uv.x; + p1.texCoord.y += uv.y; + p2.texCoord.x += uv.x; + p2.texCoord.y += uv.y; + } + + int xx = mx*(m_brick/m_subdivMapping) + x; + int yy = my*(m_brick/m_subdivMapping) + y; + p1.texCoord2.x = (static_cast(ox%5)*m_brick+xx+0.0f)/(m_brick*5); + p1.texCoord2.y = (static_cast(oy%5)*m_brick+yy+0.0f)/(m_brick*5); + p2.texCoord2.x = (static_cast(ox%5)*m_brick+xx+0.0f)/(m_brick*5); + p2.texCoord2.y = (static_cast(oy%5)*m_brick+yy+1.0f)/(m_brick*5); + +// Correction for 1 pixel cover +// There is 1 pixel cover around each of the 16 surfaces: +// +// |<--------------256-------------->| +// | |<----------254---------->| | +// |---|---|---|-- ... --|---|---|---| +// | 0.0 1.0 | +// | | | | +// 0.0 min max 1.0 +// +// The uv coordinates used for texturing are between min and max (instead of 0 and 1) +// This allows to exclude the pixels situated in a margin of a pixel around the surface + + p1.texCoord2.x = (p1.texCoord2.x+pixel)*(1.0f-pixel)/(1.0f+pixel); + p1.texCoord2.y = (p1.texCoord2.y+pixel)*(1.0f-pixel)/(1.0f+pixel); + p2.texCoord2.x = (p2.texCoord2.x+pixel)*(1.0f-pixel)/(1.0f+pixel); + p2.texCoord2.y = (p2.texCoord2.y+pixel)*(1.0f-pixel)/(1.0f+pixel); + + + buffer.vertices.push_back(p1); + buffer.vertices.push_back(p2); + } + m_engine->AddQuick(objRank, buffer, texName1, texName2, min, max, true); + } + } + } + + Math::Matrix transform; + transform.LoadIdentity(); + transform.Set(1, 4, o.coord.x); + transform.Set(3, 4, o.coord.z); + m_engine->SetObjectTransform(objRank, transform); + + return true; +} + +Gfx::TerrainMaterial* Gfx::CTerrain::LevelSearchMat(int id) +{ + for (int i = 0; i < static_cast( m_levelMat.size() ); i++) + { + if (id == m_levelMat[i].id) + return &m_levelMat[i]; + } + + return nullptr; +} + +void Gfx::CTerrain::LevelTextureName(int x, int y, std::string& name, Math::Point &uv) +{ + x /= m_brick/m_subdivMapping; + y /= m_brick/m_subdivMapping; + + TerrainMaterial* tm = LevelSearchMat(m_levelDot[x+y*m_levelDotSize].id); + if (tm == nullptr) + { + name = "xxx.png"; + uv.x = 0.0f; + uv.y = 0.0f; + } + else + { + name = tm->texName; + uv.x = tm->u; + uv.y = tm->v; + } +} + +float Gfx::CTerrain::LevelGetHeight(int x, int y) +{ + int size = (m_mosaic*m_brick+1); + + if (x < 0 ) x = 0; + if (x >= size) x = size-1; + if (y < 0 ) y = 0; + if (y >= size) y = size-1; + + return m_relief[x+y*size]; +} + +bool Gfx::CTerrain::LevelGetDot(int x, int y, float min, float max, float slope) +{ + float hc = LevelGetHeight(x, y); + float h[4] = + { + LevelGetHeight(x+0, y+1), + LevelGetHeight(x+1, y+0), + LevelGetHeight(x+0, y-1), + LevelGetHeight(x-1, y+0) + }; + + if (hc < min || hc > max) + return false; + + if (slope == 0.0f) + return true; + + if (slope > 0.0f) + { + for (int i = 0; i < 4; i++) + { + if (fabs(hc - h[i]) >= slope) + return false; + } + return true; + } + + if (slope < 0.0f) + { + for (int i = 0; i < 4; i++) + { + if (fabs(hc - h[i]) < -slope) + return false; + } + return true; + } + + return false; +} + + +/** Returns the index within m_levelMat or -1 if there is not. + m_levelMat[i].id gives the identifier. */ +int Gfx::CTerrain::LevelTestMat(char *mat) +{ + for (int i = 0; i < static_cast( m_levelMat.size() ); i++) + { + if ( m_levelMat[i].mat[0] == mat[0] && + m_levelMat[i].mat[1] == mat[1] && + m_levelMat[i].mat[2] == mat[2] && + m_levelMat[i].mat[3] == mat[3] ) return i; + } + + return -1; +} + +void Gfx::CTerrain::LevelSetDot(int x, int y, int id, char *mat) +{ + TerrainMaterial* tm = LevelSearchMat(id); + if (tm == nullptr) return; + + if ( tm->mat[0] != mat[0] || + tm->mat[1] != mat[1] || + tm->mat[2] != mat[2] || + tm->mat[3] != mat[3] ) // id incompatible with mat? + { + int ii = LevelTestMat(mat); + if (ii == -1) return; + id = m_levelMat[ii].id; // looking for a id compatible with mat + } + + // Changes the point + m_levelDot[x+y*m_levelDotSize].id = id; + m_levelDot[x+y*m_levelDotSize].mat[0] = mat[0]; + m_levelDot[x+y*m_levelDotSize].mat[1] = mat[1]; + m_levelDot[x+y*m_levelDotSize].mat[2] = mat[2]; + m_levelDot[x+y*m_levelDotSize].mat[3] = mat[3]; + + // Changes the lower neighbor + if ( (x+0) >= 0 && (x+0) < m_levelDotSize && + (y-1) >= 0 && (y-1) < m_levelDotSize ) + { + int i = (x+0)+(y-1)*m_levelDotSize; + if (m_levelDot[i].mat[0] != mat[2]) + { + m_levelDot[i].mat[0] = mat[2]; + int ii = LevelTestMat(m_levelDot[i].mat); + if (ii != -1) + m_levelDot[i].id = m_levelMat[ii].id; + } + } + + // Modifies the left neighbor + if ( (x-1) >= 0 && (x-1) < m_levelDotSize && + (y+0) >= 0 && (y+0) < m_levelDotSize ) + { + int i = (x-1)+(y+0)*m_levelDotSize; + if (m_levelDot[i].mat[1] != mat[3]) + { + m_levelDot[i].mat[1] = mat[3]; + int ii = LevelTestMat(m_levelDot[i].mat); + if (ii != -1) + m_levelDot[i].id = m_levelMat[ii].id; + } + } + + // Changes the upper neighbor + if ( (x+0) >= 0 && (x+0) < m_levelDotSize && + (y+1) >= 0 && (y+1) < m_levelDotSize ) + { + int i = (x+0)+(y+1)*m_levelDotSize; + if (m_levelDot[i].mat[2] != mat[0]) + { + m_levelDot[i].mat[2] = mat[0]; + int ii = LevelTestMat(m_levelDot[i].mat); + if (ii != -1) + m_levelDot[i].id = m_levelMat[ii].id; + } + } + + // Changes the right neighbor + if ( (x+1) >= 0 && (x+1) < m_levelDotSize && + (y+0) >= 0 && (y+0) < m_levelDotSize ) + { + int i = (x+1)+(y+0)*m_levelDotSize; + if ( m_levelDot[i].mat[3] != mat[1] ) + { + m_levelDot[i].mat[3] = mat[1]; + int ii = LevelTestMat(m_levelDot[i].mat); + if (ii != -1) + m_levelDot[i].id = m_levelMat[ii].id; + } + } +} + +bool Gfx::CTerrain::LevelIfDot(int x, int y, int id, char *mat) +{ + char test[4]; + + // Compatible with lower neighbor? + if ( x+0 >= 0 && x+0 < m_levelDotSize && + y-1 >= 0 && y-1 < m_levelDotSize ) + { + test[0] = mat[2]; + test[1] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[1]; + test[2] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[2]; + test[3] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[3]; + + if ( LevelTestMat(test) == -1 ) return false; + } + + // Compatible with left neighbor? + if ( x-1 >= 0 && x-1 < m_levelDotSize && + y+0 >= 0 && y+0 < m_levelDotSize ) + { + test[0] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[0]; + test[1] = mat[3]; + test[2] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[2]; + test[3] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[3]; + + if ( LevelTestMat(test) == -1 ) return false; + } + + // Compatible with upper neighbor? + if ( x+0 >= 0 && x+0 < m_levelDotSize && + y+1 >= 0 && y+1 < m_levelDotSize ) + { + test[0] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[0]; + test[1] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[1]; + test[2] = mat[0]; + test[3] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[3]; + + if ( LevelTestMat(test) == -1 ) return false; + } + + // Compatible with right neighbor? + if ( x+1 >= 0 && x+1 < m_levelDotSize && + y+0 >= 0 && y+0 < m_levelDotSize ) + { + test[0] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[0]; + test[1] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[1]; + test[2] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[2]; + test[3] = mat[1]; + + if ( LevelTestMat(test) == -1 ) return false; + } + + LevelSetDot(x, y, id, mat); // puts the point + return true; +} + +bool Gfx::CTerrain::LevelPutDot(int x, int y, int id) +{ + char mat[4]; + + x /= m_brick/m_subdivMapping; + y /= m_brick/m_subdivMapping; + + if ( x < 0 || x >= m_levelDotSize || + y < 0 || y >= m_levelDotSize ) return false; + + TerrainMaterial* tm = LevelSearchMat(id); + if (tm == nullptr) return false; + + // Tries without changing neighbors. + if ( LevelIfDot(x, y, id, tm->mat) ) return true; + + // Tries changing a single neighbor (4x). + for (int up = 0; up < m_levelMatMax; up++) + { + mat[0] = up; + mat[1] = tm->mat[1]; + mat[2] = tm->mat[2]; + mat[3] = tm->mat[3]; + + if (LevelIfDot(x, y, id, mat)) return true; + } + + for (int right = 0; right < m_levelMatMax; right++) + { + mat[0] = tm->mat[0]; + mat[1] = right; + mat[2] = tm->mat[2]; + mat[3] = tm->mat[3]; + + if (LevelIfDot(x, y, id, mat)) return true; + } + + for (int down = 0; down < m_levelMatMax; down++) + { + mat[0] = tm->mat[0]; + mat[1] = tm->mat[1]; + mat[2] = down; + mat[3] = tm->mat[3]; + + if (LevelIfDot(x, y, id, mat)) return true; + } + + for (int left = 0; left < m_levelMatMax; left++) + { + mat[0] = tm->mat[0]; + mat[1] = tm->mat[1]; + mat[2] = tm->mat[2]; + mat[3] = left; + + if (LevelIfDot(x, y, id, mat)) return true; + } + + // Tries changing two neighbors (6x). + for (int up = 0; up < m_levelMatMax; up++) + { + for (int down = 0; down < m_levelMatMax; down++) + { + mat[0] = up; + mat[1] = tm->mat[1]; + mat[2] = down; + mat[3] = tm->mat[3]; + + if (LevelIfDot(x, y, id, mat)) return true; + } + } + + for (int right = 0; right < m_levelMatMax; right++) + { + for (int left = 0; left < m_levelMatMax; left++) + { + mat[0] = tm->mat[0]; + mat[1] = right; + mat[2] = tm->mat[2]; + mat[3] = left; + + if (LevelIfDot(x, y, id, mat)) return true; + } + } + + for (int up = 0; up < m_levelMatMax; up++) + { + for (int right = 0; right < m_levelMatMax; right++) + { + mat[0] = up; + mat[1] = right; + mat[2] = tm->mat[2]; + mat[3] = tm->mat[3]; + + if (LevelIfDot(x, y, id, mat)) return true; + } + } + + for (int right = 0; right < m_levelMatMax; right++) + { + for (int down = 0; down < m_levelMatMax; down++) + { + mat[0] = tm->mat[0]; + mat[1] = right; + mat[2] = down; + mat[3] = tm->mat[3]; + + if (LevelIfDot(x, y, id, mat)) return true; + } + } + + for (int down = 0; down < m_levelMatMax; down++) + { + for (int left = 0; left < m_levelMatMax; left++) + { + mat[0] = tm->mat[0]; + mat[1] = tm->mat[1]; + mat[2] = down; + mat[3] = left; + + if (LevelIfDot(x, y, id, mat)) return true; + } + } + + for (int up = 0; up < m_levelMatMax; up++) + { + for (int left = 0; left < m_levelMatMax; left++) + { + mat[0] = up; + mat[1] = tm->mat[1]; + mat[2] = tm->mat[2]; + mat[3] = left; + + if (LevelIfDot(x, y, id, mat)) return true; + } + } + + // Tries changing all the neighbors. + for (int up = 0; up < m_levelMatMax; up++) + { + for (int right = 0; right < m_levelMatMax; right++) + { + for (int down = 0; down < m_levelMatMax; down++) + { + for (int left = 0; left < m_levelMatMax; left++) + { + mat[0] = up; + mat[1] = right; + mat[2] = down; + mat[3] = left; + + if (LevelIfDot(x, y, id, mat)) return true; + } + } + } + } + + GetLogger()->Error("LevelPutDot error\n"); + return false; +} + +bool Gfx::CTerrain::LevelInit(int id) +{ + TerrainMaterial* tm = LevelSearchMat(id); + if (tm == nullptr) return false; + + for (int i = 0; i < m_levelDotSize*m_levelDotSize; i++) + { + m_levelDot[i].id = id; + + for (int j = 0; j < 4; j++) + m_levelDot[i].mat[j] = tm->mat[j]; + } + + return true; +} + +bool Gfx::CTerrain::LevelGenerate(int *id, float min, float max, + float slope, float freq, + Math::Vector center, float radius) +{ + static char random[100] = + { + 84,25,12, 6,34,52,85,38,97,16, + 21,31,65,19,62,40,72,22,48,61, + 56,47, 8,53,73,77, 4,91,26,88, + 76, 1,44,93,39,11,71,17,98,95, + 88,83,18,30, 3,57,28,49,74, 9, + 32,13,96,66,15,70,36,10,59,94, + 45,86, 2,29,63,42,51, 0,79,27, + 54, 7,20,69,89,23,64,43,81,92, + 90,33,46,14,67,35,50, 5,87,60, + 68,55,24,78,41,75,58,80,37,82, + }; + + TerrainMaterial* tm = nullptr; + + int i = 0; + while ( id[i] != 0 ) + { + tm = LevelSearchMat(id[i++]); + if (tm == nullptr) return false; + } + int numID = i; + + int group = m_brick / m_subdivMapping; + + if (radius > 0.0f && radius < 5.0f) // just a square? + { + float dim = (m_mosaic*m_brick*m_size)/2.0f; + + int xx = static_cast((center.x+dim)/m_size); + int yy = static_cast((center.z+dim)/m_size); + + int x = xx/group; + int y = yy/group; + + tm = LevelSearchMat(id[0]); + if (tm != nullptr) + LevelSetDot(x, y, id[0], tm->mat); // puts the point + } + else + { + for (int y = 0; y < m_levelDotSize; y++) + { + for (int x = 0; x < m_levelDotSize; x++) + { + if (radius != 0.0f) + { + Math::Vector pos; + pos.x = (static_cast(x)-m_levelDotSize/2.0f)*group*m_size; + pos.z = (static_cast(y)-m_levelDotSize/2.0f)*group*m_size; + if (Math::DistanceProjected(pos, center) > radius) continue; + } + + if (freq < 100.0f) + { + int rnd = random[(x%10)+(y%10)*10]; + if ( static_cast(rnd) > freq ) continue; + } + + int xx = x*group + group/2; + int yy = y*group + group/2; + + if (LevelGetDot(xx, yy, min, max, slope)) + { + int rnd = random[(x%10)+(y%10)*10]; + int ii = rnd % numID; + LevelPutDot(xx, yy, id[ii]); + } + } + } + } + + return true; +} + +void Gfx::CTerrain::LevelOpenTable() +{ + if (! m_levelText) return; + if (! m_levelDot.empty()) return; // already allocated + + m_levelDotSize = (m_mosaic*m_brick)/(m_brick/m_subdivMapping)+1; + std::vector(m_levelDotSize*m_levelDotSize).swap(m_levelDot); + + for (int i = 0; i < m_levelDotSize * m_levelDotSize; i++) + { + for (int j = 0; j < 4; j++) + m_levelDot[i].mat[j] = 0; + } +} + +void Gfx::CTerrain::LevelCloseTable() +{ + m_levelDot.clear(); +} + +bool Gfx::CTerrain::CreateSquare(bool multiRes, int x, int y) +{ + Gfx::Material mat; + mat.diffuse = Gfx::Color(1.0f, 1.0f, 1.0f); + mat.ambient = Gfx::Color(0.0f, 0.0f, 0.0f); + + int objRank = m_engine->CreateObject(); + m_engine->SetObjectType(objRank, Gfx::ENG_OBJTYPE_TERRAIN); // it is a terrain + + m_objRank[x+y*m_mosaic] = objRank; + + if (multiRes) + { + float min = 0.0f; + float max = m_vision; + max *= m_engine->GetClippingDistance(); + for (int step = 0; step < m_depth; step++) + { + CreateMosaic(x, y, 1 << step, objRank, mat, min, max); + min = max; + max *= 2; + if (step == m_depth-1) max = Math::HUGE_NUM; + } + } + else + { + CreateMosaic(x, y, 1, objRank, mat, 0.0f, Math::HUGE_NUM); + } + + return true; +} + +bool Gfx::CTerrain::CreateObjects(bool multiRes) +{ + AdjustRelief(); + + for (int y = 0; y < m_mosaic; y++) + { + for (int x = 0; x < m_mosaic; x++) + CreateSquare(multiRes, x, y); + } + + return true; +} + +/** ATTENTION: ok only with m_depth = 2! */ +bool Gfx::CTerrain::Terraform(const Math::Vector &p1, const Math::Vector &p2, float height) +{ + float dim = (m_mosaic*m_brick*m_size)/2.0f; + + Math::IntPoint tp1, tp2; + tp1.x = static_cast((p1.x+dim+m_size/2.0f)/m_size); + tp1.y = static_cast((p1.z+dim+m_size/2.0f)/m_size); + tp2.x = static_cast((p2.x+dim+m_size/2.0f)/m_size); + tp2.y = static_cast((p2.z+dim+m_size/2.0f)/m_size); + + if (tp1.x > tp2.x) + { + int x = tp1.x; + tp1.x = tp2.x; + tp2.x = x; + } + + if (tp1.y > tp2.y) + { + int y = tp1.y; + tp1.y = tp2.y; + tp2.y = y; + } + + int size = (m_mosaic*m_brick)+1; + + // Calculates the current average height + float avg = 0.0f; + int nb = 0; + for (int y = tp1.y; y <= tp2.y; y++) + { + for (int x = tp1.x; x <= tp2.x; x++) + { + avg += m_relief[x+y*size]; + nb ++; + } + } + avg /= static_cast(nb); + + // Changes the description of the relief + for (int y = tp1.y; y <= tp2.y; y++) + { + for (int x = tp1.x; x <= tp2.x; x++) + { + m_relief[x+y*size] = avg+height; + + if (x % m_brick == 0 && y % m_depth != 0) + { + m_relief[(x+0)+(y-1)*size] = avg+height; + m_relief[(x+0)+(y+1)*size] = avg+height; + } + + if (y % m_brick == 0 && x % m_depth != 0) + { + m_relief[(x-1)+(y+0)*size] = avg+height; + m_relief[(x+1)+(y+0)*size] = avg+height; + } + } + } + AdjustRelief(); + + Math::IntPoint pp1, pp2; + pp1.x = (tp1.x-2)/m_brick; + pp1.y = (tp1.y-2)/m_brick; + pp2.x = (tp2.x+1)/m_brick; + pp2.y = (tp2.y+1)/m_brick; + + if (pp1.x < 0 ) pp1.x = 0; + if (pp1.x >= m_mosaic) pp1.x = m_mosaic-1; + if (pp1.y < 0 ) pp1.y = 0; + if (pp1.y >= m_mosaic) pp1.y = m_mosaic-1; + + for (int y = pp1.y; y <= pp2.y; y++) + { + for (int x = pp1.x; x <= pp2.x; x++) + { + m_engine->DeleteObject(m_objRank[x+y*m_mosaic]); + CreateSquare(m_multiText, x, y); // recreates the square + } + } + m_engine->Update(); + + return true; +} + +void Gfx::CTerrain::SetWind(Math::Vector speed) +{ + m_wind = speed; +} + +Math::Vector Gfx::CTerrain::GetWind() +{ + return m_wind; +} + +float Gfx::CTerrain::GetFineSlope(const Math::Vector &pos) +{ + Math::Vector n; + if (! GetNormal(n, pos)) return 0.0f; + return fabs(Math::RotateAngle(Math::Point(n.x, n.z).Length(), n.y) - Math::PI/2.0f); +} + +float Gfx::CTerrain::GetCoarseSlope(const Math::Vector &pos) +{ + if (m_relief.empty()) return 0.0f; + + float dim = (m_mosaic*m_brick*m_size)/2.0f; + + int x = static_cast((pos.x+dim)/m_size); + int y = static_cast((pos.z+dim)/m_size); + + if ( x < 0 || x >= m_mosaic*m_brick || + y < 0 || y >= m_mosaic*m_brick ) return 0.0f; + + float level[4] = + { + m_relief[(x+0)+(y+0)*(m_mosaic*m_brick+1)], + m_relief[(x+1)+(y+0)*(m_mosaic*m_brick+1)], + m_relief[(x+0)+(y+1)*(m_mosaic*m_brick+1)], + m_relief[(x+1)+(y+1)*(m_mosaic*m_brick+1)], + }; + + float min = Math::Min(level[0], level[1], level[2], level[3]); + float max = Math::Max(level[0], level[1], level[2], level[3]); + + return atanf((max-min)/m_size); +} + +bool Gfx::CTerrain::GetNormal(Math::Vector &n, const Math::Vector &p) +{ + float dim = (m_mosaic*m_brick*m_size)/2.0f; + + int x = static_cast((p.x+dim)/m_size); + int y = static_cast((p.z+dim)/m_size); + + if ( x < 0 || x > m_mosaic*m_brick || + y < 0 || y > m_mosaic*m_brick ) return false; + + Math::Vector p1 = GetVector(x+0, y+0); + Math::Vector p2 = GetVector(x+1, y+0); + Math::Vector p3 = GetVector(x+0, y+1); + Math::Vector p4 = GetVector(x+1, y+1); + + if ( fabs(p.z - p2.z) < fabs(p.x - p2.x) ) + n = Math::NormalToPlane(p1,p2,p3); + else + n = Math::NormalToPlane(p2,p4,p3); + + return true; +} + +float Gfx::CTerrain::GetFloorLevel(const Math::Vector &p, bool brut, bool water) +{ + float dim = (m_mosaic*m_brick*m_size)/2.0f; + + int x = static_cast((p.x+dim)/m_size); + int y = static_cast((p.z+dim)/m_size); + + if ( x < 0 || x > m_mosaic*m_brick || + y < 0 || y > m_mosaic*m_brick ) return false; + + Math::Vector p1 = GetVector(x+0, y+0); + Math::Vector p2 = GetVector(x+1, y+0); + Math::Vector p3 = GetVector(x+0, y+1); + Math::Vector p4 = GetVector(x+1, y+1); + + Math::Vector ps = p; + if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) ) + { + if ( !IntersectY(p1, p2, p3, ps) ) return 0.0f; + } + else + { + if ( !IntersectY(p2, p4, p3, ps) ) return 0.0f; + } + + if (! brut) AdjustBuildingLevel(ps); + + if (water) // not going underwater? + { + float level = m_water->GetLevel(); + if (ps.y < level) ps.y = level; // not under water + } + + return ps.y; +} + + +/** This height is positive when you are above the ground */ +float Gfx::CTerrain::GetFloorHeight(const Math::Vector &p, bool brut, bool water) +{ + float dim = (m_mosaic*m_brick*m_size)/2.0f; + + int x = static_cast((p.x+dim)/m_size); + int y = static_cast((p.z+dim)/m_size); + + if ( x < 0 || x > m_mosaic*m_brick || + y < 0 || y > m_mosaic*m_brick ) return false; + + Math::Vector p1 = GetVector(x+0, y+0); + Math::Vector p2 = GetVector(x+1, y+0); + Math::Vector p3 = GetVector(x+0, y+1); + Math::Vector p4 = GetVector(x+1, y+1); + + Math::Vector ps = p; + if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) ) + { + if ( !IntersectY(p1, p2, p3, ps) ) return 0.0f; + } + else + { + if ( !IntersectY(p2, p4, p3, ps) ) return 0.0f; + } + + if (! brut) AdjustBuildingLevel(ps); + + if (water) // not going underwater? + { + float level = m_water->GetLevel(); + if ( ps.y < level ) ps.y = level; // not under water + } + + return p.y-ps.y; +} + +bool Gfx::CTerrain::MoveOnFloor(Math::Vector &p, bool brut, bool water) +{ + float dim = (m_mosaic*m_brick*m_size)/2.0f; + + int x = static_cast((p.x + dim) / m_size); + int y = static_cast((p.z + dim) / m_size); + + if ( x < 0 || x > m_mosaic*m_brick || + y < 0 || y > m_mosaic*m_brick ) return false; + + Math::Vector p1 = GetVector(x+0, y+0); + Math::Vector p2 = GetVector(x+1, y+0); + Math::Vector p3 = GetVector(x+0, y+1); + Math::Vector p4 = GetVector(x+1, y+1); + + if (fabs(p.z - p2.z) < fabs(p.x - p2.x)) + { + if (! Math::IntersectY(p1, p2, p3, p)) return false; + } + else + { + if (! Math::IntersectY(p2, p4, p3, p)) return false; + } + + if (! brut) AdjustBuildingLevel(p); + + if (water) // not going underwater? + { + float level = m_water->GetLevel(); + if (p.y < level) p.y = level; // not under water + } + + return true; +} + + +/** Returns false if the initial coordinate was too far */ +bool Gfx::CTerrain::ValidPosition(Math::Vector &p, float marging) +{ + bool ok = true; + + float limit = m_mosaic*m_brick*m_size/2.0f - marging; + + if (p.x < -limit) + { + p.x = -limit; + ok = false; + } + + if (p.z < -limit) + { + p.z = -limit; + ok = false; + } + + if (p.x > limit) + { + p.x = limit; + ok = false; + } + + if (p.z > limit) + { + p.z = limit; + ok = false; + } + + return ok; +} + +void Gfx::CTerrain::FlushBuildingLevel() +{ + m_buildingLevels.clear(); +} + +bool Gfx::CTerrain::AddBuildingLevel(Math::Vector center, float min, float max, + float height, float factor) +{ + int i = 0; + for ( ; i < static_cast( m_buildingLevels.size() ); i++) + { + if ( center.x == m_buildingLevels[i].center.x && + center.z == m_buildingLevels[i].center.z ) + { + break; + } + } + + if (i == static_cast( m_buildingLevels.size() )) + m_buildingLevels.push_back(Gfx::BuildingLevel()); + + m_buildingLevels[i].center = center; + m_buildingLevels[i].min = min; + m_buildingLevels[i].max = max; + m_buildingLevels[i].level = GetFloorLevel(center, true); + m_buildingLevels[i].height = height; + m_buildingLevels[i].factor = factor; + m_buildingLevels[i].bboxMinX = center.x-max; + m_buildingLevels[i].bboxMaxX = center.x+max; + m_buildingLevels[i].bboxMinZ = center.z-max; + m_buildingLevels[i].bboxMaxZ = center.z+max; + + return true; +} + +bool Gfx::CTerrain::UpdateBuildingLevel(Math::Vector center) +{ + for (int i = 0; i < static_cast( m_buildingLevels.size() ); i++) + { + if ( center.x == m_buildingLevels[i].center.x && + center.z == m_buildingLevels[i].center.z ) + { + m_buildingLevels[i].center = center; + m_buildingLevels[i].level = GetFloorLevel(center, true); + return true; + } + } + return false; +} + +bool Gfx::CTerrain::DeleteBuildingLevel(Math::Vector center) +{ + for (int i = 0; i < static_cast( m_buildingLevels.size() ); i++) + { + if ( center.x == m_buildingLevels[i].center.x && + center.z == m_buildingLevels[i].center.z ) + { + for (int j = i+1; j < static_cast( m_buildingLevels.size() ); j++) + m_buildingLevels[j-1] = m_buildingLevels[j]; + + m_buildingLevels.pop_back(); + return true; + } + } + return false; +} + +float Gfx::CTerrain::GetBuildingFactor(const Math::Vector &p) +{ + for (int i = 0; i < static_cast( m_buildingLevels.size() ); i++) + { + if ( p.x < m_buildingLevels[i].bboxMinX || + p.x > m_buildingLevels[i].bboxMaxX || + p.z < m_buildingLevels[i].bboxMinZ || + p.z > m_buildingLevels[i].bboxMaxZ ) continue; + + float dist = Math::DistanceProjected(p, m_buildingLevels[i].center); + + if (dist <= m_buildingLevels[i].max) + return m_buildingLevels[i].factor; + } + return 1.0f; // it is normal on the ground +} + +void Gfx::CTerrain::AdjustBuildingLevel(Math::Vector &p) +{ + for (int i = 0; i < static_cast( m_buildingLevels.size() ); i++) + { + if ( p.x < m_buildingLevels[i].bboxMinX || + p.x > m_buildingLevels[i].bboxMaxX || + p.z < m_buildingLevels[i].bboxMinZ || + p.z > m_buildingLevels[i].bboxMaxZ ) continue; + + float dist = Math::DistanceProjected(p, m_buildingLevels[i].center); + + if (dist > m_buildingLevels[i].max) continue; + + if (dist < m_buildingLevels[i].min) + { + p.y = m_buildingLevels[i].level + m_buildingLevels[i].height; + return; + } + + Math::Vector border; + border.x = ((p.x - m_buildingLevels[i].center.x) * m_buildingLevels[i].max) / + dist + m_buildingLevels[i].center.x; + border.z = ((p.z - m_buildingLevels[i].center.z) * m_buildingLevels[i].max) / + dist + m_buildingLevels[i].center.z; + + float base = GetFloorLevel(border, true); + + p.y = (m_buildingLevels[i].max - dist) / + (m_buildingLevels[i].max - m_buildingLevels[i].min) * + (m_buildingLevels[i].level + m_buildingLevels[i].height-base) + + base; + + return; + } +} + + +// returns the hardness of the ground in a given place. +// The hardness determines the noise (SOUND_STEP and SOUND_BOUM). + +float Gfx::CTerrain::GetHardness(const Math::Vector &p) +{ + float factor = GetBuildingFactor(p); + if (factor != 1.0f) return 1.0f; // on building + + if (m_levelDot.empty()) return m_defHardness; + + float dim = (m_mosaic*m_brick*m_size)/2.0f; + + int x, y; + + x = static_cast((p.x+dim)/m_size); + y = static_cast((p.z+dim)/m_size); + + if ( x < 0 || x > m_mosaic*m_brick || + y < 0 || y > m_mosaic*m_brick ) return m_defHardness; + + x /= m_brick/m_subdivMapping; + y /= m_brick/m_subdivMapping; + + if ( x < 0 || x >= m_levelDotSize || + y < 0 || y >= m_levelDotSize ) return m_defHardness; + + int id = m_levelDot[x+y*m_levelDotSize].id; + TerrainMaterial* tm = LevelSearchMat(id); + if (tm == nullptr) return m_defHardness; + + return tm->hardness; +} + +void Gfx::CTerrain::GroundFlat(Math::Vector pos) +{ + static char table[41*41]; + + + float rapport = 3200.0f/1024.0f; + + for (int y = 0; y <= 40; y++) + { + for (int x = 0; x <= 40; x++) + { + int i = x + y*41; + table[i] = 0; + + Math::Vector p; + p.x = (x-20)*rapport; + p.z = (y-20)*rapport; + p.y = 0.0f; + + if (Math::Point(p.x, p.y).Length() > 20.0f*rapport) + continue; + + float angle = GetFineSlope(pos+p); + + if (angle < FLATLIMIT) + table[i] = 1; + else + table[i] = 2; + } + } + + m_engine->GroundMarkCreate(pos, 40.0f, 0.001f, 15.0f, 0.001f, 41, 41, table); +} + +float Gfx::CTerrain::GetFlatZoneRadius(Math::Vector center, float max) +{ + float angle = GetFineSlope(center); + if (angle >= Gfx::FLATLIMIT) + return 0.0f; + + float ref = GetFloorLevel(center, true); + + float radius = 1.0f; + while (radius <= max) + { + angle = 0.0f; + int nb = static_cast(2.0f*Math::PI*radius); + if (nb < 8) nb = 8; + + for (int i = 0; i < nb; i++) + { + Math::Point c(center.x, center.z); + Math::Point p (center.x+radius, center.z); + p = Math::RotatePoint(c, angle, p); + Math::Vector pos; + pos.x = p.x; + pos.z = p.y; + float h = GetFloorLevel(pos, true); + if ( fabs(h-ref) > 1.0f ) return radius; + + angle += Math::PI*2.0f/8.0f; + } + radius += 1.0f; + } + return max; +} + +void Gfx::CTerrain::SetFlyingMaxHeight(float height) +{ + m_flyingMaxHeight = height; +} + +float Gfx::CTerrain::GetFlyingMaxHeight() +{ + return m_flyingMaxHeight; +} + +void Gfx::CTerrain::FlushFlyingLimit() +{ + m_flyingMaxHeight = 280.0f; + m_flyingLimits.clear(); +} + +void Gfx::CTerrain::AddFlyingLimit(Math::Vector center, + float extRadius, float intRadius, + float maxHeight) +{ + Gfx::FlyingLimit fl; + fl.center = center; + fl.extRadius = extRadius; + fl.intRadius = intRadius; + fl.maxHeight = maxHeight; + m_flyingLimits.push_back(fl); +} + +float Gfx::CTerrain::GetFlyingLimit(Math::Vector pos, bool noLimit) +{ + if (noLimit) + return 280.0f; + + if (m_flyingLimits.empty()) + return m_flyingMaxHeight; + + for (int i = 0; i < static_cast( m_flyingLimits.size() ); i++) + { + float dist = Math::DistanceProjected(pos, m_flyingLimits[i].center); + + if (dist >= m_flyingLimits[i].extRadius) + continue; + + if (dist <= m_flyingLimits[i].intRadius) + return m_flyingLimits[i].maxHeight; + + dist -= m_flyingLimits[i].intRadius; + + float h = dist * (m_flyingMaxHeight - m_flyingLimits[i].maxHeight) / + (m_flyingLimits[i].extRadius - m_flyingLimits[i].intRadius); + + return h + m_flyingLimits[i].maxHeight; + } + + return m_flyingMaxHeight; +} diff --git a/src/graphics/engine/terrain.h b/src/graphics/engine/terrain.h index 8d8b165..a198590 100644 --- a/src/graphics/engine/terrain.h +++ b/src/graphics/engine/terrain.h @@ -40,56 +40,72 @@ enum TerrainRes TR_STONE = 1, TR_URANIUM = 2, TR_POWER = 3, - TR_KEYa = 4, - TR_KEYb = 5, - TR_KEYc = 6, - TR_KEYd = 7, + TR_KEY_A = 4, + TR_KEY_B = 5, + TR_KEY_C = 6, + TR_KEY_D = 7, }; - -const short MAXBUILDINGLEVEL = 100; - struct BuildingLevel { - Math::Vector center; - float factor; - float min; - float max; - float level; - float height; - float bboxMinX; - float bboxMaxX; - float bboxMinZ; - float bboxMaxZ; + Math::Vector center; + float factor; + float min; + float max; + float level; + float height; + float bboxMinX; + float bboxMaxX; + float bboxMinZ; + float bboxMaxZ; + + BuildingLevel() + { + factor = min = max = level = height = 0.0f; + bboxMinX = bboxMaxX = bboxMinZ = bboxMaxZ = 0.0f; + } }; - -const short MAXMATTERRAIN = 100; - struct TerrainMaterial { short id; - char texName[20]; + std::string texName; float u,v; float hardness; char mat[4]; // up, right, down, left + + TerrainMaterial() + { + id = 0; + u = v = 0.0f; + hardness = 0.0f; + mat[0] = mat[1] = mat[2] = mat[3] = 0; + } }; struct DotLevel { short id; char mat[4]; // up, right, down, left -}; - -const short MAXFLYINGLIMIT = 10; + DotLevel() + { + id = 0; + mat[0] = mat[1] = mat[2] = mat[3] = 0; + } +}; struct FlyingLimit { - Math::Vector center; - float extRadius; - float intRadius; - float maxHeight; + Math::Vector center; + float extRadius; + float intRadius; + float maxHeight; + + FlyingLimit() + { + extRadius = intRadius = maxHeight = 0.0f; + } }; @@ -100,72 +116,124 @@ public: CTerrain(CInstanceManager* iMan); ~CTerrain(); - bool Generate(int mosaic, int brickP2, float size, float vision, int depth, float hardness); - bool InitTextures(char* baseName, int* table, int dx, int dy); + //! Generates a new flat terrain + bool Generate(int mosaic, int brickPow2, float size, float vision, int depth, float hardness); + //! Initializes the names of textures to use for the land + bool InitTextures(const std::string& baseName, int* table, int dx, int dy); + //! Empties level void LevelFlush(); - bool LevelMaterial(int id, char* baseName, float u, float v, int up, int right, int down, int left, float hardness); + //! Initializes the names of textures to use for the land + void LevelMaterial(int id, std::string& baseName, float u, float v, int up, int right, int down, int left, float hardness); + //! Initializes all the ground with a material bool LevelInit(int id); + //! Generates a level in the terrain bool LevelGenerate(int *id, float min, float max, float slope, float freq, Math::Vector center, float radius); + //! Initializes a completely flat terrain void FlushRelief(); - bool ReliefFromBMP(const char* filename, float scaleRelief, bool adjustBorder); - bool ReliefFromDXF(const char* filename, float scaleRelief); - bool ResFromBMP(const char* filename); - bool CreateObjects(bool bMultiRes); - bool Terraform(const Math::Vector &p1, const Math::Vector &p2, float height); - - void SetWind(Math::Vector speed); - Math::Vector RetWind(); - - float RetFineSlope(const Math::Vector &pos); - float RetCoarseSlope(const Math::Vector &pos); - bool GetNormal(Math::Vector &n, const Math::Vector &p); - float RetFloorLevel(const Math::Vector &p, bool bBrut=false, bool bWater=false); - float RetFloorHeight(const Math::Vector &p, bool bBrut=false, bool bWater=false); - bool MoveOnFloor(Math::Vector &p, bool bBrut=false, bool bWater=false); - bool ValidPosition(Math::Vector &p, float marging); - TerrainRes RetResource(const Math::Vector &p); + //! Load relief from a PNG file + bool ReliefFromPNG(const std::string& filename, float scaleRelief, bool adjustBorder); + //! Load resources from a PNG file + bool ResFromPNG(const std::string& filename); + //! Creates all objects of the terrain within the 3D engine + bool CreateObjects(bool multiRes); + //! Modifies the terrain's relief + bool Terraform(const Math::Vector& p1, const Math::Vector& p2, float height); + + //@{ + //! Management of the wind + void SetWind(Math::Vector speed); + Math::Vector GetWind(); + //@} + + //! Gives the exact slope of the terrain of a place given + float GetFineSlope(const Math::Vector& pos); + //! Gives the approximate slope of the terrain of a specific location + float GetCoarseSlope(const Math::Vector& pos); + //! Gives the normal vector at the position p (x,-,z) of the ground + bool GetNormal(Math::Vector& n, const Math::Vector &p); + //! returns the height of the ground + float GetFloorLevel(const Math::Vector& p, bool brut=false, bool water=false); + //! Returns the height to the ground + float GetFloorHeight(const Math::Vector& p, bool brut=false, bool water=false); + //! Modifies the coordinate "y" of point "p" to rest on the ground floor + bool MoveOnFloor(Math::Vector& p, bool brut=false, bool water=false); + //! Modifies a coordinate so that it is on the ground + bool ValidPosition(Math::Vector& p, float marging); + //! Returns the resource type available underground + Gfx::TerrainRes GetResource(const Math::Vector& p); + //! Adjusts a position so that it does not exceed the boundaries void LimitPos(Math::Vector &pos); + //! Empty the table of elevations void FlushBuildingLevel(); + //! Adds a new elevation for a building bool AddBuildingLevel(Math::Vector center, float min, float max, float height, float factor); + //! Updates the elevation for a building when it was moved up (after a terraforming) bool UpdateBuildingLevel(Math::Vector center); + //! Removes the elevation for a building when it was destroyed bool DeleteBuildingLevel(Math::Vector center); - float RetBuildingFactor(const Math::Vector &p); - float RetHardness(const Math::Vector &p); + //! Returns the influence factor whether a position is on a possible rise + float GetBuildingFactor(const Math::Vector& p); + float GetHardness(const Math::Vector& p); - int RetMosaic(); - int RetBrick(); - float RetSize(); - float RetScaleRelief(); + int GetMosaic(); + int GetBrick(); + float GetSize(); + float GetScaleRelief(); + //! Shows the flat areas on the ground void GroundFlat(Math::Vector pos); - float RetFlatZoneRadius(Math::Vector center, float max); + //! Calculates the radius of the largest flat area available + float GetFlatZoneRadius(Math::Vector center, float max); + //@{ + //! Management of the global max flying height void SetFlyingMaxHeight(float height); - float RetFlyingMaxHeight(); + float GetFlyingMaxHeight(); + //@} + //! Empty the table of flying limits void FlushFlyingLimit(); - bool AddFlyingLimit(Math::Vector center, float extRadius, float intRadius, float maxHeight); - float RetFlyingLimit(Math::Vector pos, bool bNoLimit); + //! Adds a new flying limit + void AddFlyingLimit(Math::Vector center, float extRadius, float intRadius, float maxHeight); + //! Returns the maximum height of flight + float GetFlyingLimit(Math::Vector pos, bool noLimit); protected: + //! Adds a point of elevation in the buffer of relief bool ReliefAddDot(Math::Vector pos, float scaleRelief); + //! Adjust the edges of each mosaic to be compatible with all lower resolutions void AdjustRelief(); - Math::Vector RetVector(int x, int y); - Gfx::VertexTex2 RetVertex(int x, int y, int step); - bool CreateMosaic(int ox, int oy, int step, int objRank, const Gfx::Material &mat, float min, float max); - bool CreateSquare(bool bMultiRes, int x, int y); - - TerrainMaterial* LevelSearchMat(int id); - void LevelTextureName(int x, int y, char *name, Math::Point &uv); - float LevelRetHeight(int x, int y); + //! Calculates a vector of the terrain + Math::Vector GetVector(int x, int y); + //! Calculates a vertex of the terrain + Gfx::VertexTex2 GetVertex(int x, int y, int step); + //! Creates all objects of a mosaic + bool CreateMosaic(int ox, int oy, int step, int objRank, const Gfx::Material& mat, float min, float max); + //! Creates all objects in a mesh square ground + bool CreateSquare(bool multiRes, int x, int y); + + //! Seeks a materials based on theirs identifier + Gfx::TerrainMaterial* LevelSearchMat(int id); + //! Chooses texture to use for a given square + void LevelTextureName(int x, int y, std::string& name, Math::Point &uv); + //! Returns the height of the terrain + float LevelGetHeight(int x, int y); + //! Decide whether a point is using the materials bool LevelGetDot(int x, int y, float min, float max, float slope); + //! Seeks if material exists int LevelTestMat(char *mat); + //! Modifies the state of a point and its four neighbors, without testing if possible void LevelSetDot(int x, int y, int id, char *mat); + //! Tests if a material can give a place, according to its four neighbors. If yes, puts the point. bool LevelIfDot(int x, int y, int id, char *mat); + //! Modifies the state of a point bool LevelPutDot(int x, int y, int id); + //! Initializes a table with empty levels void LevelOpenTable(); + //! Closes the level table void LevelCloseTable(); + //! Adjusts a position according to a possible rise void AdjustBuildingLevel(Math::Vector &p); protected: @@ -173,39 +241,49 @@ protected: CEngine* m_engine; CWater* m_water; - int m_mosaic; // number of mosaics - int m_brick; // number of bricks per mosaics - float m_size; // size of an item in an brick - float m_vision; // vision before a change of resolution - float* m_relief; // table of the relief - int* m_texture; // table of textures - int* m_objRank; // table of rows of objects - bool m_bMultiText; - bool m_bLevelText; - float m_scaleMapping; // scale of the mapping + //! Number of mosaics + int m_mosaic; + //! Number of bricks per mosaics + int m_brick; + int m_levelDotSize; + //! Size of an item in a brick + float m_size; + //! Vision before a change of resolution + float m_vision; + //! Table of the relief + std::vector m_relief; + //! Table of textures + std::vector m_texture; + //! Table of rows of objects + std::vector m_objRank; + //! Table of resources + std::vector m_resources; + bool m_multiText; + bool m_levelText; + //! Scale of the mapping + float m_scaleMapping; float m_scaleRelief; - int m_subdivMapping; - int m_depth; // number of different resolutions (1,2,3,4) - char m_texBaseName[20]; - char m_texBaseExt[10]; + int m_subdivMapping; + //! Number of different resolutions (1,2,3,4) + int m_depth; + std::string m_texBaseName; + std::string m_texBaseExt; float m_defHardness; - TerrainMaterial m_levelMat[MAXMATTERRAIN+1]; - int m_levelMatTotal; + std::vector m_levelMat; + std::vector m_levelDot; int m_levelMatMax; - int m_levelDotSize; - DotLevel* m_levelDot; int m_levelID; - int m_buildingUsed; - BuildingLevel m_buildingTable[MAXBUILDINGLEVEL]; + std::vector m_buildingLevels; - unsigned char* m_resources; - Math::Vector m_wind; // wind speed + //! Wind speed + Math::Vector m_wind; + //! Global flying height limit float m_flyingMaxHeight; - int m_flyingLimitTotal; - FlyingLimit m_flyingLimit[MAXFLYINGLIMIT]; + //! List of local flight limits + std::vector m_flyingLimits; }; }; // namespace Gfx diff --git a/src/graphics/engine/water.h b/src/graphics/engine/water.h index 67be9dc..6d3736e 100644 --- a/src/graphics/engine/water.h +++ b/src/graphics/engine/water.h @@ -72,7 +72,7 @@ public: CWater(CInstanceManager* iMan, Gfx::CEngine* engine); ~CWater(); - void SetGLDevice(Gfx::CDevice device); + void SetDevice(Gfx::CDevice* device); bool EventProcess(const Event &event); void Flush(); bool Create(WaterType type1, WaterType type2, const char *filename, Gfx::Color diffuse, Gfx::Color ambient, float level, float glint, Math::Vector eddy); @@ -80,11 +80,11 @@ public: void DrawSurf(); bool SetLevel(float level); - float RetLevel(); - float RetLevel(CObject* object); + float GetLevel(); + float GetLevel(CObject* object); void SetLava(bool bLava); - bool RetLava(); + bool GetLava(); void AdjustEye(Math::Vector &eye); @@ -92,7 +92,7 @@ protected: bool EventFrame(const Event &event); void LavaFrame(float rTime); void AdjustLevel(Math::Vector &pos, Math::Vector &norm, Math::Point &uv1, Math::Point &uv2); - bool RetWater(int x, int y); + bool GetWater(int x, int y); bool CreateLine(int x, int y, int len); void VaporFlush(); @@ -101,8 +101,8 @@ protected: protected: CInstanceManager* m_iMan; - CEngine* m_engine; - CDevice* m_pDevice; + CEngine* m_engine; + CDevice* m_device; CTerrain* m_terrain; CParticle* m_particule; CSound* m_sound; -- cgit v1.2.3-1-g7c22 From c1936514c054d6d7c85843bf2c3e0b97653ef651 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Wed, 8 Aug 2012 23:51:19 +0200 Subject: CWater and CCloud basic implementation Added rewritten implementation for CWater and CCloud Won't link yet because of missing functions --- src/graphics/engine/cloud.cpp | 267 +++++++++++++++++- src/graphics/engine/cloud.h | 74 +++-- src/graphics/engine/water.cpp | 640 +++++++++++++++++++++++++++++++++++++++++- src/graphics/engine/water.h | 137 +++++---- 4 files changed, 1043 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/graphics/engine/cloud.cpp b/src/graphics/engine/cloud.cpp index d0e5ed8..e46b074 100644 --- a/src/graphics/engine/cloud.cpp +++ b/src/graphics/engine/cloud.cpp @@ -19,5 +19,270 @@ #include "graphics/engine/cloud.h" +#include "common/iman.h" +#include "graphics/engine/engine.h" +#include "graphics/engine/terrain.h" +#include "math/geometry.h" -// TODO implementation + +const int CLOUD_LINE_PREALLOCATE_COUNT = 100; + +const int DIMEXPAND = 4; // extension of the dimensions + + +Gfx::CCloud::CCloud(CInstanceManager* iMan, Gfx::CEngine* engine) +{ + m_iMan = iMan; + m_iMan->AddInstance(CLASS_CLOUD, this); + + m_engine = engine; + m_terrain = nullptr; + + m_level = 0.0f; + m_wind = Math::Vector(0.0f, 0.0f, 0.0f); + m_subdiv = 8; + m_enable = true; + + m_line.reserve(CLOUD_LINE_PREALLOCATE_COUNT); +} + +Gfx::CCloud::~CCloud() +{ + m_iMan = nullptr; + m_engine = nullptr; + m_terrain = nullptr; +} + +bool Gfx::CCloud::EventProcess(const Event &event) +{ + /* TODO! + if ( event.event == EVENT_FRAME ) + return EventFrame(event); */ + + return true; +} + +bool Gfx::CCloud::EventFrame(const Event &event) +{ + /* TODO! + if (m_engine->GetPause()) return true; + + m_time += event.rTime; + + if (m_level == 0.0f) return true; + + if (m_time - m_lastTest < 0.2f) return true; + + m_lastTest = m_time; */ + + return true; +} + +void Gfx::CCloud::AdjustLevel(Math::Vector &pos, Math::Vector &eye, float deep, + Math::Point &uv1, Math::Point &uv2) +{ + uv1.x = (pos.x+20000.0f)/1280.0f; + uv1.y = (pos.z+20000.0f)/1280.0f; + uv1.x -= m_time*(m_wind.x/100.0f); + uv1.y -= m_time*(m_wind.z/100.0f); + + uv2.x = 0.0f; + uv2.y = 0.0f; + + float dist = Math::DistanceProjected(pos, eye); + float factor = powf(dist/deep, 2.0f); + pos.y -= m_level*factor*10.0f; +} + +void Gfx::CCloud::Draw() +{ + /* TODO! + LPDIRECT3DDEVICE7 device; + D3DVERTEX2* vertex; + Math::Matrix* matView; + D3DMATERIAL7 material; + Math::Matrix matrix; + Math::Vector n, pos, p, eye; + Math::Point uv1, uv2; + float iDeep, deep, size, fogStart, fogEnd; + int i, j, u; + + if ( !m_enable ) return; + if ( m_level == 0.0f ) return; + if ( m_lineUsed == 0 ) return; + + vertex = (D3DVERTEX2*)malloc(sizeof(D3DVERTEX2)*(m_brick+2)*2); + + iDeep = m_engine->GetDeepView(); + deep = (m_brick*m_size)/2.0f; + m_engine->SetDeepView(deep); + m_engine->SetFocus(m_engine->GetFocus()); + m_engine->UpdateMatProj(); // increases the depth of view + + fogStart = deep*0.15f; + fogEnd = deep*0.24f; + + device = m_engine->GetD3DDevice(); + device->SetRenderState(D3DRENDERSTATE_AMBIENT, 0x00000000); + device->SetRenderState(D3DRENDERSTATE_LIGHTING, false); + device->SetRenderState(D3DRENDERSTATE_ZENABLE, false); + device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true); + device->SetRenderState(D3DRENDERSTATE_FOGSTART, F2DW(fogStart)); + device->SetRenderState(D3DRENDERSTATE_FOGEND, F2DW(fogEnd)); + + matView = m_engine->GetMatView(); + { + D3DMATRIX mat = MAT_TO_D3DMAT(*matView); + device->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat); + } + + ZeroMemory( &material, sizeof(D3DMATERIAL7) ); + material.diffuse = m_diffuse; + material.ambient = m_ambient; + m_engine->SetMaterial(material); + + m_engine->SetTexture(m_filename, 0); + m_engine->SetTexture(m_filename, 1); + + m_engine->SetState(D3DSTATETTb|D3DSTATEFOG|D3DSTATEWRAP); + + matrix.LoadIdentity(); + { + D3DMATRIX mat = MAT_TO_D3DMAT(matrix); + device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); + } + + size = m_size/2.0f; + eye = m_engine->GetEyePt(); + n = Math::Vector(0.0f, -1.0f, 0.0f); + + // Draws all the lines. + for ( i=0 ; iDrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, u, NULL); + m_engine->AddStatisticTriangle(u-2); + } + + m_engine->SetDeepView(iDeep); + m_engine->SetFocus(m_engine->GetFocus()); + m_engine->UpdateMatProj(); // gives depth to initial + + free(vertex); */ +} + +void Gfx::CCloud::CreateLine(int x, int y, int len) +{ + Gfx::CloudLine line; + + line.x = x; + line.y = y; + line.len = len; + + float offset = m_brick*m_size/2.0f - m_size/2.0f; + + line.px1 = m_size* line.x - offset; + line.px2 = m_size*(line.x+line.len) - offset; + line.pz = m_size* line.y - offset; + + m_line.push_back(line); +} + +void Gfx::CCloud::Create(const std::string& fileName, + Gfx::Color diffuse, Gfx::Color ambient, + float level) +{ + m_diffuse = diffuse; + m_ambient = ambient; + m_level = level; + m_time = 0.0f; + m_lastTest = 0.0f; + m_fileName = fileName; + + if (! m_fileName.empty()) + { + m_engine->LoadTexture(m_fileName, 0); + m_engine->LoadTexture(m_fileName, 1); + } + + if (m_terrain == nullptr) + m_terrain = static_cast(m_iMan->SearchInstance(CLASS_TERRAIN)); + + m_wind = m_terrain->GetWind(); + + m_brick = m_terrain->GetBrick()*m_terrain->GetMosaic()*DIMEXPAND; + m_size = m_terrain->GetSize(); + + m_brick /= m_subdiv*DIMEXPAND; + m_size *= m_subdiv*DIMEXPAND; + + if (m_level == 0.0f) + return; + + m_line.clear(); + for (int y = 0; y < m_brick; y++) + CreateLine(0, y, m_brick); + + return; +} + +void Gfx::CCloud::Flush() +{ + m_level = 0.0f; +} + + +void Gfx::CCloud::SetLevel(float level) +{ + m_level = level; + + Create(m_fileName, m_diffuse, m_ambient, m_level); +} + +float Gfx::CCloud::GetLevel() +{ + return m_level; +} + +void Gfx::CCloud::SetEnable(bool enable) +{ + m_enable = enable; +} + +bool Gfx::CCloud::GetEnable() +{ + return m_enable; +} diff --git a/src/graphics/engine/cloud.h b/src/graphics/engine/cloud.h index 562f651..676dfe8 100644 --- a/src/graphics/engine/cloud.h +++ b/src/graphics/engine/cloud.h @@ -24,6 +24,9 @@ #include "math/point.h" #include "math/vector.h" +#include +#include + class CInstanceManager; @@ -34,13 +37,20 @@ namespace Gfx { class CEngine; class CTerrain; -const short MAXCLOUDLINE = 100; - struct CloudLine { - short x, y; // beginning - short len; // in length x + //! Beginning + short x, y; + //! In length x + short len; float px1, px2, pz; + + CloudLine() + { + x = y = 0; + len = 0; + px1 = px2 = pz = 0; + } }; @@ -51,43 +61,59 @@ public: ~CCloud(); bool EventProcess(const Event &event); + //! Removes all the clouds void Flush(); - bool Create(const char *filename, Gfx::Color diffuse, Gfx::Color ambient, float level); + //! Creates all areas of cloud + void Create(const std::string& fileName, Gfx::Color diffuse, Gfx::Color ambient, float level); + //! Draw the clouds void Draw(); - bool SetLevel(float level); + //! Modifies the cloud level + void SetLevel(float level); + //! Returns the current level of clouds float GetLevel(); - void SetEnable(bool bEnable); + //! Activate management of clouds + void SetEnable(bool enable); bool GetEnable(); protected: + //! Makes the clouds evolve bool EventFrame(const Event &event); - void AdjustLevel(Math::Vector &pos, Math::Vector &eye, float deep, Math::Point &uv1, Math::Point &uv2); - bool CreateLine(int x, int y, int len); + //! Adjusts the position to normal, to imitate the clouds at movement + void AdjustLevel(Math::Vector &pos, Math::Vector &eye, float deep, + Math::Point &uv1, Math::Point &uv2); + //! Updates the positions, relative to the ground + void CreateLine(int x, int y, int len); protected: - CInstanceManager* m_iMan; - CEngine* m_engine; - CTerrain* m_terrain; - - char m_filename[100]; - float m_level; // overall level - Math::Point m_speed; // feedrate (wind) - Gfx::Color m_diffuse; // diffuse color - Gfx::Color m_ambient; // ambient color + CInstanceManager* m_iMan; + Gfx::CEngine* m_engine; + Gfx::CTerrain* m_terrain; + + std::string m_fileName; + //! Overall level + float m_level; + //! Feedrate (wind) + Math::Point m_speed; + //! Diffuse color + Gfx::Color m_diffuse; + //! Ambient color + Gfx::Color m_ambient; float m_time; float m_lastTest; int m_subdiv; - Math::Vector m_wind; // wind speed - int m_brick; // brick mosaic - float m_size; // size of a brick element + //! Wind speed + Math::Vector m_wind; + //! Brick mosaic + int m_brick; + //! Size of a brick element + float m_size; - int m_lineUsed; - CloudLine m_line[MAXCLOUDLINE]; + std::vector m_line; - bool m_bEnable; + bool m_enable; }; diff --git a/src/graphics/engine/water.cpp b/src/graphics/engine/water.cpp index a157e82..1f11671 100644 --- a/src/graphics/engine/water.cpp +++ b/src/graphics/engine/water.cpp @@ -19,5 +19,643 @@ #include "graphics/engine/water.h" +#include "common/iman.h" +#include "graphics/engine/engine.h" +#include "graphics/engine/terrain.h" +#include "sound/sound.h" + + +const int WATERLINE_PREALLOCATE_COUNT = 500; + +// TODO: remove the limit? +const int VAPOR_SIZE = 10; + + +Gfx::CWater::CWater(CInstanceManager* iMan, Gfx::CEngine* engine) +{ + m_iMan = iMan; + m_iMan->AddInstance(CLASS_WATER, this); + + m_engine = engine; + m_terrain = nullptr; + m_particule = nullptr; + m_sound = nullptr; + + m_type[0] = WATER_NULL; + m_type[1] = WATER_NULL; + m_level = 0.0f; + m_draw = true; + m_lava = false; + m_color = 0xffffffff; + m_subdiv = 4; + + m_line.reserve(WATERLINE_PREALLOCATE_COUNT); + + std::vector(VAPOR_SIZE).swap(m_vapor); +} + +Gfx::CWater::~CWater() +{ + m_iMan = nullptr; + m_engine = nullptr; + m_terrain = nullptr; + m_particule = nullptr; + m_sound = nullptr; +} + + +bool Gfx::CWater::EventProcess(const Event &event) +{ + /* TODO! + if (event.type == EVENT_FRAME) + return EventFrame(event); +*/ + return true; +} + +bool Gfx::CWater::EventFrame(const Event &event) +{ + /* TODO! + if (m_engine->GetPause()) return true; + + m_time += event.rTime; + + if (m_type[0] == WATER_NULL) return true; + + if (m_lava) + LavaFrame(event.rTime);*/ + + return true; +} + +void Gfx::CWater::LavaFrame(float rTime) +{ + if (m_particule == nullptr) + m_particule = static_cast( m_iMan->SearchInstance(CLASS_PARTICULE) ); + + for (int i = 0; i < static_cast( m_vapor.size() ); i++) + VaporFrame(i, rTime); + + if (m_time - m_lastLava >= 0.1f) + { + Math::Vector eye = m_engine->GetEyePt(); + Math::Vector lookat = m_engine->GetLookatPt(); + + float distance = Math::Rand()*200.0f; + float shift = (Math::Rand()-0.5f)*200.0f; + + Math::Vector dir = Normalize(lookat-eye); + Math::Vector pos = eye + dir*distance; + + Math::Vector perp; + perp.x = -dir.z; + perp.y = dir.y; + perp.z = dir.x; + pos = pos + perp*shift; + + float level = m_terrain->GetFloorLevel(pos, true); + if (level < m_level) + { + pos.y = m_level; + + level = Math::Rand(); + if (level < 0.8f) + { + if ( VaporCreate(Gfx::PARTIFIRE, pos, 0.02f+Math::Rand()*0.06f) ) + m_lastLava = m_time; + } + else if (level < 0.9f) + { + if ( VaporCreate(Gfx::PARTIFLAME, pos, 0.5f+Math::Rand()*3.0f) ) + m_lastLava = m_time; + } + else + { + if ( VaporCreate(Gfx::PARTIVAPOR, pos, 0.2f+Math::Rand()*2.0f) ) + m_lastLava = m_time; + } + } + } +} + +void Gfx::CWater::VaporFlush() +{ + m_vapor.clear(); +} + +bool Gfx::CWater::VaporCreate(Gfx::ParticleType type, Math::Vector pos, float delay) +{ + for (int i = 0; i < static_cast( m_vapor.size() ); i++) + { + if (! m_vapor[i].used) + { + m_vapor[i].used = true; + m_vapor[i].type = type; + m_vapor[i].pos = pos; + m_vapor[i].delay = delay; + m_vapor[i].time = 0.0f; + m_vapor[i].last = 0.0f; + + if (m_vapor[i].type == PARTIFIRE) + m_sound->Play(SOUND_BLUP, pos, 1.0f, 1.0f-Math::Rand()*0.5f); + + if (m_vapor[i].type == PARTIVAPOR) + m_sound->Play(SOUND_PSHHH, pos, 0.3f, 2.0f); + + return true; + } + } + + return false; +} + +void Gfx::CWater::VaporFrame(int i, float rTime) +{ + m_vapor[i].time += rTime; + + if (m_sound == nullptr) + m_sound = static_cast(m_iMan->SearchInstance(CLASS_SOUND)); + + if (m_vapor[i].time <= m_vapor[i].delay) + { + if (m_time-m_vapor[i].last >= m_engine->ParticleAdapt(0.02f)) + { + m_vapor[i].last = m_time; + + if (m_vapor[i].type == PARTIFIRE) + { + for (int j = 0; j < 10; j++) + { + Math::Vector pos = m_vapor[i].pos; + pos.x += (Math::Rand()-0.5f)*2.0f; + pos.z += (Math::Rand()-0.5f)*2.0f; + pos.y -= 1.0f; + Math::Vector speed; + speed.x = (Math::Rand()-0.5f)*6.0f; + speed.z = (Math::Rand()-0.5f)*6.0f; + speed.y = 8.0f+Math::Rand()*5.0f; + Math::Point dim; + dim.x = Math::Rand()*1.5f+1.5f; + dim.y = dim.x; + m_particule->CreateParticle(pos, speed, dim, PARTIERROR, 2.0f, 10.0f); + } + } + else if (m_vapor[i].type == PARTIFLAME) + { + Math::Vector pos = m_vapor[i].pos; + pos.x += (Math::Rand()-0.5f)*8.0f; + pos.z += (Math::Rand()-0.5f)*8.0f; + pos.y -= 2.0f; + Math::Vector speed; + speed.x = (Math::Rand()-0.5f)*2.0f; + speed.z = (Math::Rand()-0.5f)*2.0f; + speed.y = 4.0f+Math::Rand()*4.0f; + Math::Point dim; + dim.x = Math::Rand()*2.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticle(pos, speed, dim, PARTIFLAME); + } + else + { + Math::Vector pos = m_vapor[i].pos; + pos.x += (Math::Rand()-0.5f)*4.0f; + pos.z += (Math::Rand()-0.5f)*4.0f; + pos.y -= 2.0f; + Math::Vector speed; + speed.x = (Math::Rand()-0.5f)*2.0f; + speed.z = (Math::Rand()-0.5f)*2.0f; + speed.y = 8.0f+Math::Rand()*8.0f; + Math::Point dim; + dim.x = Math::Rand()*1.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticle(pos, speed, dim, PARTIVAPOR); + } + } + } + else + { + m_vapor[i].used = false; + } +} + +void Gfx::CWater::AdjustLevel(Math::Vector &pos, Math::Vector &norm, + Math::Point &uv1, Math::Point &uv2) +{ + float t1 = m_time*1.5f + pos.x*0.1f * pos.z*0.2f; + pos.y += sinf(t1)*m_eddy.y; + + t1 = m_time*1.5f; + uv1.x = (pos.x+10000.0f)/40.0f+sinf(t1)*m_eddy.x*0.02f; + uv1.y = (pos.z+10000.0f)/40.0f-cosf(t1)*m_eddy.z*0.02f; + uv2.x = (pos.x+10010.0f)/20.0f+cosf(-t1)*m_eddy.x*0.02f; + uv2.y = (pos.z+10010.0f)/20.0f-sinf(-t1)*m_eddy.z*0.02f; + + t1 = m_time*0.50f + pos.x*2.1f + pos.z*1.1f; + float t2 = m_time*0.75f + pos.x*2.0f + pos.z*1.0f; + norm = Math::Vector(sinf(t1)*m_glint, 1.0f, sinf(t2)*m_glint); +} + +/** This surface prevents to see the sky (background) underwater! */ +void Gfx::CWater::DrawBack() +{ + /* TODO! + LPDIRECT3DDEVICE7 device; + D3DVERTEX2 vertex[4]; // 2 triangles + D3DMATERIAL7 material; + Math::Matrix matrix; + Math::Vector eye, lookat, n, p, p1, p2; + Math::Point uv1, uv2; + float deep, dist; + + if ( !m_bDraw ) return; + if ( m_type[0] == WATER_NULL ) return; + if ( m_lineUsed == 0 ) return; + + eye = m_engine->GetEyePt(); + lookat = m_engine->GetLookatPt(); + + ZeroMemory( &material, sizeof(D3DMATERIAL7) ); + material.diffuse = m_diffuse; + material.ambient = m_ambient; + m_engine->SetMaterial(material); + + m_engine->SetTexture("", 0); + + device = m_engine->GetD3DDevice(); + device->SetRenderState(D3DRENDERSTATE_LIGHTING, false); + device->SetRenderState(D3DRENDERSTATE_ZENABLE, false); + device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false); + m_engine->SetState(D3DSTATENORMAL); + + deep = m_engine->GetDeepView(0); + m_engine->SetDeepView(deep*2.0f, 0); + m_engine->SetFocus(m_engine->GetFocus()); + m_engine->UpdateMatProj(); // twice the depth of view + + matrix.LoadIdentity(); + { + D3DMATRIX mat = MAT_TO_D3DMAT(matrix); + device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); + } + + p.x = eye.x; + p.z = eye.z; + dist = Math::DistanceProjected(eye, lookat); + p.x = (lookat.x-eye.x)*deep*1.0f/dist + eye.x; + p.z = (lookat.z-eye.z)*deep*1.0f/dist + eye.z; + + p1.x = (lookat.z-eye.z)*deep*2.0f/dist + p.x; + p1.z = -(lookat.x-eye.x)*deep*2.0f/dist + p.z; + p2.x = -(lookat.z-eye.z)*deep*2.0f/dist + p.x; + p2.z = (lookat.x-eye.x)*deep*2.0f/dist + p.z; + + p1.y = -50.0f; + p2.y = m_level; + + n.x = (lookat.x-eye.x)/dist; + n.z = (lookat.z-eye.z)/dist; + n.y = 0.0f; + + uv1.x = uv1.y = 0.0f; + uv2.x = uv2.y = 0.0f; + + vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p2.y, p1.z), n, uv1.x,uv2.y); + vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p1.y, p1.z), n, uv1.x,uv1.y); + vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p2.y, p2.z), n, uv2.x,uv2.y); + vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p1.y, p2.z), n, uv2.x,uv1.y); + + device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL); + m_engine->AddStatisticTriangle(2); + + m_engine->SetDeepView(deep, 0); + m_engine->SetFocus(m_engine->GetFocus()); + m_engine->UpdateMatProj(); // gives the initial depth of view + + device->SetRenderState(D3DRENDERSTATE_LIGHTING, true); + device->SetRenderState(D3DRENDERSTATE_ZENABLE, true); + device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);*/ +} + +void Gfx::CWater::DrawSurf() +{ + /* TODO! + LPDIRECT3DDEVICE7 device; + D3DVERTEX2* vertex; // triangles + D3DMATERIAL7 material; + Math::Matrix matrix; + Math::Vector eye, lookat, n, pos, p; + Math::Point uv1, uv2; + bool bUnder; + DWORD flags; + float deep, size, sizez, radius; + int rankview, i, j, u; + + if (! m_draw) return; + if (m_type[0] == Gfx::WATER_NULL) return; + if (m_line.empty()) return; + + vertex = (D3DVERTEX2*)malloc(sizeof(D3DVERTEX2)*(m_brick+2)*2); + + eye = m_engine->GetEyePt(); + lookat = m_engine->GetLookatPt(); + + rankview = m_engine->GetRankView(); + bUnder = ( rankview == 1); + + device = m_engine->GetD3DDevice(); + device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false); + + matrix.LoadIdentity(); + { + D3DMATRIX mat = MAT_TO_D3DMAT(matrix); + device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); + } + + ZeroMemory( &material, sizeof(D3DMATERIAL7) ); + material.diffuse = m_diffuse; + material.ambient = m_ambient; + m_engine->SetMaterial(material); + + m_engine->SetTexture(m_filename, 0); + m_engine->SetTexture(m_filename, 1); + + if ( m_type[rankview] == WATER_TT ) + { + m_engine->SetState(D3DSTATETTb|D3DSTATEDUALw|D3DSTATEWRAP, m_color); + } + if ( m_type[rankview] == WATER_TO ) + { + m_engine->SetState(D3DSTATENORMAL|D3DSTATEDUALw|D3DSTATEWRAP); + } + if ( m_type[rankview] == WATER_CT ) + { + m_engine->SetState(D3DSTATETTb); + } + if ( m_type[rankview] == WATER_CO ) + { + m_engine->SetState(D3DSTATENORMAL); + } + device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true); + + size = m_size/2.0f; + if ( bUnder ) sizez = -size; + else sizez = size; + + // Draws all the lines. + deep = m_engine->GetDeepView(0)*1.5f; + + for ( i=0 ; i deep+radius ) continue; + + D3DVECTOR pD3D = VEC_TO_D3DVEC(p); + device->ComputeSphereVisibility(&pD3D, &radius, 1, 0, &flags); + + if ( flags & D3DSTATUS_CLIPINTERSECTIONALL ) continue; + + u = 0; + p.x = pos.x-size; + p.z = pos.z-sizez; + p.y = pos.y; + AdjustLevel(p, n, uv1, uv2); + if ( bUnder ) n.y = -n.y; + vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y); + + p.x = pos.x-size; + p.z = pos.z+sizez; + p.y = pos.y; + AdjustLevel(p, n, uv1, uv2); + if ( bUnder ) n.y = -n.y; + vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y); + + for ( j=0 ; jDrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, u, NULL); + m_engine->AddStatisticTriangle(u-2); + } + + free(vertex);*/ +} + +bool Gfx::CWater::GetWater(int x, int y) +{ + x *= m_subdiv; + y *= m_subdiv; + + float size = m_size/m_subdiv; + float offset = m_brick*m_size/2.0f; + + for (int dy = 0; dy <= m_subdiv; dy++) + { + for (int dx = 0; dx <= m_subdiv; dx++) + { + Math::Vector pos; + pos.x = (x+dx)*size - offset; + pos.z = (y+dy)*size - offset; + pos.y = 0.0f; + float level = m_terrain->GetFloorLevel(pos, true); + if (level < m_level+m_eddy.y) + return true; + } + } + return false; +} + +void Gfx::CWater::CreateLine(int x, int y, int len) +{ + Gfx::WaterLine line; + + line.x = x; + line.y = y; + line.len = len; + + float offset = m_brick*m_size/2.0f - m_size/2.0f; + + line.px1 = m_size* line.x - offset; + line.px2 = m_size*(line.x+line.len) - offset; + line.pz = m_size* line.y - offset; + + m_line.push_back(line); +} + +void Gfx::CWater::Create(Gfx::WaterType type1, Gfx::WaterType type2, const std::string& fileName, + Gfx::Color diffuse, Gfx::Color ambient, + float level, float glint, Math::Vector eddy) +{ + m_type[0] = type1; + m_type[1] = type2; + m_diffuse = diffuse; + m_ambient = ambient; + m_level = level; + m_glint = glint; + m_eddy = eddy; + m_time = 0.0f; + m_lastLava = 0.0f; + m_fileName = fileName; + + VaporFlush(); + + if (! m_fileName.empty()) + { + m_engine->LoadTexture(m_fileName, 0); + m_engine->LoadTexture(m_fileName, 1); + } + + if (m_terrain == nullptr) + m_terrain = static_cast(m_iMan->SearchInstance(CLASS_TERRAIN)); + + m_brick = m_terrain->GetBrick()*m_terrain->GetMosaic(); + m_size = m_terrain->GetSize(); + + m_brick /= m_subdiv; + m_size *= m_subdiv; + + if (m_type[0] == WATER_NULL) + return; + + m_line.clear(); + + for (int y = 0; y < m_brick; y++) + { + int len = 0; + for (int x = 0; x < m_brick; x++) + { + if (GetWater(x,y)) // water here? + { + len ++; + if (len >= 5) + { + CreateLine(x-len+1, y, len); + len = 0; + } + } + else // dry? + { + if (len != 0) + { + CreateLine(x-len, y, len); + len = 0; + } + } + } + if (len != 0) + CreateLine(m_brick - len, y, len); + } +} + +void Gfx::CWater::Flush() +{ + m_type[0] = Gfx::WATER_NULL; + m_type[1] = Gfx::WATER_NULL; + m_level = 0.0f; + m_lava = false; +} + +void Gfx::CWater::SetLevel(float level) +{ + m_level = level; + + Create(m_type[0], m_type[1], m_fileName, m_diffuse, m_ambient, + m_level, m_glint, m_eddy); +} + +float Gfx::CWater::GetLevel() +{ + return m_level; +} + +float Gfx::CWater::GetLevel(CObject* object) +{ + /* TODO! + ObjectType type = object->GetType(); + + if ( type == OBJECT_HUMAN || + type == OBJECT_TECH ) + { + return m_level-3.0f; + } + + if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEta || + type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEis || + type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs || + type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEtg || + type == OBJECT_MOBILEft || + type == OBJECT_MOBILEtt || + type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEit || + type == OBJECT_MOBILEdr ) + { + return m_level-2.0f; + } +*/ + return m_level; +} + +void Gfx::CWater::SetLava(bool lava) +{ + m_lava = lava; +} + +bool Gfx::CWater::GetLava() +{ + return m_lava; +} + +void Gfx::CWater::AdjustEye(Math::Vector &eye) +{ + if (m_lava) + { + if (eye.y < m_level+2.0f) + eye.y = m_level+2.0f; // never under the lava + } + else + { + if (eye.y >= m_level-2.0f && + eye.y <= m_level+2.0f) // close to the surface? + eye.y = m_level+2.0f; // bam, well above + } +} -// TODO implementation diff --git a/src/graphics/engine/water.h b/src/graphics/engine/water.h index 6d3736e..245baf7 100644 --- a/src/graphics/engine/water.h +++ b/src/graphics/engine/water.h @@ -19,50 +19,64 @@ #pragma once -#include "graphics/engine/engine.h" -#include "graphics/engine/particle.h" #include "common/event.h" +#include "graphics/engine/particle.h" class CInstanceManager; -class CSound; +class CSoundInterface; namespace Gfx { +class CEngine; class CTerrain; - -const short MAXWATERLINE = 500; - struct WaterLine { - short x, y; // beginning - short len; // length by x + //! Beginning + short x, y; + //! Length by x + short len; float px1, px2, pz; -}; - -const short MAXWATVAPOR = 10; + WaterLine() + { + x = y = 0; + len = 0; + px1 = px2 = pz = 0.0f; + } +}; struct WaterVapor { - bool bUsed; - ParticleType type; - Math::Vector pos; - float delay; - float time; - float last; + bool used; + Gfx::ParticleType type; + Math::Vector pos; + float delay; + float time; + float last; + + WaterVapor() + { + used = false; + type = Gfx::PARTIWATER; + delay = time = last = 0.0f; + } }; - enum WaterType { - WATER_NULL = 0, // no water - WATER_TT = 1, // transparent texture - WATER_TO = 2, // opaque texture - WATER_CT = 3, // transparent color - WATER_CO = 4, // opaque color + //! No water + WATER_NULL = 0, + //! Transparent texture + WATER_TT = 1, + //! Opaque texture + WATER_TO = 2, + //! Transparent color + WATER_CT = 3, + //! Opaque color + WATER_CO = 4, }; @@ -74,61 +88,86 @@ public: void SetDevice(Gfx::CDevice* device); bool EventProcess(const Event &event); + //! Removes all the water void Flush(); - bool Create(WaterType type1, WaterType type2, const char *filename, Gfx::Color diffuse, Gfx::Color ambient, float level, float glint, Math::Vector eddy); + //! Creates all expanses of water + void Create(WaterType type1, WaterType type2, const std::string& fileName, + Gfx::Color diffuse, Gfx::Color ambient, float level, float glint, Math::Vector eddy); + //! Draw the back surface of the water void DrawBack(); + //! Draws the flat surface of the water void DrawSurf(); - bool SetLevel(float level); + //! Changes the level of the water + void SetLevel(float level); + //! Returns the current level of water float GetLevel(); + //! Returns the current level of water for a given object float GetLevel(CObject* object); - void SetLava(bool bLava); + //@{ + //! Management of the mode of lava/water + void SetLava(bool lava); bool GetLava(); + //@} + //! Adjusts the eye of the camera, not to be in the water void AdjustEye(Math::Vector &eye); protected: + //! Makes water evolve bool EventFrame(const Event &event); + //! Makes evolve the steam jets on the lava void LavaFrame(float rTime); + //! Adjusts the position to normal, to imitate reflections on an expanse of water at rest void AdjustLevel(Math::Vector &pos, Math::Vector &norm, Math::Point &uv1, Math::Point &uv2); + //! Indicates if there is water in a given position bool GetWater(int x, int y); - bool CreateLine(int x, int y, int len); + //! Updates the positions, relative to the ground + void CreateLine(int x, int y, int len); + //! Removes all the steam jets void VaporFlush(); + //! Creates a new steam bool VaporCreate(ParticleType type, Math::Vector pos, float delay); + //! Makes evolve a steam jet void VaporFrame(int i, float rTime); protected: - CInstanceManager* m_iMan; - CEngine* m_engine; - CDevice* m_device; - CTerrain* m_terrain; - CParticle* m_particule; - CSound* m_sound; + CInstanceManager* m_iMan; + Gfx::CEngine* m_engine; + Gfx::CDevice* m_device; + Gfx::CTerrain* m_terrain; + Gfx::CParticle* m_particule; + CSoundInterface* m_sound; WaterType m_type[2]; - char m_filename[100]; - float m_level; // overall level - float m_glint; // amplitude of reflections - Math::Vector m_eddy; // amplitude of swirls - Gfx::Color m_diffuse; // diffuse color - Gfx::Color m_ambient; // ambient color + std::string m_fileName; + //! Overall level + float m_level; + //! Amplitude of reflections + float m_glint; + //! Amplitude of swirls + Math::Vector m_eddy; + //! Diffuse color + Gfx::Color m_diffuse; + //! Ambient color + Gfx::Color m_ambient; float m_time; float m_lastLava; - int m_subdiv; - - int m_brick; // number of brick*mosaics - float m_size; // size of a item in an brick + int m_subdiv; - int m_lineUsed; - WaterLine m_line[MAXWATERLINE]; + //! Number of brick*mosaics + int m_brick; + //! Size of a item in an brick + float m_size; - WaterVapor m_vapor[MAXWATVAPOR]; + std::vector m_line; + std::vector m_vapor; - bool m_bDraw; - bool m_bLava; - long m_color; + bool m_draw; + bool m_lava; + long m_color; }; }; // namespace Gfx -- cgit v1.2.3-1-g7c22 From f1d1cdceee3ec49546ba800a1b53a2dfb9c21e11 Mon Sep 17 00:00:00 2001 From: erihel Date: Thu, 9 Aug 2012 21:21:14 +0200 Subject: Changes after merge --- src/plugins/plugin.cpp | 97 ---------------------------------------- src/plugins/plugin.h | 46 ------------------- src/plugins/pluginloader.cpp | 97 ++++++++++++++++++++++++++++++++++++++++ src/plugins/pluginloader.h | 46 +++++++++++++++++++ src/plugins/test/CMakeLists.txt | 2 +- src/plugins/test/plugin_test.cpp | 4 +- src/sound/sound.h | 4 +- 7 files changed, 148 insertions(+), 148 deletions(-) delete mode 100644 src/plugins/plugin.cpp delete mode 100644 src/plugins/plugin.h create mode 100644 src/plugins/pluginloader.cpp create mode 100644 src/plugins/pluginloader.h (limited to 'src') diff --git a/src/plugins/plugin.cpp b/src/plugins/plugin.cpp deleted file mode 100644 index ca0fe0e..0000000 --- a/src/plugins/plugin.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// * This file is part of the COLOBOT source code -// * Copyright (C) 2012 Polish Portal of Colobot (PPC) -// * -// * 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/. - -// plugin.cpp - - -#include "plugin.h" - - -CPlugin::CPlugin(std::string filename) -{ - mInterface = nullptr; - mFilename = filename; - mLoaded = false; -} - - -char* CPlugin::GetName() -{ - if (mLoaded) - return mInterface->PluginName(); - return nullptr; -} - - -int CPlugin::GetVersion() -{ - if (mLoaded) - return mInterface->PluginVersion(); - return 0; -} - - -bool CPlugin::IsLoaded() -{ - return mLoaded; -} - - -bool CPlugin::UnloadPlugin() -{ - if (!mLoaded) { - GetLogger()->Warn("Plugin %s is not loaded.\n"); - return true; - } - - void (*uninstall)() = (void (*)()) lt_dlsym(mHandle, "UninstallPluginEntry"); - if (!uninstall) { - GetLogger()->Error("Error getting UninstallPluginEntry for plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); - return false; - } - - lt_dlclose(mHandle); - mLoaded = false; - return true; -} - - -bool CPlugin::LoadPlugin() -{ - mHandle = lt_dlopenext(mFilename.c_str()); - if (!mHandle) { - GetLogger()->Error("Error loading plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); - return false; - } - - void (*install)() = (void (*)()) lt_dlsym(mHandle, "InstallPluginEntry"); - if (!install) { - GetLogger()->Error("Error getting InstallPluginEntry for plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); - return false; - } - - CPluginInterface* (*getInterface)() = (CPluginInterface* (*)()) lt_dlsym(mHandle, "GetPluginInterfaceEntry"); - - if (!getInterface) { - GetLogger()->Error("Error getting GetPluginInterfaceEntry for plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); - return false; - } - - install(); - mInterface = getInterface(); - mLoaded = true; - return true; -} diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h deleted file mode 100644 index e7d4b12..0000000 --- a/src/plugins/plugin.h +++ /dev/null @@ -1,46 +0,0 @@ -// * This file is part of the COLOBOT source code -// * Copyright (C) 2012, Polish Portal of Colobot (PPC) -// * -// * 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/. - -// plugin.h - - -#pragma once - -#include -#include - -#include - -#include "plugininterface.h" - - -class CPlugin { - public: - CPlugin(std::string filename); - - char* GetName(); - int GetVersion(); - bool UnloadPlugin(); - bool LoadPlugin(); - bool IsLoaded(); - - - private: - CPluginInterface* mInterface; - std::string mFilename; - lt_dlhandle mHandle; - bool mLoaded; -}; diff --git a/src/plugins/pluginloader.cpp b/src/plugins/pluginloader.cpp new file mode 100644 index 0000000..adceb6b --- /dev/null +++ b/src/plugins/pluginloader.cpp @@ -0,0 +1,97 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012 Polish Portal of Colobot (PPC) +// * +// * 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/. + +// pluginloader.cpp + + +#include "pluginloader.h" + + +CPluginLoader::CPluginLoader(std::string filename) +{ + mInterface = nullptr; + mFilename = filename; + mLoaded = false; +} + + +char* CPluginLoader::GetName() +{ + if (mLoaded) + return mInterface->PluginName(); + return nullptr; +} + + +int CPluginLoader::GetVersion() +{ + if (mLoaded) + return mInterface->PluginVersion(); + return 0; +} + + +bool CPluginLoader::IsLoaded() +{ + return mLoaded; +} + + +bool CPluginLoader::UnloadPlugin() +{ + if (!mLoaded) { + GetLogger()->Warn("Plugin %s is not loaded.\n"); + return true; + } + + void (*uninstall)() = (void (*)()) lt_dlsym(mHandle, "UninstallPluginEntry"); + if (!uninstall) { + GetLogger()->Error("Error getting UninstallPluginEntry for plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); + return false; + } + + lt_dlclose(mHandle); + mLoaded = false; + return true; +} + + +bool CPluginLoader::LoadPlugin() +{ + mHandle = lt_dlopenext(mFilename.c_str()); + if (!mHandle) { + GetLogger()->Error("Error loading plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); + return false; + } + + void (*install)() = (void (*)()) lt_dlsym(mHandle, "InstallPluginEntry"); + if (!install) { + GetLogger()->Error("Error getting InstallPluginEntry for plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); + return false; + } + + CPluginInterface* (*getInterface)() = (CPluginInterface* (*)()) lt_dlsym(mHandle, "GetPluginInterfaceEntry"); + + if (!getInterface) { + GetLogger()->Error("Error getting GetPluginInterfaceEntry for plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); + return false; + } + + install(); + mInterface = getInterface(); + mLoaded = true; + return true; +} diff --git a/src/plugins/pluginloader.h b/src/plugins/pluginloader.h new file mode 100644 index 0000000..d9ee041 --- /dev/null +++ b/src/plugins/pluginloader.h @@ -0,0 +1,46 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// pluginloader.h + + +#pragma once + +#include +#include + +#include + +#include "plugininterface.h" + + +class CPluginLoader { + public: + CPluginLoader(std::string filename); + + char* GetName(); + int GetVersion(); + bool UnloadPlugin(); + bool LoadPlugin(); + bool IsLoaded(); + + + private: + CPluginInterface* mInterface; + std::string mFilename; + lt_dlhandle mHandle; + bool mLoaded; +}; diff --git a/src/plugins/test/CMakeLists.txt b/src/plugins/test/CMakeLists.txt index 551daeb..5953468 100644 --- a/src/plugins/test/CMakeLists.txt +++ b/src/plugins/test/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8) set(CMAKE_BUILD_TYPE debug) set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0 -std=c++11 -rdynamic") -add_executable(plugin_test plugin_test.cpp ../../common/iman.cpp ../../common/logger.cpp ../plugin.cpp) +add_executable(plugin_test plugin_test.cpp ../../common/iman.cpp ../../common/logger.cpp ../pluginloader.cpp) # Change to DirectX SDK directory include_directories("../../") diff --git a/src/plugins/test/plugin_test.cpp b/src/plugins/test/plugin_test.cpp index 7175773..9aadfac 100644 --- a/src/plugins/test/plugin_test.cpp +++ b/src/plugins/test/plugin_test.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include int main() { @@ -14,7 +14,7 @@ int main() { lt_dlinit(); - CPlugin *plugin = new CPlugin("libopenalsound"); + CPluginLoader *plugin = new CPluginLoader("libopenalsound"); if (plugin->LoadPlugin()) { CSoundInterface *sound = static_cast(CInstanceManager::GetInstancePointer()->SearchInstance(CLASS_SOUND)); diff --git a/src/sound/sound.h b/src/sound/sound.h index d323918..f18a76a 100644 --- a/src/sound/sound.h +++ b/src/sound/sound.h @@ -26,7 +26,7 @@ #include -#include +#include #include @@ -148,7 +148,7 @@ enum SoundNext * @brief Sound plugin interface * */ -class CSoundInterface : public CPlugin +class CSoundInterface : public CPluginInterface { public: CSoundInterface() { -- cgit v1.2.3-1-g7c22 From acff306cc132c4f8cc71f44f85ffd7bdd18a114e Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Thu, 9 Aug 2012 22:49:13 +0200 Subject: CPlanet implementation Added rewritten CPlanet implementation --- src/graphics/engine/planet.cpp | 164 ++++++++++++++++++++++++++++++++++++++++- src/graphics/engine/planet.h | 72 +++++++++++------- 2 files changed, 209 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/graphics/engine/planet.cpp b/src/graphics/engine/planet.cpp index 4f1f614..022de66 100644 --- a/src/graphics/engine/planet.cpp +++ b/src/graphics/engine/planet.cpp @@ -19,5 +19,167 @@ #include "graphics/engine/planet.h" +#include "common/iman.h" +#include "graphics/core/device.h" +#include "graphics/engine/engine.h" -// TODO implementation + +const int PLANET_PREALLOCATE_COUNT = 10; + + +Gfx::CPlanet::CPlanet(CInstanceManager* iMan, Gfx::CEngine* engine) +{ + m_iMan = iMan; + m_iMan->AddInstance(CLASS_PLANET, this); + + m_planet[0].reserve(PLANET_PREALLOCATE_COUNT); + m_planet[1].reserve(PLANET_PREALLOCATE_COUNT); + + m_engine = engine; + Flush(); + +} + +Gfx::CPlanet::~CPlanet() +{ + m_iMan = nullptr; +} + +void Gfx::CPlanet::Flush() +{ + for (int j = 0; j < 2; j++) + m_planet[j].clear(); + + m_planetExist = false; + m_mode = 0; + m_time = 0.0f; +} + +bool Gfx::CPlanet::EventProcess(const Event &event) +{ + if (event.type == EVENT_FRAME) + return EventFrame(event); + + return true; +} + +bool Gfx::CPlanet::EventFrame(const Event &event) +{ + if (m_engine->GetPause()) return true; + + m_time += event.rTime; + + for (int i = 0; i < static_cast( m_planet[m_mode].size() ); i++) + { + float a = m_time*m_planet[m_mode][i].speed; + if (a < 0.0f) + a += Math::PI*1000.0f; + + m_planet[m_mode][i].angle.x = a+m_planet[m_mode][i].start.x; + m_planet[m_mode][i].angle.y = sinf(a)*sinf(m_planet[m_mode][i].dir)+m_planet[m_mode][i].start.y; + } + + return true; +} + +void Gfx::CPlanet::LoadTexture() +{ + for (int j = 0; j < 2; j++) + { + for (int i = 0; i < static_cast( m_planet[j].size() ); i++) + { + m_engine->LoadTexture(m_planet[j][i].name); + } + } +} + +void Gfx::CPlanet::Draw() +{ + Gfx::CDevice* device = m_engine->GetDevice(); + float eyeDirH = m_engine->GetEyeDirH(); + float eyeDirV = m_engine->GetEyeDirV(); + + Math::Vector n = Math::Vector(0.0f, 0.0f, -1.0f); // normal + float dp = 0.5f/256.0f; + + for (int i = 0; i < static_cast( m_planet[m_mode].size() ); i++) + { + m_engine->SetTexture(m_planet[m_mode][i].name); + + if (m_planet[m_mode][i].transparent) + m_engine->SetState(Gfx::ENG_RSTATE_WRAP | Gfx::ENG_RSTATE_ALPHA); + else + m_engine->SetState(Gfx::ENG_RSTATE_WRAP | Gfx::ENG_RSTATE_TTEXTURE_BLACK); + + Math::Point p1, p2; + + float a = eyeDirH + m_planet[m_mode][i].angle.x; + p1.x = Math::Mod(a, Math::PI*2.0f)-0.5f; + + a = eyeDirV + m_planet[m_mode][i].angle.y; + p1.y = 0.4f+(Math::Mod(a+Math::PI, Math::PI*2.0f)-Math::PI)*(2.0f/Math::PI); + + p1.x -= m_planet[m_mode][i].dim/2.0f*0.75f; + p1.y -= m_planet[m_mode][i].dim/2.0f; + p2.x = p1.x+m_planet[m_mode][i].dim*0.75f; + p2.y = p1.y+m_planet[m_mode][i].dim; + + float u1 = m_planet[m_mode][i].uv1.x + dp; + float v1 = m_planet[m_mode][i].uv1.y + dp; + float u2 = m_planet[m_mode][i].uv2.x - dp; + float v2 = m_planet[m_mode][i].uv2.y - dp; + + Gfx::Vertex quad[4] = + { + Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), n, Math::Point(u1, v2)), + Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), n, Math::Point(u1, v1)), + Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(u2, v2)), + Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(u2, v1)) + }; + + device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); + m_engine->AddStatisticTriangle(2); + } +} + +void Gfx::CPlanet::Create(int mode, Math::Point start, float dim, float speed, + float dir, const std::string& name, Math::Point uv1, Math::Point uv2) +{ + if (mode < 0) mode = 0; + if (mode > 1) mode = 1; + + Gfx::Planet planet; + + planet.start = start; + planet.angle = start; + planet.dim = dim; + planet.speed = speed; + planet.dir = dir; + + planet.name = name; + planet.uv1 = uv1; + planet.uv2 = uv2; + + planet.transparent = planet.name.find("planet") != std::string::npos; + + m_planet[mode].push_back(planet); + + m_planetExist = true; +} + +bool Gfx::CPlanet::PlanetExist() +{ + return m_planetExist; +} + +void Gfx::CPlanet::SetMode(int mode) +{ + if (mode < 0) mode = 0; + if (mode > 1) mode = 1; + m_mode = mode; +} + +int Gfx::CPlanet::GetMode() +{ + return m_mode; +} diff --git a/src/graphics/engine/planet.h b/src/graphics/engine/planet.h index 264d05c..5ba318b 100644 --- a/src/graphics/engine/planet.h +++ b/src/graphics/engine/planet.h @@ -22,6 +22,8 @@ #include "common/event.h" #include "math/point.h" +#include + class CInstanceManager; @@ -30,51 +32,69 @@ namespace Gfx { class CEngine; - -const short MAXPLANET = 10; - struct Planet { - char bUsed; // TRUE -> planet exists - Math::Point start; // initial position in degrees - Math::Point angle; // current position in degrees - float dim; // dimensions (0..1) - float speed; // speed - float dir; // direction in the sky - char name[20]; // name of the texture - Math::Point uv1, uv2; // texture mapping - char bTGA; // texture .TGA + //! Initial position in degrees + Math::Point start; + //! Current position in degrees + Math::Point angle; + //! Dimensions (0..1) + float dim; + //! Speed + float speed; + //! Direction in the sky + float dir; + //! Name of the texture + std::string name; + //! Texture mapping + Math::Point uv1, uv2; + //! Transparent texture + bool transparent; + + Planet() + { + dim = speed = dir = 0.0f; + transparent = false; + } }; - - - -class CPlanet { +class CPlanet +{ public: - CPlanet(CInstanceManager* iMan, CEngine* engine); + CPlanet(CInstanceManager* iMan, Gfx::CEngine* engine); ~CPlanet(); + //! Removes all the planets void Flush(); + //! Management of an event bool EventProcess(const Event &event); - bool Create(int mode, Math::Point start, float dim, float speed, float dir, char *name, Math::Point uv1, Math::Point uv2); + //! Creates a new planet + void Create(int mode, Math::Point start, float dim, float speed, float dir, + const std::string& name, Math::Point uv1, Math::Point uv2); + //! Indicates if there is at least one planet bool PlanetExist(); + //! Load all the textures for the planets void LoadTexture(); + //! Draws all the planets void Draw(); + //@{ + //! Choice of mode void SetMode(int mode); - int RetMode(); + int GetMode(); + //@} protected: + //! Makes the planets evolve bool EventFrame(const Event &event); protected: - CInstanceManager* m_iMan; - CEngine* m_engine; + CInstanceManager* m_iMan; + Gfx::CEngine* m_engine; - float m_time; - int m_mode; - Planet m_planet[2][MAXPLANET]; - bool m_bPlanetExist; + float m_time; + int m_mode; + std::vector m_planet[2]; + bool m_planetExist; }; - }; // namespace Gfx -- cgit v1.2.3-1-g7c22 From c3ab23ac9dc02d59180f2f1af5f3aa5b50f9f8d8 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Thu, 9 Aug 2012 22:50:04 +0200 Subject: Graphics stubs - added stubs for functions in CLightning, CParticle and CPyro - cleaned object.h and physics.h headers - created temporary stubs to compile CCamera - other necessary changes to compile successfully --- src/CMakeLists.txt | 2 +- src/common/event.h | 59 ++++---- src/graphics/engine/camera.cpp | 81 +++++++++-- src/graphics/engine/camera.h | 4 +- src/graphics/engine/cloud.cpp | 8 +- src/graphics/engine/engine.cpp | 129 ++++++++++++++++- src/graphics/engine/engine.h | 22 ++- src/graphics/engine/lightning.cpp | 68 ++++++++- src/graphics/engine/lightning.h | 2 +- src/graphics/engine/particle.cpp | 281 +++++++++++++++++++++++++++++++++++++- src/graphics/engine/particle.h | 91 ++++++------ src/graphics/engine/pyro.cpp | 158 ++++++++++++++++++++- src/graphics/engine/pyro.h | 51 ++++--- src/graphics/engine/water.cpp | 6 +- src/object/object.h | 220 ++++++++++++++--------------- src/physics/physics.h | 82 +++++------ 16 files changed, 989 insertions(+), 275 deletions(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 25a576e..b998d19 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -67,7 +67,7 @@ common/iman.cpp # common/restext.cpp common/stringutils.cpp graphics/core/color.cpp -# graphics/engine/camera.cpp # new code but depends on other modules +graphics/engine/camera.cpp graphics/engine/cloud.cpp graphics/engine/engine.cpp graphics/engine/lightman.cpp diff --git a/src/common/event.h b/src/common/event.h index 0d9aa7c..a82282e 100644 --- a/src/common/event.h +++ b/src/common/event.h @@ -40,9 +40,10 @@ enum EventType EVENT_NULL = 0, //! Event sent on user or system quit request - EVENT_QUIT = 1, + EVENT_QUIT = 1, - //? EVENT_FRAME = 2, + //! Frame update event + EVENT_FRAME = 2, //! Event sent after pressing a mouse button EVENT_MOUSE_BUTTON_DOWN = 3, @@ -669,29 +670,41 @@ struct Event //! If true, the event was produced by system (SDL); else, it has come from user interface bool systemEvent; - //! Additional data for EVENT_KEY_DOWN and EVENT_KEY_UP - KeyEventData key; - //! Additional data for EVENT_MOUSE_BUTTON_DOWN and EVENT_MOUSE_BUTTON_UP - MouseButtonEventData mouseButton; - //! Additional data for EVENT_MOUSE_MOVE - MouseMoveEventData mouseMove; - //! Additional data for EVENT_JOY - JoyAxisEventData joyAxis; - //! Additional data for EVENT_JOY_AXIS - JoyButtonEventData joyButton; - //! Additional data for EVENT_ACTIVE - ActiveEventData active; - - //? long param; // parameter - //? Math::Point pos; // mouse position (0 .. 1) - //? float axeX; // control the X axis (-1 .. 1) - //? float axeY; // control of the Y axis (-1 .. 1) - //? float axeZ; // control the Z axis (-1 .. 1) - //? short keyState; // state of the keyboard (KS_ *) - //? float rTime; // relative time + union + { + //! Additional data for EVENT_KEY_DOWN and EVENT_KEY_UP + KeyEventData key; + //! Additional data for EVENT_MOUSE_BUTTON_DOWN and EVENT_MOUSE_BUTTON_UP + MouseButtonEventData mouseButton; + //! Additional data for EVENT_MOUSE_MOVE + MouseMoveEventData mouseMove; + //! Additional data for EVENT_JOY + JoyAxisEventData joyAxis; + //! Additional data for EVENT_JOY_AXIS + JoyButtonEventData joyButton; + //! Additional data for EVENT_ACTIVE + ActiveEventData active; + }; + + // TODO: refactor/rewrite + long param; // parameter + Math::Point pos; // mouse position (0 .. 1) + float axeX; // control the X axis (-1 .. 1) + float axeY; // control of the Y axis (-1 .. 1) + float axeZ; // control the Z axis (-1 .. 1) + short keyState; // state of the keyboard (KS_ *) + float rTime; // relative time Event(EventType aType = EVENT_NULL) - : type(aType), systemEvent(false) {} + { + type = aType; + systemEvent = false; + + param = 0; + axeX = axeY = axeZ = 0.0f; + keyState = 0; + rTime = 0.0f; + } }; diff --git a/src/graphics/engine/camera.cpp b/src/graphics/engine/camera.cpp index c7ca503..2db6398 100644 --- a/src/graphics/engine/camera.cpp +++ b/src/graphics/engine/camera.cpp @@ -29,6 +29,66 @@ #include "physics/physics.h" +// TODO temporary stubs for CObject and CPhysics + +void CObject::SetTransparency(float) +{ +} + +CObject* CObject::GetFret() +{ + return nullptr; +} + +CObject* CObject::GetPower() +{ + return nullptr; +} + +CObject* CObject::GetTruck() +{ + return nullptr; +} + +ObjectType CObject::GetType() +{ + return OBJECT_NULL; +} + +void CObject::SetGunGoalH(float) +{ +} + +void CObject::GetGlobalSphere(Math::Vector &pos, float &radius) +{ +} + +float CObject::GetAngleY(int) +{ + return 0.0f; +} + +Math::Vector CObject::GetPosition(int) +{ + return Math::Vector(); +} + +void CObject::SetViewFromHere(Math::Vector &eye, float &dirH, float &dirV, + Math::Vector &lookat, Math::Vector &upVec, + Gfx::CameraType type) +{ +} + +CPhysics* CObject::GetPhysics() +{ + return nullptr; +} + +bool CPhysics::GetLand() +{ + return false; +} + //! Changes the level of transparency of an object and objects transported (battery & cargo) void SetTransparency(CObject* obj, float value) { @@ -332,7 +392,7 @@ void Gfx::CCamera::SetType(CameraType type) SetSmooth(Gfx::CAM_SMOOTH_NORM); } -CameraType Gfx::CCamera::GetType() +Gfx::CameraType Gfx::CCamera::GetType() { return m_type; } @@ -342,7 +402,7 @@ void Gfx::CCamera::SetSmooth(CameraSmooth type) m_smooth = type; } -CameraSmooth Gfx::CCamera::GetSmoth() +Gfx::CameraSmooth Gfx::CCamera::GetSmoth() { return m_smooth; } @@ -692,7 +752,7 @@ void Gfx::CCamera::OverFrame(const Event &event) } else { - color = Gfx::Color(0.0f. 0.0f, 0.0f); + color = Gfx::Color(0.0f, 0.0f, 0.0f); } color.a = 0.0f; m_engine->SetOverColor(color, m_overMode); @@ -873,7 +933,7 @@ bool Gfx::CCamera::IsCollisionBack(Math::Vector &eye, Math::Vector lookat) for (int i = 0 ;i < 1000000; i++) { - CObject *obj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + CObject *obj = static_cast( m_iMan->SearchInstance(CLASS_OBJECT, i) ); if (obj == NULL) break; if (obj->GetTruck()) continue; // battery or cargo? @@ -899,7 +959,7 @@ bool Gfx::CCamera::IsCollisionBack(Math::Vector &eye, Math::Vector lookat) iType == OBJECT_SAFE || iType == OBJECT_HUSTON ) continue; - ObjType oType = obj->GetType(); + ObjectType oType = obj->GetType(); if ( oType == OBJECT_HUMAN || oType == OBJECT_TECH || oType == OBJECT_TOTO || @@ -995,7 +1055,6 @@ bool Gfx::CCamera::EventProcess(const Event &event) { switch (event.type) { - // TODO: frame update event case EVENT_FRAME: EventFrame(event); break; @@ -1004,11 +1063,11 @@ bool Gfx::CCamera::EventProcess(const Event &event) EventMouseMove(event); break; - case EVENT_KEY_DOWN: - // TODO: mouse wheel event + // TODO: mouse wheel event + /*case EVENT_KEY_DOWN: if ( event.param == VK_WHEELUP ) EventMouseWheel(+1); if ( event.param == VK_WHEELDOWN ) EventMouseWheel(-1); - break; + break;*/ default: break; @@ -1489,8 +1548,6 @@ bool Gfx::CCamera::EventFrameFix(const Event &event) bool Gfx::CCamera::EventFrameExplo(const Event &event) { - float factor = m_heightEye * 0.5f + 30.0f; - if (m_mouseDirH != 0.0f) m_directionH -= m_mouseDirH * event.rTime * 0.7f * m_speed; @@ -1526,7 +1583,7 @@ bool Gfx::CCamera::EventFrameOnBoard(const Event &event) { Math::Vector lookatPt, upVec; m_cameraObj->SetViewFromHere(m_eyePt, m_directionH, m_directionV, - lookatPt, vUpVec, m_type); + lookatPt, upVec, m_type); Math::Vector eye = m_effectOffset * 0.3f + m_eyePt; Math::Vector lookat = m_effectOffset * 0.3f + lookatPt; diff --git a/src/graphics/engine/camera.h b/src/graphics/engine/camera.h index 935f8b0..ec6afcb 100644 --- a/src/graphics/engine/camera.h +++ b/src/graphics/engine/camera.h @@ -353,13 +353,13 @@ protected: float m_centeringTime; float m_centeringProgress; - CameraEffect m_effectType; + Gfx::CameraEffect m_effectType; Math::Vector m_effectPos; float m_effectForce; float m_effectProgress; Math::Vector m_effectOffset; - OverEffect m_overType; + Gfx::CameraOverEffect m_overType; float m_overForce; float m_overTime; Gfx::Color m_overColorBase; diff --git a/src/graphics/engine/cloud.cpp b/src/graphics/engine/cloud.cpp index e46b074..71dd969 100644 --- a/src/graphics/engine/cloud.cpp +++ b/src/graphics/engine/cloud.cpp @@ -55,16 +55,14 @@ Gfx::CCloud::~CCloud() bool Gfx::CCloud::EventProcess(const Event &event) { - /* TODO! - if ( event.event == EVENT_FRAME ) - return EventFrame(event); */ + if ( event.type == EVENT_FRAME ) + return EventFrame(event); return true; } bool Gfx::CCloud::EventFrame(const Event &event) { - /* TODO! if (m_engine->GetPause()) return true; m_time += event.rTime; @@ -73,7 +71,7 @@ bool Gfx::CCloud::EventFrame(const Event &event) if (m_time - m_lastTest < 0.2f) return true; - m_lastTest = m_time; */ + m_lastTest = m_time; return true; } diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 4bf80d2..c8fa05c 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -25,8 +25,16 @@ #include "common/key.h" #include "common/logger.h" #include "graphics/core/device.h" +#include "graphics/engine/camera.h" +#include "graphics/engine/cloud.h" #include "graphics/engine/lightman.h" +#include "graphics/engine/lightning.h" +#include "graphics/engine/particle.h" +#include "graphics/engine/planet.h" +#include "graphics/engine/pyro.h" +#include "graphics/engine/terrain.h" #include "graphics/engine/text.h" +#include "graphics/engine/water.h" #include "math/geometry.h" // Initial size of various vectors @@ -207,12 +215,11 @@ bool Gfx::CEngine::Create() m_lightMan = new Gfx::CLightManager(m_iMan, this); m_text = new Gfx::CText(m_iMan, this); - /* TODO: m_particle = new Gfx::CParticle(m_iMan, this); m_water = new Gfx::CWater(m_iMan, this); m_cloud = new Gfx::CCloud(m_iMan, this); m_lightning = new Gfx::CLightning(m_iMan, this); - m_planet = new Gfx::CPlanet(m_iMan, this);*/ + m_planet = new Gfx::CPlanet(m_iMan, this); m_text->SetDevice(m_device); if (! m_text->Create()) @@ -250,7 +257,6 @@ void Gfx::CEngine::Destroy() delete m_text; m_text = nullptr; - /* TODO: delete m_particle; m_particle = nullptr; @@ -264,7 +270,7 @@ void Gfx::CEngine::Destroy() m_lightning = nullptr; delete m_planet; - m_planet = nullptr;*/ + m_planet = nullptr; } void Gfx::CEngine::ResetAfterDeviceChanged() @@ -807,3 +813,118 @@ bool Gfx::CEngine::GetShowStat() return m_showStats; } +void Gfx::CEngine::SetFocus(float focus) +{ + m_focus = focus; +} + + +void Gfx::CEngine::SetOverColor(const Gfx::Color& color, int mode) +{ + // TODO! +} + +void Gfx::CEngine::SetFogColor(const Gfx::Color& color, int rank) +{ + // TODO! +} + +Gfx::Color Gfx::CEngine::GetFogColor(int rank) +{ + // TODO! + return Gfx::Color(); +} + +void Gfx::CEngine::SetViewParams(const Math::Vector& eyePt, const Math::Vector& lookatPt, + const Math::Vector& upVec, float eyeDistance) +{ + // TODO! +} + +void Gfx::CEngine::SetRankView(int rank) +{ + m_rankView = rank; +} + +float Gfx::CEngine::GetEyeDirH() +{ + return m_eyeDirH; +} + +float Gfx::CEngine::GetEyeDirV() +{ + return m_eyeDirV; +} + +float Gfx::CEngine::GetClippingDistance() +{ + return m_clippingDistance; +} + +bool Gfx::CEngine::GetGroundSpot() +{ + return m_groundSpotVisible; +} + +void Gfx::CEngine::SetTerrain(Gfx::CTerrain* terrain) +{ + m_terrain = terrain; +} + +void Gfx::CEngine::SetTerrainVision(float vision) +{ + // TODO! +} + +bool Gfx::CEngine::LoadTexture(const std::string& name, int stage) +{ + // TODO! + return true; +} + +float Gfx::CEngine::ParticleAdapt(float factor) +{ + // TODO! + return 0.0f; +} + +bool Gfx::CEngine::SetObjectType(int objRank, Gfx::EngineObjectType type) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectTransform(int objRank, const Math::Matrix& transform) +{ + // TODO! + return true; +} + +int Gfx::CEngine::CreateObject() +{ + // TODO! + return 0; +} + +bool Gfx::CEngine::DeleteObject(int objRank) +{ + // TODO! + return true; +} + +int Gfx::CEngine::GroundMarkCreate(Math::Vector pos, float radius, float delay1, float delay2, float delay3, int dx, int dy, char* table) +{ + // TODO! + return 0; +} + +bool Gfx::CEngine::AddQuick(int objRank, const Gfx::EngineObjLevel5& buffer, std::string texName1, std::string texName2, float min, float max, bool globalUpdate) +{ + // TODO! + return false; +} + +void Gfx::CEngine::Update() +{ + // TODO! +} diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index cd89a1c..e61aca6 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -170,7 +170,10 @@ struct EngineObjLevel5 Gfx::EngineTriangleType type; std::vector vertices; - EngineObjLevel5(); + EngineObjLevel5() + { + state = 0; + } }; /** @@ -182,7 +185,10 @@ struct EngineObjLevel4 std::vector up; Gfx::EngineObjLevel3* down; - EngineObjLevel4(); + EngineObjLevel4() + { + reserved = 0; + } }; /** @@ -195,7 +201,10 @@ struct EngineObjLevel3 std::vector up; Gfx::EngineObjLevel2* down; - EngineObjLevel3(); + EngineObjLevel3() + { + min = max = 0.0f; + } }; /** @@ -207,7 +216,10 @@ struct EngineObjLevel2 std::vector up; Gfx::EngineObjLevel1* down; - EngineObjLevel2(); + EngineObjLevel2() + { + objRank = 0; + } }; /** @@ -219,7 +231,7 @@ struct EngineObjLevel1 Gfx::Texture tex2; std::vector up; - EngineObjLevel1(); + EngineObjLevel1() {} }; /** diff --git a/src/graphics/engine/lightning.cpp b/src/graphics/engine/lightning.cpp index 4db5511..4ecdb3c 100644 --- a/src/graphics/engine/lightning.cpp +++ b/src/graphics/engine/lightning.cpp @@ -19,5 +19,71 @@ #include "graphics/engine/lightning.h" +#include "common/logger.h" -// TODO implementation + +Gfx::CLightning::CLightning(CInstanceManager* iMan, Gfx::CEngine* engine) +{ + GetLogger()->Info("CLightning::CLightning() stub!\n"); + // TODO! +} + +Gfx::CLightning::~CLightning() +{ + GetLogger()->Info("CLightning::~CLightning() stub!\n"); + // TODO! +} + +void Gfx::CLightning::Flush() +{ + GetLogger()->Info("CLightning::Flush() stub!\n"); + // TODO! +} + +bool Gfx::CLightning::EventProcess(const Event &event) +{ + GetLogger()->Info("CLightning::EventProcess() stub!\n"); + // TODO! + return true; +} + +bool Gfx::CLightning::Create(float sleep, float delay, float magnetic) +{ + GetLogger()->Info("CLightning::Create() stub!\n"); + // TODO! + return true; +} + +bool Gfx::CLightning::GetStatus(float &sleep, float &delay, float &magnetic, float &progress) +{ + GetLogger()->Info("CLightning::GetStatus() stub!\n"); + // TODO! + return true; +} + +bool Gfx::CLightning::SetStatus(float sleep, float delay, float magnetic, float progress) +{ + GetLogger()->Info("CLightning::SetStatus() stub!\n"); + // TODO! + return true; +} + +void Gfx::CLightning::Draw() +{ + GetLogger()->Info("CLightning::Draw() stub!\n"); + // TODO! +} + +bool Gfx::CLightning::EventFrame(const Event &event) +{ + GetLogger()->Info("CLightning::EventFrame() stub!\n"); + // TODO! + return true; +} + +CObject* Gfx::CLightning::SearchObject(Math::Vector pos) +{ + GetLogger()->Info("CLightning::SearchObject() stub!\n"); + // TODO! + return nullptr; +} diff --git a/src/graphics/engine/lightning.h b/src/graphics/engine/lightning.h index 957344c..9e854be 100644 --- a/src/graphics/engine/lightning.h +++ b/src/graphics/engine/lightning.h @@ -73,7 +73,7 @@ protected: float m_sleep; float m_delay; float m_magnetic; - BlitzPhase m_phase; + Gfx::BlitzPhase m_phase; float m_time; float m_speed; float m_progress; diff --git a/src/graphics/engine/particle.cpp b/src/graphics/engine/particle.cpp index 84e2f9d..9a21fe0 100644 --- a/src/graphics/engine/particle.cpp +++ b/src/graphics/engine/particle.cpp @@ -19,5 +19,284 @@ #include "graphics/engine/particle.h" +#include "common/logger.h" -// TODO implementation + +Gfx::CParticle::CParticle(CInstanceManager* iMan, Gfx::CEngine* engine) +{ + GetLogger()->Info("CParticle::CParticle() stub!\n"); + // TODO! +} + +Gfx::CParticle::~CParticle() +{ + GetLogger()->Info("CParticle::~CParticle() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetDevice(Gfx::CDevice* device) +{ + GetLogger()->Info("CParticle::SetDevice() stub!\n"); + // TODO! +} + +void Gfx::CParticle::FlushParticle() +{ + GetLogger()->Info("CParticle::FlushParticle() stub!\n"); + // TODO! +} + +void Gfx::CParticle::FlushParticle(int sheet) +{ + GetLogger()->Info("CParticle::FlushParticle() stub!\n"); + // TODO! +} + +int Gfx::CParticle::CreateParticle(Math::Vector pos, Math::Vector speed, Math::Point dim, + Gfx::ParticleType type, float duration, float mass, + float windSensitivity, int sheet) +{ + GetLogger()->Info("CParticle::CreateParticle() stub!\n"); + // TODO! + return 0; +} + +int Gfx::CParticle::CreateFrag(Math::Vector pos, Math::Vector speed, Gfx::EngineTriangle *triangle, + Gfx::ParticleType type, float duration, float mass, + float windSensitivity, int sheet) +{ + GetLogger()->Info("CParticle::CreateFrag() stub!\n"); + // TODO! + return 0; +} + +int Gfx::CParticle::CreatePart(Math::Vector pos, Math::Vector speed, Gfx::ParticleType type, + float duration, float mass, float weight, + float windSensitivity, int sheet) +{ + GetLogger()->Info("CParticle::CreatePart() stub!\n"); + // TODO! + return 0; +} + +int Gfx::CParticle::CreateRay(Math::Vector pos, Math::Vector goal, Gfx::ParticleType type, Math::Point dim, + float duration, int sheet) +{ + GetLogger()->Info("CParticle::CreateRay() stub!\n"); + // TODO! + return 0; +} + +int Gfx::CParticle::CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, Gfx::ParticleType type, + float duration, float mass, float length, float width) +{ + GetLogger()->Info("CParticle::CreateTrack() stub!\n"); + // TODO! + return 0; +} + +void Gfx::CParticle::CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3, + const Math::Vector &p4, Gfx::ParticleType type) +{ + GetLogger()->Info("CParticle::CreateWheelTrace() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DeleteParticle(Gfx::ParticleType type) +{ + GetLogger()->Info("CParticle::DeleteParticle() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DeleteParticle(int channel) +{ + GetLogger()->Info("CParticle::DeleteParticle() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetObjectLink(int channel, CObject *object) +{ + GetLogger()->Info("CParticle::SetObjectLink() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetObjectFather(int channel, CObject *object) +{ + GetLogger()->Info("CParticle::SetObjectFather() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetPosition(int channel, Math::Vector pos) +{ + GetLogger()->Info("CParticle::SetPosition() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetDimension(int channel, Math::Point dim) +{ + GetLogger()->Info("CParticle::SetDimension() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetZoom(int channel, float zoom) +{ + GetLogger()->Info("CParticle::SetZoom() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetAngle(int channel, float angle) +{ + GetLogger()->Info("CParticle::SetAngle() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetIntensity(int channel, float intensity) +{ + GetLogger()->Info("CParticle::SetIntensity() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom, float angle, float intensity) +{ + GetLogger()->Info("CParticle::SetParam() stub!\n"); + // TODO! +} + +void Gfx::CParticle::SetPhase(int channel, Gfx::ParticlePhase phase, float duration) +{ + GetLogger()->Info("CParticle::SetPhase() stub!\n"); + // TODO! +} + +bool Gfx::CParticle::GetPosition(int channel, Math::Vector &pos) +{ + GetLogger()->Info("CParticle::GetPosition() stub!\n"); + // TODO! + return true; +} + +Gfx::Color Gfx::CParticle::GetFogColor(Math::Vector pos) +{ + GetLogger()->Info("CParticle::GetFogColor() stub!\n"); + // TODO! + return Gfx::Color(); +} + +void Gfx::CParticle::SetFrameUpdate(int sheet, bool update) +{ + GetLogger()->Info("CParticle::SetFrameUpdate() stub!\n"); + // TODO! +} + +void Gfx::CParticle::FrameParticle(float rTime) +{ + GetLogger()->Info("CParticle::FrameParticle() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DrawParticle(int sheet) +{ + GetLogger()->Info("CParticle::DrawParticle() stub!\n"); + // TODO! +} + +bool Gfx::CParticle::WriteWheelTrace(char *filename, int width, int height, Math::Vector dl, Math::Vector ur) +{ + GetLogger()->Info("CParticle::WriteWheelTrace() stub!\n"); + // TODO! + return true; +} + +void Gfx::CParticle::DeleteRank(int rank) +{ + GetLogger()->Info("CParticle::DeleteRank() stub!\n"); + // TODO! +} + +bool Gfx::CParticle::CheckChannel(int &channel) +{ + GetLogger()->Info("CParticle::CheckChannel() stub!\n"); + // TODO! + return true; +} + +void Gfx::CParticle::DrawParticleTriangle(int i) +{ + GetLogger()->Info("CParticle::DrawParticleTriangle() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DrawParticleNorm(int i) +{ + GetLogger()->Info("CParticle::DrawParticleNorm() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DrawParticleFlat(int i) +{ + GetLogger()->Info("CParticle::DrawParticleFlat() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DrawParticleFog(int i) +{ + GetLogger()->Info("CParticle::DrawParticleFog() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DrawParticleRay(int i) +{ + GetLogger()->Info("CParticle::DrawParticleRay() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DrawParticleSphere(int i) +{ + GetLogger()->Info("CParticle::DrawParticleSphere() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DrawParticleCylinder(int i) +{ + GetLogger()->Info("CParticle::DrawParticleCylinder() stub!\n"); + // TODO! +} + +void Gfx::CParticle::DrawParticleWheel(int i) +{ + GetLogger()->Info("CParticle::DrawParticleWheel() stub!\n"); + // TODO! +} + +CObject* Gfx::CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos, Gfx::ParticleType type, CObject *father) +{ + GetLogger()->Info("CParticle::SearchObjectGun() stub!\n"); + // TODO! + return nullptr; +} + +CObject* Gfx::CParticle::SearchObjectRay(Math::Vector pos, Math::Vector goal, Gfx::ParticleType type, CObject *father) +{ + GetLogger()->Info("CParticle::SearchObjectRay() stub!\n"); + // TODO! + return nullptr; +} + +void Gfx::CParticle::Play(Sound sound, Math::Vector pos, float amplitude) +{ + GetLogger()->Info("CParticle::Play() stub!\n"); + // TODO! +} + +bool Gfx::CParticle::TrackMove(int i, Math::Vector pos, float progress) +{ + GetLogger()->Info("CParticle::TrackMove() stub!\n"); + // TODO! + return true; +} + +void Gfx::CParticle::TrackDraw(int i, Gfx::ParticleType type) +{ + GetLogger()->Info("CParticle::TrackDraw() stub!\n"); + // TODO! +} diff --git a/src/graphics/engine/particle.h b/src/graphics/engine/particle.h index 94aacfc..89e2c5b 100644 --- a/src/graphics/engine/particle.h +++ b/src/graphics/engine/particle.h @@ -202,26 +202,26 @@ enum ParticlePhase struct Particle { - char bUsed; // TRUE -> particle used - char bRay; // TRUE -> ray with goal - unsigned short uniqueStamp; // unique mark + char used; // TRUE -> particle used + char ray; // TRUE -> ray with goal + unsigned short uniqueStamp; // unique mark short sheet; // sheet (0..n) - ParticleType type; // type PARTI* - ParticlePhase phase; // phase PARPH* + ParticleType type; // type PARTI* + ParticlePhase phase; // phase PARPH* float mass; // mass of the particle (in rebounding) float weight; // weight of the particle (for noise) float duration; // length of life - Math::Vector pos; // absolute position (relative if object links) - Math::Vector goal; // goal position (if bRay) - Math::Vector speed; // speed of displacement + Math::Vector pos; // absolute position (relative if object links) + Math::Vector goal; // goal position (if ray) + Math::Vector speed; // speed of displacement float windSensitivity; short bounce; // number of rebounds - Math::Point dim; // dimensions of the rectangle + Math::Point dim; // dimensions of the rectangle float zoom; // zoom (0..1) float angle; // angle of rotation float intensity; // intensity - Math::Point texSup; // coordinated upper texture - Math::Point texInf; // coordinated lower texture + Math::Point texSup; // coordinated upper texture + Math::Point texInf; // coordinated lower texture float time; // age of the particle (0..n) float phaseTime; // age at the beginning of phase float testTime; // time since last test @@ -233,22 +233,22 @@ struct Particle struct Track { - char bUsed; // TRUE -> drag used - char bDrawParticle; + char used; // TRUE -> drag used + char drawParticle; float step; // duration of not float last; // increase last not memorized float intensity; // intensity at starting (0..1) float width; // tail width - int used; // number of positions in "pos" - int head; // head to write index - Math::Vector pos[MAXTRACKLEN]; + int posUsed; // number of positions in "pos" + int head; // head to write index + Math::Vector pos[MAXTRACKLEN]; float len[MAXTRACKLEN]; }; struct WheelTrace { - ParticleType type; // type PARTI* - Math::Vector pos[4]; // rectangle positions + ParticleType type; // type PARTI* + Math::Vector pos[4]; // rectangle positions float startTime; // beginning of life }; @@ -257,20 +257,29 @@ struct WheelTrace class CParticle { public: - CParticle(CInstanceManager* iMan, CEngine* engine); + CParticle(CInstanceManager* iMan, Gfx::CEngine* engine); ~CParticle(); - void SetDevice(CDevice* device); + void SetDevice(Gfx::CDevice* device); void FlushParticle(); void FlushParticle(int sheet); - int CreateParticle(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0); - int CreateFrag(Math::Vector pos, Math::Vector speed, Gfx::EngineTriangle *triangle, ParticleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0); - int CreatePart(Math::Vector pos, Math::Vector speed, ParticleType type, float duration=1.0f, float mass=0.0f, float weight=0.0f, float windSensitivity=1.0f, int sheet=0); - int CreateRay(Math::Vector pos, Math::Vector goal, ParticleType type, Math::Point dim, float duration=1.0f, int sheet=0); - int CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticleType type, float duration=1.0f, float mass=0.0f, float length=10.0f, float width=1.0f); - void CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3, const Math::Vector &p4, ParticleType type); - void DeleteParticle(ParticleType type); + int CreateParticle(Math::Vector pos, Math::Vector speed, Math::Point dim, + Gfx::ParticleType type, float duration=1.0f, float mass=0.0f, + float windSensitivity=1.0f, int sheet=0); + int CreateFrag(Math::Vector pos, Math::Vector speed, Gfx::EngineTriangle *triangle, + Gfx::ParticleType type, float duration=1.0f, float mass=0.0f, + float windSensitivity=1.0f, int sheet=0); + int CreatePart(Math::Vector pos, Math::Vector speed, Gfx::ParticleType type, + float duration=1.0f, float mass=0.0f, float weight=0.0f, + float windSensitivity=1.0f, int sheet=0); + int CreateRay(Math::Vector pos, Math::Vector goal, Gfx::ParticleType type, Math::Point dim, + float duration=1.0f, int sheet=0); + int CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, Gfx::ParticleType type, + float duration=1.0f, float mass=0.0f, float length=10.0f, float width=1.0f); + void CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3, + const Math::Vector &p4, Gfx::ParticleType type); + void DeleteParticle(Gfx::ParticleType type); void DeleteParticle(int channel); void SetObjectLink(int channel, CObject *object); void SetObjectFather(int channel, CObject *object); @@ -280,12 +289,12 @@ public: void SetAngle(int channel, float angle); void SetIntensity(int channel, float intensity); void SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom, float angle, float intensity); - void SetPhase(int channel, ParticlePhase phase, float duration); + void SetPhase(int channel, Gfx::ParticlePhase phase, float duration); bool GetPosition(int channel, Math::Vector &pos); Gfx::Color GetFogColor(Math::Vector pos); - void SetFrameUpdate(int sheet, bool bUpdate); + void SetFrameUpdate(int sheet, bool update); void FrameParticle(float rTime); void DrawParticle(int sheet); @@ -302,29 +311,29 @@ protected: void DrawParticleSphere(int i); void DrawParticleCylinder(int i); void DrawParticleWheel(int i); - CObject* SearchObjectGun(Math::Vector old, Math::Vector pos, ParticleType type, CObject *father); - CObject* SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticleType type, CObject *father); + CObject* SearchObjectGun(Math::Vector old, Math::Vector pos, Gfx::ParticleType type, CObject *father); + CObject* SearchObjectRay(Math::Vector pos, Math::Vector goal, Gfx::ParticleType type, CObject *father); void Play(Sound sound, Math::Vector pos, float amplitude); bool TrackMove(int i, Math::Vector pos, float progress); - void TrackDraw(int i, ParticleType type); + void TrackDraw(int i, Gfx::ParticleType type); protected: CInstanceManager* m_iMan; - CEngine* m_engine; - CDevice* m_device; - CRobotMain* m_main; - CTerrain* m_terrain; - CWater* m_water; - CSound* m_sound; + Gfx::CEngine* m_engine; + Gfx::CDevice* m_device; + Gfx::CTerrain* m_terrain; + Gfx::CWater* m_water; + CRobotMain* m_main; + CSound* m_sound; Gfx::Particle m_particule[MAXPARTICULE*MAXPARTITYPE]; Gfx::EngineTriangle m_triangle[MAXPARTICULE]; // triangle if PartiType == 0 - Track m_track[MAXTRACK]; + Gfx::Track m_track[MAXTRACK]; int m_wheelTraceTotal; int m_wheelTraceIndex; - WheelTrace m_wheelTrace[MAXWHEELTRACE]; + Gfx::WheelTrace m_wheelTrace[MAXWHEELTRACE]; int m_totalInterface[MAXPARTITYPE][SH_MAX]; - bool m_bFrameUpdate[SH_MAX]; + bool m_frameUpdate[SH_MAX]; int m_fogTotal; int m_fog[MAXPARTIFOG]; int m_uniqueStamp; diff --git a/src/graphics/engine/pyro.cpp b/src/graphics/engine/pyro.cpp index e699db2..327befa 100644 --- a/src/graphics/engine/pyro.cpp +++ b/src/graphics/engine/pyro.cpp @@ -19,5 +19,161 @@ #include "graphics/engine/pyro.h" +#include "common/logger.h" -// TODO implementation + +Gfx::CPyro::CPyro(CInstanceManager* iMan) +{ + GetLogger()->Info("CParticle::CPyro() stub!\n"); + // TODO! +} + +Gfx::CPyro::~CPyro() +{ + GetLogger()->Info("CPyro::~CPyro() stub!"); + // TODO! +} + +void Gfx::CPyro::DeleteObject(bool all) +{ + GetLogger()->Info("CPyro::DeleteObject() stub!"); + // TODO! +} + +bool Gfx::CPyro::Create(Gfx::PyroType type, CObject* pObj, float force) +{ + GetLogger()->Info("CPyro::Create() stub!"); + // TODO! + return true; +} + +bool Gfx::CPyro::EventProcess(const Event &event) +{ + GetLogger()->Info("CPyro::EventProcess() stub!\n"); + // TODO! + return true; +} + +Error Gfx::CPyro::IsEnded() +{ + GetLogger()->Info("CPyro::IsEnded() stub!\n"); + // TODO! + return ERR_OK; +} + +void Gfx::CPyro::CutObjectLink(CObject* pObj) +{ + GetLogger()->Info("CPyro::CutObjectLink() stub!\n"); + // TODO! +} + +void Gfx::CPyro::DisplayError(PyroType type, CObject* pObj) +{ + GetLogger()->Info("CPyro::DisplayError() stub!\n"); + // TODO! +} + +bool Gfx::CPyro::CreateLight(Math::Vector pos, float height) +{ + GetLogger()->Info("CPyro::CreateLight() stub!\n"); + // TODO! + return true; +} + +void Gfx::CPyro::DeleteObject(bool primary, bool secondary) +{ + GetLogger()->Info("CPyro::DeleteObject() stub!\n"); + // TODO! +} + +void Gfx::CPyro::CreateTriangle(CObject* pObj, ObjectType oType, int part) +{ + GetLogger()->Info("CPyro::CreateTriangle() stub!\n"); + // TODO! +} + +void Gfx::CPyro::ExploStart() +{ + GetLogger()->Info("CPyro::ExploStart() stub!\n"); + // TODO! +} +void Gfx::CPyro::ExploTerminate() +{ + GetLogger()->Info("CPyro::ExploTerminate() stub!\n"); + // TODO! +} + +void Gfx::CPyro::BurnStart() +{ + GetLogger()->Info("CPyro::BurnStart() stub!\n"); + // TODO! +} + +void Gfx::CPyro::BurnAddPart(int part, Math::Vector pos, Math::Vector angle) +{ + GetLogger()->Info("CPyro::BurnAddPart() stub!\n"); + // TODO! +} + +void Gfx::CPyro::BurnProgress() +{ + GetLogger()->Info("CPyro::BurnProgress() stub!\n"); + // TODO! +} + +bool Gfx::CPyro::BurnIsKeepPart(int part) +{ + GetLogger()->Info("CPyro::BurnIsKeepPart() stub!\n"); + // TODO! + return true; +} + +void Gfx::CPyro::BurnTerminate() +{ + GetLogger()->Info("CPyro::BurnTerminate() stub!\n"); + // TODO! +} + +void Gfx::CPyro::FallStart() +{ + GetLogger()->Info("CPyro::FallStart() stub!\n"); + // TODO! +} + +CObject* Gfx::CPyro::FallSearchBeeExplo() +{ + GetLogger()->Info("CPyro::FallSearchBeeExplo() stub!\n"); + // TODO! + return nullptr; +} + +void Gfx::CPyro::FallProgress(float rTime) +{ + GetLogger()->Info("CPyro::FallProgress() stub!\n"); + // TODO! +} + +Error Gfx::CPyro::FallIsEnded() +{ + GetLogger()->Info("CPyro::FallIsEnded() stub!\n"); + // TODO! + return ERR_OK; +} + +void Gfx::CPyro::LightOperFlush() +{ + GetLogger()->Info("CPyro::LightOperFlush() stub!\n"); + // TODO! +} + +void Gfx::CPyro::LightOperAdd(float progress, float intensity, float r, float g, float b) +{ + GetLogger()->Info("CPyro::LightOperAdd() stub!\n"); + // TODO! +} + +void Gfx::CPyro::LightOperFrame(float rTime) +{ + GetLogger()->Info("CPyro::LightOperFrame() stub!\n"); + // TODO! +} diff --git a/src/graphics/engine/pyro.h b/src/graphics/engine/pyro.h index d663ca5..35b5c5f 100644 --- a/src/graphics/engine/pyro.h +++ b/src/graphics/engine/pyro.h @@ -21,9 +21,7 @@ #include "common/misc.h" #include "graphics/engine/engine.h" -//#include "object/object.h" -// TEMPORARILY! -enum ObjectType {}; +#include "object/object.h" class CInstanceManager; @@ -90,13 +88,14 @@ struct PyroLightOper -class CPyro { +class CPyro +{ public: CPyro(CInstanceManager* iMan); ~CPyro(); - void DeleteObject(bool bAll=false); - bool Create(PyroType type, CObject* pObj, float force=1.0f); + void DeleteObject(bool all=false); + bool Create(Gfx::PyroType type, CObject* pObj, float force=1.0f); bool EventProcess(const Event &event); Error IsEnded(); void CutObjectLink(CObject* pObj); @@ -104,7 +103,7 @@ public: protected: void DisplayError(PyroType type, CObject* pObj); bool CreateLight(Math::Vector pos, float height); - void DeleteObject(bool bPrimary, bool bSecondary); + void DeleteObject(bool primary, bool secondary); void CreateTriangle(CObject* pObj, ObjectType oType, int part); @@ -127,21 +126,21 @@ protected: void LightOperFrame(float rTime); protected: - CInstanceManager* m_iMan; - CEngine* m_engine; - CTerrain* m_terrain; - CCamera* m_camera; - CParticle* m_particule; - CLight* m_light; - CObject* m_object; - CDisplayText* m_displayText; - CRobotMain* m_main; - CSound* m_sound; - - Math::Vector m_pos; // center of the effect - Math::Vector m_posPower; // center of the battery - bool m_bPower; // battery exists? - PyroType m_type; + CInstanceManager* m_iMan; + Gfx::CEngine* m_engine; + Gfx::CTerrain* m_terrain; + Gfx::CCamera* m_camera; + Gfx::CParticle* m_particule; + Gfx::CLightManager* m_lightMan; + CObject* m_object; + CDisplayText* m_displayText; + CRobotMain* m_main; + CSound* m_sound; + + Math::Vector m_pos; // center of the effect + Math::Vector m_posPower; // center of the battery + bool m_power; // battery exists? + Gfx::PyroType m_type; float m_force; float m_size; float m_progress; @@ -153,22 +152,22 @@ protected: int m_lightRank; int m_lightOperTotal; - PyroLightOper m_lightOper[10]; + Gfx::PyroLightOper m_lightOper[10]; float m_lightHeight; ObjectType m_burnType; int m_burnPartTotal; - PyroBurnPart m_burnPart[10]; + Gfx::PyroBurnPart m_burnPart[10]; int m_burnKeepPart[10]; float m_burnFall; float m_fallFloor; float m_fallSpeed; float m_fallBulletTime; - bool m_bFallEnding; + bool m_fallEnding; int m_crashSphereUsed; // number of spheres used - Math::Vector m_crashSpherePos[50]; + Math::Vector m_crashSpherePos[50]; float m_crashSphereRadius[50]; }; diff --git a/src/graphics/engine/water.cpp b/src/graphics/engine/water.cpp index 1f11671..0ec52eb 100644 --- a/src/graphics/engine/water.cpp +++ b/src/graphics/engine/water.cpp @@ -66,16 +66,14 @@ Gfx::CWater::~CWater() bool Gfx::CWater::EventProcess(const Event &event) { - /* TODO! if (event.type == EVENT_FRAME) return EventFrame(event); -*/ + return true; } bool Gfx::CWater::EventFrame(const Event &event) { - /* TODO! if (m_engine->GetPause()) return true; m_time += event.rTime; @@ -83,7 +81,7 @@ bool Gfx::CWater::EventFrame(const Event &event) if (m_type[0] == WATER_NULL) return true; if (m_lava) - LavaFrame(event.rTime);*/ + LavaFrame(event.rTime); return true; } diff --git a/src/object/object.h b/src/object/object.h index 75283d6..3825412 100644 --- a/src/object/object.h +++ b/src/object/object.h @@ -19,9 +19,9 @@ #pragma once -#include "old/d3dengine.h" -#include "old/camera.h" -#include "old/sound.h" +#include "graphics/engine/engine.h" +#include "graphics/engine/camera.h" +#include "sound/sound.h" class CInstanceManager; @@ -377,16 +377,16 @@ public: int CreatePart(); void DeletePart(int part); void SetObjectRank(int part, int objRank); - int RetObjectRank(int part); + int GetObjectRank(int part); void SetObjectParent(int part, int parent); void SetType(ObjectType type); - ObjectType RetType(); - char* RetName(); + ObjectType GetType(); + char* GetName(); void SetOption(int option); - int RetOption(); + int GetOption(); void SetID(int id); - int RetID(); + int GetID(); bool Write(char *line); bool Read(char *line); @@ -413,203 +413,205 @@ public: bool WriteProgram(int rank, char* filename); bool RunProgram(int rank); - int RetShadowLight(); - int RetEffectLight(); + int GetShadowLight(); + int GetEffectLight(); void FlushCrashShere(); int CreateCrashSphere(Math::Vector pos, float radius, Sound sound, float hardness=0.45f); - int RetCrashSphereTotal(); + int GetCrashSphereTotal(); bool GetCrashSphere(int rank, Math::Vector &pos, float &radius); - float RetCrashSphereHardness(int rank); - Sound RetCrashSphereSound(int rank); + float GetCrashSphereHardness(int rank); + Sound GetCrashSphereSound(int rank); void DeleteCrashSphere(int rank); void SetGlobalSphere(Math::Vector pos, float radius); void GetGlobalSphere(Math::Vector &pos, float &radius); void SetJotlerSphere(Math::Vector pos, float radius); void GetJotlerSphere(Math::Vector &pos, float &radius); void SetShieldRadius(float radius); - float RetShieldRadius(); + float GetShieldRadius(); void SetFloorHeight(float height); void FloorAdjust(); void SetLinVibration(Math::Vector dir); - Math::Vector RetLinVibration(); + Math::Vector GetLinVibration(); void SetCirVibration(Math::Vector dir); - Math::Vector RetCirVibration(); + Math::Vector GetCirVibration(); void SetInclinaison(Math::Vector dir); - Math::Vector RetInclinaison(); + Math::Vector GetInclinaison(); void SetPosition(int part, const Math::Vector &pos); - Math::Vector RetPosition(int part); + Math::Vector GetPosition(int part); void SetAngle(int part, const Math::Vector &angle); - Math::Vector RetAngle(int part); + Math::Vector GetAngle(int part); void SetAngleY(int part, float angle); void SetAngleX(int part, float angle); void SetAngleZ(int part, float angle); - float RetAngleY(int part); - float RetAngleX(int part); - float RetAngleZ(int part); + float GetAngleY(int part); + float GetAngleX(int part); + float GetAngleZ(int part); void SetZoom(int part, float zoom); void SetZoom(int part, Math::Vector zoom); - Math::Vector RetZoom(int part); + Math::Vector GetZoom(int part); void SetZoomX(int part, float zoom); - float RetZoomX(int part); + float GetZoomX(int part); void SetZoomY(int part, float zoom); - float RetZoomY(int part); + float GetZoomY(int part); void SetZoomZ(int part, float zoom); - float RetZoomZ(int part); + float GetZoomZ(int part); - float RetWaterLevel(); + float GetWaterLevel(); void SetTrainer(bool bEnable); - bool RetTrainer(); + bool GetTrainer(); void SetToy(bool bEnable); - bool RetToy(); + bool GetToy(); void SetManual(bool bManual); - bool RetManual(); + bool GetManual(); void SetResetCap(ResetCap cap); - ResetCap RetResetCap(); + ResetCap GetResetCap(); void SetResetBusy(bool bBusy); - bool RetResetBusy(); + bool GetResetBusy(); void SetResetPosition(const Math::Vector &pos); - Math::Vector RetResetPosition(); + Math::Vector GetResetPosition(); void SetResetAngle(const Math::Vector &angle); - Math::Vector RetResetAngle(); + Math::Vector GetResetAngle(); void SetResetRun(int run); - int RetResetRun(); + int GetResetRun(); void SetMasterParticule(int part, int parti); - int RetMasterParticule(int part); + int GetMasterParticule(int part); void SetPower(CObject* power); - CObject* RetPower(); + CObject* GetPower(); void SetFret(CObject* fret); - CObject* RetFret(); + CObject* GetFret(); void SetTruck(CObject* truck); - CObject* RetTruck(); + CObject* GetTruck(); void SetTruckPart(int part); - int RetTruckPart(); + int GetTruckPart(); void InfoFlush(); void DeleteInfo(int rank); void SetInfo(int rank, Info info); - Info RetInfo(int rank); - int RetInfoTotal(); - void SetInfoReturn(float value); - float RetInfoReturn(); + Info GetInfo(int rank); + int GetInfoTotal(); + void SetInfoGeturn(float value); + float GetInfoGeturn(); void SetInfoUpdate(bool bUpdate); - bool RetInfoUpdate(); + bool GetInfoUpdate(); bool SetCmdLine(int rank, float value); - float RetCmdLine(int rank); + float GetCmdLine(int rank); - Math::Matrix* RetRotateMatrix(int part); - Math::Matrix* RetTranslateMatrix(int part); - Math::Matrix* RetTransformMatrix(int part); - Math::Matrix* RetWorldMatrix(int part); + Math::Matrix* GetRotateMatrix(int part); + Math::Matrix* GetTranslateMatrix(int part); + Math::Matrix* GetTransformMatrix(int part); + Math::Matrix* GetWorldMatrix(int part); - void SetViewFromHere(Math::Vector &eye, float &dirH, float &dirV, Math::Vector &lookat, Math::Vector &upVec, CameraType type); + void SetViewFromHere(Math::Vector &eye, float &dirH, float &dirV, + Math::Vector &lookat, Math::Vector &upVec, + Gfx::CameraType type); void SetCharacter(Character* character); void GetCharacter(Character* character); - Character* RetCharacter(); + Character* GetCharacter(); - float RetAbsTime(); + float GetAbsTime(); void SetEnergy(float level); - float RetEnergy(); + float GetEnergy(); void SetCapacity(float capacity); - float RetCapacity(); + float GetCapacity(); void SetShield(float level); - float RetShield(); + float GetShield(); void SetRange(float delay); - float RetRange(); + float GetRange(); void SetTransparency(float value); - float RetTransparency(); + float GetTransparency(); - ObjectMaterial RetMaterial(); + ObjectMaterial GetMaterial(); void SetGadget(bool bMode); - bool RetGadget(); + bool GetGadget(); void SetFixed(bool bFixed); - bool RetFixed(); + bool GetFixed(); void SetClip(bool bClip); - bool RetClip(); + bool GetClip(); bool JostleObject(float force); void StartDetectEffect(CObject *target, bool bFound); void SetVirusMode(bool bEnable); - bool RetVirusMode(); - float RetVirusTime(); + bool GetVirusMode(); + float GetVirusTime(); - void SetCameraType(CameraType type); - CameraType RetCameraType(); + void SetCameraType(Gfx::CameraType type); + Gfx::CameraType GetCameraType(); void SetCameraDist(float dist); - float RetCameraDist(); + float GetCameraDist(); void SetCameraLock(bool bLock); - bool RetCameraLock(); + bool GetCameraLock(); void SetHilite(bool bMode); - bool RetHilite(); + bool GetHilite(); void SetSelect(bool bMode, bool bDisplayError=true); - bool RetSelect(bool bReal=false); + bool GetSelect(bool bReal=false); void SetSelectable(bool bMode); - bool RetSelectable(); + bool GetSelectable(); void SetActivity(bool bMode); - bool RetActivity(); + bool GetActivity(); void SetVisible(bool bVisible); - bool RetVisible(); + bool GetVisible(); void SetEnable(bool bEnable); - bool RetEnable(); + bool GetEnable(); void SetCheckToken(bool bMode); - bool RetCheckToken(); + bool GetCheckToken(); void SetProxyActivate(bool bActivate); - bool RetProxyActivate(); + bool GetProxyActivate(); void SetProxyDistance(float distance); - float RetProxyDistance(); + float GetProxyDistance(); void SetMagnifyDamage(float factor); - float RetMagnifyDamage(); + float GetMagnifyDamage(); void SetParam(float value); - float RetParam(); + float GetParam(); void SetExplo(bool bExplo); - bool RetExplo(); + bool GetExplo(); void SetLock(bool bLock); - bool RetLock(); + bool GetLock(); void SetCargo(bool bCargo); - bool RetCargo(); + bool GetCargo(); void SetBurn(bool bBurn); - bool RetBurn(); + bool GetBurn(); void SetDead(bool bDead); - bool RetDead(); - bool RetRuin(); - bool RetActif(); + bool GetDead(); + bool GetRuin(); + bool GetActif(); void SetGunGoalV(float gunGoal); void SetGunGoalH(float gunGoal); - float RetGunGoalV(); - float RetGunGoalH(); + float GetGunGoalV(); + float GetGunGoalH(); bool StartShowLimit(); void StopShowLimit(); @@ -618,16 +620,16 @@ public: void CreateSelectParticule(); void SetRunScript(CScript* script); - CScript* RetRunScript(); - CBotVar* RetBotVar(); - CPhysics* RetPhysics(); - CBrain* RetBrain(); - CMotion* RetMotion(); - CAuto* RetAuto(); + CScript* GetRunScript(); + CBotVar* GetBotVar(); + CPhysics* GetPhysics(); + CBrain* GetBrain(); + CMotion* GetMotion(); + CAuto* GetAuto(); void SetAuto(CAuto* automat); void SetDefRank(int rank); - int RetDefRank(); + int GetDefRank(); bool GetTooltipName(char* name); @@ -635,17 +637,17 @@ public: CObject* SubDeselList(); void DeleteDeselList(CObject* pObj); - bool CreateShadowCircle(float radius, float intensity, D3DShadowType type=D3DSHADOWNORM); - bool CreateShadowLight(float height, D3DCOLORVALUE color); - bool CreateEffectLight(float height, D3DCOLORVALUE color); + bool CreateShadowCircle(float radius, float intensity, Gfx::EngineShadowType type = Gfx::ENG_SHADOW_NORM); + bool CreateShadowLight(float height, Gfx::Color color); + bool CreateEffectLight(float height, Gfx::Color color); void FlatParent(); - bool RetTraceDown(); + bool GetTraceDown(); void SetTraceDown(bool bDown); - int RetTraceColor(); + int GetTraceColor(); void SetTraceColor(int color); - float RetTraceWidth(); + float GetTraceWidth(); void SetTraceWidth(float width); protected: @@ -663,12 +665,12 @@ protected: protected: CInstanceManager* m_iMan; - CD3DEngine* m_engine; - CLight* m_light; - CTerrain* m_terrain; - CWater* m_water; - CCamera* m_camera; - CParticule* m_particule; + Gfx::CEngine* m_engine; + Gfx::CLightManager* m_lightMan; + Gfx::CTerrain* m_terrain; + Gfx::CWater* m_water; + Gfx::CCamera* m_camera; + Gfx::CParticle* m_particle; CPhysics* m_physics; CBrain* m_brain; CMotion* m_motion; @@ -732,7 +734,7 @@ protected: float m_showLimitRadius; float m_gunGoalV; float m_gunGoalH; - CameraType m_cameraType; + Gfx::CameraType m_cameraType; float m_cameraDist; bool m_bCameraLock; int m_defRank; @@ -767,7 +769,7 @@ protected: int m_infoTotal; Info m_info[OBJECTMAXINFO]; - float m_infoReturn; + float m_infoGeturn; bool m_bInfoUpdate; float m_cmdLine[OBJECTMAXCMDLINE]; diff --git a/src/physics/physics.h b/src/physics/physics.h index 6865b6a..2e1f5eb 100644 --- a/src/physics/physics.h +++ b/src/physics/physics.h @@ -19,23 +19,27 @@ #pragma once -#include "old/d3dengine.h" #include "common/misc.h" #include "object/object.h" +#include "math/vector.h" class CInstanceManager; -class CD3DEngine; -class CLight; -class CParticule; -class CTerrain; -class CWater; class CCamera; class CObject; class CBrain; class CMotion; class CSound; +namespace Gfx +{ +class CEngine; +class CLight; +class CParticule; +class CTerrain; +class CWater; +}; + enum PhysicsType { @@ -98,64 +102,64 @@ public: void SetMotion(CMotion* motion); void SetType(PhysicsType type); - PhysicsType RetType(); + PhysicsType GetType(); bool Write(char *line); bool Read(char *line); void SetGravity(float value); - float RetGravity(); + float GetGravity(); - float RetFloorHeight(); + float GetFloorHeight(); void SetLinMotion(PhysicsMode mode, Math::Vector value); - Math::Vector RetLinMotion(PhysicsMode mode); + Math::Vector GetLinMotion(PhysicsMode mode); void SetLinMotionX(PhysicsMode mode, float value); void SetLinMotionY(PhysicsMode mode, float value); void SetLinMotionZ(PhysicsMode mode, float value); - float RetLinMotionX(PhysicsMode mode); - float RetLinMotionY(PhysicsMode mode); - float RetLinMotionZ(PhysicsMode mode); + float GetLinMotionX(PhysicsMode mode); + float GetLinMotionY(PhysicsMode mode); + float GetLinMotionZ(PhysicsMode mode); void SetCirMotion(PhysicsMode mode, Math::Vector value); - Math::Vector RetCirMotion(PhysicsMode mode); + Math::Vector GetCirMotion(PhysicsMode mode); void SetCirMotionX(PhysicsMode mode, float value); void SetCirMotionY(PhysicsMode mode, float value); void SetCirMotionZ(PhysicsMode mode, float value); - float RetCirMotionX(PhysicsMode mode); - float RetCirMotionY(PhysicsMode mode); - float RetCirMotionZ(PhysicsMode mode); + float GetCirMotionX(PhysicsMode mode); + float GetCirMotionY(PhysicsMode mode); + float GetCirMotionZ(PhysicsMode mode); - float RetLinStopLength(PhysicsMode sMode=MO_ADVSPEED, PhysicsMode aMode=MO_STOACCEL); - float RetCirStopLength(); - float RetLinMaxLength(float dir); - float RetLinTimeLength(float dist, float dir=1.0f); - float RetLinLength(float dist); + float GetLinStopLength(PhysicsMode sMode=MO_ADVSPEED, PhysicsMode aMode=MO_STOACCEL); + float GetCirStopLength(); + float GetLinMaxLength(float dir); + float GetLinTimeLength(float dist, float dir=1.0f); + float GetLinLength(float dist); void SetMotor(bool bState); - bool RetMotor(); + bool GetMotor(); void SetLand(bool bState); - bool RetLand(); + bool GetLand(); void SetSwim(bool bState); - bool RetSwim(); + bool GetSwim(); void SetCollision(bool bCollision); - bool RetCollision(); + bool GetCollision(); void SetFreeze(bool bFreeze); - bool RetFreeze(); + bool GetFreeze(); void SetReactorRange(float range); - float RetReactorRange(); + float GetReactorRange(); void SetMotorSpeed(Math::Vector speed); void SetMotorSpeedX(float speed); void SetMotorSpeedY(float speed); void SetMotorSpeedZ(float speed); - Math::Vector RetMotorSpeed(); - float RetMotorSpeedX(); - float RetMotorSpeedY(); - float RetMotorSpeedZ(); + Math::Vector GetMotorSpeed(); + float GetMotorSpeedX(); + float GetMotorSpeedY(); + float GetMotorSpeedZ(); void CreateInterface(bool bSelect); - Error RetError(); + Error GetError(); protected: bool EventFrame(const Event &event); @@ -186,12 +190,12 @@ protected: protected: CInstanceManager* m_iMan; - CD3DEngine* m_engine; - CLight* m_light; - CParticule* m_particule; - CTerrain* m_terrain; - CWater* m_water; - CCamera* m_camera; + Gfx::CEngine* m_engine; + Gfx::CLightManager* m_lightMan; + Gfx::CParticle* m_particle; + Gfx::CTerrain* m_terrain; + Gfx::CWater* m_water; + Gfx::CCamera* m_camera; CObject* m_object; CBrain* m_brain; CMotion* m_motion; -- cgit v1.2.3-1-g7c22 From 9946459c0cd65c3b66719a2aefc42c7ab2a29c04 Mon Sep 17 00:00:00 2001 From: erihel Date: Thu, 9 Aug 2012 23:04:29 +0200 Subject: * changed 0, NULL to nullptr * changed profile.cpp to use SimpleIni to load config files * added new CProfile singleton class for loading config * added SimpleIni to lib/ dir * added config loading tests --- src/common/iman.cpp | 2 +- src/common/logger.cpp | 2 +- src/common/profile.cpp | 96 +++++++++++++++------------------------- src/common/profile.h | 33 +++++++++++--- src/common/test/CMakeLists.txt | 10 ++++- src/common/test/colobot.ini | 8 ++++ src/common/test/profile_test.cpp | 35 +++++++++++++++ src/plugins/pluginloader.cpp | 6 +-- src/plugins/test/CMakeLists.txt | 3 +- 9 files changed, 118 insertions(+), 77 deletions(-) create mode 100644 src/common/test/colobot.ini create mode 100644 src/common/test/profile_test.cpp (limited to 'src') diff --git a/src/common/iman.cpp b/src/common/iman.cpp index 4c70cde..4b89ecf 100644 --- a/src/common/iman.cpp +++ b/src/common/iman.cpp @@ -23,7 +23,7 @@ #include "common/iman.h" -template<> CInstanceManager* CSingleton::mInstance = 0; +template<> CInstanceManager* CSingleton::mInstance = nullptr; CInstanceManager& CInstanceManager::GetInstance() diff --git a/src/common/logger.cpp b/src/common/logger.cpp index f24726e..a0dcca0 100644 --- a/src/common/logger.cpp +++ b/src/common/logger.cpp @@ -21,7 +21,7 @@ #include -template<> CLogger* CSingleton::mInstance = 0; +template<> CLogger* CSingleton::mInstance = nullptr; CLogger& CLogger::GetInstance() diff --git a/src/common/profile.cpp b/src/common/profile.cpp index d921d34..467e991 100644 --- a/src/common/profile.cpp +++ b/src/common/profile.cpp @@ -17,98 +17,72 @@ // profile.cpp -#include -#include -#include +#include -#include "common/language.h" -#include "common/struct.h" -#include "common/profile.h" +template<> CProfile* CSingleton::mInstance = nullptr; -static char g_filename[100]; - +CProfile::CProfile() +{ + m_ini = new CSimpleIniA(); + m_ini->SetUnicode(); +} -bool InitCurrentDirectory() +CProfile::~CProfile() { -#if _SCHOOL - _fullpath(g_filename, "ceebot.ini", 100); -#else - _fullpath(g_filename, "colobot.ini", 100); -#endif - return true; + m_ini->Reset(); + delete m_ini; } -bool SetLocalProfileString(char* section, char* key, char* string) +bool CProfile::InitCurrentDirectory() { - WritePrivateProfileString(section, key, string, g_filename); + m_ini->LoadFile("colobot.ini"); return true; } -bool GetLocalProfileString(char* section, char* key, char* buffer, int max) -{ - int nb; - nb = GetPrivateProfileString(section, key, "", buffer, max, g_filename); - if ( nb == 0 ) - { - buffer[0] = 0; - return false; - } - return true; +bool CProfile::SetLocalProfileString(std::string section, std::string key, std::string value) +{ + return (m_ini->SetValue(section.c_str(), key.c_str(), value.c_str()) == SI_OK); } -bool SetLocalProfileInt(char* section, char* key, int value) +bool CProfile::GetLocalProfileString(std::string section, std::string key, std::string &buffer) { - char s[20]; + const char* value = m_ini->GetValue(section.c_str(), key.c_str(), nullptr); + if (strlen(value) > 0) { + buffer = std::string(value); + return true; + } - sprintf(s, "%d", value); - WritePrivateProfileString(section, key, s, g_filename); - return true; + return false; } -bool GetLocalProfileInt(char* section, char* key, int &value) + +bool CProfile::SetLocalProfileInt(std::string section, std::string key, int value) { - char s[20]; - int nb; - - nb = GetPrivateProfileString(section, key, "", s, 20, g_filename); - if ( nb == 0 ) - { - value = 0; - return false; - } - sscanf(s, "%d", &value); - return true; + return (m_ini->SetLongValue(section.c_str(), key.c_str(), value) == SI_OK); } -bool SetLocalProfileFloat(char* section, char* key, float value) +bool CProfile::GetLocalProfileInt(std::string section, std::string key, int &value) { - char s[20]; - - sprintf(s, "%.2f", value); - WritePrivateProfileString(section, key, s, g_filename); + value = m_ini->GetLongValue(section.c_str(), key.c_str(), 0L); return true; } -bool GetLocalProfileFloat(char* section, char* key, float &value) + +bool CProfile::SetLocalProfileFloat(std::string section, std::string key, float value) { - char s[20]; - int nb; - - nb = GetPrivateProfileString(section, key, "", s, 20, g_filename); - if ( nb == 0 ) - { - value = 0.0f; - return false; - } - sscanf(s, "%f", &value); - return true; + return (m_ini->SetDoubleValue(section.c_str(), key.c_str(), value) == SI_OK); } +bool CProfile::GetLocalProfileFloat(std::string section, std::string key, float &value) +{ + value = m_ini->GetDoubleValue(section.c_str(), key.c_str(), 0.0d); + return true; +} diff --git a/src/common/profile.h b/src/common/profile.h index 2c76a0b..ae67e52 100644 --- a/src/common/profile.h +++ b/src/common/profile.h @@ -18,13 +18,32 @@ #pragma once +#include -extern bool InitCurrentDirectory(); -extern bool SetLocalProfileString(char* section, char* key, char* string); -extern bool GetLocalProfileString(char* section, char* key, char* buffer, int max); -extern bool SetLocalProfileInt(char* section, char* key, int value); -extern bool GetLocalProfileInt(char* section, char* key, int &value); -extern bool SetLocalProfileFloat(char* section, char* key, float value); -extern bool GetLocalProfileFloat(char* section, char* key, float &value); +#include +#include + +class CProfile : public CSingleton +{ + public: + CProfile(); + ~CProfile(); + + bool InitCurrentDirectory(); + bool SetLocalProfileString(std::string section, std::string key, std::string value); + bool GetLocalProfileString(std::string section, std::string key, std::string& buffer); + + bool SetLocalProfileInt(std::string section, std::string key, int value); + bool GetLocalProfileInt(std::string section, std::string key, int &value); + + bool SetLocalProfileFloat(std::string section, std::string key, float value); + bool GetLocalProfileFloat(std::string section, std::string key, float &value); + + static CProfile& GetInstance(); + static CProfile* GetInstancePointer(); + + private: + CSimpleIniA *m_ini; +}; diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt index 680116c..3adca4e 100644 --- a/src/common/test/CMakeLists.txt +++ b/src/common/test/CMakeLists.txt @@ -1,6 +1,12 @@ cmake_minimum_required(VERSION 2.8) set(CMAKE_BUILD_TYPE debug) -set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0") +set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0 -std=c++11") -add_executable(image_test ../image.cpp image_test.cpp) +include_directories("../../") +include_directories("../../../") + +#add_executable(image_test ../image.cpp image_test.cpp) +add_executable(profile_test ../profile.cpp profile_test.cpp) + +add_test(profile_test ./profile_test) diff --git a/src/common/test/colobot.ini b/src/common/test/colobot.ini new file mode 100644 index 0000000..c4d2162 --- /dev/null +++ b/src/common/test/colobot.ini @@ -0,0 +1,8 @@ +[test_float] +float_value=1.5 + +[test_string] +string_value=Hello world + +[test_int] +int_value=42 diff --git a/src/common/test/profile_test.cpp b/src/common/test/profile_test.cpp new file mode 100644 index 0000000..3ba0fad --- /dev/null +++ b/src/common/test/profile_test.cpp @@ -0,0 +1,35 @@ +#include "../profile.h" + +#include +#include + +using namespace std; + +int main() +{ + CProfile profile; + profile.InitCurrentDirectory(); // load colobot.ini file + + string result; + profile.GetLocalProfileString("test_string", "string_value", result); + if (result != "Hello world") { + cout << "GetLocalProfileString failed!" << endl; + return 1; + } + + int int_value; + profile.GetLocalProfileInt("test_int", "int_value", int_value); + if (int_value != 42) { + cout << "GetLocalProfileInt failed!" << endl; + return 1; + } + + float float_value; + profile.GetLocalProfileFloat("test_float", "float_value", float_value); + if (float_value != 1.5) { + cout << "GetLocalProfileFloat failed!" << endl; + return 1; + } + + return 0; +} diff --git a/src/plugins/pluginloader.cpp b/src/plugins/pluginloader.cpp index adceb6b..337c0ce 100644 --- a/src/plugins/pluginloader.cpp +++ b/src/plugins/pluginloader.cpp @@ -56,13 +56,13 @@ bool CPluginLoader::UnloadPlugin() GetLogger()->Warn("Plugin %s is not loaded.\n"); return true; } - + void (*uninstall)() = (void (*)()) lt_dlsym(mHandle, "UninstallPluginEntry"); if (!uninstall) { GetLogger()->Error("Error getting UninstallPluginEntry for plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); return false; } - + lt_dlclose(mHandle); mLoaded = false; return true; @@ -89,7 +89,7 @@ bool CPluginLoader::LoadPlugin() GetLogger()->Error("Error getting GetPluginInterfaceEntry for plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); return false; } - + install(); mInterface = getInterface(); mLoaded = true; diff --git a/src/plugins/test/CMakeLists.txt b/src/plugins/test/CMakeLists.txt index 5953468..cd4e6be 100644 --- a/src/plugins/test/CMakeLists.txt +++ b/src/plugins/test/CMakeLists.txt @@ -5,7 +5,6 @@ set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0 -std=c++11 -rdynamic") add_executable(plugin_test plugin_test.cpp ../../common/iman.cpp ../../common/logger.cpp ../pluginloader.cpp) -# Change to DirectX SDK directory include_directories("../../") -target_link_libraries(plugin_test ltdl) \ No newline at end of file +target_link_libraries(plugin_test ltdl) -- cgit v1.2.3-1-g7c22 From 63257034c946d40fb3ecc73a9ee3dc9d1e0a1e34 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Fri, 10 Aug 2012 23:31:42 +0200 Subject: Partial CEngine implementation - added rewritten implementation for basic modesetting in CEngine - started rewriting proper rendering and object handling in CEngine --- src/app/app.cpp | 21 +- src/app/app.h | 2 +- src/graphics/core/color.h | 6 +- src/graphics/engine/engine.cpp | 2722 +++++++++++++++++++++++++++++++++------- src/graphics/engine/engine.h | 477 ++++--- src/object/object.h | 9 +- 6 files changed, 2569 insertions(+), 668 deletions(-) (limited to 'src') diff --git a/src/app/app.cpp b/src/app/app.cpp index 3681172..e116914 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -573,16 +573,7 @@ int CApplication::Run() } // Update game and render a frame during idle time (no messages are waiting) - bool ok = Render(); - - // If an error occurs, push quit event to the queue - if (! ok) - { - SDL_Event quitEvent; - memset(&quitEvent, 0, sizeof(SDL_Event)); - quitEvent.type = SDL_QUIT; - SDL_PushEvent(&quitEvent); - } + Render(); } } @@ -751,17 +742,13 @@ bool CApplication::ProcessEvent(const Event &event) return true; } -/** Renders the frame and swaps buffers as necessary. Returns \c false on error. */ -bool CApplication::Render() +/** Renders the frame and swaps buffers as necessary */ +void CApplication::Render() { - bool result = m_engine->Render(); - if (! result) - return false; + m_engine->Render(); if (m_deviceConfig.doubleBuf) SDL_GL_SwapBuffers(); - - return true; } void CApplication::StepSimulation(float rTime) diff --git a/src/app/app.h b/src/app/app.h index bba55b2..e7ffd54 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -198,7 +198,7 @@ protected: //! Handles some incoming events bool ProcessEvent(const Event &event); //! Renders the image in window - bool Render(); + void Render(); //! Opens the joystick device bool OpenJoystick(); diff --git a/src/graphics/core/color.h b/src/graphics/core/color.h index 6973644..0e08de3 100644 --- a/src/graphics/core/color.h +++ b/src/graphics/core/color.h @@ -18,7 +18,6 @@ #pragma once - #include @@ -66,6 +65,11 @@ struct Color { return r == other.r && g == other.g && b == other.b && a == other.a; } + + inline bool operator!=(const Gfx::Color &other) const + { + return ! this->operator==(other); + } }; /** diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index c8fa05c..4244fb2 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -36,6 +36,8 @@ #include "graphics/engine/text.h" #include "graphics/engine/water.h" #include "math/geometry.h" +#include "sound/sound.h" + // Initial size of various vectors const int OBJECT_PREALLOCATE_COUNT = 1200; @@ -50,6 +52,13 @@ const int LEVEL5_PREALLOCATE_COUNT = 100; const int LEVEL5_VERTEX_PREALLOCATE_COUNT = 200; +// TODO: temporary stub for CInterface +class CInterface +{ +public: + void Draw() {} +}; + Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) { m_iMan = iMan; @@ -60,7 +69,7 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_iMan->AddInstance(CLASS_ENGINE, this); m_app = app; - m_lightMan = nullptr; + m_lightMan = nullptr; m_text = nullptr; m_particle = nullptr; m_water = nullptr; @@ -107,15 +116,14 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_overFront = true; m_overColor = 0; m_overMode = ENG_RSTATE_TCOLOR_BLACK; - m_frontsizeName = ""; // no front image - m_hiliteRank[0] = -1; // empty list + m_highlightRank[0] = -1; // empty list m_eyePt = Math::Vector(0.0f, 0.0f, 0.0f); m_lookatPt = Math::Vector(0.0f, 0.0f, 1.0f); m_drawWorld = true; m_drawFront = false; m_limitLOD[0] = 100.0f; m_limitLOD[1] = 200.0f; - m_particuleDensity = 1.0f; + m_particleDensity = 1.0f; m_clippingDistance = 1.0f; m_lastClippingDistance = m_clippingDistance; m_objectDetail = 1.0f; @@ -186,11 +194,10 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) Gfx::CEngine::~CEngine() { - m_iMan = nullptr; - m_app = nullptr; - m_device = nullptr; - - m_sound = nullptr; + m_iMan = nullptr; + m_app = nullptr; + m_device = nullptr; + m_sound = nullptr; m_terrain = nullptr; } @@ -209,6 +216,16 @@ Gfx::CDevice* Gfx::CEngine::GetDevice() return m_device; } +void Gfx::CEngine::SetTerrain(Gfx::CTerrain* terrain) +{ + m_terrain = terrain; +} + +Gfx::CText* Gfx::CEngine::GetText() +{ + return m_text; +} + bool Gfx::CEngine::Create() { m_size = m_lastSize = m_app->GetVideoConfig().size; @@ -228,14 +245,17 @@ bool Gfx::CEngine::Create() return false; } + m_device->SetClearColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); + m_device->SetShadeModel(Gfx::SHADE_SMOOTH); + m_device->SetFillMode(Gfx::FILL_FILL); + + SetFocus(m_focus); m_matWorldInterface.LoadIdentity(); m_matViewInterface.LoadIdentity(); - Math::LoadOrthoProjectionMatrix(m_matProjInterface, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); - - m_device->SetClearColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); + Math::LoadOrthoProjectionMatrix(m_matProjInterface, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); Gfx::TextureCreateParams params; params.format = Gfx::TEX_IMG_RGB; @@ -275,414 +295,2326 @@ void Gfx::CEngine::Destroy() void Gfx::CEngine::ResetAfterDeviceChanged() { - // TODO + // TODO reload textures, reset device state, etc. } -Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName, const Gfx::TextureCreateParams ¶ms) +bool Gfx::CEngine::ProcessEvent(const Event &event) { - CImage img; - if (! img.Load(m_app->GetDataFilePath(m_texPath, texName))) + if (event.type == EVENT_MOUSE_MOVE) { - std::stringstream str; - str << "Couldn't load texture '" << texName << "': " << img.GetError(); - m_error = str.str(); - return Gfx::Texture(); // invalid texture + m_mousePos = event.mouseMove.pos; } + else if (event.type == EVENT_KEY_DOWN) + { + // !! Debug, to be removed later !! - Gfx::Texture result = m_device->CreateTexture(&img, params); + if (event.key.key == KEY(F1)) + { + m_mouseVisible = !m_mouseVisible; + m_app->SetSystemMouseVisible(! m_app->GetSystemMouseVisibile()); + } + else if (event.key.key == KEY(F2)) + { + int index = static_cast(m_mouseType); + m_mouseType = static_cast( (index + 1) % Gfx::ENG_MOUSE_COUNT ); + } + } - if (! result.valid) + // By default, pass on all events + return true; +} + +void Gfx::CEngine::FrameMove(float rTime) +{ + m_lightMan->UpdateProgression(rTime); + m_particle->FrameParticle(rTime); + ComputeDistance(); + UpdateGeometry(); + + if (m_groundMark.draw) { - std::stringstream str; - str << "Couldn't load texture '" << texName << "': " << m_device->GetError(); - m_error = str.str(); - return result; + if (m_groundMark.phase == Gfx::ENG_GR_MARK_PHASE_INC) // growing? + { + m_groundMark.intensity += rTime*(1.0f/m_groundMark.delay[0]); + if (m_groundMark.intensity >= 1.0f) + { + m_groundMark.intensity = 1.0f; + m_groundMark.fix = 0.0f; + m_groundMark.phase = Gfx::ENG_GR_MARK_PHASE_FIX; + } + } + else if (m_groundMark.phase == Gfx::ENG_GR_MARK_PHASE_FIX) // fixed? + { + m_groundMark.fix += rTime*(1.0f/m_groundMark.delay[1]); + if (m_groundMark.fix >= 1.0f) + m_groundMark.phase = Gfx::ENG_GR_MARK_PHASE_DEC; + } + else if (m_groundMark.phase == Gfx::ENG_GR_MARK_PHASE_DEC) // decay? + { + m_groundMark.intensity -= rTime*(1.0f/m_groundMark.delay[2]); + if (m_groundMark.intensity < 0.0f) + { + m_groundMark.intensity = 0.0f; + m_groundMark.phase = Gfx::ENG_GR_MARK_PHASE_NULL; + m_groundMark.draw = false; + } + } } - m_texNameMap[texName] = result; - m_revTexNameMap[result] = texName; + if (m_sound == nullptr) + m_sound = static_cast( m_iMan->SearchInstance(CLASS_SOUND) ); - return result; + m_sound->FrameMove(rTime); } -Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName) +void Gfx::CEngine::StepSimulation(float rTime) { - return CreateTexture(texName, m_defaultTexParams); + m_app->StepSimulation(rTime); } -void Gfx::CEngine::DestroyTexture(const std::string &texName) +void Gfx::CEngine::TimeInit() { - std::map::iterator it = m_texNameMap.find(texName); - if (it == m_texNameMap.end()) - return; - - std::map::iterator revIt = m_revTexNameMap.find((*it).second); + /* TODO! + m_baseTime = timeGetTime(); + m_lastTime = 0; + m_absTime = 0.0f;*/ +} - m_device->DestroyTexture((*it).second); +void Gfx::CEngine::TimeEnterGel() +{ + /* TODO! + m_stopTime = timeGetTime();*/ +} - m_revTexNameMap.erase(revIt); - m_texNameMap.erase(it); +void Gfx::CEngine::TimeExitGel() +{ + /* TODO! + m_baseTime += timeGetTime() - m_stopTime;*/ } -void Gfx::CEngine::SetTexture(const std::string &name, int stage) +float Gfx::CEngine::TimeGet() { - std::map::iterator it = m_texNameMap.find(name); - if (it != m_texNameMap.end()) - m_device->SetTexture(stage, (*it).second); + /* TODO! + float aTime = (timeGetTime()-m_baseTime)*0.001f; // in ms + float rTime = (aTime - m_lastTime)*m_speed; + m_absTime += rTime; + m_lastTime = aTime; - // TODO if not present... + return rTime;*/ + return 0.0f; } -void Gfx::CEngine::SetMaterial(const Gfx::Material &mat) +bool Gfx::CEngine::WriteScreenShot(const std::string& fileName, int width, int height) { - m_device->SetMaterial(mat); + // TODO! + return true; } -void Gfx::CEngine::SetState(int state, Gfx::Color color) +bool Gfx::CEngine::ReadSettings() { - if ( state == m_lastState && color == m_lastColor ) - return; + // TODO! + return true; +} - m_lastState = state; - m_lastColor = color; +bool Gfx::CEngine::WriteSettings() +{ + // TODO! + return true; +} - if ( m_alphaMode != 1 && (state & Gfx::ENG_RSTATE_ALPHA) ) - { - state &= ~Gfx::ENG_RSTATE_ALPHA; +void Gfx::CEngine::SetPause(bool pause) +{ + m_pause = pause; +} - if (m_alphaMode == 2) - state |= Gfx::ENG_RSTATE_TTEXTURE_BLACK; - } +bool Gfx::CEngine::GetPause() +{ + return m_pause; +} - // TODO other modes & thorough testing +void Gfx::CEngine::SetMovieLock(bool lock) +{ + m_movieLock = lock; +} - if (state & Gfx::ENG_RSTATE_TTEXTURE_BLACK) // The transparent black texture? - { - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); - m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); +bool Gfx::CEngine::GetMovieLock() +{ + return m_movieLock; +} - m_device->SetBlendFunc(Gfx::BLEND_ONE, Gfx::BLEND_INV_SRC_COLOR); - m_device->SetTextureEnabled(0, true); - m_device->SetTextureFactor(color); +void Gfx::CEngine::SetShowStats(bool show) +{ + m_showStats = show; +} - Gfx::TextureStageParams params; - params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE; - params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; - params.colorArg2 = Gfx::TEX_MIX_ARG_FACTOR; - params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE; - m_device->SetTextureStageParams(0, params); - } - else if (state & Gfx::ENG_RSTATE_TTEXTURE_WHITE) // The transparent white texture? - { - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); - m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); +bool Gfx::CEngine::GetShowStats() +{ + return m_showStats; +} - m_device->SetBlendFunc(Gfx::BLEND_DST_COLOR, Gfx::BLEND_ZERO); - m_device->SetTextureEnabled(0, true); - m_device->SetTextureFactor(color.Inverse()); +void Gfx::CEngine::SetRenderEnable(bool enable) +{ + m_render = enable; +} - Gfx::TextureStageParams params; - params.colorOperation = Gfx::TEX_MIX_OPER_ADD; - params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; - params.colorArg2 = Gfx::TEX_MIX_ARG_FACTOR; - params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE; - m_device->SetTextureStageParams(0, params); - } - else if (state & Gfx::ENG_RSTATE_TCOLOR_BLACK) // The transparent black color? - { - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); - m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); +Math::IntSize Gfx::CEngine::GetWindowSize() +{ + return m_size; +} - m_device->SetBlendFunc(Gfx::BLEND_ONE, Gfx::BLEND_INV_SRC_COLOR); +Math::IntSize Gfx::CEngine::GetLastWindowSize() +{ + return m_lastSize; +} - m_device->SetTextureFactor(color); - m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); - } - else if (state & Gfx::ENG_RSTATE_TCOLOR_WHITE) // The transparent white color? - { - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); - m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); +Math::Point Gfx::CEngine::WindowToInterfaceCoords(Math::IntPoint pos) +{ + return Math::Point( static_cast(pos.x) / static_cast(m_size.w), + 1.0f - static_cast(pos.y) / static_cast(m_size.h) ); +} - m_device->SetBlendFunc(Gfx::BLEND_DST_COLOR, Gfx::BLEND_ZERO); +Math::IntPoint Gfx::CEngine::InterfaceToWindowCoords(Math::Point pos) +{ + return Math::IntPoint(static_cast(pos.x * m_size.w), + static_cast((1.0f - pos.y) * m_size.h)); +} - m_device->SetTextureFactor(color.Inverse()); - m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); - } - else if (state & Gfx::ENG_RSTATE_TDIFFUSE) // diffuse color as transparent? - { - /*m_device->SetRenderState(D3DRENDERSTATE_FOGENABLE, false); - m_device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false); - m_device->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true); - m_device->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false); - m_device->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_diffuseSrcBlend[1]); - m_device->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_diffuseDestBlend[1]); +Math::Size Gfx::CEngine::WindowToInterfaceSize(Math::IntSize size) +{ + return Math::Size( static_cast(size.w) / static_cast(m_size.w), + static_cast(size.h) / static_cast(m_size.h) ); +} - m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);*/ - } - else if (state & Gfx::ENG_RSTATE_ALPHA) // image with alpha channel? - { - /*m_device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true); - m_device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true); - m_device->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false); - m_device->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, true); - m_device->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATER); - m_device->SetRenderState(D3DRENDERSTATE_ALPHAREF, (DWORD)(128)); - m_device->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_alphaSrcBlend[1]); - m_device->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_alphaSrcBlend[1]); +Math::IntSize Gfx::CEngine::InterfaceToWindowSize(Math::Size size) +{ + return Math::IntSize(static_cast(size.w * m_size.w), + static_cast(size.h * m_size.h)); +} - m_device->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color); - m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - m_device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);*/ - } - else if (state & Gfx::ENG_RSTATE_TEXT) - { - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); +std::string Gfx::CEngine::GetTextureDir() +{ + return m_texPath; +} - m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); +void Gfx::CEngine::AddStatisticTriangle(int count) +{ + m_statisticTriangle += count; +} + +int Gfx::CEngine::GetStatisticTriangle() +{ + return m_statisticTriangle; +} + + + +/******************************************************* + Object management + *******************************************************/ + + + +int Gfx::CEngine::CreateObject() +{ + // TODO! + return 0; +} + +void Gfx::CEngine::FlushObject() +{ + // TODO! +} + +bool Gfx::CEngine::DeleteObject(int objRank) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetDrawWorld(int objRank, bool draw) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetDrawFront(int objRank, bool draw) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::AddTriangle(int objRank, Gfx::VertexTex2* vertex, int nb, + const Gfx::Material& mat, int state, + std::string texName1, std::string texName2, + float min, float max, bool globalUpdate) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::AddSurface(int objRank, Gfx::VertexTex2* vertex, int nb, + const Gfx::Material& mat, int state, + std::string texName1, std::string texName2, + float min, float max, bool globalUpdate) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::AddQuick(int objRank, const Gfx::EngineObjLevel5& buffer, + std::string texName1, std::string texName2, + float min, float max, bool globalUpdate) +{ + // TODO! + return true; +} + +Gfx::EngineObjLevel5* Gfx::CEngine::SearchTriangle(int objRank, const Gfx::Material& mat, + int state, std::string texName1, + std::string texName2, float min, float max) +{ + // TODO! + return nullptr; +} + +void Gfx::CEngine::ChangeLOD() +{ + // TODO! +} + +bool Gfx::CEngine::ChangeSecondTexture(int objRank, const std::string& texName2) +{ + // TODO! + return true; +} + +int Gfx::CEngine::GetTotalTriangles(int objRank) +{ + // TODO! + return 0; +} + +int Gfx::CEngine::GetTriangles(int objRank, float min, float max, Gfx::EngineTriangle* buffer, int size, float percent) +{ + // TODO! + return 0; +} + +bool Gfx::CEngine::GetBBox(int objRank, Math::Vector& min, Math::Vector& max) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::ChangeTextureMapping(int objRank, const Gfx::Material& mat, int state, + const std::string& texName1, const std::string& texName2, + float min, float max, Gfx::EngineTextureMapping mode, + float au, float bu, float av, float bv) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::TrackTextureMapping(int objRank, const Gfx::Material& mat, int state, + const std::string& texName1, const std::string& texName2, + float min, float max, Gfx::EngineTextureMapping mode, + float pos, float factor, float tl, float ts, float tt) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectTransform(int objRank, const Math::Matrix& transform) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::GetObjectTransform(int objRank, Math::Matrix& transform) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectType(int objRank, Gfx::EngineObjectType type) +{ + // TODO! + return true; +} + +Gfx::EngineObjectType Gfx::CEngine::GetObjectType(int objRank) +{ + // TODO! + return Gfx::ENG_OBJTYPE_FIX; +} + +bool Gfx::CEngine::SetObjectTransparency(int objRank, float value) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::ShadowCreate(int objRank) +{ + // TODO! + return true; +} + +void Gfx::CEngine::ShadowDelete(int objRank) +{ + // TODO! +} + +bool Gfx::CEngine::SetObjectShadowHide(int objRank, bool hide) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectShadowType(int objRank, Gfx::EngineShadowType type) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectShadowPos(int objRank, const Math::Vector& pos) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectShadowNormal(int objRank, const Math::Vector& n) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectShadowAngle(int objRank, float angle) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectShadowRadius(int objRank, float radius) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectShadowIntensity(int objRank, float intensity) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectShadowHeight(int objRank, float h) +{ + // TODO! + return true; +} + +float Gfx::CEngine::GetObjectShadowRadius(int objRank) +{ + // TODO! + return 0.0f; +} + +bool Gfx::CEngine::GetHighlight(Math::Point &p1, Math::Point &p2) +{ + p1 = m_highlightP1; + p2 = m_highlightP2; + return m_highlight; +} + +void Gfx::CEngine::SetHighlightRank(int *rankList) +{ + int i = 0; + while ( *rankList != -1 ) + { + m_highlightRank[i++] = *rankList++; + } + m_highlightRank[i] = -1; // terminator +} + +bool Gfx::CEngine::GetBBox2D(int objRank, Math::Point &min, Math::Point &max) +{ + min.x = 1000000.0f; + min.y = 1000000.0f; + max.x = -1000000.0f; + max.y = -1000000.0f; + + for (int i = 0; i < 8; i++) + { + Math::Vector p; + + if ( i & (1<<0) ) p.x = m_objects[objRank].bboxMin.x; + else p.x = m_objects[objRank].bboxMax.x; + if ( i & (1<<1) ) p.y = m_objects[objRank].bboxMin.y; + else p.y = m_objects[objRank].bboxMax.y; + if ( i & (1<<2) ) p.z = m_objects[objRank].bboxMin.z; + else p.z = m_objects[objRank].bboxMax.z; + + Math::Vector pp; + if (TransformPoint(pp, objRank, p)) + { + if (pp.x < min.x) min.x = pp.x; + if (pp.x > max.x) max.x = pp.x; + if (pp.y < min.y) min.y = pp.y; + if (pp.y > max.y) max.y = pp.y; + } + } + + if ( min.x == 1000000.0f || + min.y == 1000000.0f || + max.x == -1000000.0f || + max.y == -1000000.0f ) return false; + + return true; +} + +void Gfx::CEngine::GroundSpotFlush() +{ + // TODO +} + +int Gfx::CEngine::GroundSpotCreate() +{ + // TODO! + return 0; +} + +void Gfx::CEngine::GroundSpotDelete(int rank) +{ + // TODO! +} + +bool Gfx::CEngine::SetObjectGroundSpotPos(int rank, const Math::Vector& pos) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectGroundSpotRadius(int rank, float radius) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectGroundSpotColor(int rank, const Gfx::Color& color) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectGroundSpotMinMax(int rank, float min, float max) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetObjectGroundSpotSmooth(int rank, float smooth) +{ + // TODO! + return true; +} + +int Gfx::CEngine::GroundMarkCreate(Math::Vector pos, float radius, + float delay1, float delay2, float delay3, + int dx, int dy, char* table) +{ + // TODO! + return 0; +} + +bool Gfx::CEngine::GroundMarkDelete(int rank) +{ + // TODO! + return true; +} + +void Gfx::CEngine::ComputeDistance() +{ + // TODO! +} + +void Gfx::CEngine::UpdateGeometry() +{ + // TODO! +} + +void Gfx::CEngine::Update() +{ + ComputeDistance(); + UpdateGeometry(); +} + +bool Gfx::CEngine::DetectBBox(int objRank, Math::Point mouse) +{ + // TODO! + return true; +} + +int Gfx::CEngine::DetectObject(Math::Point mouse) +{ + // TODO! + return 0; +} + +bool Gfx::CEngine::DetectTriangle(Math::Point mouse, Gfx::VertexTex2* triangle, int objRank, float& dist) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::IsVisible(int objRank) +{ + // TODO! + return true; +} + +bool Gfx::CEngine::TransformPoint(Math::Vector& p2D, int objRank, Math::Vector p3D) +{ + // TODO! + return true; +} + + + +/******************************************************* + Mode setting + *******************************************************/ + + + +void Gfx::CEngine::SetState(int state, const Gfx::Color& color) +{ + if ( state == m_lastState && color == m_lastColor ) + return; + + m_lastState = state; + m_lastColor = color; + + if ( m_alphaMode != 1 && (state & Gfx::ENG_RSTATE_ALPHA) ) + { + state &= ~Gfx::ENG_RSTATE_ALPHA; + + if (m_alphaMode == 2) + state |= Gfx::ENG_RSTATE_TTEXTURE_BLACK; + } + + // TODO other modes & thorough testing + + if (state & Gfx::ENG_RSTATE_TTEXTURE_BLACK) // The transparent black texture? + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + + m_device->SetBlendFunc(Gfx::BLEND_ONE, Gfx::BLEND_INV_SRC_COLOR); + m_device->SetTextureEnabled(0, true); + m_device->SetTextureFactor(color); + + Gfx::TextureStageParams params; + params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE; + params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; + params.colorArg2 = Gfx::TEX_MIX_ARG_FACTOR; + params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE; + m_device->SetTextureStageParams(0, params); + } + else if (state & Gfx::ENG_RSTATE_TTEXTURE_WHITE) // The transparent white texture? + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + + m_device->SetBlendFunc(Gfx::BLEND_DST_COLOR, Gfx::BLEND_ZERO); + m_device->SetTextureEnabled(0, true); + m_device->SetTextureFactor(color.Inverse()); + + Gfx::TextureStageParams params; + params.colorOperation = Gfx::TEX_MIX_OPER_ADD; + params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; + params.colorArg2 = Gfx::TEX_MIX_ARG_FACTOR; + params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE; + m_device->SetTextureStageParams(0, params); + } + else if (state & Gfx::ENG_RSTATE_TCOLOR_BLACK) // The transparent black color? + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + + m_device->SetBlendFunc(Gfx::BLEND_ONE, Gfx::BLEND_INV_SRC_COLOR); + + m_device->SetTextureFactor(color); + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + } + else if (state & Gfx::ENG_RSTATE_TCOLOR_WHITE) // The transparent white color? + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + + m_device->SetBlendFunc(Gfx::BLEND_DST_COLOR, Gfx::BLEND_ZERO); + + m_device->SetTextureFactor(color.Inverse()); + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + } + else if (state & Gfx::ENG_RSTATE_TDIFFUSE) // diffuse color as transparent? + { + /*m_device->SetRenderState(D3DRENDERSTATE_FOGENABLE, false); + m_device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false); + m_device->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true); + m_device->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false); + m_device->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_diffuseSrcBlend[1]); + m_device->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_diffuseDestBlend[1]); + + m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);*/ + } + else if (state & Gfx::ENG_RSTATE_ALPHA) // image with alpha channel? + { + /*m_device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true); + m_device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true); + m_device->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false); + m_device->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, true); + m_device->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATER); + m_device->SetRenderState(D3DRENDERSTATE_ALPHAREF, (DWORD)(128)); + m_device->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_alphaSrcBlend[1]); + m_device->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_alphaSrcBlend[1]); + + m_device->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color); + m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + m_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + m_device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);*/ + } + else if (state & Gfx::ENG_RSTATE_TEXT) + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + + m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_INV_SRC_ALPHA); + } + else // normal ? + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, true); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + + /*m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + m_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);*/ + } + + if (state & Gfx::ENG_RSTATE_FOG) + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); + + + bool second = m_groundSpotVisible || m_dirty; + + if ( !m_groundSpotVisible && (state & Gfx::ENG_RSTATE_SECOND) != 0 ) second = false; + if ( !m_dirty && (state & Gfx::ENG_RSTATE_SECOND) == 0 ) second = false; + + if ( (state & ENG_RSTATE_DUAL_BLACK) && second ) + { + /*m_device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); + m_device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); + m_device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); + m_device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + m_device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);*/ + } + else if ( (state & ENG_RSTATE_DUAL_WHITE) && second ) + { + /*m_device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD); + m_device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); + m_device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); + m_device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + m_device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);*/ + } + else + { + m_device->SetTextureEnabled(1, false); + } + + if (state & Gfx::ENG_RSTATE_WRAP) + { + /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP); + m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);*/ + } + else if (state & Gfx::ENG_RSTATE_CLAMP) + { + /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP); + m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);*/ + } + else + { + /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP); + m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);*/ + } + + if (state & Gfx::ENG_RSTATE_2FACE) + { + m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); + } + else + { + m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, true); + m_device->SetCullMode(Gfx::CULL_CCW); + } + + if (state & Gfx::ENG_RSTATE_LIGHT) + m_device->SetGlobalAmbient(Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)); + else + m_device->SetGlobalAmbient(m_ambientColor[m_rankView]); +} + +void Gfx::CEngine::SetMaterial(const Gfx::Material &mat) +{ + m_device->SetMaterial(mat); +} + +void Gfx::CEngine::SetViewParams(const Math::Vector& eyePt, const Math::Vector& lookatPt, + const Math::Vector& upVec, float eyeDistance) +{ + m_eyePt = eyePt; + m_lookatPt = lookatPt; + m_eyeDirH = Math::RotateAngle(eyePt.x - lookatPt.x, eyePt.z - lookatPt.z); + m_eyeDirV = Math::RotateAngle(Math::DistanceProjected(eyePt, lookatPt), eyePt.y - lookatPt.y); + + Math::LoadViewMatrix(m_matView, eyePt, lookatPt, upVec); + + if (m_sound == nullptr) + m_sound = static_cast( m_iMan->SearchInstance(CLASS_SOUND) ); + + m_sound->SetListener(eyePt, lookatPt); +} + +Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName, const Gfx::TextureCreateParams ¶ms) +{ + CImage img; + if (! img.Load(m_app->GetDataFilePath(m_texPath, texName))) + { + std::stringstream str; + str << "Couldn't load texture '" << texName << "': " << img.GetError(); + m_error = str.str(); + return Gfx::Texture(); // invalid texture + } + + Gfx::Texture result = m_device->CreateTexture(&img, params); + + if (! result.valid) + { + std::stringstream str; + str << "Couldn't load texture '" << texName << "': " << m_device->GetError(); + m_error = str.str(); + return result; + } + + m_texNameMap[texName] = result; + m_revTexNameMap[result] = texName; + + return result; +} + +Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName) +{ + return CreateTexture(texName, m_defaultTexParams); +} + +void Gfx::CEngine::DestroyTexture(const std::string &texName) +{ + std::map::iterator it = m_texNameMap.find(texName); + if (it == m_texNameMap.end()) + return; + + std::map::iterator revIt = m_revTexNameMap.find((*it).second); + + m_device->DestroyTexture((*it).second); + + m_revTexNameMap.erase(revIt); + m_texNameMap.erase(it); +} + +bool Gfx::CEngine::LoadTexture(const std::string& name, int stage) +{ + std::map::iterator it = m_texNameMap.find(name); + if (it != m_texNameMap.end()) + { + m_device->SetTexture(stage, (*it).second); + return true; + } + + // TODO if not present... + return false; +} + +bool Gfx::CEngine::LoadAllTextures() +{ + // TODO! + return true; +} + +bool Gfx::CEngine::SetTexture(const std::string& name, int stage) +{ + // TODO! + return true; +} + +void Gfx::CEngine::SetLimitLOD(int rank, float limit) +{ + m_limitLOD[rank] = limit; +} + +float Gfx::CEngine::GetLimitLOD(int rank, bool last) +{ + float limit = 0.0f; + + if (last) + { + limit = m_limitLOD[rank]; + limit *= m_lastSize.w/640.0f; // limit further if large window! + limit += m_limitLOD[0]*(m_lastObjectDetail*2.0f); + } + else + { + limit = m_limitLOD[rank]; + limit *= m_size.w/640.0f; // limit further if large window! + limit += m_limitLOD[0]*(m_objectDetail*2.0f); + } + + if (limit < 0.0f) limit = 0.0f; + + return limit; +} + +void Gfx::CEngine::SetTerrainVision(float vision) +{ + m_terrainVision = vision; +} + +void Gfx::CEngine::SetFocus(float focus) +{ + m_focus = focus; + m_size = m_app->GetVideoConfig().size; + + float aspect = (static_cast(m_size.h)) / m_size.w; + Math::LoadProjectionMatrix(m_matProj, m_focus, aspect, 0.5f, m_deepView[0]); +} + +float Gfx::CEngine::GetFocus() +{ + return m_focus; +} + +void Gfx::CEngine::SetGroundSpot(bool mode) +{ + m_groundSpotVisible = mode; +} + +bool Gfx::CEngine::GetGroundSpot() +{ + return m_groundSpotVisible; +} + +void Gfx::CEngine::SetShadow(bool mode) +{ + m_shadowVisible = mode; +} + +bool Gfx::CEngine::GetShadow() +{ + return m_shadowVisible; +} + +void Gfx::CEngine::SetDirty(bool mode) +{ + m_dirty = mode; +} + +bool Gfx::CEngine::GetDirty() +{ + return m_dirty; +} + +void Gfx::CEngine::SetFog(bool mode) +{ + m_fog = mode; +} + +bool Gfx::CEngine::GetFog() +{ + return m_fog; +} + +bool Gfx::CEngine::GetStateColor() +{ + return m_stateColor; +} + +void Gfx::CEngine::SetSecondTexture(int texNum) +{ + m_secondTexNum = texNum; +} + +int Gfx::CEngine::GetSecondTexture() +{ + return m_secondTexNum; +} + +void Gfx::CEngine::SetRankView(int rank) +{ + if (rank < 0) rank = 0; + if (rank > 1) rank = 1; + + if (m_rankView == 0 && rank == 1) // enters the water? + m_lightMan->AdaptLightColor(m_waterAddColor, +1.0f); + + if (m_rankView == 1 && rank == 0) // out of the water? + m_lightMan->AdaptLightColor(m_waterAddColor, -1.0f); + + m_rankView = rank; +} + +int Gfx::CEngine::GetRankView() +{ + return m_rankView; +} + +void Gfx::CEngine::SetDrawWorld(bool draw) +{ + m_drawWorld = draw; +} + +void Gfx::CEngine::SetDrawFront(bool draw) +{ + m_drawFront = draw; +} + +void Gfx::CEngine::SetAmbientColor(const Gfx::Color& color, int rank) +{ + m_ambientColor[rank] = color; +} + +Gfx::Color Gfx::CEngine::GetAmbientColor(int rank) +{ + return m_ambientColor[rank]; +} + +void Gfx::CEngine::SetWaterAddColor(const Gfx::Color& color) +{ + m_waterAddColor = color; +} + +Gfx::Color Gfx::CEngine::GetWaterAddColor() +{ + return m_waterAddColor; +} + +void Gfx::CEngine::SetFogColor(const Gfx::Color& color, int rank) +{ + m_fogColor[rank] = color; +} + +Gfx::Color Gfx::CEngine::GetFogColor(int rank) +{ + return m_fogColor[rank]; +} + +void Gfx::CEngine::SetDeepView(float length, int rank, bool ref) +{ + if (ref) + length *= m_clippingDistance; + + m_deepView[rank] = length; +} + +float Gfx::CEngine::GetDeepView(int rank) +{ + return m_deepView[rank]; +} + +void Gfx::CEngine::SetFogStart(float start, int rank) +{ + m_fogStart[rank] = start; +} + +float Gfx::CEngine::GetFogStart(int rank) +{ + return m_fogStart[rank]; +} + + +void Gfx::CEngine::SetBackground(const std::string& name, Gfx::Color up, Gfx::Color down, + Gfx::Color cloudUp, Gfx::Color cloudDown, + bool full, bool quarter) +{ + m_backgroundName = name; + m_backgroundColorUp = up; + m_backgroundColorDown = down; + m_backgroundCloudUp = cloudUp; + m_backgroundCloudDown = cloudDown; + m_backgroundFull = full; + m_backgroundQuarter = quarter; +} + +void Gfx::CEngine::GetBackground(std::string& name, Gfx::Color& up, Gfx::Color& down, + Gfx::Color& cloudUp, Gfx::Color& cloudDown, + bool &full, bool &quarter) +{ + name = m_backgroundName; + up = m_backgroundColorUp; + down = m_backgroundColorDown; + cloudUp = m_backgroundCloudUp; + cloudDown = m_backgroundCloudDown; + full = m_backgroundFull; + quarter = m_backgroundQuarter; +} + +void Gfx::CEngine::SetForegroundImageName(const std::string& name) +{ + if (! m_foregroundImageName.empty()) + DestroyTexture(m_foregroundImageName); + + m_foregroundImageName = name; +} + +void Gfx::CEngine::SetOverFront(bool front) +{ + m_overFront = front; +} + +void Gfx::CEngine::SetOverColor(const Gfx::Color& color, int mode) +{ + m_overColor = color; + m_overMode = mode; +} + +void Gfx::CEngine::SetParticleDensity(float value) +{ + if (value < 0.0f) value = 0.0f; + if (value > 2.0f) value = 2.0f; + m_particleDensity = value; +} + +float Gfx::CEngine::GetParticleDensity() +{ + return m_particleDensity; +} + +float Gfx::CEngine::ParticleAdapt(float factor) +{ + if (m_particleDensity == 0.0f) + return 1000000.0f; + + return factor / m_particleDensity; +} + +void Gfx::CEngine::SetClippingDistance(float value) +{ + if (value < 0.5f) value = 0.5f; + if (value > 2.0f) value = 2.0f; + m_clippingDistance = value; +} + +float Gfx::CEngine::GetClippingDistance() +{ + return m_clippingDistance; +} + +void Gfx::CEngine::SetObjectDetail(float value) +{ + if ( value < 0.0f ) value = 0.0f; + if ( value > 2.0f ) value = 2.0f; + m_objectDetail = value; +} + +float Gfx::CEngine::GetObjectDetail() +{ + return m_objectDetail; +} + +void Gfx::CEngine::SetGadgetQuantity(float value) +{ + if (value < 0.0f) value = 0.0f; + if (value > 1.0f) value = 1.0f; + + m_gadgetQuantity = value; +} + +float Gfx::CEngine::GetGadgetQuantity() +{ + return m_gadgetQuantity; +} + +void Gfx::CEngine::SetTextureQuality(int value) +{ + if (value < 0) value = 0; + if (value > 2) value = 2; + + if (value != m_textureQuality) + { + m_textureQuality = value; + LoadAllTextures(); + } +} + +int Gfx::CEngine::GetTextureQuality() +{ + return m_textureQuality; +} + +void Gfx::CEngine::SetTotoMode(bool present) +{ + m_totoMode = present; +} + +bool Gfx::CEngine::GetTotoMode() +{ + return m_totoMode; +} + +void Gfx::CEngine::SetLensMode(bool present) +{ + m_lensMode = present; +} + +bool Gfx::CEngine::GetLensMode() +{ + return m_lensMode; +} + +void Gfx::CEngine::SetWaterMode(bool present) +{ + m_waterMode = present; +} + +bool Gfx::CEngine::GetWaterMode() +{ + return m_waterMode; +} + +void Gfx::CEngine::SetLightingMode(bool present) +{ + m_lightMode = present; +} + +bool Gfx::CEngine::GetLightingMode() +{ + return m_lightMode; +} + +void Gfx::CEngine::SetSkyMode(bool present) +{ + m_skyMode = present; +} + +bool Gfx::CEngine::GetSkyMode() +{ + return m_skyMode; +} + +void Gfx::CEngine::SetBackForce(bool present) +{ + m_backForce = present; +} + +bool Gfx::CEngine::GetBackForce() +{ + return m_backForce; +} + +void Gfx::CEngine::SetPlanetMode(bool present) +{ + m_planetMode = present; +} + +bool Gfx::CEngine::GetPlanetMode() +{ + return m_planetMode; +} + +void Gfx::CEngine::SetLightMode(bool present) +{ + m_lightMode = present; +} + +bool Gfx::CEngine::GetLightMode() +{ + return m_lightMode; +} + +void Gfx::CEngine::SetEditIndentMode(bool autoIndent) +{ + m_editIndentMode = autoIndent; +} + +bool Gfx::CEngine::GetEditIndentMode() +{ + return m_editIndentMode; +} + +void Gfx::CEngine::SetEditIndentValue(int value) +{ + m_editIndentValue = value; +} + +int Gfx::CEngine::GetEditIndentValue() +{ + return m_editIndentValue; +} + +void Gfx::CEngine::SetSpeed(float speed) +{ + m_speed = speed; +} + +float Gfx::CEngine::GetSpeed() +{ + return m_speed; +} + +void Gfx::CEngine::SetTracePrecision(float factor) +{ + m_tracePrecision = factor; +} + +float Gfx::CEngine::GetTracePrecision() +{ + return m_tracePrecision; +} + +void Gfx::CEngine::SetMouseVisible(bool visible) +{ + m_mouseVisible = visible; +} + +bool Gfx::CEngine::GetMouseVisible() +{ + return m_mouseVisible; +} + +void Gfx::CEngine::SetMousePos(Math::Point pos) +{ + m_mousePos = pos; +} + +Math::Point Gfx::CEngine::GetMousePos() +{ + return m_mousePos; +} + +void Gfx::CEngine::SetMouseType(Gfx::EngineMouseType type) +{ + m_mouseType = type; +} + +Gfx::EngineMouseType Gfx::CEngine::GetMouseType() +{ + return m_mouseType; +} + +const Math::Matrix& Gfx::CEngine::GetMatView() +{ + return m_matView; +} + +Math::Vector Gfx::CEngine::GetEyePt() +{ + return m_eyePt; +} + +Math::Vector Gfx::CEngine::GetLookatPt() +{ + return m_lookatPt; +} - m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_INV_SRC_ALPHA); +float Gfx::CEngine::GetEyeDirH() +{ + return m_eyeDirH; +} + +float Gfx::CEngine::GetEyeDirV() +{ + return m_eyeDirV; +} + +bool Gfx::CEngine::IsVisiblePoint(const Math::Vector &pos) +{ + return Math::Distance(m_eyePt, pos) <= m_deepView[0]; +} + +void Gfx::CEngine::UpdateMatProj() +{ + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProj); +} + +void Gfx::CEngine::ApplyChange() +{ + m_deepView[0] /= m_lastClippingDistance; + m_deepView[1] /= m_lastClippingDistance; + + SetFocus(m_focus); + ChangeLOD(); + + m_deepView[0] *= m_clippingDistance; + m_deepView[1] *= m_clippingDistance; +} + + + +/******************************************************* + Rendering + *******************************************************/ + + + +/** + This function sets up render states, clears the + viewport, and renders the scene. */ +void Gfx::CEngine::Render() +{ + /* TODO! + D3DObjLevel1* p1; + D3DObjLevel2* p2; + D3DObjLevel3* p3; + D3DObjLevel4* p4; + D3DObjLevel5* p5; + D3DVERTEX2* pv; + int l1, l2, l3, l4, l5, objRank;*/ + + if (! m_render) return; + + m_statisticTriangle = 0; + m_lastState = -1; + m_lastColor = 999; + m_lastMaterial = Gfx::Material(); + + m_lightMan->UpdateLights(); + + Gfx::Color color; + if (m_skyMode && m_cloud->GetLevel() != 0.0f) // clouds? + color = m_backgroundCloudDown; + else + color = m_backgroundColorDown; + + m_device->SetClearColor(color); + + // Begin the scene + m_device->BeginScene(); + + + if (m_drawWorld) + { + Draw3DScene(); } - else // normal ? + + + DrawInterface(); + + // End the scene + m_device->EndScene(); +} + +void Gfx::CEngine::Draw3DScene() +{ + if (m_groundSpotVisible) + UpdateGroundSpotTextures(); + + DrawBackground(); // draws the background + if (m_planetMode) DrawPlanet(); // draws the planets + if (m_skyMode) m_cloud->Draw(); // draws the clouds + + + // Display the objects + + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, true); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); + + float fogStart = m_deepView[m_rankView]*m_fogStart[m_rankView]; + float fogEnd = m_deepView[m_rankView]; + m_device->SetFogParams(Gfx::FOG_LINEAR, m_fogColor[m_rankView], fogStart, fogEnd, 1.0f); + + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProj); + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matView); + + if (m_waterMode) m_water->DrawBack(); // draws water background + + if (m_shadowVisible) { - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, true); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, false); - m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + // Draw the field + // TODO! + /* + p1 = m_objectPointer; + for ( l1=0 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + SetTexture(p2->texName1, 0); + SetTexture(p2->texName2, 1); + for ( l2=0 ; l2totalUsed ; l2++ ) + { + p3 = p2->table[l2]; + if ( p3 == 0 ) continue; + objRank = p3->objRank; + if ( m_objectParam[objRank].type != TYPETERRAIN ) continue; + if ( !m_objectParam[objRank].bDrawWorld ) continue; + + { + D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform); + m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); + } + + if ( !IsVisible(objRank) ) continue; + m_light->LightUpdate(m_objectParam[objRank].type); + for ( l3=0 ; l3totalUsed ; l3++ ) + { + p4 = p3->table[l3]; + if ( p4 == 0 ) continue; + if ( m_objectParam[objRank].distance < p4->min || + m_objectParam[objRank].distance >= p4->max ) continue; + for ( l4=0 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; l5++ ) + { + p6 = p5->table[l5]; + if ( p6 == 0 ) continue; + SetMaterial(p6->material); + SetState(p6->state); + if ( p6->type == D3DTYPE6T ) + { + pv = &p6->vertex[0]; + m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, + D3DFVF_VERTEX2, + pv, p6->totalUsed, + NULL); + m_statisticTriangle += p6->totalUsed/3; + } + if ( p6->type == D3DTYPE6S ) + { + pv = &p6->vertex[0]; + m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, + D3DFVF_VERTEX2, + pv, p6->totalUsed, + NULL); + m_statisticTriangle += p6->totalUsed-2; + } + } + } + } + } + }*/ + + // Draws the shadows + DrawShadow(); + } - m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + // Draw objects + bool transparent = false; + /* TODO! + p1 = m_objectPointer; + for ( l1=0 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + SetTexture(p2->texName1, 0); + SetTexture(p2->texName2, 1); + for ( l2=0 ; l2totalUsed ; l2++ ) + { + p3 = p2->table[l2]; + if ( p3 == 0 ) continue; + objRank = p3->objRank; + if ( m_bShadow && m_objectParam[objRank].type == TYPETERRAIN ) continue; + if ( !m_objectParam[objRank].bDrawWorld ) continue; + + { + D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform); + m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); + } + + if ( !IsVisible(objRank) ) continue; + m_light->LightUpdate(m_objectParam[objRank].type); + for ( l3=0 ; l3totalUsed ; l3++ ) + { + p4 = p3->table[l3]; + if ( p4 == 0 ) continue; + if ( m_objectParam[objRank].distance < p4->min || + m_objectParam[objRank].distance >= p4->max ) continue; + for ( l4=0 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; l5++ ) + { + p6 = p5->table[l5]; + if ( p6 == 0 ) continue; + SetMaterial(p6->material); + if ( m_objectParam[objRank].transparency != 0.0f ) // transparent ? + { + transparent = true; + continue; + } + SetState(p6->state); + if ( p6->type == D3DTYPE6T ) + { + pv = &p6->vertex[0]; + m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, + D3DFVF_VERTEX2, + pv, p6->totalUsed, + NULL); + m_statisticTriangle += p6->totalUsed/3; + } + if ( p6->type == D3DTYPE6S ) + { + pv = &p6->vertex[0]; + m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, + D3DFVF_VERTEX2, + pv, p6->totalUsed, + NULL); + m_statisticTriangle += p6->totalUsed-2; + } + } + } + } + } + }*/ - /*m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);*/ + if (transparent) + { + int tState = 0; + Gfx::Color tColor; + if (m_stateColor) + { + tState = Gfx::ENG_RSTATE_TTEXTURE_BLACK | Gfx::ENG_RSTATE_2FACE; + tColor = Gfx::Color(68.0f / 255.0f, 68.0f / 255.0f, 68.0f / 255.0f, 68.0f / 255.0f); + } + else + { + tState = Gfx::ENG_RSTATE_TCOLOR_BLACK; + tColor = Gfx::Color(136.0f / 255.0f, 136.0f / 255.0f, 136.0f / 255.0f, 136.0f / 255.0f); + } + + // Draw transparent objects. + /* TODO! + p1 = m_objectPointer; + for ( l1=0 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + SetTexture(p2->texName1, 0); + SetTexture(p2->texName2, 1); + for ( l2=0 ; l2totalUsed ; l2++ ) + { + p3 = p2->table[l2]; + if ( p3 == 0 ) continue; + objRank = p3->objRank; + if ( m_bShadow && m_objectParam[objRank].type == TYPETERRAIN ) continue; + if ( !m_objectParam[objRank].bDrawWorld ) continue; + + { + D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform); + m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); + } + + if ( !IsVisible(objRank) ) continue; + m_light->LightUpdate(m_objectParam[objRank].type); + for ( l3=0 ; l3totalUsed ; l3++ ) + { + p4 = p3->table[l3]; + if ( p4 == 0 ) continue; + if ( m_objectParam[objRank].distance < p4->min || + m_objectParam[objRank].distance >= p4->max ) continue; + for ( l4=0 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; l5++ ) + { + p6 = p5->table[l5]; + if ( p6 == 0 ) continue; + SetMaterial(p6->material); + if ( m_objectParam[objRank].transparency == 0.0f ) continue; + SetState(tState, tColor); + if ( p6->type == D3DTYPE6T ) + { + pv = &p6->vertex[0]; + m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, + D3DFVF_VERTEX2, + pv, p6->totalUsed, + NULL); + m_statisticTriangle += p6->totalUsed/3; + } + if ( p6->type == D3DTYPE6S ) + { + pv = &p6->vertex[0]; + m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, + D3DFVF_VERTEX2, + pv, p6->totalUsed, + NULL); + m_statisticTriangle += p6->totalUsed-2; + } + } + } + } + } + } */ } - if (state & Gfx::ENG_RSTATE_FOG) + m_lightMan->UpdateLightsEnableState(Gfx::ENG_OBJTYPE_TERRAIN); + + if (m_waterMode) m_water->DrawSurf(); // draws water surface + + m_particle->DrawParticle(Gfx::SH_WORLD); // draws the particles of the 3D world + m_lightning->Draw(); // draws lightning + if (m_lensMode) DrawForegroundImage(); // draws the foreground + if (! m_overFront) DrawOverColor(); // draws the foreground color +} + +void Gfx::CEngine::DrawInterface() +{ + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); + + // Draw the entire interface + CInterface* interface = static_cast( m_iMan->SearchInstance(CLASS_INTERFACE) ); + if (interface != nullptr) + interface->Draw(); + + m_particle->DrawParticle(Gfx::SH_INTERFACE); // draws the particles of the interface + + // 3D objects drawn in front of interface + if (m_drawFront) + { + // Display the objects + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, true); + + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProj); + + m_device->SetGlobalAmbient(m_ambientColor[m_rankView]); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); + float fogStart = m_deepView[m_rankView]*m_fogStart[m_rankView]; + float fogEnd = m_deepView[m_rankView]; + m_device->SetFogParams(Gfx::FOG_LINEAR, m_fogColor[m_rankView], fogStart, fogEnd, 1.0f); - bool second = m_groundSpotVisible || m_dirty; + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matView); - if ( !m_groundSpotVisible && (state & Gfx::ENG_RSTATE_SECOND) != 0 ) second = false; - if ( !m_dirty && (state & Gfx::ENG_RSTATE_SECOND) == 0 ) second = false; + // TODO! + /* + for (int l1 = 0; l1 < m_objectTree.size(); l1++) + { + Gfx::EngineObjLevel1* p1 = &m_objectTree[l1]; + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + SetTexture(p2->texName1, 0); + SetTexture(p2->texName2, 1); + for ( l2=0 ; l2totalUsed ; l2++ ) + { + p3 = p2->table[l2]; + if ( p3 == 0 ) continue; + objRank = p3->objRank; + if ( !m_objectParam[objRank].bDrawFront ) continue; + + { + D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform); + m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat); + } + + if ( !IsVisible(objRank) ) continue; + m_light->LightUpdate(m_objectParam[objRank].type); + for ( l3=0 ; l3totalUsed ; l3++ ) + { + p4 = p3->table[l3]; + if ( p4 == 0 ) continue; + if ( m_objectParam[objRank].distance < p4->min || + m_objectParam[objRank].distance >= p4->max ) continue; + for ( l4=0 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; l5++ ) + { + p6 = p5->table[l5]; + if ( p6 == 0 ) continue; + SetMaterial(p6->material); + SetState(p6->state); + if ( p6->type == D3DTYPE6T ) + { + pv = &p6->vertex[0]; + m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, + D3DFVF_VERTEX2, + pv, p6->totalUsed, + NULL); + m_statisticTriangle += p6->totalUsed/3; + } + if ( p6->type == D3DTYPE6S ) + { + pv = &p6->vertex[0]; + m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, + D3DFVF_VERTEX2, + pv, p6->totalUsed, + NULL); + m_statisticTriangle += p6->totalUsed-2; + } + } + } + } + } + }*/ + + m_particle->DrawParticle(Gfx::SH_FRONT); // draws the particles of the 3D world + + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - if ( (state & ENG_RSTATE_DUAL_BLACK) && second ) + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); + } + + // Draw foreground color + if (m_overFront) + DrawOverColor(); + + // Mouse & highlight at the end + DrawMouse(); + DrawHighlight(); +} + +void Gfx::CEngine::UpdateGroundSpotTextures() +{ + // TODO! +} + +void Gfx::CEngine::DrawShadow() +{ + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); + + Math::Matrix matrix; + matrix.LoadIdentity(); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, matrix); + + + Gfx::Material material; + material.diffuse = Gfx::Color(1.0f, 1.0f, 1.0f); + material.ambient = Gfx::Color(0.5f, 0.5f, 0.5f); + SetMaterial(material); + + // TODO: wtf? + SetTexture("text.png"); + + Math::Point ts, ti; + + float dp = 0.5f/256.0f; + ts.y = 192.0f/256.0f; + ti.y = 224.0f/256.0f; + ts.y += dp; + ti.y -= dp; + + Math::Vector n(0.0f, 1.0f, 0.0f); + + float startDeepView = m_deepView[m_rankView]*m_fogStart[m_rankView]; + float endDeepView = m_deepView[m_rankView]; + + float lastIntensity = -1.0f; + for (int i = 0; i < static_cast( m_shadow.size() ); i++) { - /*m_device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); - m_device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); - m_device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); - m_device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);*/ + if (m_shadow[i].hide) continue; + + Math::Vector pos = m_shadow[i].pos; // pos = center of the shadow on the ground + + if (m_eyePt.y == pos.y) continue; // camera at the same level? + + float d = 0.0f; + float D = 0.0f; + + // h is the height above the ground to which the shadow + // will be drawn. + if (m_eyePt.y > pos.y) // camera on? + { + float height = m_eyePt.y-pos.y; + float h = m_shadow[i].radius; + float max = height*0.5f; + if ( h > max ) h = max; + if ( h > 4.0f ) h = 4.0f; + + D = Math::Distance(m_eyePt, pos); + if ( D >= endDeepView ) continue; + d = D*h/height; + + pos.x += (m_eyePt.x-pos.x)*d/D; + pos.z += (m_eyePt.z-pos.z)*d/D; + pos.y += h; + } + else // camera underneath? + { + float height = pos.y-m_eyePt.y; + float h = m_shadow[i].radius; + float max = height*0.1f; + if ( h > max ) h = max; + if ( h > 4.0f ) h = 4.0f; + + D = Math::Distance(m_eyePt, pos); + if ( D >= endDeepView ) continue; + d = D*h/height; + + pos.x += (m_eyePt.x-pos.x)*d/D; + pos.z += (m_eyePt.z-pos.z)*d/D; + pos.y -= h; + } + + // The hFactor decreases the intensity and size increases more + // the object is high relative to the ground. + float hFactor = m_shadow[i].height/20.0f; + if ( hFactor < 0.0f ) hFactor = 0.0f; + if ( hFactor > 1.0f ) hFactor = 1.0f; + hFactor = powf(1.0f-hFactor, 2.0f); + if ( hFactor < 0.2f ) hFactor = 0.2f; + + float radius = m_shadow[i].radius*1.5f; + radius *= 2.0f-hFactor; // greater if high + radius *= 1.0f-d/D; // smaller if close + + + Math::Vector corner[4]; + + if (m_shadow[i].type == Gfx::ENG_SHADOW_NORM) + { + corner[0].x = +radius; + corner[0].z = +radius; + corner[0].y = 0.0f; + + corner[1].x = -radius; + corner[1].z = +radius; + corner[1].y = 0.0f; + + corner[2].x = +radius; + corner[2].z = -radius; + corner[2].y = 0.0f; + + corner[3].x = -radius; + corner[3].z = -radius; + corner[3].y = 0.0f; + + ts.x = 64.0f/256.0f; + ti.x = 96.0f/256.0f; + } + else + { + Math::Point rot; + + rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(radius, radius)); + corner[0].x = rot.x; + corner[0].z = rot.y; + corner[0].y = 0.0f; + + rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(-radius, radius)); + corner[1].x = rot.x; + corner[1].z = rot.y; + corner[1].y = 0.0f; + + rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(radius, -radius)); + corner[2].x = rot.x; + corner[2].z = rot.y; + corner[2].y = 0.0f; + + rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(-radius, -radius)); + corner[3].x = rot.x; + corner[3].z = rot.y; + corner[3].y = 0.0f; + + if (m_shadow[i].type == Gfx::ENG_SHADOW_WORM) + { + ts.x = 96.0f/256.0f; + ti.x = 128.0f/256.0f; + } + else + { + ts.x = 64.0f/256.0f; + ti.x = 96.0f/256.0f; + } + } + + corner[0] = Math::CrossProduct(corner[0], m_shadow[i].normal); + corner[1] = Math::CrossProduct(corner[1], m_shadow[i].normal); + corner[2] = Math::CrossProduct(corner[2], m_shadow[i].normal); + corner[3] = Math::CrossProduct(corner[3], m_shadow[i].normal); + + corner[0] += pos; + corner[1] += pos; + corner[2] += pos; + corner[3] += pos; + + ts.x += dp; + ti.x -= dp; + + Gfx::Vertex vertex[4] = + { + Gfx::Vertex(corner[1], n, Math::Point(ts.x, ts.y)), + Gfx::Vertex(corner[0], n, Math::Point(ti.x, ts.y)), + Gfx::Vertex(corner[3], n, Math::Point(ts.x, ti.y)), + Gfx::Vertex(corner[2], n, Math::Point(ti.x, ti.y)) + }; + + float intensity = (0.5f+m_shadow[i].intensity*0.5f)*hFactor; + + // Decreases the intensity of the shade if you're in the area + // between the beginning and the end of the fog. + if ( D > startDeepView ) + intensity *= 1.0f-(D-startDeepView)/(endDeepView-startDeepView); + + if (intensity == 0.0f) continue; + + if (lastIntensity != intensity) // intensity changed? + { + lastIntensity = intensity; + SetState(Gfx::ENG_RSTATE_TTEXTURE_WHITE, Gfx::Color(intensity, intensity, intensity, intensity)); + } + + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + AddStatisticTriangle(2); } - else if ( (state & ENG_RSTATE_DUAL_WHITE) && second ) + + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, true); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true); +} + +void Gfx::CEngine::DrawBackground() +{ + if (m_skyMode && m_cloud->GetLevel() != 0.0f) // clouds ? { - /*m_device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD); - m_device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); - m_device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); - m_device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);*/ + if (m_backgroundCloudUp != m_backgroundCloudDown) // degraded? + DrawBackgroundGradient(m_backgroundCloudUp, m_backgroundCloudDown); } else { - m_device->SetTextureEnabled(1, false); + if (m_backgroundColorUp != m_backgroundColorDown) // degraded? + DrawBackgroundGradient(m_backgroundColorUp, m_backgroundColorDown); } - if (state & Gfx::ENG_RSTATE_WRAP) + if (m_backForce || (m_skyMode && m_backgroundName[0] != 0) ) { - /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP); - m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);*/ + DrawBackgroundImage(); // image } - else if (state & Gfx::ENG_RSTATE_CLAMP) +} + +void Gfx::CEngine::DrawBackgroundGradient(const Gfx::Color& up, const Gfx::Color& down) +{ + Math::Point p1(0.0f, 0.5f); + Math::Point p2(1.0f, 1.0f); + + Gfx::Color color[3] = { - /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP); - m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);*/ - } - else + up, + down, + Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f) + }; + + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); + + SetState(Gfx::ENG_RSTATE_NORMAL); + + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); + + Gfx::VertexCol vertex[4] = { - /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP); - m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);*/ - } + Gfx::VertexCol(Math::Vector(p1.x, p1.y, 0.0f), color[1], color[2]), + Gfx::VertexCol(Math::Vector(p1.x, p2.y, 0.0f), color[0], color[2]), + Gfx::VertexCol(Math::Vector(p2.x, p1.y, 0.0f), color[1], color[2]), + Gfx::VertexCol(Math::Vector(p2.x, p2.y, 0.0f), color[0], color[2]) + }; - if (state & Gfx::ENG_RSTATE_2FACE) + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + AddStatisticTriangle(2); +} + +void Gfx::CEngine::DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, const std::string& name) +{ + Math::Vector n = Math::Vector(0.0f, 0.0f, -1.0f); // normal + + float u1, u2, v1, v2; + if (m_backgroundFull) { - m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); + u1 = 0.0f; + v1 = 0.0f; + u2 = 1.0f; + v2 = 1.0f; + + if (m_backgroundQuarter) + { + u1 += 0.5f/512.0f; + v1 += 0.5f/384.0f; + u2 -= 0.5f/512.0f; + v2 -= 0.5f/384.0f; + } } else { - m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, true); - m_device->SetCullMode(Gfx::CULL_CCW); + float h = 0.5f; // visible area vertically (1=all) + float a = m_eyeDirV-Math::PI*0.15f; + if (a > Math::PI ) a -= Math::PI*2.0f; // a = -Math::PI..Math::PI + if (a > Math::PI/4.0f) a = Math::PI/4.0f; + if (a < -Math::PI/4.0f) a = -Math::PI/4.0f; + + u1 = -m_eyeDirH/Math::PI; + u2 = u1+1.0f/Math::PI; + + v1 = (1.0f-h)*(0.5f+a/(2.0f*Math::PI/4.0f))+0.1f; + v2 = v1+h; } - if (state & Gfx::ENG_RSTATE_LIGHT) - m_device->SetGlobalAmbient(Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)); - else - m_device->SetGlobalAmbient(m_ambientColor[m_rankView]); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + + SetTexture(name); + SetState(Gfx::ENG_RSTATE_WRAP); + + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); + + Gfx::Vertex vertex[4] = + { + Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), n, Math::Point(u1, v2)), + Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), n, Math::Point(u1, v1)), + Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(u2, v2)), + Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(u2, v1)) + }; + + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + AddStatisticTriangle(2); } -bool Gfx::CEngine::ProcessEvent(const Event &event) +void QuarterName(std::string& buffer, const std::string& name, int quarter) { - if (event.type == EVENT_MOUSE_MOVE) + size_t pos = name.find('.'); + if (pos == std::string::npos) { - m_mousePos = event.mouseMove.pos; + buffer = name; + return; } - else if (event.type == EVENT_KEY_DOWN) - { - // !! Debug, to be removed later !! - if (event.key.key == KEY(F1)) - { - m_mouseVisible = !m_mouseVisible; - m_app->SetSystemMouseVisible(! m_app->GetSystemMouseVisibile()); - } - else if (event.key.key == KEY(F2)) - { - int index = static_cast(m_mouseType); - m_mouseType = static_cast( (index + 1) % Gfx::ENG_MOUSE_COUNT ); - } + buffer = name.substr(0, pos) + std::string(1, static_cast('a' + quarter)) + name.substr(pos); +} + +void Gfx::CEngine::DrawBackgroundImage() +{ + Math::Point p1, p2; + std::string name; + + if (m_backgroundQuarter) + { + p1.x = 0.0f; + p1.y = 0.5f; + p2.x = 0.5f; + p2.y = 1.0f; + QuarterName(name, m_backgroundName, 0); + DrawBackgroundImageQuarter(p1, p2, name); + + p1.x = 0.5f; + p1.y = 0.5f; + p2.x = 1.0f; + p2.y = 1.0f; + QuarterName(name, m_backgroundName, 1); + DrawBackgroundImageQuarter(p1, p2, name); + + p1.x = 0.0f; + p1.y = 0.0f; + p2.x = 0.5f; + p2.y = 0.5f; + QuarterName(name, m_backgroundName, 2); + DrawBackgroundImageQuarter(p1, p2, name); + + p1.x = 0.5f; + p1.y = 0.0f; + p2.x = 1.0f; + p2.y = 0.5f; + QuarterName(name, m_backgroundName, 3); + DrawBackgroundImageQuarter(p1, p2, name); + } + else + { + p1.x = 0.0f; + p1.y = 0.0f; + p2.x = 1.0f; + p2.y = 1.0f; + DrawBackgroundImageQuarter(p1, p2, m_backgroundName); } - - // By default, pass on all events - return true; } -bool Gfx::CEngine::Render() +void Gfx::CEngine::DrawPlanet() { - m_statisticTriangle = 0; + if (! m_planet->PlanetExist()) return; - m_lastState = -1; - SetState(Gfx::ENG_RSTATE_NORMAL); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->BeginScene(); + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); - SetUp3DView(); + m_planet->Draw(); // draws the planets +} - if (! Draw3DScene() ) - return false; +void Gfx::CEngine::DrawForegroundImage() +{ + if (m_foregroundImageName.empty()) return; - SetUpInterfaceView(); + Math::Vector n = Math::Vector(0.0f, 0.0f, -1.0f); // normal - if (! DrawInterface() ) - return false; + Math::Point p1(0.0f, 0.0f); + Math::Point p2(1.0f, 1.0f); - m_device->EndScene(); + float u1 = -m_eyeDirH/(Math::PI*0.6f)+Math::PI*0.5f; + float u2 = u1+0.50f; - return true; -} + float v1 = 0.2f; + float v2 = 1.0f; -void Gfx::CEngine::SetUp3DView() -{ - // TODO -} -bool Gfx::CEngine::Draw3DScene() -{ - // TODO - return true; -} + Gfx::Vertex vertex[4] = + { + Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), n, Math::Point(u1, v2)), + Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), n, Math::Point(u1, v1)), + Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(u2, v2)), + Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(u2, v1)) + }; -void Gfx::CEngine::SetUpInterfaceView() -{ - m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); - m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false ); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + + SetTexture(m_foregroundImageName); + SetState(Gfx::ENG_RSTATE_CLAMP | Gfx::ENG_RSTATE_TTEXTURE_BLACK); + + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); + + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + AddStatisticTriangle(2); } -bool Gfx::CEngine::DrawInterface() +void Gfx::CEngine::DrawOverColor() { - Gfx::VertexCol vertices[3] = - { - Gfx::VertexCol(Math::Vector( 0.25f, 0.25f, 0.0f), Gfx::Color(1.0f, 0.0f, 0.0f)), - Gfx::VertexCol(Math::Vector( 0.75f, 0.25f, 0.0f), Gfx::Color(0.0f, 1.0f, 0.0f)), - Gfx::VertexCol(Math::Vector( 0.5f, 0.75f, 0.0f), Gfx::Color(0.0f, 0.0f, 1.0f)) - }; + if (! m_stateColor) return; - m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, vertices, 3); + // TODO: fuzzy compare? + if ( (m_overColor == Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f) && m_overMode == Gfx::ENG_RSTATE_TCOLOR_BLACK) || + (m_overColor == Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f) && m_overMode == Gfx::ENG_RSTATE_TCOLOR_WHITE) ) return; - DrawMouse(); - - std::vector format; - for (int i = 0; i < 10; ++i) - format.push_back(Gfx::FONT_COLOBOT_BOLD | Gfx::FONT_HIGHLIGHT_CONST); - for (int i = 0; i < 10; ++i) - format.push_back(Gfx::FONT_COLOBOT_ITALIC | Gfx::FONT_HIGHLIGHT_KEY); - for (int i = 0; i < 10; ++i) - format.push_back(Gfx::FONT_COURIER | Gfx::FONT_HIGHLIGHT_LINK); - for (int i = 0; i < 5; ++i) - format.push_back(Gfx::FONT_COURIER_BOLD | Gfx::FONT_HIGHLIGHT_REM); + Math::Point p1(0.0f, 0.0f); + Math::Point p2(1.0f, 1.0f); - m_text->DrawText("abcdefghijklmnopqrstuvwxyz ąęśćółńż", Gfx::FONT_COLOBOT, 15.0f, Math::Point(0.25f, 0.2f), 1.0f, Gfx::TEXT_ALIGN_LEFT, 0); - float h = m_text->GetHeight(Gfx::FONT_COLOBOT, 15.0f); - m_text->DrawText("abcdefghijklmnopqrstuvwxyz ąęśćółńż", format, 13.0f, Math::Point(0.25f, 0.2f - h), 1.0f, Gfx::TEXT_ALIGN_LEFT, 0); + Gfx::Color color[3] = + { + m_overColor, + m_overColor, + Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f) + }; - return true; -} + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); -Math::IntSize Gfx::CEngine::GetWindowSize() -{ - return m_size; -} + SetState(m_overMode); -Math::IntSize Gfx::CEngine::GetLastWindowSize() -{ - return m_lastSize; -} + m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); -/** Conversion of the position of the mouse from window coords to interface coords: - - x: 0=left, 1=right - - y: 0=down, 1=up */ -Math::Point Gfx::CEngine::WindowToInterfaceCoords(Math::IntPoint pos) -{ - return Math::Point( static_cast(pos.x) / static_cast(m_size.w), - 1.0f - static_cast(pos.y) / static_cast(m_size.h) ); -} + Gfx::VertexCol vertex[4] = + { + Gfx::VertexCol(Math::Vector(p1.x, p1.y, 0.0f), color[1],color[2]), + Gfx::VertexCol(Math::Vector(p1.x, p2.y, 0.0f), color[0],color[2]), + Gfx::VertexCol(Math::Vector(p2.x, p1.y, 0.0f), color[1],color[2]), + Gfx::VertexCol(Math::Vector(p2.x, p2.y, 0.0f), color[0],color[2]) + }; -Math::IntPoint Gfx::CEngine::InterfaceToWindowCoords(Math::Point pos) -{ - return Math::IntPoint(static_cast(pos.x * m_size.w), - static_cast((1.0f - pos.y) * m_size.h)); + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + AddStatisticTriangle(2); } -Math::Size Gfx::CEngine::WindowToInterfaceSize(Math::IntSize size) +void Gfx::CEngine::DrawHighlight() { - return Math::Size( static_cast(size.w) / static_cast(m_size.w), - static_cast(size.h) / static_cast(m_size.h) ); -} + Math::Point min, max; + min.x = 1000000.0f; + min.y = 1000000.0f; + max.x = -1000000.0f; + max.y = -1000000.0f; + + int i = 0; + while (m_highlightRank[i] != -1) + { + Math::Point omin, omax; + if (GetBBox2D(m_highlightRank[i++], omin, omax)) + { + min.x = Math::Min(min.x, omin.x); + min.y = Math::Min(min.y, omin.y); + max.x = Math::Max(max.x, omax.x); + max.y = Math::Max(max.y, omax.y); + } + } -Math::IntSize Gfx::CEngine::InterfaceToWindowSize(Math::Size size) -{ - return Math::IntSize(static_cast(size.w * m_size.w), - static_cast(size.h * m_size.h)); -} + if ( min.x == 1000000.0f || + min.y == 1000000.0f || + max.x == -1000000.0f || + max.y == -1000000.0f ) + { + m_highlight = false; // not highlighted + } + else + { + m_highlightP1 = min; + m_highlightP2 = max; + m_highlight = true; + } -std::string Gfx::CEngine::GetTextureDir() -{ - return m_texPath; + // TODO: draw highlight! } void Gfx::CEngine::DrawMouse() @@ -752,179 +2684,3 @@ void Gfx::CEngine::DrawMouseSprite(Math::Point pos, Math::Point size, int icon) m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); AddStatisticTriangle(2); } - -bool Gfx::CEngine::GetPause() -{ - return m_pause; -} - -Math::Vector Gfx::CEngine::GetLookatPt() -{ - return m_lookatPt; -} - -Math::Vector Gfx::CEngine::GetEyePt() -{ - return m_eyePt; -} - -void Gfx::CEngine::SetMouseVisible(bool visible) -{ - m_mouseVisible = visible; -} - -bool Gfx::CEngine::GetMouseVisible() -{ - return m_mouseVisible; -} - -void Gfx::CEngine::SetMousePos(Math::Point pos) -{ - m_mousePos = pos; -} - -Math::Point Gfx::CEngine::GetMousePos() -{ - return m_mousePos; -} - -void Gfx::CEngine::SetMouseType(Gfx::EngineMouseType type) -{ - m_mouseType = type; -} - -Gfx::EngineMouseType Gfx::CEngine::GetMouseType() -{ - return m_mouseType; -} - -void Gfx::CEngine::AddStatisticTriangle(int count) -{ - m_statisticTriangle += count; -} - -void Gfx::CEngine::SetShowStat(bool show) -{ - m_showStats = show; -} - -bool Gfx::CEngine::GetShowStat() -{ - return m_showStats; -} - -void Gfx::CEngine::SetFocus(float focus) -{ - m_focus = focus; -} - - -void Gfx::CEngine::SetOverColor(const Gfx::Color& color, int mode) -{ - // TODO! -} - -void Gfx::CEngine::SetFogColor(const Gfx::Color& color, int rank) -{ - // TODO! -} - -Gfx::Color Gfx::CEngine::GetFogColor(int rank) -{ - // TODO! - return Gfx::Color(); -} - -void Gfx::CEngine::SetViewParams(const Math::Vector& eyePt, const Math::Vector& lookatPt, - const Math::Vector& upVec, float eyeDistance) -{ - // TODO! -} - -void Gfx::CEngine::SetRankView(int rank) -{ - m_rankView = rank; -} - -float Gfx::CEngine::GetEyeDirH() -{ - return m_eyeDirH; -} - -float Gfx::CEngine::GetEyeDirV() -{ - return m_eyeDirV; -} - -float Gfx::CEngine::GetClippingDistance() -{ - return m_clippingDistance; -} - -bool Gfx::CEngine::GetGroundSpot() -{ - return m_groundSpotVisible; -} - -void Gfx::CEngine::SetTerrain(Gfx::CTerrain* terrain) -{ - m_terrain = terrain; -} - -void Gfx::CEngine::SetTerrainVision(float vision) -{ - // TODO! -} - -bool Gfx::CEngine::LoadTexture(const std::string& name, int stage) -{ - // TODO! - return true; -} - -float Gfx::CEngine::ParticleAdapt(float factor) -{ - // TODO! - return 0.0f; -} - -bool Gfx::CEngine::SetObjectType(int objRank, Gfx::EngineObjectType type) -{ - // TODO! - return true; -} - -bool Gfx::CEngine::SetObjectTransform(int objRank, const Math::Matrix& transform) -{ - // TODO! - return true; -} - -int Gfx::CEngine::CreateObject() -{ - // TODO! - return 0; -} - -bool Gfx::CEngine::DeleteObject(int objRank) -{ - // TODO! - return true; -} - -int Gfx::CEngine::GroundMarkCreate(Math::Vector pos, float radius, float delay1, float delay2, float delay3, int dx, int dy, char* table) -{ - // TODO! - return 0; -} - -bool Gfx::CEngine::AddQuick(int objRank, const Gfx::EngineObjLevel5& buffer, std::string texName1, std::string texName2, float min, float max, bool globalUpdate) -{ - // TODO! - return false; -} - -void Gfx::CEngine::Update() -{ - // TODO! -} diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index e61aca6..d01a679 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -1,5 +1,5 @@ // * This file is part of the COLOBOT source code -// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * Copyright (C) 2001-2008, Daniel ROUX& EPSITEC SA, www.epsitec.ch // * Copyright (C) 2012, Polish Portal of Colobot (PPC) // * // * This program is free software: you can redistribute it and/or modify @@ -41,7 +41,7 @@ class CApplication; class CInstanceManager; class CObject; -class CSound; +class CSoundInterface; namespace Gfx { @@ -310,12 +310,14 @@ struct EngineGroundSpot \brief Phase of life of an EngineGroundMark */ enum EngineGroundMarkPhase { + //! Null phase + ENG_GR_MARK_PHASE_NULL = 0, //! Increase ENG_GR_MARK_PHASE_INC = 1, //! Fixed ENG_GR_MARK_PHASE_FIX = 2, //! Decrease - ENG_GR_MARK_PHASE_DEC = 2 + ENG_GR_MARK_PHASE_DEC = 3 }; /** @@ -526,17 +528,24 @@ struct EngineMouse class CEngine { public: - CEngine(CInstanceManager *iMan, CApplication *app); + CEngine(CInstanceManager* iMan, CApplication* app); ~CEngine(); //! Returns the last error encountered std::string GetError(); //! Sets the device to be used - void SetDevice(Gfx::CDevice *device); + void SetDevice(Gfx::CDevice* device); //! Returns the current device Gfx::CDevice* GetDevice(); + //! Sets the terrain object + void SetTerrain(Gfx::CTerrain* terrain); + + //! Returns the text rendering engine + CText* GetText(); + + //! Performs the initialization; must be called after device was set bool Create(); //! Frees all resources before exit @@ -545,102 +554,122 @@ public: //! Resets some states and flushes textures after device was changed (e.g. resoulution changed) void ResetAfterDeviceChanged(); - void SetTerrain(Gfx::CTerrain* terrain); + + //! Called once per frame, the call is the entry point for rendering + void Render(); + //! Processes incoming event - bool ProcessEvent(const Event &event); + bool ProcessEvent(const Event& event); - //! Renders a single frame - bool Render(); + //! Called once per frame, the call is the entry point for animating the scene + void FrameMove(float rTime); + //! Evolved throughout the game + void StepSimulation(float rTime); + //! Initialize timestamps at the beginning of animation + void TimeInit(); + //! Suspend animation + void TimeEnterGel(); + //! Resume animation + void TimeExitGel(); + //! Returns the relative time since last animation update + float TimeGet(); - //! Converts window coords to interface coords - Math::Point WindowToInterfaceCoords(Math::IntPoint pos); - //! Converts interface coords to window coords - Math::IntPoint InterfaceToWindowCoords(Math::Point pos); - //! Converts window size to interface size - Math::Size WindowToInterfaceSize(Math::IntSize size); - //! Converts interface size to window size - Math::IntSize InterfaceToWindowSize(Math::Size size); + //! Writes a screenshot containing the current frame + bool WriteScreenShot(const std::string& fileName, int width, int height); - std::string GetTextureDir(); - bool WriteProfile(); + //! Reads settings from INI + bool ReadSettings(); + //! Writes settings to INI + bool WriteSettings(); + //@{ + //! Management of game pause mode void SetPause(bool pause); bool GetPause(); + //@} + //@{ + //! Management of lock for the duration of movie sequence void SetMovieLock(bool lock); bool GetMovieLock(); + //@} - void SetShowStat(bool show); - bool GetShowStat(); + //@{ + //! Management of displaying statistic information + void SetShowStats(bool show); + bool GetShowStats(); + //@} + //! Enables/disables rendering void SetRenderEnable(bool enable); - int OneTimeSceneInit(); - int InitDeviceObjects(); - int DeleteDeviceObjects(); - int RestoreSurfaces(); - int FrameMove(float rTime); - void StepSimulation(float rTime); - int FinalCleanup(); + //! Returns current size of viewport window + Math::IntSize GetWindowSize(); + //! Returns the last size of viewport window + Math::IntSize GetLastWindowSize(); + + //! Converts window coords to interface coords + /** Conversion of the position of the mouse from window coords to interface coords: + - x: 0=left, 1=right + - y: 0=down, 1=up */ + Math::Point WindowToInterfaceCoords(Math::IntPoint pos); + //! Converts interface coords to window coords + Math::IntPoint InterfaceToWindowCoords(Math::Point pos); + + //! Converts window size to interface size + Math::Size WindowToInterfaceSize(Math::IntSize size); + //! Converts interface size to window size + Math::IntSize InterfaceToWindowSize(Math::Size size); + + //! Returns the name of directory with textures + std::string GetTextureDir(); + + //! Increments the triangle counter for the current frame void AddStatisticTriangle(int nb); + //! Returns the number of triangles in current frame int GetStatisticTriangle(); - void SetHiliteRank(int *rankList); - bool GetHilite(Math::Point &p1, Math::Point &p2); - bool GetSpriteCoord(int &x, int &y); - void SetInfoText(int line, char* text); - char* GetInfoText(int line); - void FirstExecuteAdapt(bool first); - bool GetFullScreen(); - Math::Matrix* GetMatView(); - Math::Matrix* GetMatLeftView(); - Math::Matrix* GetMatRightView(); + /* *************** Object management *************** */ - void TimeInit(); - void TimeEnterGel(); - void TimeExitGel(); - float TimeGet(); - - int GetRestCreate(); int CreateObject(); void FlushObject(); bool DeleteObject(int objRank); bool SetDrawWorld(int objRank, bool draw); bool SetDrawFront(int objRank, bool draw); - bool AddTriangle(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material &mat, + bool AddTriangle(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material& mat, int state, std::string texName1, std::string texName2, float min, float max, bool globalUpdate); - bool AddSurface(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material &mat, + bool AddSurface(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material& mat, int state, std::string texName1, std::string texName2, float min, float max, bool globalUpdate); bool AddQuick(int objRank, const Gfx::EngineObjLevel5& buffer, std::string texName1, std::string texName2, float min, float max, bool globalUpdate); - Gfx::EngineObjLevel5* SearchTriangle(int objRank, const Gfx::Material &mat, + Gfx::EngineObjLevel5* SearchTriangle(int objRank, const Gfx::Material& mat, int state, std::string texName1, std::string texName2, float min, float max); void ChangeLOD(); - bool ChangeSecondTexture(int objRank, char* texName2); + bool ChangeSecondTexture(int objRank, const std::string& texName2); int GetTotalTriangles(int objRank); int GetTriangles(int objRank, float min, float max, Gfx::EngineTriangle* buffer, int size, float percent); - bool GetBBox(int objRank, Math::Vector &min, Math::Vector &max); - bool ChangeTextureMapping(int objRank, const Gfx::Material &mat, int state, - const std::string &texName1, const std::string &texName2, + bool GetBBox(int objRank, Math::Vector& min, Math::Vector& max); + bool ChangeTextureMapping(int objRank, const Gfx::Material& mat, int state, + const std::string& texName1, const std::string& texName2, float min, float max, Gfx::EngineTextureMapping mode, float au, float bu, float av, float bv); - bool TrackTextureMapping(int objRank, const Gfx::Material &mat, int state, - const std::string &texName1, const std::string &texName2, + bool TrackTextureMapping(int objRank, const Gfx::Material& mat, int state, + const std::string& texName1, const std::string& texName2, float min, float max, Gfx::EngineTextureMapping mode, float pos, float factor, float tl, float ts, float tt); - bool SetObjectTransform(int objRank, const Math::Matrix &transform); - bool GetObjectTransform(int objRank, Math::Matrix &transform); + bool SetObjectTransform(int objRank, const Math::Matrix& transform); + bool GetObjectTransform(int objRank, Math::Matrix& transform); bool SetObjectType(int objRank, Gfx::EngineObjectType type); Gfx::EngineObjectType GetObjectType(int objRank); bool SetObjectTransparency(int objRank, float value); @@ -649,20 +678,25 @@ public: void ShadowDelete(int objRank); bool SetObjectShadowHide(int objRank, bool hide); bool SetObjectShadowType(int objRank, Gfx::EngineShadowType type); - bool SetObjectShadowPos(int objRank, const Math::Vector &pos); - bool SetObjectShadowNormal(int objRank, const Math::Vector &n); + bool SetObjectShadowPos(int objRank, const Math::Vector& pos); + bool SetObjectShadowNormal(int objRank, const Math::Vector& n); bool SetObjectShadowAngle(int objRank, float angle); bool SetObjectShadowRadius(int objRank, float radius); bool SetObjectShadowIntensity(int objRank, float intensity); bool SetObjectShadowHeight(int objRank, float h); float GetObjectShadowRadius(int objRank); + //! Lists the ranks of objects and subobjects selected + void SetHighlightRank(int* rankList); + //! Returns the highlighted rectangle + bool GetHighlight(Math::Point& p1, Math::Point& p2); + void GroundSpotFlush(); int GroundSpotCreate(); void GroundSpotDelete(int rank); - bool SetObjectGroundSpotPos(int rank, const Math::Vector &pos); + bool SetObjectGroundSpotPos(int rank, const Math::Vector& pos); bool SetObjectGroundSpotRadius(int rank, float radius); - bool SetObjectGroundSpotColor(int rank, const Gfx::Color &color); + bool SetObjectGroundSpotColor(int rank, const Gfx::Color& color); bool SetObjectGroundSpotMinMax(int rank, float min, float max); bool SetObjectGroundSpotSmooth(int rank, float smooth); @@ -671,217 +705,347 @@ public: int dx, int dy, char* table); bool GroundMarkDelete(int rank); + //! Updates the state after creating objects void Update(); - void SetViewParams(const Math::Vector &eyePt, const Math::Vector &lookatPt, - const Math::Vector &upVec, float eyeDistance); - Gfx::Texture CreateTexture(const std::string &texName, - const Gfx::TextureCreateParams ¶ms); - Gfx::Texture CreateTexture(const std::string &texName); - void DestroyTexture(const std::string &texName); + /* *************** Mode setting *************** */ + + //! Sets the current rendering state + void SetState(int state, const Gfx::Color& color = Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)); + + //! Sets the current material + void SetMaterial(const Gfx::Material& mat); + + //! Specifies the location and direction of view + void SetViewParams(const Math::Vector& eyePt, const Math::Vector& lookatPt, + const Math::Vector& upVec, float eyeDistance); - bool LoadTexture(const std::string &name, int stage = 0); + Gfx::Texture CreateTexture(const std::string& texName, + const Gfx::TextureCreateParams& params); + Gfx::Texture CreateTexture(const std::string& texName); + void DestroyTexture(const std::string& texName); + bool LoadTexture(const std::string& name, int stage = 0); bool LoadAllTextures(); + bool SetTexture(const std::string& name, int stage = 0); + //@{ + //! Border management (distance limits) depends of the resolution (LOD = level-of-detail) void SetLimitLOD(int rank, float limit); float GetLimitLOD(int rank, bool last=false); + //@} + //! Defines of the distance field of vision void SetTerrainVision(float vision); + //@{ + //! Management of camera angle + /** + 0.75 = normal + 1.50 = wide-angle */ + void SetFocus(float focus); + float GetFocus(); + //@} + + //@{ + //! Management of the global mode of marking void SetGroundSpot(bool mode); bool GetGroundSpot(); + //@} + + //@{ + //! Management of the global mode of shading void SetShadow(bool mode); bool GetShadow(); + //@} + + //@{ + //! Management of the global mode of contamination void SetDirty(bool mode); bool GetDirty(); + //@} + + //@{ + //! Management of the global mode of horizontal fog patches void SetFog(bool mode); bool GetFog(); + //@} + + //! Indicates whether it is possible to give a color SetState bool GetStateColor(); + //@{ + //! Management of the global mode of secondary texturing void SetSecondTexture(int texNum); int GetSecondTexture(); + //@} + //@{ + //! Management of view mode void SetRankView(int rank); int GetRankView(); + //@} + //! Whether to draw the world void SetDrawWorld(bool draw); + + //! Whether to draw the world on the interface void SetDrawFront(bool draw); - void SetAmbientColor(const Gfx::Color &color, int rank = 0); + //@{ + //! Ambient color management + void SetAmbientColor(const Gfx::Color& color, int rank = 0); Gfx::Color GetAmbientColor(int rank = 0); + //@} - void SetWaterAddColor(const Gfx::Color &color); + //@{ + //! Color management under water + void SetWaterAddColor(const Gfx::Color& color); Gfx::Color GetWaterAddColor(); + //@} - void SetFogColor(const Gfx::Color &color, int rank = 0); + //@{ + //! Management of the fog color + void SetFogColor(const Gfx::Color& color, int rank = 0); Gfx::Color GetFogColor(int rank = 0); + //@} + //@{ + //! Management of the depth of field. + /** Beyond this distance, nothing is visible. + Shortly (according SetFogStart), one enters the fog. */ void SetDeepView(float length, int rank = 0, bool ref=false); float GetDeepView(int rank = 0); + //@} + + //@{ + //! Management the start of fog. + /** With 0.0, the fog from the point of view (fog max). + With 1.0, the fog from the depth of field (no fog). */ void SetFogStart(float start, int rank = 0); float GetFogStart(int rank = 0); + //@} - void SetBackground(const std::string &name, Gfx::Color up = Gfx::Color(), Gfx::Color down = Gfx::Color(), + //@{ + //! Management of the background image to use + void SetBackground(const std::string& name, Gfx::Color up = Gfx::Color(), Gfx::Color down = Gfx::Color(), Gfx::Color cloudUp = Gfx::Color(), Gfx::Color cloudDown = Gfx::Color(), bool full = false, bool quarter = false); - void GetBackground(const std::string &name, Gfx::Color &up, Gfx::Color &down, - Gfx::Color &cloudUp, Gfx::Color &cloudDown, - bool &full, bool &quarter); - void SetFrontsizeName(char *name); + void GetBackground(std::string& name, Gfx::Color& up, Gfx::Color& down, + Gfx::Color& cloudUp, Gfx::Color& cloudDown, + bool& full, bool& quarter); + //@} + + //! Specifies the foreground image + void SetForegroundImageName(const std::string& name); + //! Specifies whether to draw the foreground void SetOverFront(bool front); - void SetOverColor(const Gfx::Color &color = Gfx::Color(), int mode = ENG_RSTATE_TCOLOR_BLACK); + //! Sets the foreground overlay color + void SetOverColor(const Gfx::Color& color = Gfx::Color(), int mode = ENG_RSTATE_TCOLOR_BLACK); + //@{ + //! Management of the particle density void SetParticleDensity(float value); float GetParticleDensity(); + //@} + + //! Adapts particle factor according to particle density float ParticleAdapt(float factor); + //@{ + //! Management of the distance of clipping. void SetClippingDistance(float value); float GetClippingDistance(); + //@} + //@{ + //! Management of objects detals. void SetObjectDetail(float value); float GetObjectDetail(); + //@} + //@{ + //! The amount of management objects gadgets void SetGadgetQuantity(float value); float GetGadgetQuantity(); + //@} + //@{ + //! Management the quality of textures void SetTextureQuality(int value); int GetTextureQuality(); + //@} + //@{ + //! Management mode of toto void SetTotoMode(bool present); bool GetTotoMode(); + //@} + //@{ + //! Management the mode of foreground void SetLensMode(bool present); bool GetLensMode(); + //@} + //@{ + //! Management the mode of water void SetWaterMode(bool present); bool GetWaterMode(); + //@} void SetLightingMode(bool present); bool GetLightingMode(); + //@{ + //! Management the mode of sky void SetSkyMode(bool present); bool GetSkyMode(); + //@} + //@{ + //! Management the mode of background void SetBackForce(bool present); bool GetBackForce(); + //@} + //@{ + //! Management the mode of planets void SetPlanetMode(bool present); bool GetPlanetMode(); + //@} + //@{ + //! Managing the mode of dynamic lights. void SetLightMode(bool present); bool GetLightMode(); + //@} + //@{ + // TODO: move to more appropriate class ? + //! Management of the indentation mode while editing (CEdit) void SetEditIndentMode(bool autoIndent); bool GetEditIndentMode(); + //@} + //@{ + // TODO: move to more appropriate class ? + //! Management of tab indent when editing (CEdit) void SetEditIndentValue(int value); int GetEditIndentValue(); + //@} + //@{ + //! Management of game speed void SetSpeed(float speed); float GetSpeed(); + //@{ + //! Management of precision of robot tracks void SetTracePrecision(float factor); float GetTracePrecision(); + //@} - void SetFocus(float focus); - float GetFocus(); - Math::Vector GetEyePt(); - Math::Vector GetLookatPt(); - float GetEyeDirH(); - float GetEyeDirV(); - Math::IntSize GetWindowSize(); - Math::IntSize GetLastWindowSize(); - void UpdateMatProj(); - - void ApplyChange(); - - void FlushPressKey(); - void ResetKey(); - void SetKey(int keyRank, int option, int key); - int GetKey(int keyRank, int option); - - void SetJoystick(bool enable); - bool GetJoystick(); - - void SetDebugMode(bool mode); - bool GetDebugMode(); - bool GetSetupMode(); - - bool IsVisiblePoint(const Math::Vector &pos); - - int DetectObject(Math::Point mouse); - void SetState(int state, Gfx::Color color = Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)); - void SetTexture(const std::string &name, int stage = 0); - void SetMaterial(const Gfx::Material &mat); - + //@{ + //! Management of mouse cursor visibility void SetMouseVisible(bool show); bool GetMouseVisible(); + //@} + + //@{ + //! Management of mouse cursor position void SetMousePos(Math::Point pos); Math::Point GetMousePos(); + //@} + + //@{ + //! Management of mouse cursor type void SetMouseType(Gfx::EngineMouseType type); Gfx::EngineMouseType GetMouseType(); + //@} - CText* GetText(); + //! Returns the view matrix + const Math::Matrix& GetMatView(); + //! Returns the camera center point + Math::Vector GetEyePt(); + //! Returns the camera target point + Math::Vector GetLookatPt(); + //! Returns the horizontal direction angle of view + float GetEyeDirH(); + //! Returns the vertical direction angle of view + float GetEyeDirV(); + //! Indicates whether a point is visible + bool IsVisiblePoint(const Math::Vector& pos); - bool ChangeColor(char *name, Gfx::Color colorRef1, Gfx::Color colorNew1, - Gfx::Color colorRef2, Gfx::Color colorNew2, - float tolerance1, float tolerance2, - Math::Point ts, Math::Point ti, - Math::Point *pExclu=0, float shift=0.0f, bool hSV=false); - bool OpenImage(char *name); - bool CopyImage(); - bool LoadImage(); - bool ScrollImage(int dx, int dy); - bool SetDot(int x, int y, Gfx::Color color); - bool CloseImage(); - bool WriteScreenShot(char *filename, int width, int height); - //bool GetRenderDC(HDC &hDC); - //bool ReleaseRenderDC(HDC &hDC); - //PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp); - //bool CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC); + //! Resets the projection matrix after changes + void UpdateMatProj(); -protected: + //! Updates the scene after a change of parameters + void ApplyChange(); - void SetUp3DView(); - bool Draw3DScene(); +protected: + //! Prepares the interface for 3D scene + void Draw3DScene(); + //! Draws the user interface over the scene + void DrawInterface(); - void SetUpInterfaceView(); - bool DrawInterface(); + //! Updates the textures used for drawing ground spot + void UpdateGroundSpotTextures(); - void DrawGroundSpot(); + //! Draws shadows void DrawShadow(); + //! Draws the gradient background void DrawBackground(); - void DrawBackgroundGradient(Gfx::Color up, Gfx::Color down); - void DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, char *name); + //! Draws the gradient background + void DrawBackgroundGradient(const Gfx::Color& up, const Gfx::Color& down); + //! Draws a portion of the image background + void DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, const std::string& name); + //! Draws the image background void DrawBackgroundImage(); + //! Draws all the planets void DrawPlanet(); - void DrawFrontsize(); + //! Draws the image foreground + void DrawForegroundImage(); + //! Draws the foreground color void DrawOverColor(); - void DrawHilite(); + //! Draws the rectangle of the object highlighted + void DrawHighlight(); + //! Draws the mouse cursor void DrawMouse(); + //! Draw part of mouse cursor sprite void DrawMouseSprite(Math::Point pos, Math::Point dim, int icon); - /* - Gfx::ObjLevel2* AddLevel1(Gfx::ObjLevel1 *&p1, char* texName1, char* texName2); - Gfx::ObjLevel3* AddLevel2(Gfx::ObjLevel2 *&p2, int objRank); - Gfx::ObjLevel4* AddLevel3(Gfx::ObjLevel3 *&p3, float min, float max); - Gfx::ObjLevel5* AddLevel4(Gfx::ObjLevel4 *&p4, int reserve); - Gfx::ObjLevel6* AddLevel5(Gfx::ObjLevel5 *&p5, Gfx::TriangleType type, const Gfx::Material &mat, int state, int nb);*/ - + //! Tests whether the given object is visible bool IsVisible(int objRank); + + //! Detects whether an object is affected by the mouse bool DetectBBox(int objRank, Math::Point mouse); - bool GetBBox2D(int objRank, Math::Point &min, Math::Point &max); - bool DetectTriangle(Math::Point mouse, Gfx::VertexTex2 *triangle, int objRank, float &dist); - bool TransformPoint(Math::Vector &p2D, int objRank, Math::Vector p3D); + + //! Compute and return the 2D box on screen of any object + bool GetBBox2D(int objRank, Math::Point& min, Math::Point& max); + + //! Detects the target object that is selected with the mouse + /** Returns the rank of the object or -1. */ + int DetectObject(Math::Point mouse); + + //! Detects whether the mouse is in a triangle. + bool DetectTriangle(Math::Point mouse, Gfx::VertexTex2* triangle, int objRank, float& dist); + + //! Transforms a 3D point (x, y, z) in 2D space (x, y, -) of the window + /** The coordinated p2D.z gives the distance. */ + bool TransformPoint(Math::Vector& p2D, int objRank, Math::Vector p3D); + + //! Calculates the distances between the viewpoint and the origin of different objects void ComputeDistance(); + + //! Updates all the geometric parameters of objects void UpdateGeometry(); protected: CInstanceManager* m_iMan; CApplication* m_app; - CSound* m_sound; + CSoundInterface* m_sound; Gfx::CDevice* m_device; Gfx::CText* m_text; Gfx::CLightManager* m_lightMan; @@ -892,7 +1056,7 @@ protected: Gfx::CPlanet* m_planet; Gfx::CTerrain* m_terrain; - bool m_wasInit; + //! Last encountered error std::string m_error; //! Whether to show stats (FPS, etc) @@ -926,9 +1090,9 @@ protected: bool m_render; bool m_movieLock; - //! Current size of viewport + //! Current size of viewport window Math::IntSize m_size; - //! Previous size of viewport + //! Previous size of viewport window Math::IntSize m_lastSize; std::vector m_objectTree; @@ -950,7 +1114,6 @@ protected: Gfx::Color m_waterAddColor; int m_statisticTriangle; bool m_updateGeometry; - //char m_infoText[10][200]; int m_alphaMode; bool m_stateColor; bool m_forceStateColor; @@ -970,11 +1133,11 @@ protected: bool m_overFront; Gfx::Color m_overColor; int m_overMode; - std::string m_frontsizeName; + std::string m_foregroundImageName; bool m_drawWorld; bool m_drawFront; float m_limitLOD[2]; - float m_particuleDensity; + float m_particleDensity; float m_clippingDistance; float m_lastClippingDistance; float m_objectDetail; @@ -993,10 +1156,10 @@ protected: int m_editIndentValue; float m_tracePrecision; - int m_hiliteRank[100]; - bool m_hilite; - Math::Point m_hiliteP1; - Math::Point m_hiliteP2; + int m_highlightRank[100]; + bool m_highlight; + Math::Point m_highlightP1; + Math::Point m_highlightP2; int m_lastState; Gfx::Color m_lastColor; @@ -1015,12 +1178,6 @@ protected: Gfx::EngineMouseType m_mouseType; Math::Point m_mousePos; bool m_mouseVisible; - - //LPDIRECTDRAWSURFACE7 m_imageSurface; - //DDSURFACEDESC2 m_imageDDSD; - //WORD* m_imageCopy; - //int m_imageDX; - //int m_imageDY; }; }; // namespace Gfx diff --git a/src/object/object.h b/src/object/object.h index 3825412..4a4dcb0 100644 --- a/src/object/object.h +++ b/src/object/object.h @@ -25,10 +25,6 @@ class CInstanceManager; -class CLight; -class CTerrain; -class CWater; -class CParticule; class CPhysics; class CBrain; class CMotion; @@ -40,6 +36,7 @@ class CScript; + // The father of all parts must always be the part number zero! const int OBJECTMAXPART = 40; @@ -306,7 +303,7 @@ enum ObjectMaterial struct ObjectPart { char bUsed; - int object; // number of the object in CD3DEngine + int object; // number of the object in CEngine int parentPart; // number of father part int masterParti; // master canal of the particle Math::Vector position; @@ -677,7 +674,7 @@ protected: CAuto* m_auto; CDisplayText* m_displayText; CRobotMain* m_main; - CSound* m_sound; + CSoundInterface* m_sound; CBotVar* m_botVar; CScript* m_runScript; -- cgit v1.2.3-1-g7c22 From 7f80ca297154809523cd533edf1842ab1ae391aa Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sat, 11 Aug 2012 17:17:04 +0200 Subject: Render mode setting, refactoring - finished SetState in CEngine - refactored Size and IntSize back to Point and IntPoint - other minor changes in CEngine --- src/app/app.cpp | 6 +- src/app/app.h | 2 +- src/graphics/core/device.h | 6 +- src/graphics/core/texture.h | 4 +- src/graphics/engine/engine.cpp | 367 +++++++++++++++++++-------------------- src/graphics/engine/engine.h | 114 ++++++------ src/graphics/engine/text.cpp | 64 +++---- src/graphics/engine/text.h | 7 +- src/graphics/opengl/gldevice.cpp | 6 +- src/math/intsize.h | 70 -------- src/math/size.h | 75 -------- 11 files changed, 291 insertions(+), 430 deletions(-) delete mode 100644 src/math/intsize.h delete mode 100644 src/math/size.h (limited to 'src') diff --git a/src/app/app.cpp b/src/app/app.cpp index e116914..4f7120d 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -285,7 +285,7 @@ bool CApplication::CreateVideoSurface() if (m_deviceConfig.hardwareAccel) SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); - m_private->surface = SDL_SetVideoMode(m_deviceConfig.size.w, m_deviceConfig.size.h, + m_private->surface = SDL_SetVideoMode(m_deviceConfig.size.x, m_deviceConfig.size.y, m_deviceConfig.bpp, videoFlags); return true; @@ -761,7 +761,7 @@ Gfx::GLDeviceConfig CApplication::GetVideoConfig() return m_deviceConfig; } -VideoQueryResult CApplication::GetVideoResolutionList(std::vector &resolutions, +VideoQueryResult CApplication::GetVideoResolutionList(std::vector &resolutions, bool fullScreen, bool resizeable) { resolutions.clear(); @@ -799,7 +799,7 @@ VideoQueryResult CApplication::GetVideoResolutionList(std::vector for (int i = 0; modes[i] != NULL; ++i) - resolutions.push_back(Math::IntSize(modes[i]->w, modes[i]->h)); + resolutions.push_back(Math::IntPoint(modes[i]->w, modes[i]->h)); return VIDEO_QUERY_OK; } diff --git a/src/app/app.h b/src/app/app.h index e7ffd54..d3b1368 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -132,7 +132,7 @@ public: void Destroy(); //! Returns a list of possible video modes - VideoQueryResult GetVideoResolutionList(std::vector &resolutions, + VideoQueryResult GetVideoResolutionList(std::vector &resolutions, bool fullScreen, bool resizeable); //! Returns the current video mode diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h index 3ab86dd..d4fcd26 100644 --- a/src/graphics/core/device.h +++ b/src/graphics/core/device.h @@ -25,7 +25,7 @@ #include "graphics/core/material.h" #include "graphics/core/texture.h" #include "graphics/core/vertex.h" -#include "math/intsize.h" +#include "math/intpoint.h" #include "math/matrix.h" #include @@ -46,7 +46,7 @@ namespace Gfx { struct DeviceConfig { //! Screen size - Math::IntSize size; + Math::IntPoint size; //! Bits per pixel int bpp; //! Full screen @@ -64,7 +64,7 @@ struct DeviceConfig //! Loads the default values inline void LoadDefault() { - size = Math::IntSize(800, 600); + size = Math::IntPoint(800, 600); bpp = 32; fullScreen = false; resizeable = false; diff --git a/src/graphics/core/texture.h b/src/graphics/core/texture.h index 8d6b082..bb5b52f 100644 --- a/src/graphics/core/texture.h +++ b/src/graphics/core/texture.h @@ -18,7 +18,7 @@ #pragma once -#include "math/intsize.h" +#include "math/intpoint.h" namespace Gfx { @@ -194,7 +194,7 @@ struct Texture //! ID of the texture in graphics engine unsigned int id; //! Size of texture - Math::IntSize size; + Math::IntPoint size; //! Whether the texture has alpha channel bool alpha; diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 4244fb2..0461636 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -80,9 +80,7 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_terrain = nullptr; m_focus = 0.75f; - m_baseTime = 0; - m_lastTime = 0; - m_absTime = 0.0f; + m_rankView = 0; m_ambientColor[0] = Gfx::Color(0.5f, 0.5f, 0.5f, 0.5f); @@ -147,15 +145,6 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_forceStateColor = true; m_stateColor = false; - m_blackSrcBlend[0] = 0; - m_blackDestBlend[0] = 0; - m_whiteSrcBlend[0] = 0; - m_whiteDestBlend[0] = 0; - m_diffuseSrcBlend[0] = 0; - m_diffuseDestBlend[0] = 0; - m_alphaSrcBlend[0] = 0; - m_alphaDestBlend[0] = 0; - m_updateGeometry = false; m_mice[Gfx::ENG_MOUSE_NORM] = Gfx::EngineMouse( 0, 1, 32, Gfx::ENG_RSTATE_TCOLOR_WHITE, Gfx::ENG_RSTATE_TCOLOR_BLACK, Math::Point( 1.0f, 1.0f)); @@ -188,8 +177,8 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_objectTree.reserve(LEVEL1_PREALLOCATE_COUNT); m_objects.reserve(OBJECT_PREALLOCATE_COUNT); - m_shadow.reserve(SHADOW_PREALLOCATE_COUNT); - m_groundSpot.reserve(GROUNDSPOT_PREALLOCATE_COUNT); + m_shadows.reserve(SHADOW_PREALLOCATE_COUNT); + m_groundSpots.reserve(GROUNDSPOT_PREALLOCATE_COUNT); } Gfx::CEngine::~CEngine() @@ -372,38 +361,6 @@ void Gfx::CEngine::StepSimulation(float rTime) m_app->StepSimulation(rTime); } -void Gfx::CEngine::TimeInit() -{ - /* TODO! - m_baseTime = timeGetTime(); - m_lastTime = 0; - m_absTime = 0.0f;*/ -} - -void Gfx::CEngine::TimeEnterGel() -{ - /* TODO! - m_stopTime = timeGetTime();*/ -} - -void Gfx::CEngine::TimeExitGel() -{ - /* TODO! - m_baseTime += timeGetTime() - m_stopTime;*/ -} - -float Gfx::CEngine::TimeGet() -{ - /* TODO! - float aTime = (timeGetTime()-m_baseTime)*0.001f; // in ms - float rTime = (aTime - m_lastTime)*m_speed; - m_absTime += rTime; - m_lastTime = aTime; - - return rTime;*/ - return 0.0f; -} - bool Gfx::CEngine::WriteScreenShot(const std::string& fileName, int width, int height) { // TODO! @@ -457,38 +414,38 @@ void Gfx::CEngine::SetRenderEnable(bool enable) m_render = enable; } -Math::IntSize Gfx::CEngine::GetWindowSize() +Math::IntPoint Gfx::CEngine::GetWindowSize() { return m_size; } -Math::IntSize Gfx::CEngine::GetLastWindowSize() +Math::IntPoint Gfx::CEngine::GetLastWindowSize() { return m_lastSize; } Math::Point Gfx::CEngine::WindowToInterfaceCoords(Math::IntPoint pos) { - return Math::Point( static_cast(pos.x) / static_cast(m_size.w), - 1.0f - static_cast(pos.y) / static_cast(m_size.h) ); + return Math::Point( static_cast(pos.x) / static_cast(m_size.x), + 1.0f - static_cast(pos.y) / static_cast(m_size.y) ); } Math::IntPoint Gfx::CEngine::InterfaceToWindowCoords(Math::Point pos) { - return Math::IntPoint(static_cast(pos.x * m_size.w), - static_cast((1.0f - pos.y) * m_size.h)); + return Math::IntPoint(static_cast(pos.x * m_size.x), + static_cast((1.0f - pos.y) * m_size.y)); } -Math::Size Gfx::CEngine::WindowToInterfaceSize(Math::IntSize size) +Math::Point Gfx::CEngine::WindowToInterfaceSize(Math::IntPoint size) { - return Math::Size( static_cast(size.w) / static_cast(m_size.w), - static_cast(size.h) / static_cast(m_size.h) ); + return Math::Point(static_cast(size.x) / static_cast(m_size.x), + static_cast(size.y) / static_cast(m_size.y)); } -Math::IntSize Gfx::CEngine::InterfaceToWindowSize(Math::Size size) +Math::IntPoint Gfx::CEngine::InterfaceToWindowSize(Math::Point size) { - return Math::IntSize(static_cast(size.w * m_size.w), - static_cast(size.h * m_size.h)); + return Math::IntPoint(static_cast(size.x * m_size.x), + static_cast(size.y * m_size.y)); } std::string Gfx::CEngine::GetTextureDir() @@ -874,7 +831,18 @@ bool Gfx::CEngine::IsVisible(int objRank) bool Gfx::CEngine::TransformPoint(Math::Vector& p2D, int objRank, Math::Vector p3D) { - // TODO! + p3D = Math::Transform(m_objects[objRank].transform, p3D); + p3D = Math::Transform(m_matView, p3D); + + if (p3D.z < 2.0f) return false; // behind? + + p2D.x = (p3D.x/p3D.z)*m_matProj.Get(1,1); + p2D.y = (p3D.y/p3D.z)*m_matProj.Get(2,2); + p2D.z = p3D.z; + + p2D.x = (p2D.x+1.0f)/2.0f; // [-1..1] -> [0..1] + p2D.y = (p2D.y+1.0f)/2.0f; + return true; } @@ -888,13 +856,13 @@ bool Gfx::CEngine::TransformPoint(Math::Vector& p2D, int objRank, Math::Vector p void Gfx::CEngine::SetState(int state, const Gfx::Color& color) { - if ( state == m_lastState && color == m_lastColor ) + if (state == m_lastState && color == m_lastColor) return; m_lastState = state; m_lastColor = color; - if ( m_alphaMode != 1 && (state & Gfx::ENG_RSTATE_ALPHA) ) + if (m_alphaMode != 1 && (state & Gfx::ENG_RSTATE_ALPHA)) { state &= ~Gfx::ENG_RSTATE_ALPHA; @@ -902,133 +870,150 @@ void Gfx::CEngine::SetState(int state, const Gfx::Color& color) state |= Gfx::ENG_RSTATE_TTEXTURE_BLACK; } - // TODO other modes & thorough testing - if (state & Gfx::ENG_RSTATE_TTEXTURE_BLACK) // The transparent black texture? + if (state & Gfx::ENG_RSTATE_TTEXTURE_BLACK) // transparent black texture? { m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); m_device->SetBlendFunc(Gfx::BLEND_ONE, Gfx::BLEND_INV_SRC_COLOR); - m_device->SetTextureEnabled(0, true); + + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetTextureFactor(color); Gfx::TextureStageParams params; params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE; params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; params.colorArg2 = Gfx::TEX_MIX_ARG_FACTOR; - params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE; + params.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ? + + m_device->SetTextureEnabled(0, true); m_device->SetTextureStageParams(0, params); } - else if (state & Gfx::ENG_RSTATE_TTEXTURE_WHITE) // The transparent white texture? + else if (state & Gfx::ENG_RSTATE_TTEXTURE_WHITE) // transparent white texture? { m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); m_device->SetBlendFunc(Gfx::BLEND_DST_COLOR, Gfx::BLEND_ZERO); - m_device->SetTextureEnabled(0, true); + + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetTextureFactor(color.Inverse()); Gfx::TextureStageParams params; params.colorOperation = Gfx::TEX_MIX_OPER_ADD; params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; params.colorArg2 = Gfx::TEX_MIX_ARG_FACTOR; - params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE; + params.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ? + + m_device->SetTextureEnabled(0, true); m_device->SetTextureStageParams(0, params); } - else if (state & Gfx::ENG_RSTATE_TCOLOR_BLACK) // The transparent black color? + else if (state & Gfx::ENG_RSTATE_TCOLOR_BLACK) // transparent black color? { - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); - m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); m_device->SetBlendFunc(Gfx::BLEND_ONE, Gfx::BLEND_INV_SRC_COLOR); - - m_device->SetTextureFactor(color); - m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); } - else if (state & Gfx::ENG_RSTATE_TCOLOR_WHITE) // The transparent white color? + else if (state & Gfx::ENG_RSTATE_TCOLOR_WHITE) // transparent white color? { - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); - m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); m_device->SetBlendFunc(Gfx::BLEND_DST_COLOR, Gfx::BLEND_ZERO); - - m_device->SetTextureFactor(color.Inverse()); - m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); } else if (state & Gfx::ENG_RSTATE_TDIFFUSE) // diffuse color as transparent? - { - /*m_device->SetRenderState(D3DRENDERSTATE_FOGENABLE, false); - m_device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false); - m_device->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true); - m_device->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false); - m_device->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_diffuseSrcBlend[1]); - m_device->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_diffuseDestBlend[1]); - - m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);*/ - } - else if (state & Gfx::ENG_RSTATE_ALPHA) // image with alpha channel? - { - /*m_device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true); - m_device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true); - m_device->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false); - m_device->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, true); - m_device->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATER); - m_device->SetRenderState(D3DRENDERSTATE_ALPHAREF, (DWORD)(128)); - m_device->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_alphaSrcBlend[1]); - m_device->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_alphaSrcBlend[1]); - - m_device->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color); - m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - m_device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);*/ - } - else if (state & Gfx::ENG_RSTATE_TEXT) { m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); + m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_DST_ALPHA); + + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + + Gfx::TextureStageParams params; + params.colorOperation = Gfx::TEX_MIX_OPER_REPLACE; + params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; + params.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ? m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + m_device->SetTextureStageParams(0, params); + } + else if (state & Gfx::ENG_RSTATE_TEXT) // font rendering? + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); // TODO: depth test setting elsewhere! + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true); m_device->SetBlendFunc(Gfx::BLEND_SRC_ALPHA, Gfx::BLEND_INV_SRC_ALPHA); + + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + + Gfx::TextureStageParams params; + params.colorOperation = Gfx::TEX_MIX_OPER_DEFAULT; // default modulate operation + params.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; // default modulate operation + + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, params); } - else // normal ? + else if (state & Gfx::ENG_RSTATE_ALPHA) // image with alpha channel? { + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, true); - m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, false); - m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, true); + + m_device->SetAlphaTestFunc(Gfx::COMP_FUNC_GREATER, 0.5f); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetTextureFactor(color); + + Gfx::TextureStageParams params; + params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE; + params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; + params.colorArg2 = Gfx::TEX_MIX_ARG_SRC_COLOR; + params.alphaOperation = Gfx::TEX_MIX_OPER_REPLACE; + params.alphaArg1 = Gfx::TEX_MIX_ARG_TEXTURE; + m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); + m_device->SetTextureStageParams(0, params); + } + else // normal ? + { + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, false); + + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, true); + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true); + + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + + Gfx::TextureStageParams params; + params.colorOperation = Gfx::TEX_MIX_OPER_DEFAULT; // default modulate + params.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ? - /*m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);*/ + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, params); } if (state & Gfx::ENG_RSTATE_FOG) @@ -1040,21 +1025,25 @@ void Gfx::CEngine::SetState(int state, const Gfx::Color& color) if ( !m_groundSpotVisible && (state & Gfx::ENG_RSTATE_SECOND) != 0 ) second = false; if ( !m_dirty && (state & Gfx::ENG_RSTATE_SECOND) == 0 ) second = false; - if ( (state & ENG_RSTATE_DUAL_BLACK) && second ) + if ((state & ENG_RSTATE_DUAL_BLACK) && second) { - /*m_device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); - m_device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); - m_device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); - m_device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);*/ + Gfx::TextureStageParams params; + params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE; + params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; + params.colorArg2 = Gfx::TEX_MIX_ARG_COMPUTED_COLOR; + params.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; // TODO: ??? + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(1, params); } - else if ( (state & ENG_RSTATE_DUAL_WHITE) && second ) + else if ((state & ENG_RSTATE_DUAL_WHITE) && second) { - /*m_device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD); - m_device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); - m_device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); - m_device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); - m_device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);*/ + Gfx::TextureStageParams params; + params.colorOperation = Gfx::TEX_MIX_OPER_ADD; + params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE; + params.colorArg2 = Gfx::TEX_MIX_ARG_COMPUTED_COLOR; + params.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT; // TODO: ??? + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(1, params); } else { @@ -1063,18 +1052,25 @@ void Gfx::CEngine::SetState(int state, const Gfx::Color& color) if (state & Gfx::ENG_RSTATE_WRAP) { - /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP); - m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);*/ - } - else if (state & Gfx::ENG_RSTATE_CLAMP) - { - /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP); - m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);*/ + // TODO: separate function for setting wrap mode? + + Gfx::TextureStageParams p1 = m_device->GetTextureStageParams(0); + p1.wrapS = p1.wrapT = Gfx::TEX_WRAP_REPEAT; + m_device->SetTextureStageParams(0, p1); + + Gfx::TextureStageParams p2 = m_device->GetTextureStageParams(1); + p2.wrapS = p2.wrapT = Gfx::TEX_WRAP_REPEAT; + m_device->SetTextureStageParams(1, p2); } - else + else // if (state & Gfx::ENG_RSTATE_CLAMP) or otherwise { - /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP); - m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);*/ + Gfx::TextureStageParams p1 = m_device->GetTextureStageParams(0); + p1.wrapS = p1.wrapT = Gfx::TEX_WRAP_CLAMP; + m_device->SetTextureStageParams(0, p1); + + Gfx::TextureStageParams p2 = m_device->GetTextureStageParams(1); + p2.wrapS = p2.wrapT = Gfx::TEX_WRAP_CLAMP; + m_device->SetTextureStageParams(1, p2); } if (state & Gfx::ENG_RSTATE_2FACE) @@ -1197,13 +1193,13 @@ float Gfx::CEngine::GetLimitLOD(int rank, bool last) if (last) { limit = m_limitLOD[rank]; - limit *= m_lastSize.w/640.0f; // limit further if large window! + limit *= m_lastSize.x/640.0f; // limit further if large window! limit += m_limitLOD[0]*(m_lastObjectDetail*2.0f); } else { limit = m_limitLOD[rank]; - limit *= m_size.w/640.0f; // limit further if large window! + limit *= m_size.x/640.0f; // limit further if large window! limit += m_limitLOD[0]*(m_objectDetail*2.0f); } @@ -1222,7 +1218,7 @@ void Gfx::CEngine::SetFocus(float focus) m_focus = focus; m_size = m_app->GetVideoConfig().size; - float aspect = (static_cast(m_size.h)) / m_size.w; + float aspect = (static_cast(m_size.y)) / m_size.x; Math::LoadProjectionMatrix(m_matProj, m_focus, aspect, 0.5f, m_deepView[0]); } @@ -1698,15 +1694,6 @@ void Gfx::CEngine::ApplyChange() viewport, and renders the scene. */ void Gfx::CEngine::Render() { - /* TODO! - D3DObjLevel1* p1; - D3DObjLevel2* p2; - D3DObjLevel3* p3; - D3DObjLevel4* p4; - D3DObjLevel5* p5; - D3DVERTEX2* pv; - int l1, l2, l3, l4, l5, objRank;*/ - if (! m_render) return; m_statisticTriangle = 0; @@ -1729,19 +1716,27 @@ void Gfx::CEngine::Render() if (m_drawWorld) - { Draw3DScene(); - } DrawInterface(); + // End the scene m_device->EndScene(); } void Gfx::CEngine::Draw3DScene() { + /* TODO! + D3DObjLevel1* p1; + D3DObjLevel2* p2; + D3DObjLevel3* p3; + D3DObjLevel4* p4; + D3DObjLevel5* p5; + D3DVERTEX2* pv; + int l1, l2, l3, l4, l5, objRank;*/ + if (m_groundSpotVisible) UpdateGroundSpotTextures(); @@ -2153,11 +2148,11 @@ void Gfx::CEngine::DrawShadow() float endDeepView = m_deepView[m_rankView]; float lastIntensity = -1.0f; - for (int i = 0; i < static_cast( m_shadow.size() ); i++) + for (int i = 0; i < static_cast( m_shadows.size() ); i++) { - if (m_shadow[i].hide) continue; + if (m_shadows[i].hide) continue; - Math::Vector pos = m_shadow[i].pos; // pos = center of the shadow on the ground + Math::Vector pos = m_shadows[i].pos; // pos = center of the shadow on the ground if (m_eyePt.y == pos.y) continue; // camera at the same level? @@ -2169,7 +2164,7 @@ void Gfx::CEngine::DrawShadow() if (m_eyePt.y > pos.y) // camera on? { float height = m_eyePt.y-pos.y; - float h = m_shadow[i].radius; + float h = m_shadows[i].radius; float max = height*0.5f; if ( h > max ) h = max; if ( h > 4.0f ) h = 4.0f; @@ -2185,7 +2180,7 @@ void Gfx::CEngine::DrawShadow() else // camera underneath? { float height = pos.y-m_eyePt.y; - float h = m_shadow[i].radius; + float h = m_shadows[i].radius; float max = height*0.1f; if ( h > max ) h = max; if ( h > 4.0f ) h = 4.0f; @@ -2201,20 +2196,20 @@ void Gfx::CEngine::DrawShadow() // The hFactor decreases the intensity and size increases more // the object is high relative to the ground. - float hFactor = m_shadow[i].height/20.0f; + float hFactor = m_shadows[i].height/20.0f; if ( hFactor < 0.0f ) hFactor = 0.0f; if ( hFactor > 1.0f ) hFactor = 1.0f; hFactor = powf(1.0f-hFactor, 2.0f); if ( hFactor < 0.2f ) hFactor = 0.2f; - float radius = m_shadow[i].radius*1.5f; + float radius = m_shadows[i].radius*1.5f; radius *= 2.0f-hFactor; // greater if high radius *= 1.0f-d/D; // smaller if close Math::Vector corner[4]; - if (m_shadow[i].type == Gfx::ENG_SHADOW_NORM) + if (m_shadows[i].type == Gfx::ENG_SHADOW_NORM) { corner[0].x = +radius; corner[0].z = +radius; @@ -2239,27 +2234,27 @@ void Gfx::CEngine::DrawShadow() { Math::Point rot; - rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(radius, radius)); + rot = Math::RotatePoint(-m_shadows[i].angle, Math::Point(radius, radius)); corner[0].x = rot.x; corner[0].z = rot.y; corner[0].y = 0.0f; - rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(-radius, radius)); + rot = Math::RotatePoint(-m_shadows[i].angle, Math::Point(-radius, radius)); corner[1].x = rot.x; corner[1].z = rot.y; corner[1].y = 0.0f; - rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(radius, -radius)); + rot = Math::RotatePoint(-m_shadows[i].angle, Math::Point(radius, -radius)); corner[2].x = rot.x; corner[2].z = rot.y; corner[2].y = 0.0f; - rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(-radius, -radius)); + rot = Math::RotatePoint(-m_shadows[i].angle, Math::Point(-radius, -radius)); corner[3].x = rot.x; corner[3].z = rot.y; corner[3].y = 0.0f; - if (m_shadow[i].type == Gfx::ENG_SHADOW_WORM) + if (m_shadows[i].type == Gfx::ENG_SHADOW_WORM) { ts.x = 96.0f/256.0f; ti.x = 128.0f/256.0f; @@ -2271,10 +2266,10 @@ void Gfx::CEngine::DrawShadow() } } - corner[0] = Math::CrossProduct(corner[0], m_shadow[i].normal); - corner[1] = Math::CrossProduct(corner[1], m_shadow[i].normal); - corner[2] = Math::CrossProduct(corner[2], m_shadow[i].normal); - corner[3] = Math::CrossProduct(corner[3], m_shadow[i].normal); + corner[0] = Math::CrossProduct(corner[0], m_shadows[i].normal); + corner[1] = Math::CrossProduct(corner[1], m_shadows[i].normal); + corner[2] = Math::CrossProduct(corner[2], m_shadows[i].normal); + corner[3] = Math::CrossProduct(corner[3], m_shadows[i].normal); corner[0] += pos; corner[1] += pos; @@ -2292,7 +2287,7 @@ void Gfx::CEngine::DrawShadow() Gfx::Vertex(corner[2], n, Math::Point(ti.x, ti.y)) }; - float intensity = (0.5f+m_shadow[i].intensity*0.5f)*hFactor; + float intensity = (0.5f+m_shadows[i].intensity*0.5f)*hFactor; // Decreases the intensity of the shade if you're in the area // between the beginning and the end of the fog. diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index d01a679..8f9338a 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -19,17 +19,15 @@ #pragma once - +#include "app/system.h" #include "common/event.h" #include "graphics/core/color.h" #include "graphics/core/material.h" #include "graphics/core/texture.h" #include "graphics/core/vertex.h" #include "math/intpoint.h" -#include "math/intsize.h" #include "math/matrix.h" #include "math/point.h" -#include "math/size.h" #include "math/vector.h" @@ -567,15 +565,6 @@ public: //! Evolved throughout the game void StepSimulation(float rTime); - //! Initialize timestamps at the beginning of animation - void TimeInit(); - //! Suspend animation - void TimeEnterGel(); - //! Resume animation - void TimeExitGel(); - //! Returns the relative time since last animation update - float TimeGet(); - //! Writes a screenshot containing the current frame bool WriteScreenShot(const std::string& fileName, int width, int height); @@ -608,22 +597,24 @@ public: void SetRenderEnable(bool enable); //! Returns current size of viewport window - Math::IntSize GetWindowSize(); + Math::IntPoint GetWindowSize(); //! Returns the last size of viewport window - Math::IntSize GetLastWindowSize(); + Math::IntPoint GetLastWindowSize(); - //! Converts window coords to interface coords - /** Conversion of the position of the mouse from window coords to interface coords: - - x: 0=left, 1=right - - y: 0=down, 1=up */ + //@{ + //! Conversion functions between window and interface coordinates + /** Window coordinates are from top-left (0,0) to bottom-right (w,h) - size of window + Interface cords are from bottom-left (0,0) to top-right (1,1) - and do not depend on window size */ Math::Point WindowToInterfaceCoords(Math::IntPoint pos); - //! Converts interface coords to window coords Math::IntPoint InterfaceToWindowCoords(Math::Point pos); + //@} - //! Converts window size to interface size - Math::Size WindowToInterfaceSize(Math::IntSize size); - //! Converts interface size to window size - Math::IntSize InterfaceToWindowSize(Math::Size size); + //@{ + //! Conversion functions between window and interface sizes + /** Unlike coordinate conversions, this is only scale conversion, not translation and scale. */ + Math::Point WindowToInterfaceSize(Math::IntPoint size); + Math::IntPoint InterfaceToWindowSize(Math::Point size); + //@} //! Returns the name of directory with textures std::string GetTextureDir(); @@ -1062,46 +1053,48 @@ protected: //! Whether to show stats (FPS, etc) bool m_showStats; - int m_blackSrcBlend[2]; - int m_blackDestBlend[2]; - int m_whiteSrcBlend[2]; - int m_whiteDestBlend[2]; - int m_diffuseSrcBlend[2]; - int m_diffuseDestBlend[2]; - int m_alphaSrcBlend[2]; - int m_alphaDestBlend[2]; + //! Speed of animation + float m_speed; + //! Pause mode + bool m_pause; + //! Rendering enabled? + bool m_render; + //! Lock for duration of movie? + bool m_movieLock; + //! Projection matrix for 3D scene Math::Matrix m_matProj; - Math::Matrix m_matLeftView; - Math::Matrix m_matRightView; + //! View matrix for 3D scene Math::Matrix m_matView; + //! Camera angle for 3D scene float m_focus; + //! World matrix for 2D interface Math::Matrix m_matWorldInterface; + //! Projection matrix for 2D interface Math::Matrix m_matProjInterface; + //! View matrix for 2D interface Math::Matrix m_matViewInterface; - long m_baseTime; - long m_stopTime; - float m_absTime; - float m_lastTime; - float m_speed; - bool m_pause; - bool m_render; - bool m_movieLock; - //! Current size of viewport window - Math::IntSize m_size; + Math::IntPoint m_size; //! Previous size of viewport window - Math::IntSize m_lastSize; + Math::IntPoint m_lastSize; + //! Root of tree object structure (level 1 list) std::vector m_objectTree; + //! Object parameters std::vector m_objects; - std::vector m_shadow; - std::vector m_groundSpot; + //! Shadow list + std::vector m_shadows; + //! Ground spot list + std::vector m_groundSpots; + //! Ground mark Gfx::EngineGroundMark m_groundMark; + //! Location of camera Math::Vector m_eyePt; + //! Camera target Math::Vector m_lookatPt; float m_eyeDirH; float m_eyeDirV; @@ -1156,28 +1149,47 @@ protected: int m_editIndentValue; float m_tracePrecision; + //! Ranks of highlighted objects int m_highlightRank[100]; + //! Highlight visible? bool m_highlight; + //@{ + //! Highlight rectangle points Math::Point m_highlightP1; Math::Point m_highlightP2; + //@} - int m_lastState; - Gfx::Color m_lastColor; - char m_lastTexture[2][50]; - Gfx::Material m_lastMaterial; - + //! Texture directory name std::string m_texPath; + //! Default texture create params Gfx::TextureCreateParams m_defaultTexParams; + //! Map of loaded textures (by name) std::map m_texNameMap; + //! Reverse map of loaded textures (by texture) std::map m_revTexNameMap; + //! Mouse cursor definitions Gfx::EngineMouse m_mice[Gfx::ENG_MOUSE_COUNT]; + //! Texture with mouse cursors Gfx::Texture m_miceTexture; + //! Size of mouse cursor Math::Point m_mouseSize; + //! Type of mouse cursor Gfx::EngineMouseType m_mouseType; + //! Position of mouse in interface coords Math::Point m_mousePos; + //! Is mouse visible? bool m_mouseVisible; + + //! Last engine render state (-1 at the beginning of frame) + int m_lastState; + //! Last color set with render state + Gfx::Color m_lastColor; + //! Last texture names for 2 used texture stages + std::string m_lastTexture[2]; + //! Last material + Gfx::Material m_lastMaterial; }; }; // namespace Gfx diff --git a/src/graphics/engine/text.cpp b/src/graphics/engine/text.cpp index 77515ad..0a57026 100644 --- a/src/graphics/engine/text.cpp +++ b/src/graphics/engine/text.cpp @@ -245,10 +245,10 @@ float Gfx::CText::GetAscent(Gfx::FontType font, float size) Gfx::CachedFont* cf = GetOrOpenFont(font, size); assert(cf != nullptr); - Math::IntSize wndSize; - wndSize.h = TTF_FontAscent(cf->font); - Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); - return ifSize.h; + Math::IntPoint wndSize; + wndSize.y = TTF_FontAscent(cf->font); + Math::Point ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.y; } float Gfx::CText::GetDescent(Gfx::FontType font, float size) @@ -257,10 +257,10 @@ float Gfx::CText::GetDescent(Gfx::FontType font, float size) Gfx::CachedFont* cf = GetOrOpenFont(font, size); assert(cf != nullptr); - Math::IntSize wndSize; - wndSize.h = TTF_FontDescent(cf->font); - Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); - return ifSize.h; + Math::IntPoint wndSize; + wndSize.y = TTF_FontDescent(cf->font); + Math::Point ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.y; } float Gfx::CText::GetHeight(Gfx::FontType font, float size) @@ -269,10 +269,10 @@ float Gfx::CText::GetHeight(Gfx::FontType font, float size) Gfx::CachedFont* cf = GetOrOpenFont(font, size); assert(cf != nullptr); - Math::IntSize wndSize; - wndSize.h = TTF_FontHeight(cf->font); - Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); - return ifSize.h; + Math::IntPoint wndSize; + wndSize.y = TTF_FontHeight(cf->font); + Math::Point ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.y; } @@ -315,10 +315,10 @@ float Gfx::CText::GetStringWidth(const std::string &text, Gfx::FontType font, fl Gfx::CachedFont* cf = GetOrOpenFont(font, size); assert(cf != nullptr); - Math::IntSize wndSize; - TTF_SizeUTF8(cf->font, text.c_str(), &wndSize.w, &wndSize.h); - Math::Size ifSize = m_engine->WindowToInterfaceSize(wndSize); - return ifSize.w; + Math::IntPoint wndSize; + TTF_SizeUTF8(cf->font, text.c_str(), &wndSize.x, &wndSize.y); + Math::Point ifSize = m_engine->WindowToInterfaceSize(wndSize); + return ifSize.x; } float Gfx::CText::GetCharWidth(Gfx::UTF8Char ch, Gfx::FontType font, float size, float offset) @@ -339,7 +339,7 @@ float Gfx::CText::GetCharWidth(Gfx::UTF8Char ch, Gfx::FontType font, float size, else tex = CreateCharTexture(ch, cf); - return tex.charSize.w; + return tex.charSize.x; } @@ -539,9 +539,9 @@ void Gfx::CText::DrawString(const std::string &text, const std::vector(format[fmtIndex] & Gfx::FONT_MASK_HIGHLIGHT); if (hl != Gfx::FONT_HIGHLIGHT_NONE) { - Math::Size charSize; - charSize.w = GetCharWidth(ch, font, size, offset); - charSize.h = GetHeight(font, size); + Math::Point charSize; + charSize.x = GetCharWidth(ch, font, size, offset); + charSize.y = GetHeight(font, size); DrawHighlight(hl, pos, charSize); } @@ -580,7 +580,7 @@ void Gfx::CText::DrawString(const std::string &text, Gfx::FontType font, } } -void Gfx::CText::DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Size size) +void Gfx::CText::DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Point size) { // Gradient colors Gfx::Color grad[4]; @@ -622,16 +622,16 @@ void Gfx::CText::DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Siz return; } - Math::IntSize vsize = m_engine->GetWindowSize(); + Math::IntPoint vsize = m_engine->GetWindowSize(); float h = 0.0f; - if (vsize.h <= 768.0f) // 1024x768 or less? - h = 1.01f / vsize.h; // 1 pixel + if (vsize.y <= 768.0f) // 1024x768 or less? + h = 1.01f / vsize.y; // 1 pixel else // more than 1024x768? - h = 2.0f / vsize.h; // 2 pixels + h = 2.0f / vsize.y; // 2 pixels Math::Point p1, p2; p1.x = pos.x; - p2.x = pos.x + size.w; + p2.x = pos.x + size.x; if (hl == Gfx::FONT_HIGHLIGHT_LINK) { @@ -641,7 +641,7 @@ void Gfx::CText::DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Siz else { p1.y = pos.y; - p2.y = pos.y + size.h; + p2.y = pos.y + size.y; } m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); @@ -690,8 +690,8 @@ void Gfx::CText::DrawChar(Gfx::UTF8Char ch, Gfx::FontType font, float size, Math m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); - Math::Point p1(pos.x, pos.y + tex.charSize.h - tex.texSize.h); - Math::Point p2(pos.x + tex.texSize.w, pos.y + tex.charSize.h); + Math::Point p1(pos.x, pos.y + tex.charSize.y - tex.texSize.y); + Math::Point p2(pos.x + tex.texSize.x, pos.y + tex.charSize.y); Math::Vector n(0.0f, 0.0f, -1.0f); // normal @@ -707,7 +707,7 @@ void Gfx::CText::DrawChar(Gfx::UTF8Char ch, Gfx::FontType font, float size, Math m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); m_engine->AddStatisticTriangle(2); - pos.x += tex.charSize.w; + pos.x += tex.charSize.x; } Gfx::CachedFont* Gfx::CText::GetOrOpenFont(Gfx::FontType font, float size) @@ -797,8 +797,8 @@ Gfx::CharTexture Gfx::CText::CreateCharTexture(Gfx::UTF8Char ch, Gfx::CachedFont } texture.id = tex.id; - texture.texSize = m_engine->WindowToInterfaceSize(Math::IntSize(textureSurface->w, textureSurface->h)); - texture.charSize = m_engine->WindowToInterfaceSize(Math::IntSize(textSurface->w, textSurface->h)); + texture.texSize = m_engine->WindowToInterfaceSize(Math::IntPoint(textureSurface->w, textureSurface->h)); + texture.charSize = m_engine->WindowToInterfaceSize(Math::IntPoint(textSurface->w, textSurface->h)); return texture; } diff --git a/src/graphics/engine/text.h b/src/graphics/engine/text.h index 6209c39..7e2f84b 100644 --- a/src/graphics/engine/text.h +++ b/src/graphics/engine/text.h @@ -20,7 +20,6 @@ #pragma once #include "math/point.h" -#include "math/size.h" #include #include @@ -168,8 +167,8 @@ struct UTF8Char struct CharTexture { unsigned int id; - Math::Size texSize; - Math::Size charSize; + Math::Point texSize; + Math::Point charSize; CharTexture() : id(0) {} }; @@ -277,7 +276,7 @@ protected: float size, Math::Point pos, float width, int eol); void DrawString(const std::string &text, Gfx::FontType font, float size, Math::Point pos, float width, int eol); - void DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Size size); + void DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Point size); void DrawChar(Gfx::UTF8Char ch, Gfx::FontType font, float size, Math::Point &pos); protected: diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index cef372f..4c36053 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -122,7 +122,7 @@ bool Gfx::CGLDevice::Create() glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glViewport(0, 0, m_config.size.w, m_config.size.h); + glViewport(0, 0, m_config.size.x, m_config.size.y); m_lights = std::vector(GL_MAX_LIGHTS, Gfx::Light()); @@ -390,8 +390,8 @@ Gfx::Texture Gfx::CGLDevice::CreateTexture(ImageData *data, const Gfx::TextureCr Gfx::Texture result; result.valid = true; - result.size.w = data->surface->w; - result.size.h = data->surface->h; + result.size.x = data->surface->w; + result.size.y = data->surface->h; // Use & enable 1st texture stage glActiveTexture(GL_TEXTURE0); diff --git a/src/math/intsize.h b/src/math/intsize.h deleted file mode 100644 index c88f09b..0000000 --- a/src/math/intsize.h +++ /dev/null @@ -1,70 +0,0 @@ -// * This file is part of the COLOBOT source code -// * Copyright (C) 2012, Polish Portal of Colobot (PPC) -// * -// * 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/. - -/** @defgroup MathIntSizeModule math/intsize.h - Contains the IntSize struct. - */ - -#pragma once - -#include "math/intpoint.h" - - -// Math module namespace -namespace Math -{ - -/* @{ */ // start of group - -/** \struct IntSize math/size.h - \brief 2D size with integer dimensions */ -struct IntSize -{ - //! Width - int w; - //! Height - int h; - - //! Constructs a zero size: (0,0) - inline IntSize() - { - LoadZero(); - } - - //! Constructs a size from given dimensions: (w,h) - inline explicit IntSize(int w, int h) - { - this->w = w; - this->h = h; - } - - //! Sets the zero size: (0,0) - inline void LoadZero() - { - w = h = 0; - } - - //! Converts Point to Size - inline static Math::IntSize FromIntPoint(Math::IntPoint p) - { - return Math::IntSize(p.x, p.y); - } -}; // struct Size - - -/* @} */ // end of group - -}; // namespace Math diff --git a/src/math/size.h b/src/math/size.h deleted file mode 100644 index 03cffaa..0000000 --- a/src/math/size.h +++ /dev/null @@ -1,75 +0,0 @@ -// * This file is part of the COLOBOT source code -// * Copyright (C) 2012, Polish Portal of Colobot (PPC) -// * -// * 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/. - -/** @defgroup MathSizeModule math/size.h - Contains the Size struct. - */ - -#pragma once - -#include "math/point.h" - - -// Math module namespace -namespace Math -{ - -/* @{ */ // start of group - -/** \struct Size math/size.h - \brief 2D size - - Represents a 2D size (w, h). - Is separate from Math::Point to avoid confusion. - - */ -struct Size -{ - //! Width - float w; - //! Height - float h; - - //! Constructs a zero size: (0,0) - inline Size() - { - LoadZero(); - } - - //! Constructs a size from given dimensions: (w,h) - inline explicit Size(float w, float h) - { - this->w = w; - this->h = h; - } - - //! Sets the zero size: (0,0) - inline void LoadZero() - { - w = h = 0.0f; - } - - //! Converts Point to Size - inline static Math::Size FromPoint(Math::Point p) - { - return Math::Size(p.x, p.y); - } -}; // struct Size - - -/* @} */ // end of group - -}; // namespace Math -- cgit v1.2.3-1-g7c22 From 1996507fd3d4d9de90de99845b71a6bf3fbe62da Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sat, 11 Aug 2012 18:39:16 +0200 Subject: Documentation update - updated Doxyfile - added/changed file, dir and namespace descriptions - fixed some errors in doxygen tags --- src/app/README.txt | 7 ++++--- src/app/app.h | 5 ++++- src/app/main.cpp | 5 ++++- src/app/system.h | 9 ++++++--- src/app/system_linux.h | 9 ++++++--- src/app/system_other.h | 9 ++++++--- src/app/system_windows.h | 9 ++++++--- src/common/README.txt | 7 ++++--- src/common/logger.h | 12 ++++++------ src/graphics/README.txt | 13 +++++++++++-- src/graphics/core/README.txt | 13 +++++++------ src/graphics/core/color.h | 5 ++++- src/graphics/core/device.h | 5 ++++- src/graphics/core/light.h | 5 ++++- src/graphics/core/material.h | 5 ++++- src/graphics/core/texture.h | 5 ++++- src/graphics/core/vertex.h | 5 ++++- src/graphics/d3d/README.txt | 7 ++++--- src/graphics/engine/README.txt | 17 +++++++++-------- src/graphics/engine/camera.h | 5 ++++- src/graphics/engine/cloud.h | 5 ++++- src/graphics/engine/engine.h | 5 ++++- src/graphics/engine/lightman.h | 5 ++++- src/graphics/engine/lightning.h | 5 ++++- src/graphics/engine/modelfile.h | 5 ++++- src/graphics/engine/particle.h | 5 ++++- src/graphics/engine/planet.h | 5 ++++- src/graphics/engine/pyro.h | 5 ++++- src/graphics/engine/terrain.h | 5 ++++- src/graphics/engine/text.h | 5 ++++- src/graphics/engine/water.h | 5 ++++- src/graphics/opengl/README.txt | 13 +++++++------ src/graphics/opengl/gldevice.h | 5 ++++- src/math/README.txt | 13 +++++++++++-- src/math/all.h | 9 +++------ src/math/const.h | 7 +++---- src/math/func.h | 21 +++++++++++---------- src/math/geometry.h | 11 +++-------- src/math/intpoint.h | 12 +++++------- src/math/matrix.h | 24 +++++++++++++----------- src/math/point.h | 9 +++------ src/math/vector.h | 9 +++------ src/object/README.txt | 10 +++++++--- src/physics/README.txt | 7 ++++--- src/sound/README.txt | 7 ++++--- src/ui/README.txt | 7 ++++--- 46 files changed, 234 insertions(+), 142 deletions(-) (limited to 'src') diff --git a/src/app/README.txt b/src/app/README.txt index 1df1fcc..e4f69ec 100644 --- a/src/app/README.txt +++ b/src/app/README.txt @@ -1,3 +1,4 @@ -src/app - -Contains the main class of the application. +/** + * \dir app + * Main class of the application and system functions + */ diff --git a/src/app/app.h b/src/app/app.h index d3b1368..bfa8c25 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// app.h +/** + * \file app/app.h + * \brief CApplication class + */ #pragma once diff --git a/src/app/main.cpp b/src/app/main.cpp index dce13da..619043e 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// main.cpp +/** + * \file app/main.cpp + * \brief Entry point of application - main() function + */ #include "app/app.h" #include "app/system.h" diff --git a/src/app/system.h b/src/app/system.h index 3c04760..e216842 100644 --- a/src/app/system.h +++ b/src/app/system.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// system.h +/** + * \file app/system.h + * \brief System functions: time stamps, info dialogs, etc. + */ #pragma once @@ -26,7 +29,7 @@ /* Dialog utils */ /** - * \enum SysDialogType + * \enum SystemDialogType * \brief Type of system dialog */ enum SystemDialogType @@ -44,7 +47,7 @@ enum SystemDialogType }; /** - * \enum SysDialogResult + * \enum SystemDialogResult * \brief Result of system dialog * * Means which button was pressed. diff --git a/src/app/system_linux.h b/src/app/system_linux.h index f58c9a1..69893de 100644 --- a/src/app/system_linux.h +++ b/src/app/system_linux.h @@ -15,10 +15,13 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// system_linux.h +/** + * \file app/system_linux.h + * \brief Linux-specific implementation of system functions + */ -/* This header contains Linux-specific code for system utils - from system.h. There is no separate .cpp module for simplicity.*/ +/* NOTE: code is contained in this header; + * there is no separate .cpp module for simplicity */ #include #include diff --git a/src/app/system_other.h b/src/app/system_other.h index 9f13ffa..eff0c8a 100644 --- a/src/app/system_other.h +++ b/src/app/system_other.h @@ -15,10 +15,13 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// system_other.h +/** + * \file app/system_other.h + * \brief Fallback code for other systems + */ -/* This header contains fallback code for other platforms for system utils - from system.h. There is no separate .cpp module for simplicity.*/ +/* NOTE: code is contained in this header; + * there is no separate .cpp module for simplicity */ #include diff --git a/src/app/system_windows.h b/src/app/system_windows.h index eb6beec..72d9f88 100644 --- a/src/app/system_windows.h +++ b/src/app/system_windows.h @@ -15,10 +15,13 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// system_windows.h +/** + * \file app/system_windows.h + * \brief Windows-specific implementation of system functions + */ -/* This header contains Windows-specific code for system utils - from system.h. There is no separate .cpp module for simplicity.*/ +/* NOTE: code is contained in this header; + * there is no separate .cpp module for simplicity */ #include diff --git a/src/common/README.txt b/src/common/README.txt index 36653cc..73d65b7 100644 --- a/src/common/README.txt +++ b/src/common/README.txt @@ -1,3 +1,4 @@ -src/common - -Contains headers and modules with common structs and enums. +/** + * \dir common + * \brief Structs and utils shared throughout the application + */ diff --git a/src/common/logger.h b/src/common/logger.h index a67aefe..5de3d63 100644 --- a/src/common/logger.h +++ b/src/common/logger.h @@ -57,36 +57,36 @@ class CLogger : public CSingleton ~CLogger(); /** Write message to console or file - * @param const char str - message to write + * @param str - message to write * @param ... - additional arguments */ void Message(const char *str, ...); /** Write message to console or file with LOG_INFO level - * @param const char str - message to write + * @param str - message to write * @param ... - additional arguments */ void Info(const char *str, ...); /** Write message to console or file with LOG_WARN level - * @param const char str - message to write + * @param str - message to write * @param ... - additional arguments */ void Warn(const char *str, ...); /** Write message to console or file with LOG_ERROR level - * @param const char str - message to write + * @param str - message to write * @param ... - additional arguments */ void Error(const char *str, ...); /** Set output file to write logs to - * @param std::string filename - output file to write to + * @param filename - output file to write to */ void SetOutputFile(std::string filename); /** Set log level. Logs with level below will not be shown - * @param LogType level - minimum log level to write + * @param level - minimum log level to write */ void SetLogLevel(LogType level); diff --git a/src/graphics/README.txt b/src/graphics/README.txt index 3ec3871..479747b 100644 --- a/src/graphics/README.txt +++ b/src/graphics/README.txt @@ -1,3 +1,12 @@ -src/graphics +/** + * \dir graphics + * \brief Graphics engine + */ -Graphics engine +/** + * \namespace Gfx + * \brief Namespace for (new) graphics code + * + * This namespace was created to avoid clashing with old code, but now it still serves, + * defining a border between pure graphics engine and other parts of application. + */ \ No newline at end of file diff --git a/src/graphics/core/README.txt b/src/graphics/core/README.txt index 12beef9..ca3768c 100644 --- a/src/graphics/core/README.txt +++ b/src/graphics/core/README.txt @@ -1,6 +1,7 @@ -src/graphics/core - -Abstract core of graphics engine - -Core types, enums, structs and CDevice abstract class that define -the abstract graphics device used in graphics engine +/** + * \dir graphics/core + * \brief Abstract core of graphics engine + * + * Core types, enums, structs and CDevice abstract class that define + * the abstract graphics device used in graphics engine + */ \ No newline at end of file diff --git a/src/graphics/core/color.h b/src/graphics/core/color.h index 0e08de3..ff8a2eb 100644 --- a/src/graphics/core/color.h +++ b/src/graphics/core/color.h @@ -14,7 +14,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// color.h +/** + * \file graphics/core/color.h + * \brief Color structs and related functions + */ #pragma once diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h index d4fcd26..a829c81 100644 --- a/src/graphics/core/device.h +++ b/src/graphics/core/device.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// device.h +/** + * \file graphics/core/device.h + * \brief Abstract graphics device - Gfx::CDevice class and related structs/enums + */ #pragma once diff --git a/src/graphics/core/light.h b/src/graphics/core/light.h index b787cb2..a39d1f5 100644 --- a/src/graphics/core/light.h +++ b/src/graphics/core/light.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// light.h +/** + * \file graphics/core/light.h + * \brief Light struct and related enums + */ #pragma once diff --git a/src/graphics/core/material.h b/src/graphics/core/material.h index 31b42f3..eb73c50 100644 --- a/src/graphics/core/material.h +++ b/src/graphics/core/material.h @@ -14,7 +14,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// material.h +/** + * \file graphics/core/material.h + * \brief Material struct + */ #pragma once diff --git a/src/graphics/core/texture.h b/src/graphics/core/texture.h index bb5b52f..c36b6c6 100644 --- a/src/graphics/core/texture.h +++ b/src/graphics/core/texture.h @@ -14,7 +14,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// texture.h +/** + * \file graphics/core/texture.h + * \brief Texture struct and related enums + */ #pragma once diff --git a/src/graphics/core/vertex.h b/src/graphics/core/vertex.h index b7fab1c..53dd642 100644 --- a/src/graphics/core/vertex.h +++ b/src/graphics/core/vertex.h @@ -14,7 +14,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// vertex.h +/** + * \file graphics/core/vertex.h + * \brief Vertex structs + */ #pragma once diff --git a/src/graphics/d3d/README.txt b/src/graphics/d3d/README.txt index 8388120..524ae7b 100644 --- a/src/graphics/d3d/README.txt +++ b/src/graphics/d3d/README.txt @@ -1,3 +1,4 @@ -src/graphics/d3d - -Possible future DirectX implementation of graphics engine +/** + * \dir graphics/d3d + * \brief Possible future DirectX implementation of graphics engine + */ \ No newline at end of file diff --git a/src/graphics/engine/README.txt b/src/graphics/engine/README.txt index 308b601..f64d3dd 100644 --- a/src/graphics/engine/README.txt +++ b/src/graphics/engine/README.txt @@ -1,8 +1,9 @@ -src/graphics/engine - -Graphics engine - -CEngine class and various other classes implementing the main features -of graphics engine from model loading to decorative particles - -Graphics operations are done on abstract interface from src/graphics/core +/** + * \dir graphics/engine + * \brief Graphics engine + * + * CEngine class and various other classes implementing the main features + * of graphics engine from model loading to decorative particles + * + * Graphics operations are done on abstract interface from src/graphics/core + */ \ No newline at end of file diff --git a/src/graphics/engine/camera.h b/src/graphics/engine/camera.h index ec6afcb..1a82f9f 100644 --- a/src/graphics/engine/camera.h +++ b/src/graphics/engine/camera.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// camera.h +/** + * \file graphics/engine/camera.h + * \brief Camera handling - Gfx::CCamera class + */ #pragma once diff --git a/src/graphics/engine/cloud.h b/src/graphics/engine/cloud.h index 676dfe8..881a598 100644 --- a/src/graphics/engine/cloud.h +++ b/src/graphics/engine/cloud.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// cloud.h +/** + * \file graphics/engine/cloud.h + * \brief Cloud rendering - Gfx::CCloud class + */ #pragma once diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 8f9338a..c7ff084 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// engine.h +/** + * \file graphics/engine/engine.h + * \brief Main graphics engine - Gfx::CEngine class + */ #pragma once diff --git a/src/graphics/engine/lightman.h b/src/graphics/engine/lightman.h index 8272125..52058c8 100644 --- a/src/graphics/engine/lightman.h +++ b/src/graphics/engine/lightman.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// lightman.h +/** + * \file graphics/engine/lightman.h + * \brief Dynamic light manager - Gfx::CLightManager class + */ #pragma once diff --git a/src/graphics/engine/lightning.h b/src/graphics/engine/lightning.h index 9e854be..3b4e2cf 100644 --- a/src/graphics/engine/lightning.h +++ b/src/graphics/engine/lightning.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// lightning.h (aka blitz.h) +/** + * \file graphics/engine/lightning.h + * \brief Lightning rendering - Gfx::CLightning class (aka blitz) + */ #pragma once diff --git a/src/graphics/engine/modelfile.h b/src/graphics/engine/modelfile.h index 6a30487..fab190f 100644 --- a/src/graphics/engine/modelfile.h +++ b/src/graphics/engine/modelfile.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// modelfile.h (aka modfile.h) +/** + * \file graphics/engine/modelfile.h + * \brief Model loading - Gfx::CModelFile class (aka modfile) + */ #include "graphics/engine/engine.h" #include "graphics/core/vertex.h" diff --git a/src/graphics/engine/particle.h b/src/graphics/engine/particle.h index 89e2c5b..45396d2 100644 --- a/src/graphics/engine/particle.h +++ b/src/graphics/engine/particle.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// particle.h (aka particule.h) +/** + * \file graphics/engine/particle.h + * \brief Particle rendering - Gfx::CParticle class (aka particule) + */ #pragma once diff --git a/src/graphics/engine/planet.h b/src/graphics/engine/planet.h index 5ba318b..54d8b55 100644 --- a/src/graphics/engine/planet.h +++ b/src/graphics/engine/planet.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// planet.h +/** + * \file graphics/engine/planet.h + * \brief Planet rendering - Gfx::CPlanet class + */ #pragma once diff --git a/src/graphics/engine/pyro.h b/src/graphics/engine/pyro.h index 35b5c5f..768abf8 100644 --- a/src/graphics/engine/pyro.h +++ b/src/graphics/engine/pyro.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// pyro.h +/** + * \file graphics/engine/pyro.h + * \brief Fire effect rendering - Gfx::CPyro class + */ #pragma once diff --git a/src/graphics/engine/terrain.h b/src/graphics/engine/terrain.h index a198590..41d4bbb 100644 --- a/src/graphics/engine/terrain.h +++ b/src/graphics/engine/terrain.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// terrain.h +/** + * \file graphics/engine/terrain.h + * \brief Terrain rendering - Gfx::CTerrain class + */ #pragma once diff --git a/src/graphics/engine/text.h b/src/graphics/engine/text.h index 7e2f84b..24251ab 100644 --- a/src/graphics/engine/text.h +++ b/src/graphics/engine/text.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// text.h +/** + * \file graphics/engine/text.h + * \brief Text rendering - Gfx::CText class + */ #pragma once diff --git a/src/graphics/engine/water.h b/src/graphics/engine/water.h index 245baf7..b051889 100644 --- a/src/graphics/engine/water.h +++ b/src/graphics/engine/water.h @@ -15,7 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// water.h +/** + * \file graphics/engine/water.h + * \brief Water rendering - Gfx::CWater class + */ #pragma once diff --git a/src/graphics/opengl/README.txt b/src/graphics/opengl/README.txt index 0aba0ed..596871d 100644 --- a/src/graphics/opengl/README.txt +++ b/src/graphics/opengl/README.txt @@ -1,6 +1,7 @@ -src/graphics/opengl - -OpenGL engine implementation - -Contains the concrete implementation using OpenGL of abstract CDevice class -from src/graphics/core +/** + * \dir graphics/opengl + * \brief OpenGL engine implementation + * + * Contains the concrete implementation using OpenGL of abstract CDevice class + * from src/graphics/core + */ \ No newline at end of file diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h index a41c41c..dbe9a52 100644 --- a/src/graphics/opengl/gldevice.h +++ b/src/graphics/opengl/gldevice.h @@ -14,7 +14,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// gldevice.h +/** + * \file graphics/opengl/gldevice.h + * \brief OpenGL implementation - Gfx::CGLDevice class + */ #pragma once diff --git a/src/math/README.txt b/src/math/README.txt index 1a5ce93..fd34dcb 100644 --- a/src/math/README.txt +++ b/src/math/README.txt @@ -1,3 +1,12 @@ -src/math +/** + * \dir math + * \brief Common mathematical structures and functions + */ -Contains common mathematical structures and functions. +/** + * \namespace Math + * \brief Namespace for (new) math code + * + * This namespace was created to avoid clashing with old code, but now it still serves, + * defining a border between math and non-math-related code. + */ \ No newline at end of file diff --git a/src/math/all.h b/src/math/all.h index 13a9290..4ac9d55 100644 --- a/src/math/all.h +++ b/src/math/all.h @@ -14,14 +14,13 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -/** @defgroup MathAllModule math/all.h - Includes all other math module headers. +/** + * \file math/all.h + * \brief Includes all other math module headers */ #pragma once -/* @{ */ // start of group - #include "const.h" #include "func.h" #include "point.h" @@ -30,5 +29,3 @@ #include "geometry.h" #include "conv.h" - -/* @} */ // end of group diff --git a/src/math/const.h b/src/math/const.h index b08a400..0b6f971 100644 --- a/src/math/const.h +++ b/src/math/const.h @@ -14,8 +14,9 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -/** @defgroup MathConstModule math/const.h - Contains the math constants used in math functions. +/** + * \file math/const.h + * \brief Constants used in math functions */ #pragma once @@ -26,7 +27,6 @@ // Math module namespace namespace Math { -/* @{ */ // start of group //! Tolerance level -- minimum accepted float value const float TOLERANCE = 1e-6f; @@ -50,6 +50,5 @@ const float RAD_TO_DEG = 57.29577951308232286465f; //! Natural logarithm of 2 const float LOG_2 = log(2.0f); -/* @} */ // end of group }; // namespace Math diff --git a/src/math/func.h b/src/math/func.h index e97d990..541b084 100644 --- a/src/math/func.h +++ b/src/math/func.h @@ -15,8 +15,9 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -/** @defgroup MathFuncModule math/func.h - Contains common math functions. +/** + * \file math/func.h + * \brief Common math functions */ #pragma once @@ -31,8 +32,6 @@ namespace Math { -/* @{ */ // start of group - //! Compares \a a and \a b within \a tolerance inline bool IsEqual(float a, float b, float tolerance = Math::TOLERANCE) { @@ -188,11 +187,13 @@ inline float Direction(float a, float g) //! Managing the dead zone of a joystick. /** -\verbatimin: -1 0 1 +\verbatim +in: -1 0 1 --|-------|----o----|-------|--> <----> dead -out: -1 0 0 1\endverbatim */ +out: -1 0 0 1 +\endverbatim */ inline float Neutral(float value, float dead) { if ( fabs(value) <= dead ) @@ -226,7 +227,8 @@ inline float Smooth(float actual, float hope, float time) //! Bounces any movement /** -\verbatimout +\verbatim +out | 1+------o-------o--- | o | o o | | bounce @@ -235,7 +237,8 @@ inline float Smooth(float actual, float hope, float time) | o | | -o------|-------+----> progress 0| | 1 - |<---->|middle\endverbatim */ + |<---->|middle +\endverbatim */ inline float Bounce(float progress, float middle = 0.3f, float bounce = 0.4f) { if ( progress < middle ) @@ -250,6 +253,4 @@ inline float Bounce(float progress, float middle = 0.3f, float bounce = 0.4f) } } -/* @} */ // end of group - }; // namespace Math diff --git a/src/math/geometry.h b/src/math/geometry.h index 3a31ad6..1c5f60f 100644 --- a/src/math/geometry.h +++ b/src/math/geometry.h @@ -15,9 +15,9 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -/** @defgroup MathGeometryModule math/geometry.h - Contains math functions related to 3D geometry calculations, - transformations, etc. +/** + * \file math/geometry.h + * \brief Math functions related to 3D geometry calculations, transformations, etc. */ #pragma once @@ -36,9 +36,6 @@ namespace Math { -/* @{ */ // start of group - - //! Returns py up on the line \a a - \a b inline float MidPoint(const Math::Point &a, const Math::Point &b, float px) { @@ -566,6 +563,4 @@ inline Math::Vector RotateView(Math::Vector center, float angleH, float angleV, return eye+center; } -/* @} */ // end of group - }; // namespace Math diff --git a/src/math/intpoint.h b/src/math/intpoint.h index 476e67b..8e13b19 100644 --- a/src/math/intpoint.h +++ b/src/math/intpoint.h @@ -14,18 +14,18 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -/** @defgroup MathIntPointModule math/intpoint.h - Contains the IntPoint struct. +/** + * \file math/intpoint.h + * \brief IntPoint struct */ #pragma once namespace Math { -/* @{ */ // start of group - /** - * \struct IntPoint 2D Point with integer coords + * \struct IntPoint + * \brief 2D Point with integer coords * * Analog of WinAPI's POINT struct. */ @@ -39,6 +39,4 @@ struct IntPoint IntPoint(int aX = 0, int aY = 0) : x(aX), y(aY) {} }; -/* @} */ // end of group - }; // namespace Math diff --git a/src/math/matrix.h b/src/math/matrix.h index 45a7d75..30e629a 100644 --- a/src/math/matrix.h +++ b/src/math/matrix.h @@ -14,8 +14,9 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -/** @defgroup MathMatrixModule math/matrix.h - Contains the Matrix struct and related functions. +/** + * \file math/matrix.h + * \brief Matrix struct and related functions */ #pragma once @@ -32,8 +33,6 @@ namespace Math { -/* @{ */ // start of group - /** \struct Matrix math/matrix.h \brief 4x4 matrix @@ -42,11 +41,12 @@ namespace Math The internal representation is a 16-value table in column-major order, thus: - \verbatim +\verbatim m[0 ] m[4 ] m[8 ] m[12] m[1 ] m[5 ] m[9 ] m[13] m[2 ] m[6 ] m[10] m[14] -m[3 ] m[7 ] m[11] m[15] \endverbatim +m[3 ] m[7 ] m[11] m[15] +\endverbatim This representation is native to OpenGL; DirectX requires transposing the matrix. @@ -405,11 +405,15 @@ inline Math::Matrix MultiplyMatrices(const Math::Matrix &left, const Math::Matri } //! Calculates the result of multiplying m * v -/** The multiplication is performed thus: -\verbatim [ m.m[0 ] m.m[4 ] m.m[8 ] m.m[12] ] [ v.x ] +/** + The multiplication is performed thus: + +\verbatim +[ m.m[0 ] m.m[4 ] m.m[8 ] m.m[12] ] [ v.x ] [ m.m[1 ] m.m[5 ] m.m[9 ] m.m[13] ] [ v.y ] [ m.m[2 ] m.m[6 ] m.m[10] m.m[14] ] * [ v.z ] -[ m.m[3 ] m.m[7 ] m.m[11] m.m[15] ] [ 1 ] \endverbatim +[ m.m[3 ] m.m[7 ] m.m[11] m.m[15] ] [ 1 ] +\endverbatim The result, a 4x1 vector is then converted to 3x1 by dividing x,y,z coords by the fourth coord (w). */ @@ -434,6 +438,4 @@ inline Math::Vector MatrixVectorMultiply(const Math::Matrix &m, const Math::Vect return Math::Vector(x, y, z); } -/* @} */ // end of group - }; // namespace Math diff --git a/src/math/point.h b/src/math/point.h index ea20db9..ecf896f 100644 --- a/src/math/point.h +++ b/src/math/point.h @@ -14,8 +14,9 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -/** @defgroup MathPointModule math/point.h - Contains the Point struct and related functions. +/** + * \file math/point.h + * \brief Point struct and related functions */ #pragma once @@ -31,8 +32,6 @@ namespace Math { -/* @{ */ // start of group - /** \struct Point math/point.h \brief 2D point @@ -188,6 +187,4 @@ inline float Distance(const Point &a, const Point &b) return sqrtf((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)); } -/* @} */ // end of group - }; // namespace Math diff --git a/src/math/vector.h b/src/math/vector.h index 147869f..4378e75 100644 --- a/src/math/vector.h +++ b/src/math/vector.h @@ -14,8 +14,9 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -/** @defgroup MathVectorModule math/vector.h - Contains the Vector struct and related functions. +/** + * \file math/vector.h + * \brief Vector struct and related functions */ #pragma once @@ -31,8 +32,6 @@ namespace Math { -/* @{ */ // start of group - /** \struct Vector math/vector.h \brief 3D (3x1) vector @@ -263,6 +262,4 @@ inline float Distance(const Math::Vector &a, const Math::Vector &b) (a.z-b.z)*(a.z-b.z) ); } -/* @} */ // end of group - }; // namespace Math diff --git a/src/object/README.txt b/src/object/README.txt index f4c25d0..f3bad23 100644 --- a/src/object/README.txt +++ b/src/object/README.txt @@ -1,3 +1,7 @@ -src/object - -Contains modules of robots and buildings. +/** + * \dir object + * \brief Game engine + * + * Contains the main class of game engine - CRobotMain and the various in-game objects: + * CObject and related auto, motion and task subclasses. + */ \ No newline at end of file diff --git a/src/physics/README.txt b/src/physics/README.txt index 0003956..4ad5989 100644 --- a/src/physics/README.txt +++ b/src/physics/README.txt @@ -1,3 +1,4 @@ -src/physics - -Contains the physics module. +/** + * \dir physics + * \brief Physics engine + */ \ No newline at end of file diff --git a/src/sound/README.txt b/src/sound/README.txt index d6ac0bd..fa7bbad 100644 --- a/src/sound/README.txt +++ b/src/sound/README.txt @@ -1,3 +1,4 @@ -src/sound - -Contains the sound module - for playing sounds and music. +/** + * \dir sound + * \brief Sound module - playing sounds and music + */ \ No newline at end of file diff --git a/src/ui/README.txt b/src/ui/README.txt index 4ffd8ec..9814ef0 100644 --- a/src/ui/README.txt +++ b/src/ui/README.txt @@ -1,3 +1,4 @@ -src/ui - -Contains modules responsible for displaying the user interface controls (from game menus and HUD). +/** + * \dir ui + * \brief 2D user interface controls + */ \ No newline at end of file -- cgit v1.2.3-1-g7c22 From b4b74c30e9aa93ae736db73df5cb0c5d508ec6ed Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sun, 12 Aug 2012 10:45:04 +0200 Subject: Fixes & testing in CEngine - fixed bugs in settings modes, etc. - some additions and minor refactoring --- src/app/app.cpp | 19 ++- src/app/app.h | 3 + src/graphics/core/device.h | 7 +- src/graphics/engine/cloud.cpp | 5 +- src/graphics/engine/engine.cpp | 358 +++++++++++++++++++++++++++++---------- src/graphics/engine/engine.h | 35 +++- src/graphics/engine/text.cpp | 6 +- src/graphics/engine/water.cpp | 5 +- src/graphics/opengl/gldevice.cpp | 19 ++- src/graphics/opengl/gldevice.h | 2 + 10 files changed, 332 insertions(+), 127 deletions(-) (limited to 'src') diff --git a/src/app/app.cpp b/src/app/app.cpp index 4f7120d..a0518db 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -215,8 +215,7 @@ bool CApplication::Create() if (! m_device->Create() ) { SystemDialog( SDT_ERROR, "COLOBT - Fatal Error", - std::string("Error in CDevice::Create() :\n") + - std::string(m_device->GetError()) ); + std::string("Error in CDevice::Create()") ); m_exitCode = 1; return false; } @@ -229,8 +228,7 @@ bool CApplication::Create() if (! m_engine->Create() ) { SystemDialog( SDT_ERROR, "COLOBT - Fatal Error", - std::string("Error in CEngine::Init() :\n") + - std::string(m_engine->GetError()) ); + std::string("Error in CEngine::Init()") ); m_exitCode = 1; return false; } @@ -498,6 +496,14 @@ void CApplication::UpdateJoystick() } } +void CApplication::UpdateMouse() +{ + Math::IntPoint pos; + SDL_GetMouseState(&pos.x, &pos.y); + m_systemMousePos = m_engine->WindowToInterfaceCoords(pos); + m_engine->SetMousePos(m_systemMousePos); +} + int CApplication::Run() { m_active = true; @@ -572,6 +578,10 @@ int CApplication::Run() m_robotMain->ProcessEvent(event); */ } + /* Update mouse position explicitly right before rendering + * because mouse events are usually way behind */ + UpdateMouse(); + // Update game and render a frame during idle time (no messages are waiting) Render(); } @@ -857,7 +867,6 @@ bool CApplication::GetSystemMouseVisibile() return result == SDL_ENABLE; } - void CApplication::SetSystemMousePos(Math::Point pos) { Math::IntPoint windowPos = m_engine->InterfaceToWindowCoords(pos); diff --git a/src/app/app.h b/src/app/app.h index bfa8c25..0cfaad2 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -164,6 +164,9 @@ public: //! Polls the state of joystick axes and buttons void UpdateJoystick(); + //! Updates the mouse position explicitly + void UpdateMouse(); + void FlushPressKey(); void ResetKey(); void SetKey(int keyRank, int option, int key); diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h index a829c81..a3d0208 100644 --- a/src/graphics/core/device.h +++ b/src/graphics/core/device.h @@ -153,9 +153,9 @@ enum FogMode \brief Culling mode for polygons */ enum CullMode { - //! Cull clockwise side + //! Cull clockwise faces CULL_CW, - //! Cull counter-clockwise side + //! Cull counter-clockwise faces CULL_CCW }; @@ -278,6 +278,9 @@ class CDevice public: virtual ~CDevice() {} + //! Provides a hook to debug graphics code (implementation-specific) + virtual void DebugHook() = 0; + //! Initializes the device, setting the initial state virtual bool Create() = 0; //! Destroys the device, releasing every acquired resource diff --git a/src/graphics/engine/cloud.cpp b/src/graphics/engine/cloud.cpp index 71dd969..f3c0002 100644 --- a/src/graphics/engine/cloud.cpp +++ b/src/graphics/engine/cloud.cpp @@ -231,10 +231,7 @@ void Gfx::CCloud::Create(const std::string& fileName, m_fileName = fileName; if (! m_fileName.empty()) - { - m_engine->LoadTexture(m_fileName, 0); - m_engine->LoadTexture(m_fileName, 1); - } + m_engine->LoadTexture(m_fileName); if (m_terrain == nullptr) m_terrain = static_cast(m_iMan->SearchInstance(CLASS_TERRAIN)); diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 0461636..644ecaf 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -115,6 +115,7 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_overColor = 0; m_overMode = ENG_RSTATE_TCOLOR_BLACK; m_highlightRank[0] = -1; // empty list + m_highlightTime = 0.0f; m_eyePt = Math::Vector(0.0f, 0.0f, 0.0f); m_lookatPt = Math::Vector(0.0f, 0.0f, 1.0f); m_drawWorld = true; @@ -133,7 +134,7 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_lensMode = true; m_waterMode = true; m_skyMode = true; - m_backForce = true; + m_backForce = false; // TODO: change to true? m_planetMode = true; m_lightMode = true; m_editIndentMode = true; @@ -147,22 +148,22 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_updateGeometry = false; - m_mice[Gfx::ENG_MOUSE_NORM] = Gfx::EngineMouse( 0, 1, 32, Gfx::ENG_RSTATE_TCOLOR_WHITE, Gfx::ENG_RSTATE_TCOLOR_BLACK, Math::Point( 1.0f, 1.0f)); - m_mice[Gfx::ENG_MOUSE_WAIT] = Gfx::EngineMouse( 2, 3, 33, Gfx::ENG_RSTATE_TCOLOR_WHITE, Gfx::ENG_RSTATE_TCOLOR_BLACK, Math::Point( 8.0f, 12.0f)); - m_mice[Gfx::ENG_MOUSE_HAND] = Gfx::EngineMouse( 4, 5, 34, Gfx::ENG_RSTATE_TCOLOR_WHITE, Gfx::ENG_RSTATE_TCOLOR_BLACK, Math::Point( 7.0f, 2.0f)); - m_mice[Gfx::ENG_MOUSE_NO] = Gfx::EngineMouse( 6, 7, 35, Gfx::ENG_RSTATE_TCOLOR_WHITE, Gfx::ENG_RSTATE_TCOLOR_BLACK, Math::Point(10.0f, 10.0f)); - m_mice[Gfx::ENG_MOUSE_EDIT] = Gfx::EngineMouse( 8, 9, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 6.0f, 10.0f)); - m_mice[Gfx::ENG_MOUSE_CROSS] = Gfx::EngineMouse(10, 11, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point(10.0f, 10.0f)); - m_mice[Gfx::ENG_MOUSE_MOVEV] = Gfx::EngineMouse(12, 13, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 5.0f, 11.0f)); - m_mice[Gfx::ENG_MOUSE_MOVEH] = Gfx::EngineMouse(14, 15, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point(11.0f, 5.0f)); - m_mice[Gfx::ENG_MOUSE_MOVED] = Gfx::EngineMouse(16, 17, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 9.0f, 9.0f)); - m_mice[Gfx::ENG_MOUSE_MOVEI] = Gfx::EngineMouse(18, 19, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 9.0f, 9.0f)); - m_mice[Gfx::ENG_MOUSE_MOVE] = Gfx::EngineMouse(20, 21, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point(11.0f, 11.0f)); - m_mice[Gfx::ENG_MOUSE_TARGET] = Gfx::EngineMouse(22, 23, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point(15.0f, 15.0f)); - m_mice[Gfx::ENG_MOUSE_SCROLLL] = Gfx::EngineMouse(24, 25, 43, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 2.0f, 9.0f)); - m_mice[Gfx::ENG_MOUSE_SCROLLR] = Gfx::EngineMouse(26, 27, 44, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point(17.0f, 9.0f)); - m_mice[Gfx::ENG_MOUSE_SCROLLU] = Gfx::EngineMouse(28, 29, 45, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 9.0f, 2.0f)); - m_mice[Gfx::ENG_MOUSE_SCROLLD] = Gfx::EngineMouse(30, 31, 46, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 9.0f, 17.0f)); + m_mice[Gfx::ENG_MOUSE_NORM] = Gfx::EngineMouse( 0, 1, 32, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 1.0f, 1.0f)); + m_mice[Gfx::ENG_MOUSE_WAIT] = Gfx::EngineMouse( 2, 3, 33, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 8.0f, 12.0f)); + m_mice[Gfx::ENG_MOUSE_HAND] = Gfx::EngineMouse( 4, 5, 34, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 7.0f, 2.0f)); + m_mice[Gfx::ENG_MOUSE_NO] = Gfx::EngineMouse( 6, 7, 35, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Math::Point(10.0f, 10.0f)); + m_mice[Gfx::ENG_MOUSE_EDIT] = Gfx::EngineMouse( 8, 9, -1, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point( 6.0f, 10.0f)); + m_mice[Gfx::ENG_MOUSE_CROSS] = Gfx::EngineMouse(10, 11, -1, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point(10.0f, 10.0f)); + m_mice[Gfx::ENG_MOUSE_MOVEV] = Gfx::EngineMouse(12, 13, -1, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point( 5.0f, 11.0f)); + m_mice[Gfx::ENG_MOUSE_MOVEH] = Gfx::EngineMouse(14, 15, -1, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point(11.0f, 5.0f)); + m_mice[Gfx::ENG_MOUSE_MOVED] = Gfx::EngineMouse(16, 17, -1, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point( 9.0f, 9.0f)); + m_mice[Gfx::ENG_MOUSE_MOVEI] = Gfx::EngineMouse(18, 19, -1, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point( 9.0f, 9.0f)); + m_mice[Gfx::ENG_MOUSE_MOVE] = Gfx::EngineMouse(20, 21, -1, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point(11.0f, 11.0f)); + m_mice[Gfx::ENG_MOUSE_TARGET] = Gfx::EngineMouse(22, 23, -1, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point(15.0f, 15.0f)); + m_mice[Gfx::ENG_MOUSE_SCROLLL] = Gfx::EngineMouse(24, 25, 43, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point( 2.0f, 9.0f)); + m_mice[Gfx::ENG_MOUSE_SCROLLR] = Gfx::EngineMouse(26, 27, 44, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point(17.0f, 9.0f)); + m_mice[Gfx::ENG_MOUSE_SCROLLU] = Gfx::EngineMouse(28, 29, 45, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point( 9.0f, 2.0f)); + m_mice[Gfx::ENG_MOUSE_SCROLLD] = Gfx::EngineMouse(30, 31, 46, Gfx::ENG_RSTATE_TTEXTURE_BLACK, Gfx::ENG_RSTATE_TTEXTURE_WHITE, Math::Point( 9.0f, 17.0f)); m_mouseSize = Math::Point(0.04f, 0.04f * (800.0f / 600.0f)); m_mousePos = Math::Point(0.5f, 0.5f); @@ -170,7 +171,7 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_mouseVisible = false; m_texPath = "textures/"; - m_defaultTexParams.format = Gfx::TEX_IMG_RGBA; + m_defaultTexParams.format = Gfx::TEX_IMG_RGB; m_defaultTexParams.mipmap = true; m_defaultTexParams.minFilter = Gfx::TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR; m_defaultTexParams.magFilter = Gfx::TEX_MAG_FILTER_LINEAR; @@ -190,11 +191,6 @@ Gfx::CEngine::~CEngine() m_terrain = nullptr; } -std::string Gfx::CEngine::GetError() -{ - return m_error; -} - void Gfx::CEngine::SetDevice(Gfx::CDevice *device) { m_device = device; @@ -230,12 +226,12 @@ bool Gfx::CEngine::Create() m_text->SetDevice(m_device); if (! m_text->Create()) { - m_error = std::string("Error creating CText: ") + m_text->GetError(); + std::string error = m_text->GetError(); + GetLogger()->Error("Error creating CText: %s\n", error.c_str()); return false; } m_device->SetClearColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); m_device->SetShadeModel(Gfx::SHADE_SMOOTH); m_device->SetFillMode(Gfx::FILL_FILL); @@ -289,11 +285,7 @@ void Gfx::CEngine::ResetAfterDeviceChanged() bool Gfx::CEngine::ProcessEvent(const Event &event) { - if (event.type == EVENT_MOUSE_MOVE) - { - m_mousePos = event.mouseMove.pos; - } - else if (event.type == EVENT_KEY_DOWN) + if (event.type == EVENT_KEY_DOWN) { // !! Debug, to be removed later !! @@ -307,6 +299,37 @@ bool Gfx::CEngine::ProcessEvent(const Event &event) int index = static_cast(m_mouseType); m_mouseType = static_cast( (index + 1) % Gfx::ENG_MOUSE_COUNT ); } + else if (event.key.key == KEY(F3)) + { + m_backgroundQuarter = !m_backgroundQuarter; + if (m_backgroundQuarter) + { + m_backgroundFull = true; + m_backgroundName = "geneda.png"; + } + else + { + m_backgroundFull = false; + m_backgroundName = ""; + } + } + else if (event.key.key == KEY(F4)) + { + m_backForce = !m_backForce; + if (m_backForce) + { + m_backgroundColorDown = Gfx::Color(0.2f, 0.2f, 0.2f); + m_backgroundColorUp = Gfx::Color(0.8f, 0.8f, 0.8f); + } + else + { + m_backgroundColorDown = m_backgroundColorUp = Gfx::Color(0.0f, 0.0f, 0.0f); + } + } + } + else if (event.type == EVENT_FRAME) + { + m_highlightTime += event.rTime; } // By default, pass on all events @@ -954,10 +977,28 @@ void Gfx::CEngine::SetState(int state, const Gfx::Color& color) m_device->SetTextureEnabled(0, true); m_device->SetTextureStageParams(0, params); } + else if (state & Gfx::ENG_RSTATE_OPAQUE_TEXTURE) // opaque texture ? + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, false); + + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); + m_device->SetTextureEnabled(0, true); + m_device->SetTextureStageParams(0, Gfx::TextureStageParams()); // default operation + } + else if (state & Gfx::ENG_RSTATE_OPAQUE_COLOR) // opaque color ? + { + m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); + m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); + m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); + m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, false); + m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); + } else if (state & Gfx::ENG_RSTATE_TEXT) // font rendering? { m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); // TODO: depth test setting elsewhere! m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false); @@ -1091,6 +1132,7 @@ void Gfx::CEngine::SetState(int state, const Gfx::Color& color) void Gfx::CEngine::SetMaterial(const Gfx::Material &mat) { + m_lastMaterial = mat; m_device->SetMaterial(mat); } @@ -1112,12 +1154,18 @@ void Gfx::CEngine::SetViewParams(const Math::Vector& eyePt, const Math::Vector& Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName, const Gfx::TextureCreateParams ¶ms) { + if (m_texBlacklist.find(texName) != m_texBlacklist.end()) + return Gfx::Texture(); // invalid texture + + // TODO: detect alpha channel? + CImage img; if (! img.Load(m_app->GetDataFilePath(m_texPath, texName))) { - std::stringstream str; - str << "Couldn't load texture '" << texName << "': " << img.GetError(); - m_error = str.str(); + std::string error = img.GetError(); + GetLogger()->Error("Couldn't load texture '%s': %s\n", texName.c_str(), error.c_str()); + GetLogger()->Error("Blacklisting texture '%s'\n", texName.c_str()); + m_texBlacklist.insert(texName); return Gfx::Texture(); // invalid texture } @@ -1125,9 +1173,10 @@ Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName, const Gfx:: if (! result.valid) { - std::stringstream str; - str << "Couldn't load texture '" << texName << "': " << m_device->GetError(); - m_error = str.str(); + std::string error = m_device->GetError(); + GetLogger()->Error("Couldn't load texture '%s': %s\n", texName.c_str(), error.c_str()); + GetLogger()->Error("Blacklisting texture '%s'\n", texName.c_str()); + m_texBlacklist.insert(texName); return result; } @@ -1156,29 +1205,115 @@ void Gfx::CEngine::DestroyTexture(const std::string &texName) m_texNameMap.erase(it); } -bool Gfx::CEngine::LoadTexture(const std::string& name, int stage) +bool Gfx::CEngine::LoadTexture(const std::string& name) { + if (m_texBlacklist.find(name) != m_texBlacklist.end()) + return false; + std::map::iterator it = m_texNameMap.find(name); if (it != m_texNameMap.end()) - { - m_device->SetTexture(stage, (*it).second); return true; + + Gfx::Texture tex = CreateTexture(name); + return tex.valid; +} + +// TODO: create separate variables for 4 quarter names +void QuarterName(std::string& buffer, const std::string& name, int quarter) +{ + size_t pos = name.find('.'); + if (pos == std::string::npos) + { + buffer = name; + return; } - // TODO if not present... - return false; + buffer = name.substr(0, pos) + std::string(1, static_cast('a' + quarter)) + name.substr(pos); } bool Gfx::CEngine::LoadAllTextures() { - // TODO! - return true; + LoadTexture("text.png"); + LoadTexture("mouse.png"); + LoadTexture("button1.png"); + LoadTexture("button2.png"); + LoadTexture("button3.png"); + LoadTexture("effect00.png"); + LoadTexture("effect01.png"); + LoadTexture("effect02.png"); + LoadTexture("map.png"); + + if (! m_backgroundName.empty()) + { + if (m_backgroundQuarter) // image into 4 pieces? + { + for (int i = 0; i < 4; i++) + { + std::string name; + QuarterName(name, m_backgroundName, i); + LoadTexture(name); + } + } + else + { + LoadTexture(m_backgroundName); + } + } + + if (! m_foregroundName.empty()) + LoadTexture(m_foregroundName); + + m_planet->LoadTexture(); + + bool ok = true; + + /* TODO + D3DObjLevel1* p1; + D3DObjLevel2* p2; + int l1; + p1 = m_objectPointer; + for ( l1=0 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + + if ( p2 == 0 || p2->texName1[0] != 0 ) + { + if ( !LoadTexture(p2->texName1) ) ok = false; + } + + if ( p2 == 0 || p2->texName2[0] != 0 ) + { + if ( !LoadTexture(p2->texName2) ) ok = false; + } + }*/ + + return ok; } bool Gfx::CEngine::SetTexture(const std::string& name, int stage) { - // TODO! - return true; + auto it = m_texNameMap.find(name); + if (it != m_texNameMap.end()) + { + m_device->SetTexture(stage, (*it).second); + return true; + } + + if (! LoadTexture(name)) + { + m_device->SetTexture(stage, 0); // invalid texture + return false; + } + + it = m_texNameMap.find(name); + if (it != m_texNameMap.end()) + { + m_device->SetTexture(stage, (*it).second); + return true; + } + + m_device->SetTexture(stage, 0); // invalid texture + return false; // should not happen normally } void Gfx::CEngine::SetLimitLOD(int rank, float limit) @@ -1364,7 +1499,6 @@ float Gfx::CEngine::GetFogStart(int rank) return m_fogStart[rank]; } - void Gfx::CEngine::SetBackground(const std::string& name, Gfx::Color up, Gfx::Color down, Gfx::Color cloudUp, Gfx::Color cloudDown, bool full, bool quarter) @@ -1391,12 +1525,12 @@ void Gfx::CEngine::GetBackground(std::string& name, Gfx::Color& up, Gfx::Color& quarter = m_backgroundQuarter; } -void Gfx::CEngine::SetForegroundImageName(const std::string& name) +void Gfx::CEngine::SetForegroundName(const std::string& name) { - if (! m_foregroundImageName.empty()) - DestroyTexture(m_foregroundImageName); + if (! m_foregroundName.empty()) + DestroyTexture(m_foregroundName); - m_foregroundImageName = name; + m_foregroundName = name; } void Gfx::CEngine::SetOverFront(bool front) @@ -1714,14 +1848,11 @@ void Gfx::CEngine::Render() // Begin the scene m_device->BeginScene(); - if (m_drawWorld) Draw3DScene(); - DrawInterface(); - // End the scene m_device->EndScene(); } @@ -2113,7 +2244,8 @@ void Gfx::CEngine::DrawInterface() void Gfx::CEngine::UpdateGroundSpotTextures() { - // TODO! + // TODO the original code modifying the textures is very complex, so stub for now + GetLogger()->Info("CEngine::UpdateGroundSpotTextures(): stub!\n"); } void Gfx::CEngine::DrawShadow() @@ -2131,7 +2263,7 @@ void Gfx::CEngine::DrawShadow() material.ambient = Gfx::Color(0.5f, 0.5f, 0.5f); SetMaterial(material); - // TODO: wtf? + // TODO: create a separate texture SetTexture("text.png"); Math::Point ts, ti; @@ -2310,6 +2442,7 @@ void Gfx::CEngine::DrawShadow() m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true); } +// STATUS: TESTED, VERIFIED void Gfx::CEngine::DrawBackground() { if (m_skyMode && m_cloud->GetLevel() != 0.0f) // clouds ? @@ -2323,12 +2456,13 @@ void Gfx::CEngine::DrawBackground() DrawBackgroundGradient(m_backgroundColorUp, m_backgroundColorDown); } - if (m_backForce || (m_skyMode && m_backgroundName[0] != 0) ) + if (m_backForce || (m_skyMode && !m_backgroundName.empty()) ) { DrawBackgroundImage(); // image } } +// STATUS: TESTED void Gfx::CEngine::DrawBackgroundGradient(const Gfx::Color& up, const Gfx::Color& down) { Math::Point p1(0.0f, 0.5f); @@ -2341,12 +2475,7 @@ void Gfx::CEngine::DrawBackgroundGradient(const Gfx::Color& up, const Gfx::Color Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f) }; - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); - - SetState(Gfx::ENG_RSTATE_NORMAL); + SetState(Gfx::ENG_RSTATE_OPAQUE_COLOR); m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); @@ -2364,6 +2493,7 @@ void Gfx::CEngine::DrawBackgroundGradient(const Gfx::Color& up, const Gfx::Color AddStatisticTriangle(2); } +// Status: PART_TESTED void Gfx::CEngine::DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, const std::string& name) { Math::Vector n = Math::Vector(0.0f, 0.0f, -1.0f); // normal @@ -2399,12 +2529,8 @@ void Gfx::CEngine::DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, co v2 = v1+h; } - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - SetTexture(name); - SetState(Gfx::ENG_RSTATE_WRAP); + SetState(Gfx::ENG_RSTATE_OPAQUE_TEXTURE | Gfx::ENG_RSTATE_WRAP); m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); @@ -2422,18 +2548,7 @@ void Gfx::CEngine::DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, co AddStatisticTriangle(2); } -void QuarterName(std::string& buffer, const std::string& name, int quarter) -{ - size_t pos = name.find('.'); - if (pos == std::string::npos) - { - buffer = name; - return; - } - - buffer = name.substr(0, pos) + std::string(1, static_cast('a' + quarter)) + name.substr(pos); -} - +// Status: TESTED, VERIFIED void Gfx::CEngine::DrawBackgroundImage() { Math::Point p1, p2; @@ -2494,9 +2609,10 @@ void Gfx::CEngine::DrawPlanet() m_planet->Draw(); // draws the planets } +// Status: PART_TESTED void Gfx::CEngine::DrawForegroundImage() { - if (m_foregroundImageName.empty()) return; + if (m_foregroundName.empty()) return; Math::Vector n = Math::Vector(0.0f, 0.0f, -1.0f); // normal @@ -2518,11 +2634,7 @@ void Gfx::CEngine::DrawForegroundImage() Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(u2, v1)) }; - m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false ); - m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); - - SetTexture(m_foregroundImageName); + SetTexture(m_foregroundName); SetState(Gfx::ENG_RSTATE_CLAMP | Gfx::ENG_RSTATE_TTEXTURE_BLACK); m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); @@ -2533,6 +2645,7 @@ void Gfx::CEngine::DrawForegroundImage() AddStatisticTriangle(2); } +// Status: PART_TESTED void Gfx::CEngine::DrawOverColor() { if (! m_stateColor) return; @@ -2551,29 +2664,31 @@ void Gfx::CEngine::DrawOverColor() Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f) }; + SetState(m_overMode); + + // TODO: set also with m_overMode ? m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false); m_device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false); m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false); m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, false); - SetState(m_overMode); - m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface); m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface); m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface); Gfx::VertexCol vertex[4] = { - Gfx::VertexCol(Math::Vector(p1.x, p1.y, 0.0f), color[1],color[2]), - Gfx::VertexCol(Math::Vector(p1.x, p2.y, 0.0f), color[0],color[2]), - Gfx::VertexCol(Math::Vector(p2.x, p1.y, 0.0f), color[1],color[2]), - Gfx::VertexCol(Math::Vector(p2.x, p2.y, 0.0f), color[0],color[2]) + Gfx::VertexCol(Math::Vector(p1.x, p1.y, 0.0f), color[1], color[2]), + Gfx::VertexCol(Math::Vector(p1.x, p2.y, 0.0f), color[0], color[2]), + Gfx::VertexCol(Math::Vector(p2.x, p1.y, 0.0f), color[1], color[2]), + Gfx::VertexCol(Math::Vector(p2.x, p2.y, 0.0f), color[0], color[2]) }; m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4); AddStatisticTriangle(2); } +// Status: TESTED, VERIFIED void Gfx::CEngine::DrawHighlight() { Math::Point min, max; @@ -2609,9 +2724,63 @@ void Gfx::CEngine::DrawHighlight() m_highlight = true; } - // TODO: draw highlight! + if (! m_highlight) + return; + + Math::Point p1 = m_highlightP1; + Math::Point p2 = m_highlightP2; + + int nbOut = 0; + if (p1.x < 0.0f || p1.x > 1.0f) nbOut++; + if (p1.y < 0.0f || p1.y > 1.0f) nbOut++; + if (p2.x < 0.0f || p2.x > 1.0f) nbOut++; + if (p2.y < 0.0f || p2.y > 1.0f) nbOut++; + if (nbOut > 2) + return; + + SetState(Gfx::ENG_RSTATE_OPAQUE_COLOR); + + float d = 0.5f+sinf(m_highlightTime*6.0f)*0.5f; + d *= (p2.x-p1.x)*0.1f; + p1.x += d; + p1.y += d; + p2.x -= d; + p2.y -= d; + + Gfx::Color color(1.0f, 1.0f, 0.0f); // yellow + + Gfx::VertexCol line[3] = + { + Gfx::VertexCol(Math::Vector(), color), + Gfx::VertexCol(Math::Vector(), color), + Gfx::VertexCol(Math::Vector(), color) + }; + + float dx = (p2.x - p1.x) / 5.0f; + float dy = (p2.y - p1.y) / 5.0f; + + line[0].coord = Math::Vector(p1.x, p1.y + dy, 0.0f); + line[1].coord = Math::Vector(p1.x, p1.y, 0.0f); + line[2].coord = Math::Vector(p1.x + dx, p1.y, 0.0f); + m_device->DrawPrimitive(Gfx::PRIMITIVE_LINE_STRIP, line, 3); + + line[0].coord = Math::Vector(p2.x - dx, p1.y, 0.0f); + line[1].coord = Math::Vector(p2.x, p1.y, 0.0f); + line[2].coord = Math::Vector(p2.x, p1.y + dy, 0.0f); + m_device->DrawPrimitive(Gfx::PRIMITIVE_LINE_STRIP, line, 3); + + line[0].coord = Math::Vector(p2.x, p2.y - dy, 0.0f); + line[1].coord = Math::Vector(p2.x, p2.y, 0.0f); + line[2].coord = Math::Vector(p2.x - dx, p2.y, 0.0f); + m_device->DrawPrimitive(Gfx::PRIMITIVE_LINE_STRIP, line, 3); + + line[0].coord = Math::Vector(p1.x + dx, p2.y, 0.0f); + line[1].coord = Math::Vector(p1.x, p2.y, 0.0f); + line[2].coord = Math::Vector(p1.x, p2.y - dy, 0.0f); + m_device->DrawPrimitive(Gfx::PRIMITIVE_LINE_STRIP, line, 3); } +// Status: TESTED, VERIFIED void Gfx::CEngine::DrawMouse() { if (! m_mouseVisible) @@ -2647,6 +2816,7 @@ void Gfx::CEngine::DrawMouse() DrawMouseSprite(pos, m_mouseSize, m_mice[index].icon2); } +// Status: TESTED, VERIFIED void Gfx::CEngine::DrawMouseSprite(Math::Point pos, Math::Point size, int icon) { if (icon == -1) @@ -2671,8 +2841,8 @@ void Gfx::CEngine::DrawMouseSprite(Math::Point pos, Math::Point size, int icon) Gfx::Vertex vertex[4] = { Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), normal, Math::Point(u1, v2)), - Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), normal, Math::Point(u2, v2)), Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), normal, Math::Point(u1, v1)), + Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), normal, Math::Point(u2, v2)), Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), normal, Math::Point(u2, v1)) }; diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index c7ff084..5a64e4e 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -37,6 +37,7 @@ #include #include #include +#include class CApplication; @@ -78,7 +79,7 @@ struct EngineTriangle Gfx::VertexTex2 triangle[3]; //! Material Gfx::Material material; - //! Render state (TODO: ?) + //! Render state int state; //! 1st texture Gfx::Texture tex1; @@ -425,7 +426,11 @@ enum EngineRenderState //! The transparent color (white = no) ENG_RSTATE_TCOLOR_WHITE = (1<<17), //! Mode for rendering text - ENG_RSTATE_TEXT = (1<<18) + ENG_RSTATE_TEXT = (1<<18), + //! Only opaque texture, no blending, etc. + ENG_RSTATE_OPAQUE_TEXTURE = (1<<19), + //! Only opaque color, no texture, blending, etc. + ENG_RSTATE_OPAQUE_COLOR = (1<<20) }; @@ -532,9 +537,6 @@ public: CEngine(CInstanceManager* iMan, CApplication* app); ~CEngine(); - //! Returns the last error encountered - std::string GetError(); - //! Sets the device to be used void SetDevice(Gfx::CDevice* device); //! Returns the current device @@ -715,12 +717,21 @@ public: void SetViewParams(const Math::Vector& eyePt, const Math::Vector& lookatPt, const Math::Vector& upVec, float eyeDistance); + //! Creates texture with the specified params Gfx::Texture CreateTexture(const std::string& texName, const Gfx::TextureCreateParams& params); + //! Creates texture Gfx::Texture CreateTexture(const std::string& texName); + + //! Destroys texture, unloading it and removing from cache void DestroyTexture(const std::string& texName); - bool LoadTexture(const std::string& name, int stage = 0); + + //! Loads texture, creating it if not already present + bool LoadTexture(const std::string& name); + //! Loads all necessary textures bool LoadAllTextures(); + + //! Sets texture for given stage; if not present in cache, the texture is loaded bool SetTexture(const std::string& name, int stage = 0); //@{ @@ -831,8 +842,8 @@ public: bool& full, bool& quarter); //@} - //! Specifies the foreground image - void SetForegroundImageName(const std::string& name); + //! Specifies the name of foreground texture + void SetForegroundName(const std::string& name); //! Specifies whether to draw the foreground void SetOverFront(bool front); //! Sets the foreground overlay color @@ -1129,7 +1140,7 @@ protected: bool m_overFront; Gfx::Color m_overColor; int m_overMode; - std::string m_foregroundImageName; + std::string m_foregroundName; bool m_drawWorld; bool m_drawFront; float m_limitLOD[2]; @@ -1156,6 +1167,8 @@ protected: int m_highlightRank[100]; //! Highlight visible? bool m_highlight; + //! Time counter for highlight animation + float m_highlightTime; //@{ //! Highlight rectangle points Math::Point m_highlightP1; @@ -1171,6 +1184,10 @@ protected: std::map m_texNameMap; //! Reverse map of loaded textures (by texture) std::map m_revTexNameMap; + //! Blacklist map of textures + /** Textures on this list were not successful in first loading, + * so are disabled for subsequent load calls. */ + std::set m_texBlacklist; //! Mouse cursor definitions Gfx::EngineMouse m_mice[Gfx::ENG_MOUSE_COUNT]; diff --git a/src/graphics/engine/text.cpp b/src/graphics/engine/text.cpp index 0a57026..82abd62 100644 --- a/src/graphics/engine/text.cpp +++ b/src/graphics/engine/text.cpp @@ -649,8 +649,8 @@ void Gfx::CText::DrawHighlight(Gfx::FontHighlight hl, Math::Point pos, Math::Poi Gfx::VertexCol quad[] = { Gfx::VertexCol(Math::Vector(p1.x, p1.y, 0.0f), grad[3]), - Gfx::VertexCol(Math::Vector(p2.x, p1.y, 0.0f), grad[2]), Gfx::VertexCol(Math::Vector(p1.x, p2.y, 0.0f), grad[0]), + Gfx::VertexCol(Math::Vector(p2.x, p1.y, 0.0f), grad[2]), Gfx::VertexCol(Math::Vector(p2.x, p2.y, 0.0f), grad[1]) }; @@ -688,8 +688,6 @@ void Gfx::CText::DrawChar(Gfx::UTF8Char ch, Gfx::FontType font, float size, Math cf->cache[ch] = tex; } - m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); - Math::Point p1(pos.x, pos.y + tex.charSize.y - tex.texSize.y); Math::Point p2(pos.x + tex.texSize.x, pos.y + tex.charSize.y); @@ -698,8 +696,8 @@ void Gfx::CText::DrawChar(Gfx::UTF8Char ch, Gfx::FontType font, float size, Math Gfx::Vertex quad[4] = { Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), n, Math::Point(0.0f, 1.0f)), - Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(1.0f, 1.0f)), Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), n, Math::Point(0.0f, 0.0f)), + Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), n, Math::Point(1.0f, 1.0f)), Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), n, Math::Point(1.0f, 0.0f)) }; diff --git a/src/graphics/engine/water.cpp b/src/graphics/engine/water.cpp index 0ec52eb..8fbd1ae 100644 --- a/src/graphics/engine/water.cpp +++ b/src/graphics/engine/water.cpp @@ -519,10 +519,7 @@ void Gfx::CWater::Create(Gfx::WaterType type1, Gfx::WaterType type2, const std:: VaporFlush(); if (! m_fileName.empty()) - { - m_engine->LoadTexture(m_fileName, 0); - m_engine->LoadTexture(m_fileName, 1); - } + m_engine->LoadTexture(m_fileName); if (m_terrain == nullptr) m_terrain = static_cast(m_iMan->SearchInstance(CLASS_TERRAIN)); diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index 4c36053..caa79ee 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -73,6 +73,13 @@ Gfx::CGLDevice::~CGLDevice() { } +void Gfx::CGLDevice::DebugHook() +{ + /* This function is only called here, so it can be used + * as a breakpoint when debugging using gDEBugger */ + glColor3i(0, 0, 0); +} + std::string Gfx::CGLDevice::GetError() { return m_error; @@ -1172,17 +1179,19 @@ void Gfx::CGLDevice::GetFogParams(Gfx::FogMode &mode, Gfx::Color &color, float & void Gfx::CGLDevice::SetCullMode(Gfx::CullMode mode) { - if (mode == Gfx::CULL_CW) glCullFace(GL_CW); - else if (mode == Gfx::CULL_CCW) glCullFace(GL_CCW); + // Cull clockwise back faces, so front face is the opposite + // (assuming GL_CULL_FACE is GL_BACK) + if (mode == Gfx::CULL_CW ) glFrontFace(GL_CCW); + else if (mode == Gfx::CULL_CCW) glFrontFace(GL_CW); else assert(false); } Gfx::CullMode Gfx::CGLDevice::GetCullMode() { GLint flag = 0; - glGetIntegerv(GL_CULL_FACE, &flag); - if (flag == GL_CW) return Gfx::CULL_CW; - else if (flag == GL_CCW) return Gfx::CULL_CCW; + glGetIntegerv(GL_FRONT_FACE, &flag); + if (flag == GL_CW) return Gfx::CULL_CCW; + else if (flag == GL_CCW) return Gfx::CULL_CW; else assert(false); return Gfx::CULL_CW; } diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h index dbe9a52..3daea8a 100644 --- a/src/graphics/opengl/gldevice.h +++ b/src/graphics/opengl/gldevice.h @@ -76,6 +76,8 @@ public: CGLDevice(const Gfx::GLDeviceConfig &config); virtual ~CGLDevice(); + virtual void DebugHook(); + virtual std::string GetError(); virtual bool Create(); -- cgit v1.2.3-1-g7c22 From 5e271e550dbb88f0bbea5f46aad9f0fd1d750eb3 Mon Sep 17 00:00:00 2001 From: erihel Date: Sun, 12 Aug 2012 15:00:37 +0200 Subject: * New CPluginManager class for managing plugins based on colobot.ini * Moved sound plugin into sound dir * Minor changes in logger and profile --- src/common/event.h | 4 +- src/common/iman.h | 4 +- src/common/logger.cpp | 14 - src/common/logger.h | 3 - src/common/profile.cpp | 21 +- src/common/profile.h | 69 ++- src/common/test/CMakeLists.txt | 2 +- src/common/test/colobot.ini | 7 + src/common/test/profile_test.cpp | 8 + src/object/robotmain.cpp | 2 +- src/plugins/pluginloader.cpp | 18 + src/plugins/pluginloader.h | 8 +- src/plugins/pluginmanager.cpp | 122 ++++++ src/plugins/pluginmanager.h | 55 +++ src/plugins/sound/oalsound/CMakeLists.txt | 24 -- src/plugins/sound/oalsound/alsound.cpp | 548 ----------------------- src/plugins/sound/oalsound/alsound.h | 95 ---- src/plugins/sound/oalsound/buffer.cpp | 80 ---- src/plugins/sound/oalsound/buffer.h | 48 --- src/plugins/sound/oalsound/channel.cpp | 304 ------------- src/plugins/sound/oalsound/channel.h | 99 ----- src/plugins/sound/oalsound/check.h | 39 -- src/plugins/test/CMakeLists.txt | 6 +- src/plugins/test/colobot.ini | 3 + src/plugins/test/manager_test.cpp | 24 ++ src/plugins/test/plugin_test.cpp | 40 -- src/sound/plugins/oalsound/CMakeLists.txt | 24 ++ src/sound/plugins/oalsound/alsound.cpp | 552 ++++++++++++++++++++++++ src/sound/plugins/oalsound/alsound.h | 95 ++++ src/sound/plugins/oalsound/buffer.cpp | 80 ++++ src/sound/plugins/oalsound/buffer.h | 48 +++ src/sound/plugins/oalsound/channel.cpp | 304 +++++++++++++ src/sound/plugins/oalsound/channel.h | 99 +++++ src/sound/plugins/oalsound/check.h | 39 ++ src/sound/plugins/oalsound/test/CMakeLists.txt | 11 + src/sound/plugins/oalsound/test/plugin_test.cpp | 40 ++ 36 files changed, 1630 insertions(+), 1309 deletions(-) create mode 100644 src/plugins/pluginmanager.cpp create mode 100644 src/plugins/pluginmanager.h delete mode 100644 src/plugins/sound/oalsound/CMakeLists.txt delete mode 100644 src/plugins/sound/oalsound/alsound.cpp delete mode 100644 src/plugins/sound/oalsound/alsound.h delete mode 100644 src/plugins/sound/oalsound/buffer.cpp delete mode 100644 src/plugins/sound/oalsound/buffer.h delete mode 100644 src/plugins/sound/oalsound/channel.cpp delete mode 100644 src/plugins/sound/oalsound/channel.h delete mode 100644 src/plugins/sound/oalsound/check.h create mode 100644 src/plugins/test/colobot.ini create mode 100644 src/plugins/test/manager_test.cpp delete mode 100644 src/plugins/test/plugin_test.cpp create mode 100644 src/sound/plugins/oalsound/CMakeLists.txt create mode 100644 src/sound/plugins/oalsound/alsound.cpp create mode 100644 src/sound/plugins/oalsound/alsound.h create mode 100644 src/sound/plugins/oalsound/buffer.cpp create mode 100644 src/sound/plugins/oalsound/buffer.h create mode 100644 src/sound/plugins/oalsound/channel.cpp create mode 100644 src/sound/plugins/oalsound/channel.h create mode 100644 src/sound/plugins/oalsound/check.h create mode 100644 src/sound/plugins/oalsound/test/CMakeLists.txt create mode 100644 src/sound/plugins/oalsound/test/plugin_test.cpp (limited to 'src') diff --git a/src/common/event.h b/src/common/event.h index 0d9aa7c..54086d4 100644 --- a/src/common/event.h +++ b/src/common/event.h @@ -19,8 +19,8 @@ #pragma once -#include "common/key.h" -#include "math/point.h" +#include +#include #include diff --git a/src/common/iman.h b/src/common/iman.h index 38e5f37..89b5206 100644 --- a/src/common/iman.h +++ b/src/common/iman.h @@ -18,8 +18,8 @@ #pragma once -#include "common/singleton.h" -#include "common/misc.h" +#include +#include diff --git a/src/common/logger.cpp b/src/common/logger.cpp index a0dcca0..be73ec7 100644 --- a/src/common/logger.cpp +++ b/src/common/logger.cpp @@ -24,20 +24,6 @@ template<> CLogger* CSingleton::mInstance = nullptr; -CLogger& CLogger::GetInstance() -{ - assert(mInstance); - return *mInstance; -} - - -CLogger* CLogger::GetInstancePointer() -{ - assert(mInstance); - return mInstance; -} - - CLogger::CLogger() { mFile = NULL; diff --git a/src/common/logger.h b/src/common/logger.h index 2d0ab3e..4febff0 100644 --- a/src/common/logger.h +++ b/src/common/logger.h @@ -91,9 +91,6 @@ class CLogger : public CSingleton */ void SetLogLevel(LogType level); - static CLogger& GetInstance(); - static CLogger* GetInstancePointer(); - private: std::string mFilename; FILE *mFile; diff --git a/src/common/profile.cpp b/src/common/profile.cpp index 467e991..29a68e1 100644 --- a/src/common/profile.cpp +++ b/src/common/profile.cpp @@ -27,6 +27,7 @@ CProfile::CProfile() { m_ini = new CSimpleIniA(); m_ini->SetUnicode(); + m_ini->SetMultiKey(); } @@ -39,8 +40,8 @@ CProfile::~CProfile() bool CProfile::InitCurrentDirectory() { - m_ini->LoadFile("colobot.ini"); - return true; + bool result = m_ini->LoadFile("colobot.ini") == SI_OK; + return result; } @@ -86,3 +87,19 @@ bool CProfile::GetLocalProfileFloat(std::string section, std::string key, float value = m_ini->GetDoubleValue(section.c_str(), key.c_str(), 0.0d); return true; } + + +std::vector< std::string > CProfile::GetLocalProfileSection(std::string section, std::string key) +{ + std::vector< std::string > ret_list; + + CSimpleIniA::TNamesDepend values; + m_ini->GetAllValues(section.c_str(), key.c_str(), values); + values.sort(CSimpleIniA::Entry::LoadOrder()); + + for (auto item : values) { + ret_list.push_back(item.pItem); + } + + return ret_list; +} diff --git a/src/common/profile.h b/src/common/profile.h index ae67e52..0886522 100644 --- a/src/common/profile.h +++ b/src/common/profile.h @@ -19,31 +19,96 @@ #pragma once #include +#include +#include #include #include +/** + * @file common/profile.h + * @brief Class for loading profile (currently for loading ini config file) + */ + +/** +* @class CProfile +* +* @brief Class for loading profile (currently for loading ini config file) +* +*/ class CProfile : public CSingleton { public: CProfile(); ~CProfile(); + /** Loads colobot.ini from current directory + * @return return true on success + */ bool InitCurrentDirectory(); + + /** Sets string value in section under specified key + * @param std::string section + * @param std::string key + * @param std::string value + * @return return true on success + */ bool SetLocalProfileString(std::string section, std::string key, std::string value); + + /** Gets string value in section under specified key + * @param std::string section + * @param std::string key + * @param std::string& buffer + * @return return true on success + */ bool GetLocalProfileString(std::string section, std::string key, std::string& buffer); + /** Sets int value in section under specified key + * @param std::string section + * @param std::string key + * @param int value + * @return return true on success + */ bool SetLocalProfileInt(std::string section, std::string key, int value); + + /** Gets int value in section under specified key + * @param std::string section + * @param std::string key + * @param int& value + * @return return true on success + */ bool GetLocalProfileInt(std::string section, std::string key, int &value); + /** Sets float value in section under specified key + * @param std::string section + * @param std::string key + * @param float value + * @return return true on success + */ bool SetLocalProfileFloat(std::string section, std::string key, float value); + + /** Gets float value in section under specified key + * @param std::string section + * @param std::string key + * @param float& value + * @return return true on success + */ bool GetLocalProfileFloat(std::string section, std::string key, float &value); - static CProfile& GetInstance(); - static CProfile* GetInstancePointer(); + /** Gets all values in section under specified key + * @param std::string section + * @param std::string key + * @return vector of values + */ + std::vector< std::string > GetLocalProfileSection(std::string section, std::string key); private: CSimpleIniA *m_ini; }; + +//! Global function to get profile instance +inline CProfile* GetProfile() { + return CProfile::GetInstancePointer(); +} diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt index 3adca4e..d81acab 100644 --- a/src/common/test/CMakeLists.txt +++ b/src/common/test/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0 -std=c++11") include_directories("../../") include_directories("../../../") -#add_executable(image_test ../image.cpp image_test.cpp) +add_executable(image_test ../image.cpp image_test.cpp) add_executable(profile_test ../profile.cpp profile_test.cpp) add_test(profile_test ./profile_test) diff --git a/src/common/test/colobot.ini b/src/common/test/colobot.ini index c4d2162..f6a5f96 100644 --- a/src/common/test/colobot.ini +++ b/src/common/test/colobot.ini @@ -6,3 +6,10 @@ string_value=Hello world [test_int] int_value=42 + +[test_multi] +entry=1 +entry=2 +entry=3 +entry=4 +entry=5 diff --git a/src/common/test/profile_test.cpp b/src/common/test/profile_test.cpp index 3ba0fad..65e20c5 100644 --- a/src/common/test/profile_test.cpp +++ b/src/common/test/profile_test.cpp @@ -2,6 +2,7 @@ #include #include +#include using namespace std; @@ -31,5 +32,12 @@ int main() return 1; } + vector list; + list = profile.GetLocalProfileSection("test_multi", "entry"); + if (list.size() != 5) { + cout << "GetLocalProfileSection failed!" << endl; + return 1; + } + return 0; } diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp index fb68152..668be87 100644 --- a/src/object/robotmain.cpp +++ b/src/object/robotmain.cpp @@ -722,7 +722,7 @@ CRobotMain::CRobotMain(CInstanceManager* iMan) g_unit = 4.0f; m_gamerName[0] = 0; - GetLocalProfileString("Gamer", "LastName", m_gamerName, 100); + GetProfile()->GetLocalProfileString("Gamer", "LastName", m_gamerName, 100); SetGlobalGamerName(m_gamerName); ReadFreeParam(); m_dialog->SetupRecall(); diff --git a/src/plugins/pluginloader.cpp b/src/plugins/pluginloader.cpp index 337c0ce..8893b56 100644 --- a/src/plugins/pluginloader.cpp +++ b/src/plugins/pluginloader.cpp @@ -95,3 +95,21 @@ bool CPluginLoader::LoadPlugin() mLoaded = true; return true; } + + +bool CPluginLoader::SetFilename(std::string filename) +{ + bool ok = true; + if (mLoaded) + ok = UnloadPlugin(); + + if (ok) + mFilename = filename; + return ok; +} + + +std::string CPluginLoader::GetFilename() +{ + return mFilename; +} diff --git a/src/plugins/pluginloader.h b/src/plugins/pluginloader.h index d9ee041..873d30a 100644 --- a/src/plugins/pluginloader.h +++ b/src/plugins/pluginloader.h @@ -29,14 +29,16 @@ class CPluginLoader { public: - CPluginLoader(std::string filename); - + CPluginLoader(std::string); + char* GetName(); int GetVersion(); bool UnloadPlugin(); bool LoadPlugin(); bool IsLoaded(); - + bool SetFilename(std::string); + std::string GetFilename(); + private: CPluginInterface* mInterface; diff --git a/src/plugins/pluginmanager.cpp b/src/plugins/pluginmanager.cpp new file mode 100644 index 0000000..ab9d8ad --- /dev/null +++ b/src/plugins/pluginmanager.cpp @@ -0,0 +1,122 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012 Polish Portal of Colobot (PPC) +// * +// * 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/. + +// pluginmanager.cpp + + +#include "pluginmanager.h" + + +template<> CPluginManager* CSingleton::mInstance = nullptr; + + +CPluginManager::CPluginManager() +{ + lt_dlinit(); +} + + +CPluginManager::~CPluginManager() +{ + UnloadAllPlugins(); + lt_dlexit(); +} + + + +void CPluginManager::LoadFromProfile() +{ + std::vector< std::string > dirs = GetProfile()->GetLocalProfileSection("Plugins", "Path"); + std::vector< std::string > plugins = GetProfile()->GetLocalProfileSection("Plugins", "File"); + + for (std::string dir : dirs) + m_folders.insert(dir); + + for (std::string plugin : plugins) { + GetLogger()->Info("Trying to load plugin %s...\n", plugin.c_str()); + LoadPlugin(plugin); + } +} + + +bool CPluginManager::LoadPlugin(std::string filename) +{ + bool result = false; + CPluginLoader *loader = new CPluginLoader(""); + for (std::string dir : m_folders) { + loader->SetFilename(dir + "/" + filename); + result = loader->LoadPlugin(); + if (result) { + GetLogger()->Info("Plugin %s (%s) version %0.2f loaded!\n", filename.c_str(), loader->GetName(), loader->GetVersion() / 100.0f); + m_plugins.push_back(loader); + break; + } + } + return result; +} + + +bool CPluginManager::UnloadPlugin(std::string filename) +{ + std::vector::iterator it; + GetLogger()->Info("Trying to unload plugin %s...\n", filename.c_str()); + for (it = m_plugins.begin(); it != m_plugins.end(); it++) { + CPluginLoader *plugin = *it; + if (NameEndsWith(plugin->GetFilename(), filename)) { + m_plugins.erase(it); + plugin->UnloadPlugin(); + delete plugin; + return true; + } + } + return false; +} + + +bool CPluginManager::AddSearchDirectory(std::string dir) +{ + m_folders.insert(dir); + return true; +} + + +bool CPluginManager::RemoveSearchDirectory(std::string dir) +{ + m_folders.erase(dir); + return false; +} + + +bool CPluginManager::UnloadAllPlugins() +{ + for (CPluginLoader *plugin : m_plugins) { + GetLogger()->Info("Trying to unload plugin %s (%s)...\n", plugin->GetFilename().c_str(), plugin->GetName()); + plugin->UnloadPlugin(); + delete plugin; + } + m_plugins.clear(); + return true; +} + + +bool CPluginManager::NameEndsWith(std::string filename, std::string ending) +{ + if (filename.length() > ending.length()) { + std::string fileEnd = filename.substr(filename.length() - ending.length()); + return (fileEnd == ending); + } + return false; +} diff --git a/src/plugins/pluginmanager.h b/src/plugins/pluginmanager.h new file mode 100644 index 0000000..d267238 --- /dev/null +++ b/src/plugins/pluginmanager.h @@ -0,0 +1,55 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// pluginmanager.h + + +#pragma once + +#include +#include +#include + +#include +#include + +#include + +#include "pluginloader.h" + + +class CPluginManager : public CSingleton { + public: + CPluginManager(); + ~CPluginManager(); + + void LoadFromProfile(); + + bool LoadPlugin(std::string); + bool UnloadPlugin(std::string); + + bool AddSearchDirectory(std::string); + bool RemoveSearchDirectory(std::string); + + bool UnloadAllPlugins(); + + private: + bool NameEndsWith(std::string, std::string); + + std::set< std::string > m_folders; + std::vector m_plugins; +}; + diff --git a/src/plugins/sound/oalsound/CMakeLists.txt b/src/plugins/sound/oalsound/CMakeLists.txt deleted file mode 100644 index e36f3ac..0000000 --- a/src/plugins/sound/oalsound/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -set(SOURCES - alsound.cpp - buffer.cpp - channel.cpp -) - -SET (CMAKE_CXX_FLAGS "-Wall -g -std=c++0x -fPIC") - -include(FindPkgConfig) -include(FindOpenAL) -pkg_check_modules(OPENAL_LIB REQUIRED openal) - -set(OPENAL_LIBRARIES - openal - alut -) - - -include_directories(../../..) -include_directories(.) -add_library(openalsound SHARED ${SOURCES}) -target_link_libraries(openalsound ${OPENAL_LIBRARIES}) diff --git a/src/plugins/sound/oalsound/alsound.cpp b/src/plugins/sound/oalsound/alsound.cpp deleted file mode 100644 index 19da66a..0000000 --- a/src/plugins/sound/oalsound/alsound.cpp +++ /dev/null @@ -1,548 +0,0 @@ -// * This file is part of the COLOBOT source code -// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch -// * Copyright (C) 2012 Polish Portal of Colobot (PPC) -// * -// * 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/. - -// alsound.cpp - - -#include "alsound.h" - - -#define MIN(a, b) (a > b ? b : a) - - -PLUGIN_INTERFACE(ALSound) - - -char* ALSound::PluginName() -{ - return const_cast("Sound plugin using OpenAL library to play sounds."); -} - - -int ALSound::PluginVersion() -{ - return 1; -} - - -void ALSound::InstallPlugin() -{ - CInstanceManager::GetInstancePointer()->AddInstance(CLASS_SOUND, this); -} - - -void ALSound::UninstallPlugin() -{ - CInstanceManager::GetInstancePointer()->DeleteInstance(CLASS_SOUND, this); - CleanUp(); -} - - -ALSound::ALSound() -{ - mEnabled = false; - m3D = false; - mAudioVolume = MAXVOLUME; - mMute = false; -} - - -ALSound::~ALSound() -{ - CleanUp(); -} - - -void ALSound::CleanUp() -{ - if (mEnabled) { - GetLogger()->Info("Unloading files and closing device...\n"); - StopAll(); - - for (auto item : mSounds) - delete item.second; - - mEnabled = false; - alutExit(); - } -} - - -bool ALSound::Create(bool b3D) -{ - CleanUp(); - - if (mEnabled) - return true; - - GetLogger()->Info("Opening audio device...\n"); - if (!alutInit(NULL, NULL)) { - ALenum error = alutGetError(); - GetLogger()->Error("Could not open audio device! Reason: %s\n", alutGetErrorString(error)); - return false; - } - GetLogger()->Info("Done.\n"); - - mEnabled = true; - return true; -} - - -void ALSound::SetSound3D(bool bMode) -{ - // TODO stub! need to be implemented - m3D = bMode; -} - - -bool ALSound::RetSound3D() -{ - // TODO stub! need to be implemented - return true; -} - - -bool ALSound::RetSound3DCap() -{ - // TODO stub! need to be implemented - return true; -} - - -bool ALSound::RetEnable() -{ - return mEnabled; -} - - -void ALSound::SetAudioVolume(int volume) -{ - alListenerf(AL_GAIN, MIN(volume, MAXVOLUME) * 0.01f); - mAudioVolume = MIN(volume, MAXVOLUME); -} - - -int ALSound::RetAudioVolume() -{ - float volume; - if ( !mEnabled ) - return 0; - - alGetListenerf(AL_GAIN, &volume); - return volume * MAXVOLUME; -} - - -void ALSound::SetMusicVolume(int volume) -{ - // TODO stub! Add music support -} - - -int ALSound::RetMusicVolume() -{ - // TODO stub! Add music support - if ( !mEnabled ) - return 0; - - return 0; -} - - -bool ALSound::Cache(Sound sound, std::string filename) -{ - Buffer *buffer = new Buffer(); - if (buffer->LoadFromFile(filename, sound)) { - mSounds[sound] = buffer; - return true; - } - return false; -} - - -void ALSound::CacheAll() -{ - char filename[100]; - for ( int i = 1; i < 69; i++ ) - { - sprintf(filename, "high/sound%.3d.wav", i); - if ( !Cache((Sound) i, std::string(filename)) ) - { - fprintf(stderr, "Unable to load audio: %s\n", filename); - } - } -} - - -int ALSound::RetPriority(Sound sound) -{ - if ( sound == SOUND_FLYh || - sound == SOUND_FLY || - sound == SOUND_MOTORw || - sound == SOUND_MOTORt || - sound == SOUND_MOTORr || - sound == SOUND_MOTORs || - sound == SOUND_SLIDE || - sound == SOUND_ERROR ) - { - return 30; - } - - if ( sound == SOUND_CONVERT || - sound == SOUND_ENERGY || - sound == SOUND_DERRICK || - sound == SOUND_STATION || - sound == SOUND_REPAIR || - sound == SOUND_RESEARCH || - sound == SOUND_BURN || - sound == SOUND_BUILD || - sound == SOUND_TREMBLE || - sound == SOUND_NUCLEAR || - sound == SOUND_EXPLO || - sound == SOUND_EXPLOl || - sound == SOUND_EXPLOlp || - sound == SOUND_EXPLOp || - sound == SOUND_EXPLOi ) - { - return 20; - } - - if ( sound == SOUND_BLUP || - sound == SOUND_INSECTs || - sound == SOUND_INSECTa || - sound == SOUND_INSECTb || - sound == SOUND_INSECTw || - sound == SOUND_INSECTm || - sound == SOUND_PSHHH || - sound == SOUND_EGG ) - { - return 0; - } - - return 10; -} - - -bool ALSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded) -{ - int priority = RetPriority(sound); - - // Seeks a channel used which sound is stopped. - for (auto it : mChannels) { - if (it.second->IsPlaying()) - continue; - if (it.second->GetSoundType() != sound) - continue; - - it.second->SetPriority(priority); - channel = it.first; - bAlreadyLoaded = true; - return true; - } - - // just add a new channel if we dont have any - if (mChannels.size() == 0) { - Channel *chn = new Channel(); - // check if we channel ready to play music, if not report error - if (chn->IsReady()) { - chn->SetPriority(priority); - mChannels[1] = chn; - channel = 1; - bAlreadyLoaded = false; - return true; - } - delete chn; - GetLogger()->Error("Could not open channel to play sound!"); - return false; - } - - // Seeks a channel completely free. - auto it = mChannels.end(); - it--; - int i = (*it).first; - while (++i) - { - if (mChannels.find(i) == mChannels.end()) { - Channel *chn = new Channel(); - // check if we channel ready to play music, if not destroy it and seek free one - if (chn->IsReady()) { - chn->SetPriority(priority); - mChannels[1] = chn; - channel = 1; - bAlreadyLoaded = false; - return true; - } - delete chn; - GetLogger()->Warn("Could not open additional channel to play sound!"); - } - } - - int lowerOrEqual = -1; - for (auto it : mChannels) { - if (it.second->GetPriority() < priority) { - GetLogger()->Info("Sound channel with lower priority will be reused."); - channel = it.first; - return true; - } - if (it.second->GetPriority() <= priority) - lowerOrEqual = it.first; - } - - if (lowerOrEqual != -1) { - channel = lowerOrEqual; - GetLogger()->Info("Sound channel with lower or equal priority will be reused."); - return true; - } - - GetLogger()->Warn("Could not find free buffer to use.\n"); - return false; -} - - -int ALSound::Play(Sound sound, float amplitude, float frequency, bool bLoop) -{ - return Play(sound, Math::Vector(), amplitude, frequency, bLoop); -} - - -int ALSound::Play(Sound sound, Math::Vector pos, float amplitude, float frequency, bool bLoop) -{ - if (!mEnabled) - return -1; - - if (mAudioVolume <= 0.0f) - return -1; - - if (mSounds.find(sound) == mSounds.end()) { - GetLogger()->Warn("Sound %d was not loaded!\n", sound); - return -1; - } - - int channel; - bool bAlreadyLoaded; - if (!SearchFreeBuffer(sound, channel, bAlreadyLoaded)) - return -1; - if ( !bAlreadyLoaded ) { - mChannels[channel]->SetBuffer(mSounds[sound]); - } - - Position(channel, pos); - - // setting initial values - mChannels[channel]->SetStartAmplitude(amplitude); - mChannels[channel]->SetStartFrequency(frequency); - mChannels[channel]->SetChangeFrequency(1.0f); - mChannels[channel]->ResetOper(); - mChannels[channel]->AdjustFrequency(frequency); - mChannels[channel]->AdjustVolume(mAudioVolume); - mChannels[channel]->Play(); - return channel; -} - - -bool ALSound::FlushEnvelope(int channel) -{ - if (mChannels.find(channel) == mChannels.end()) { - return false; - } - - mChannels[channel]->ResetOper(); - return true; -} - - -bool ALSound::AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper) -{ - if (!mEnabled) - return false; - - if (mChannels.find(channel) == mChannels.end()) { - return false; - } - - SoundOper op; - op.finalAmplitude = amplitude; - op.finalFrequency = frequency; - op.totalTime = time; - op.nextOper = oper; - mChannels[channel]->AddOper(op); - - return false; -} - - -bool ALSound::Position(int channel, Math::Vector pos) -{ - if (!mEnabled) - return false; - - if (mChannels.find(channel) == mChannels.end()) { - return false; - } - - mChannels[channel]->SetPosition(pos); - return true; -} - - -bool ALSound::Frequency(int channel, float frequency) -{ - if (!mEnabled) - return false; - - if (mChannels.find(channel) == mChannels.end()) { - return false; - } - - mChannels[channel]->SetFrequency(frequency); - return true; -} - -bool ALSound::Stop(int channel) -{ - if (!mEnabled) - return false; - - if (mChannels.find(channel) == mChannels.end()) { - return false; - } - - mChannels[channel]->Stop(); - mChannels[channel]->ResetOper(); - - return true; -} - - -bool ALSound::StopAll() -{ - if (!mEnabled) - return false; - - for (auto channel : mChannels) { - channel.second->Stop(); - channel.second->ResetOper(); - } - - return true; -} - - -bool ALSound::MuteAll(bool bMute) -{ - if (!mEnabled) - return false; - - float volume; - mMute = bMute; - if (mMute) - volume = 0; - else - volume = mAudioVolume; - - for (auto channel : mChannels) { - channel.second->SetVolume(volume); - } - - return true; -} - - -void ALSound::FrameMove(float delta) -{ - if (!mEnabled) - return; - - float progress; - float volume, frequency; - for (auto it : mChannels) { - if (!it.second->IsPlaying()) - continue; - - if (!it.second->HasEnvelope()) - continue; - - //it.second->GetEnvelope().currentTime += delta; - SoundOper oper = it.second->GetEnvelope(); - progress = it.second->GetCurrentTime() / oper.totalTime; - progress = MIN(progress, 1.0f); - - // setting volume - volume = progress * abs(oper.finalAmplitude - it.second->GetStartAmplitude()); - it.second->AdjustVolume(volume * mAudioVolume); - - // setting frequency - frequency = progress * (oper.finalFrequency - it.second->GetStartFrequency()) * it.second->GetStartFrequency() * it.second->GetChangeFrequency(); - it.second->AdjustFrequency(frequency); - - if (it.second->GetEnvelope().totalTime <= it.second->GetCurrentTime()) { - - if (oper.nextOper == SOPER_LOOP) { - GetLogger()->Info("Replay.\n"); - it.second->SetCurrentTime(0.0f); - it.second->Play(); - } else { - GetLogger()->Info("Next.\n"); - it.second->SetStartAmplitude(oper.finalAmplitude); - it.second->SetStartFrequency(oper.finalFrequency); - it.second->PopEnvelope(); - } - } - } -} - - -void ALSound::SetListener(Math::Vector eye, Math::Vector lookat) -{ - GetLogger()->Info("Setting listener position.\n"); - float orientation[] = {lookat.x, lookat.y, lookat.z, 0.f, 1.f, 0.f}; - alListener3f(AL_POSITION, eye.x, eye.y, eye.z); - alListenerfv(AL_ORIENTATION, orientation); -} - - -bool ALSound::PlayMusic(int rank, bool bRepeat) -{ - // TODO stub! Add music support - return true; -} - - -bool ALSound::RestartMusic() -{ - // TODO stub! Add music support - return true; -} - -void ALSound::StopMusic() -{ - // TODO stub! Add music support - SuspendMusic(); -} - - -bool ALSound::IsPlayingMusic() -{ - // TODO stub! Add music support - return true; -} - - -void ALSound::SuspendMusic() -{ - // TODO stub! Add music support -} diff --git a/src/plugins/sound/oalsound/alsound.h b/src/plugins/sound/oalsound/alsound.h deleted file mode 100644 index 6d4e5b6..0000000 --- a/src/plugins/sound/oalsound/alsound.h +++ /dev/null @@ -1,95 +0,0 @@ -// * This file is part of the COLOBOT source code -// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch -// * Copyright (C) 2012, Polish Portal of Colobot (PPC) -// * -// * 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/. - -// alsound.h - -#pragma once - -#include -#include - -#include - -#include -#include -#include - -#include "buffer.h" -#include "channel.h" -#include "check.h" - - -class ALSound : public CSoundInterface -{ - public: - ALSound(); - ~ALSound(); - - bool Create(bool b3D); - void CacheAll(); - bool Cache(Sound, std::string); - - bool RetEnable(); - - void SetSound3D(bool bMode); - bool RetSound3D(); - bool RetSound3DCap(); - - void SetAudioVolume(int volume); - int RetAudioVolume(); - void SetMusicVolume(int volume); - int RetMusicVolume(); - - void SetListener(Math::Vector eye, Math::Vector lookat); - void FrameMove(float rTime); - - int Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false); - int Play(Sound sound, Math::Vector pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false); - bool FlushEnvelope(int channel); - bool AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper); - bool Position(int channel, Math::Vector pos); - bool Frequency(int channel, float frequency); - bool Stop(int channel); - bool StopAll(); - bool MuteAll(bool bMute); - - bool PlayMusic(int rank, bool bRepeat); - bool RestartMusic(); - void SuspendMusic(); - void StopMusic(); - bool IsPlayingMusic(); - - // plugin interface - char* PluginName(); - int PluginVersion(); - void InstallPlugin(); - void UninstallPlugin(); - - private: - void CleanUp(); - int RetPriority(Sound); - bool SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded); - - bool mEnabled; - bool m3D; - bool mMute; - int mAudioVolume; - ALCdevice* audioDevice; - ALCcontext* audioContext; - std::map mSounds; - std::map mChannels; -}; diff --git a/src/plugins/sound/oalsound/buffer.cpp b/src/plugins/sound/oalsound/buffer.cpp deleted file mode 100644 index 37211e9..0000000 --- a/src/plugins/sound/oalsound/buffer.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// * This file is part of the COLOBOT source code -// * Copyright (C) 2012, Polish Portal of Colobot (PPC) -// * -// * 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/. - -// buffer.cpp - -#include "buffer.h" - -Buffer::Buffer() { - mLoaded = false; - mDuration = 0; -} - - -Buffer::~Buffer() { - if (mLoaded) { - alDeleteBuffers(1, &mBuffer); - if (alCheck()) - GetLogger()->Warn("Failed to unload buffer. Code %d\n", alGetCode()); - } -} - - -bool Buffer::LoadFromFile(std::string filename, Sound sound) { - mSound = sound; - - GetLogger()->Info("Loading audio file: %s\n", filename.c_str()); - mBuffer = alutCreateBufferFromFile(filename.c_str()); - - ALenum error = alutGetError(); - if (error) { - GetLogger()->Warn("Failed to load file. Reason: %s\n", alutGetErrorString(error)); - mLoaded = false; - return false; - } - - ALint size, bits, channels, freq; - - alGetBufferi(mBuffer, AL_SIZE, &size); - alGetBufferi(mBuffer, AL_BITS, &bits); - alGetBufferi(mBuffer, AL_CHANNELS, &channels); - alGetBufferi(mBuffer, AL_FREQUENCY, &freq); - - mDuration = (ALfloat)size / channels / bits / 8 / (ALfloat)freq; - - mLoaded = true; - return true; -} - - -Sound Buffer::GetSoundType() { - return mSound; -} - - -ALuint Buffer::GetBuffer() { - return mBuffer; -} - - -bool Buffer::IsLoaded() { - return mLoaded; -} - - -float Buffer::GetDuration() { - return mDuration; -} diff --git a/src/plugins/sound/oalsound/buffer.h b/src/plugins/sound/oalsound/buffer.h deleted file mode 100644 index 6eefe72..0000000 --- a/src/plugins/sound/oalsound/buffer.h +++ /dev/null @@ -1,48 +0,0 @@ -// * This file is part of the COLOBOT source code -// * Copyright (C) 2012, Polish Portal of Colobot (PPC) -// * -// * 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/. - -// buffer.h - -#pragma once - -#include - -#include - -#include -#include - -#include "check.h" - -class Buffer -{ - public: - Buffer(); - ~Buffer(); - - bool LoadFromFile(std::string, Sound); - bool IsLoaded(); - - Sound GetSoundType(); - ALuint GetBuffer(); - float GetDuration(); - - private: - ALuint mBuffer; - Sound mSound; - bool mLoaded; - float mDuration; -}; diff --git a/src/plugins/sound/oalsound/channel.cpp b/src/plugins/sound/oalsound/channel.cpp deleted file mode 100644 index 4476dee..0000000 --- a/src/plugins/sound/oalsound/channel.cpp +++ /dev/null @@ -1,304 +0,0 @@ -// * This file is part of the COLOBOT source code -// * Copyright (C) 2012, Polish Portal of Colobot (PPC) -// * -// * 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/. - -// channel.cpp - -#include "channel.h" - - -Channel::Channel() { - alGenSources(1, &mSource); - - if (alCheck()) { - GetLogger()->Warn("Failed to create sound source. Code: %d\n", alGetCode()); - mReady = false; - } else { - mReady = true; - } - - mPriority = 0; - mBuffer = nullptr; -} - - -Channel::~Channel() { - if (mReady) { - alSourcei(mSource, AL_BUFFER, 0); - alDeleteSources(1, &mSource); - if (alCheck()) - GetLogger()->Warn("Failed to delete sound source. Code: %s\n", alGetCode()); - } -} - - -bool Channel::Play() { - if (!mReady) - return false; - - alSourcePlay(mSource); - if (alCheck()) - GetLogger()->Warn("Could not play audio sound source. Code: %s\n", alGetCode()); - return true; -} - - -bool Channel::SetPosition(Math::Vector pos) { - if (!mReady) - return false; - - alSource3f(mSource, AL_POSITION, pos.x, pos.y, pos.z); - if (alCheck()) { - GetLogger()->Warn("Could not set sound position. Code: %s\n", alGetCode()); - return false; - } - return true; -} - - -bool Channel::SetFrequency(float freq) -{ - if (!mReady) - return false; - - alSourcef(mSource, AL_PITCH, freq); - if (alCheck()) { - GetLogger()->Warn("Could not set sound pitch. Code: %s\n", alGetCode()); - return false; - } - return true; -} - - -float Channel::GetFrequency() -{ - ALfloat freq; - if (!mReady) - return 0; - - alGetSourcef(mSource, AL_PITCH, &freq); - if (alCheck()) { - GetLogger()->Warn("Could not get sound pitch. Code: %s\n", alGetCode()); - return 0; - } - - return freq; -} - - -bool Channel::SetVolume(float vol) -{ - if (!mReady || vol < 0) - return false; - - alSourcef(mSource, AL_GAIN, vol / MAXVOLUME); - if (alCheck()) { - GetLogger()->Warn("Could not set sound volume. Code: %s\n", alGetCode()); - return false; - } - return true; -} - - -float Channel::GetVolume() -{ - ALfloat vol; - if (!mReady) - return 0; - - alGetSourcef(mSource, AL_GAIN, &vol); - if (alCheck()) { - GetLogger()->Warn("Could not get sound volume. Code: %s\n", alGetCode()); - return 0; - } - - return vol * MAXVOLUME; -} - - -int Channel::GetPriority() -{ - return mPriority; -} - - -void Channel::SetPriority(int pri) -{ - mPriority = pri; -} - - -void Channel::SetStartAmplitude(float gain) -{ - mStartAmplitude = gain; -} - - -void Channel::SetStartFrequency(float freq) -{ - mStartFrequency = freq; -} - - -void Channel::SetChangeFrequency(float freq) -{ - mChangeFrequency = freq; -} - - -void Channel::SetInitFrequency(float freq) -{ - mInitFrequency = freq; -} - - -float Channel::GetStartAmplitude() -{ - return mStartAmplitude; -} - - -float Channel::GetStartFrequency() -{ - return mStartFrequency; -} - - -float Channel::GetChangeFrequency() -{ - return mChangeFrequency; -} - - -float Channel::GetInitFrequency() -{ - return mInitFrequency; -} - - -void Channel::AddOper(SoundOper oper) -{ - mOper.push_back(oper); -} - - -void Channel::ResetOper() -{ - mOper.clear(); -} - - -Sound Channel::GetSoundType() { - return mBuffer->GetSoundType(); -} - - -bool Channel::SetBuffer(Buffer *buffer) { - if (!mReady) - return false; - - assert(buffer); - mBuffer = buffer; - alSourcei(mSource, AL_BUFFER, buffer->GetBuffer()); - if (alCheck()) { - GetLogger()->Warn("Could not set sound buffer. Code: %s\n", alGetCode()); - return false; - } - mInitFrequency = GetFrequency(); - return true; -} - - -void Channel::AdjustFrequency(float freq) { - SetFrequency(freq * mInitFrequency); -} - - -void Channel::AdjustVolume(float volume) { - SetVolume(mStartAmplitude * (float) volume); -} - - -bool Channel::IsPlaying() { - ALint status; - if (!mReady) return false; - - alGetSourcei(mSource, AL_SOURCE_STATE, &status); - if (alCheck()) { - GetLogger()->Warn("Could not get sound status. Code: %s\n", alGetCode()); - return false; - } - - return status == AL_PLAYING; -} - - -bool Channel::IsReady() { - return mReady; -} - - -bool Channel::Stop() { - alSourceStop(mSource); - if (alCheck()) { - GetLogger()->Warn("Could not stop sound. Code: %s\n", alGetCode()); - return false; - } - return true; -} - - -float Channel::GetCurrentTime() -{ - ALfloat current; - alGetSourcef(mSource, AL_SEC_OFFSET, ¤t); - if (alCheck()) { - GetLogger()->Warn("Could not get source current play time. Code: %s\n", alGetCode()); - return 0.0f; - } - return current; -} - - -void Channel::SetCurrentTime(float current) -{ - alSourcef(mSource, AL_SEC_OFFSET, current); - if (alCheck()) - GetLogger()->Warn("Could not get source current play time. Code: %s\n", alGetCode()); -} - - -float Channel::GetDuration() -{ - return mBuffer->GetDuration(); -} - - -bool Channel::HasEnvelope() -{ - return mOper.size() > 0; -} - - -SoundOper& Channel::GetEnvelope() -{ - return mOper.front(); -} - - -void Channel::PopEnvelope() -{ - mOper.pop_front(); -} diff --git a/src/plugins/sound/oalsound/channel.h b/src/plugins/sound/oalsound/channel.h deleted file mode 100644 index 3099931..0000000 --- a/src/plugins/sound/oalsound/channel.h +++ /dev/null @@ -1,99 +0,0 @@ -// * This file is part of the COLOBOT source code -// * Copyright (C) 2012, Polish Portal of Colobot (PPC) -// * -// * 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/. - -// channel.h - -#pragma once - -#include -#include -#include - -#include -#include - -#include - -#include "buffer.h" -#include "check.h" - -struct SoundOper -{ - float finalAmplitude; - float finalFrequency; - float totalTime; - SoundNext nextOper; -}; - - -class Channel -{ - public: - Channel(); - ~Channel(); - - bool Play(); - bool Stop(); - bool SetPosition(Math::Vector); - - bool SetFrequency(float); - float GetFrequency(); - - float GetCurrentTime(); - void SetCurrentTime(float); - float GetDuration(); - - bool SetVolume(float); - float GetVolume(); - bool IsPlaying(); - bool IsReady(); - - bool SetBuffer(Buffer *); - bool HasEnvelope(); - SoundOper& GetEnvelope(); - void PopEnvelope(); - - int GetPriority(); - void SetPriority(int); - - void SetStartAmplitude(float); - void SetStartFrequency(float); - void SetChangeFrequency(float); - void SetInitFrequency(float); - - float GetStartAmplitude(); - float GetStartFrequency(); - float GetChangeFrequency(); - float GetInitFrequency(); - - void AddOper(SoundOper); - void ResetOper(); - Sound GetSoundType(); - void AdjustFrequency(float); - void AdjustVolume(float); - - private: - Buffer *mBuffer; - ALuint mSource; - - int mPriority; - float mStartAmplitude; - float mStartFrequency; - float mChangeFrequency; - float mInitFrequency; - std::deque mOper; - bool mReady; -}; diff --git a/src/plugins/sound/oalsound/check.h b/src/plugins/sound/oalsound/check.h deleted file mode 100644 index cb6b4a1..0000000 --- a/src/plugins/sound/oalsound/check.h +++ /dev/null @@ -1,39 +0,0 @@ -// * This file is part of the COLOBOT source code -// * Copyright (C) 2012, Polish Portal of Colobot (PPC) -// * -// * 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/. - -// check.h - -#pragma once - -#include -#include - -#include - -static ALenum CODE = AL_NO_ERROR; - -inline bool alCheck() -{ - CODE = alGetError(); - return CODE != AL_NO_ERROR; -} - -inline ALenum alGetCode() -{ - ALenum ret = CODE; - CODE = AL_NO_ERROR; - return ret; -} diff --git a/src/plugins/test/CMakeLists.txt b/src/plugins/test/CMakeLists.txt index cd4e6be..5f86b6f 100644 --- a/src/plugins/test/CMakeLists.txt +++ b/src/plugins/test/CMakeLists.txt @@ -3,8 +3,10 @@ cmake_minimum_required(VERSION 2.8) set(CMAKE_BUILD_TYPE debug) set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0 -std=c++11 -rdynamic") -add_executable(plugin_test plugin_test.cpp ../../common/iman.cpp ../../common/logger.cpp ../pluginloader.cpp) +add_executable(manager_test manager_test.cpp ../../common/logger.cpp ../../common/profile.cpp ../../common/iman.cpp ../pluginmanager.cpp ../pluginloader.cpp) +include_directories(".") include_directories("../../") +include_directories("../../../") -target_link_libraries(plugin_test ltdl) +target_link_libraries(manager_test ltdl) diff --git a/src/plugins/test/colobot.ini b/src/plugins/test/colobot.ini new file mode 100644 index 0000000..08956be --- /dev/null +++ b/src/plugins/test/colobot.ini @@ -0,0 +1,3 @@ +[Plugins] +Path=. +File=libopenalsound.so diff --git a/src/plugins/test/manager_test.cpp b/src/plugins/test/manager_test.cpp new file mode 100644 index 0000000..9b3f472 --- /dev/null +++ b/src/plugins/test/manager_test.cpp @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include + + +int main() { + new CLogger(); + new CProfile(); + new CInstanceManager(); + CPluginManager *mgr = new CPluginManager(); + + if (!GetProfile()->InitCurrentDirectory()) { + GetLogger()->Error("Config not found!\n"); + return 1; + } + mgr->LoadFromProfile(); + CSoundInterface *sound = static_cast(CInstanceManager::GetInstancePointer()->SearchInstance(CLASS_SOUND)); + sound->Create(true); + mgr->UnloadAllPlugins(); + + return 0; +} diff --git a/src/plugins/test/plugin_test.cpp b/src/plugins/test/plugin_test.cpp deleted file mode 100644 index 9aadfac..0000000 --- a/src/plugins/test/plugin_test.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include -#include - -#include -#include -#include -#include - - -int main() { - new CLogger(); - new CInstanceManager(); - - lt_dlinit(); - - CPluginLoader *plugin = new CPluginLoader("libopenalsound"); - if (plugin->LoadPlugin()) { - CSoundInterface *sound = static_cast(CInstanceManager::GetInstancePointer()->SearchInstance(CLASS_SOUND)); - - sound->Create(true); - sound->CacheAll(); - sound->Play((Sound)8); - sound->Play((Sound)18); - - sleep(10); - /* - while (1) - { - // just a test, very slow - plugin->FrameMove(0); - //if ('n' == getchar()) - // break; - }*/ - plugin->UnloadPlugin(); - } - - lt_dlexit(); - return 0; -} diff --git a/src/sound/plugins/oalsound/CMakeLists.txt b/src/sound/plugins/oalsound/CMakeLists.txt new file mode 100644 index 0000000..e36f3ac --- /dev/null +++ b/src/sound/plugins/oalsound/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 2.8) + +set(SOURCES + alsound.cpp + buffer.cpp + channel.cpp +) + +SET (CMAKE_CXX_FLAGS "-Wall -g -std=c++0x -fPIC") + +include(FindPkgConfig) +include(FindOpenAL) +pkg_check_modules(OPENAL_LIB REQUIRED openal) + +set(OPENAL_LIBRARIES + openal + alut +) + + +include_directories(../../..) +include_directories(.) +add_library(openalsound SHARED ${SOURCES}) +target_link_libraries(openalsound ${OPENAL_LIBRARIES}) diff --git a/src/sound/plugins/oalsound/alsound.cpp b/src/sound/plugins/oalsound/alsound.cpp new file mode 100644 index 0000000..a1d4801 --- /dev/null +++ b/src/sound/plugins/oalsound/alsound.cpp @@ -0,0 +1,552 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * Copyright (C) 2012 Polish Portal of Colobot (PPC) +// * +// * 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/. + +// alsound.cpp + + +#include "alsound.h" + + +#define MIN(a, b) (a > b ? b : a) + + +PLUGIN_INTERFACE(ALSound) + + +char* ALSound::PluginName() +{ + return const_cast("Sound plugin using OpenAL library to play sounds."); +} + + +int ALSound::PluginVersion() +{ + return 1; +} + + +void ALSound::InstallPlugin() +{ + auto pointer = CInstanceManager::GetInstancePointer(); + if (pointer != nullptr) + CInstanceManager::GetInstancePointer()->AddInstance(CLASS_SOUND, this); +} + + +void ALSound::UninstallPlugin() +{ + auto pointer = CInstanceManager::GetInstancePointer(); + if (pointer != nullptr) + CInstanceManager::GetInstancePointer()->DeleteInstance(CLASS_SOUND, this); + CleanUp(); +} + + +ALSound::ALSound() +{ + mEnabled = false; + m3D = false; + mAudioVolume = MAXVOLUME; + mMute = false; +} + + +ALSound::~ALSound() +{ + CleanUp(); +} + + +void ALSound::CleanUp() +{ + if (mEnabled) { + GetLogger()->Info("Unloading files and closing device...\n"); + StopAll(); + + for (auto item : mSounds) + delete item.second; + + mEnabled = false; + alutExit(); + } +} + + +bool ALSound::Create(bool b3D) +{ + CleanUp(); + + if (mEnabled) + return true; + + GetLogger()->Info("Opening audio device...\n"); + if (!alutInit(NULL, NULL)) { + ALenum error = alutGetError(); + GetLogger()->Error("Could not open audio device! Reason: %s\n", alutGetErrorString(error)); + return false; + } + GetLogger()->Info("Done.\n"); + + mEnabled = true; + return true; +} + + +void ALSound::SetSound3D(bool bMode) +{ + // TODO stub! need to be implemented + m3D = bMode; +} + + +bool ALSound::RetSound3D() +{ + // TODO stub! need to be implemented + return true; +} + + +bool ALSound::RetSound3DCap() +{ + // TODO stub! need to be implemented + return true; +} + + +bool ALSound::RetEnable() +{ + return mEnabled; +} + + +void ALSound::SetAudioVolume(int volume) +{ + alListenerf(AL_GAIN, MIN(volume, MAXVOLUME) * 0.01f); + mAudioVolume = MIN(volume, MAXVOLUME); +} + + +int ALSound::RetAudioVolume() +{ + float volume; + if ( !mEnabled ) + return 0; + + alGetListenerf(AL_GAIN, &volume); + return volume * MAXVOLUME; +} + + +void ALSound::SetMusicVolume(int volume) +{ + // TODO stub! Add music support +} + + +int ALSound::RetMusicVolume() +{ + // TODO stub! Add music support + if ( !mEnabled ) + return 0; + + return 0; +} + + +bool ALSound::Cache(Sound sound, std::string filename) +{ + Buffer *buffer = new Buffer(); + if (buffer->LoadFromFile(filename, sound)) { + mSounds[sound] = buffer; + return true; + } + return false; +} + + +void ALSound::CacheAll() +{ + char filename[100]; + for ( int i = 1; i < 69; i++ ) + { + sprintf(filename, "high/sound%.3d.wav", i); + if ( !Cache((Sound) i, std::string(filename)) ) + { + fprintf(stderr, "Unable to load audio: %s\n", filename); + } + } +} + + +int ALSound::RetPriority(Sound sound) +{ + if ( sound == SOUND_FLYh || + sound == SOUND_FLY || + sound == SOUND_MOTORw || + sound == SOUND_MOTORt || + sound == SOUND_MOTORr || + sound == SOUND_MOTORs || + sound == SOUND_SLIDE || + sound == SOUND_ERROR ) + { + return 30; + } + + if ( sound == SOUND_CONVERT || + sound == SOUND_ENERGY || + sound == SOUND_DERRICK || + sound == SOUND_STATION || + sound == SOUND_REPAIR || + sound == SOUND_RESEARCH || + sound == SOUND_BURN || + sound == SOUND_BUILD || + sound == SOUND_TREMBLE || + sound == SOUND_NUCLEAR || + sound == SOUND_EXPLO || + sound == SOUND_EXPLOl || + sound == SOUND_EXPLOlp || + sound == SOUND_EXPLOp || + sound == SOUND_EXPLOi ) + { + return 20; + } + + if ( sound == SOUND_BLUP || + sound == SOUND_INSECTs || + sound == SOUND_INSECTa || + sound == SOUND_INSECTb || + sound == SOUND_INSECTw || + sound == SOUND_INSECTm || + sound == SOUND_PSHHH || + sound == SOUND_EGG ) + { + return 0; + } + + return 10; +} + + +bool ALSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded) +{ + int priority = RetPriority(sound); + + // Seeks a channel used which sound is stopped. + for (auto it : mChannels) { + if (it.second->IsPlaying()) + continue; + if (it.second->GetSoundType() != sound) + continue; + + it.second->SetPriority(priority); + channel = it.first; + bAlreadyLoaded = true; + return true; + } + + // just add a new channel if we dont have any + if (mChannels.size() == 0) { + Channel *chn = new Channel(); + // check if we channel ready to play music, if not report error + if (chn->IsReady()) { + chn->SetPriority(priority); + mChannels[1] = chn; + channel = 1; + bAlreadyLoaded = false; + return true; + } + delete chn; + GetLogger()->Error("Could not open channel to play sound!"); + return false; + } + + // Seeks a channel completely free. + auto it = mChannels.end(); + it--; + int i = (*it).first; + while (++i) + { + if (mChannels.find(i) == mChannels.end()) { + Channel *chn = new Channel(); + // check if we channel ready to play music, if not destroy it and seek free one + if (chn->IsReady()) { + chn->SetPriority(priority); + mChannels[1] = chn; + channel = 1; + bAlreadyLoaded = false; + return true; + } + delete chn; + GetLogger()->Warn("Could not open additional channel to play sound!"); + } + } + + int lowerOrEqual = -1; + for (auto it : mChannels) { + if (it.second->GetPriority() < priority) { + GetLogger()->Info("Sound channel with lower priority will be reused."); + channel = it.first; + return true; + } + if (it.second->GetPriority() <= priority) + lowerOrEqual = it.first; + } + + if (lowerOrEqual != -1) { + channel = lowerOrEqual; + GetLogger()->Info("Sound channel with lower or equal priority will be reused."); + return true; + } + + GetLogger()->Warn("Could not find free buffer to use.\n"); + return false; +} + + +int ALSound::Play(Sound sound, float amplitude, float frequency, bool bLoop) +{ + return Play(sound, Math::Vector(), amplitude, frequency, bLoop); +} + + +int ALSound::Play(Sound sound, Math::Vector pos, float amplitude, float frequency, bool bLoop) +{ + if (!mEnabled) + return -1; + + if (mAudioVolume <= 0.0f) + return -1; + + if (mSounds.find(sound) == mSounds.end()) { + GetLogger()->Warn("Sound %d was not loaded!\n", sound); + return -1; + } + + int channel; + bool bAlreadyLoaded; + if (!SearchFreeBuffer(sound, channel, bAlreadyLoaded)) + return -1; + if ( !bAlreadyLoaded ) { + mChannels[channel]->SetBuffer(mSounds[sound]); + } + + Position(channel, pos); + + // setting initial values + mChannels[channel]->SetStartAmplitude(amplitude); + mChannels[channel]->SetStartFrequency(frequency); + mChannels[channel]->SetChangeFrequency(1.0f); + mChannels[channel]->ResetOper(); + mChannels[channel]->AdjustFrequency(frequency); + mChannels[channel]->AdjustVolume(mAudioVolume); + mChannels[channel]->Play(); + return channel; +} + + +bool ALSound::FlushEnvelope(int channel) +{ + if (mChannels.find(channel) == mChannels.end()) { + return false; + } + + mChannels[channel]->ResetOper(); + return true; +} + + +bool ALSound::AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper) +{ + if (!mEnabled) + return false; + + if (mChannels.find(channel) == mChannels.end()) { + return false; + } + + SoundOper op; + op.finalAmplitude = amplitude; + op.finalFrequency = frequency; + op.totalTime = time; + op.nextOper = oper; + mChannels[channel]->AddOper(op); + + return false; +} + + +bool ALSound::Position(int channel, Math::Vector pos) +{ + if (!mEnabled) + return false; + + if (mChannels.find(channel) == mChannels.end()) { + return false; + } + + mChannels[channel]->SetPosition(pos); + return true; +} + + +bool ALSound::Frequency(int channel, float frequency) +{ + if (!mEnabled) + return false; + + if (mChannels.find(channel) == mChannels.end()) { + return false; + } + + mChannels[channel]->SetFrequency(frequency); + return true; +} + +bool ALSound::Stop(int channel) +{ + if (!mEnabled) + return false; + + if (mChannels.find(channel) == mChannels.end()) { + return false; + } + + mChannels[channel]->Stop(); + mChannels[channel]->ResetOper(); + + return true; +} + + +bool ALSound::StopAll() +{ + if (!mEnabled) + return false; + + for (auto channel : mChannels) { + channel.second->Stop(); + channel.second->ResetOper(); + } + + return true; +} + + +bool ALSound::MuteAll(bool bMute) +{ + if (!mEnabled) + return false; + + float volume; + mMute = bMute; + if (mMute) + volume = 0; + else + volume = mAudioVolume; + + for (auto channel : mChannels) { + channel.second->SetVolume(volume); + } + + return true; +} + + +void ALSound::FrameMove(float delta) +{ + if (!mEnabled) + return; + + float progress; + float volume, frequency; + for (auto it : mChannels) { + if (!it.second->IsPlaying()) + continue; + + if (!it.second->HasEnvelope()) + continue; + + //it.second->GetEnvelope().currentTime += delta; + SoundOper oper = it.second->GetEnvelope(); + progress = it.second->GetCurrentTime() / oper.totalTime; + progress = MIN(progress, 1.0f); + + // setting volume + volume = progress * abs(oper.finalAmplitude - it.second->GetStartAmplitude()); + it.second->AdjustVolume(volume * mAudioVolume); + + // setting frequency + frequency = progress * (oper.finalFrequency - it.second->GetStartFrequency()) * it.second->GetStartFrequency() * it.second->GetChangeFrequency(); + it.second->AdjustFrequency(frequency); + + if (it.second->GetEnvelope().totalTime <= it.second->GetCurrentTime()) { + + if (oper.nextOper == SOPER_LOOP) { + GetLogger()->Info("Replay.\n"); + it.second->SetCurrentTime(0.0f); + it.second->Play(); + } else { + GetLogger()->Info("Next.\n"); + it.second->SetStartAmplitude(oper.finalAmplitude); + it.second->SetStartFrequency(oper.finalFrequency); + it.second->PopEnvelope(); + } + } + } +} + + +void ALSound::SetListener(Math::Vector eye, Math::Vector lookat) +{ + GetLogger()->Info("Setting listener position.\n"); + float orientation[] = {lookat.x, lookat.y, lookat.z, 0.f, 1.f, 0.f}; + alListener3f(AL_POSITION, eye.x, eye.y, eye.z); + alListenerfv(AL_ORIENTATION, orientation); +} + + +bool ALSound::PlayMusic(int rank, bool bRepeat) +{ + // TODO stub! Add music support + return true; +} + + +bool ALSound::RestartMusic() +{ + // TODO stub! Add music support + return true; +} + +void ALSound::StopMusic() +{ + // TODO stub! Add music support + SuspendMusic(); +} + + +bool ALSound::IsPlayingMusic() +{ + // TODO stub! Add music support + return true; +} + + +void ALSound::SuspendMusic() +{ + // TODO stub! Add music support +} diff --git a/src/sound/plugins/oalsound/alsound.h b/src/sound/plugins/oalsound/alsound.h new file mode 100644 index 0000000..9265e2c --- /dev/null +++ b/src/sound/plugins/oalsound/alsound.h @@ -0,0 +1,95 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// alsound.h + +#pragma once + +#include +#include + +#include + +#include +#include +#include + +#include "buffer.h" +#include "channel.h" +#include "check.h" + + +class ALSound : public CSoundInterface +{ + public: + ALSound(); + ~ALSound(); + + bool Create(bool b3D); + void CacheAll(); + bool Cache(Sound, std::string); + + bool RetEnable(); + + void SetSound3D(bool bMode); + bool RetSound3D(); + bool RetSound3DCap(); + + void SetAudioVolume(int volume); + int RetAudioVolume(); + void SetMusicVolume(int volume); + int RetMusicVolume(); + + void SetListener(Math::Vector eye, Math::Vector lookat); + void FrameMove(float rTime); + + int Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false); + int Play(Sound sound, Math::Vector pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false); + bool FlushEnvelope(int channel); + bool AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper); + bool Position(int channel, Math::Vector pos); + bool Frequency(int channel, float frequency); + bool Stop(int channel); + bool StopAll(); + bool MuteAll(bool bMute); + + bool PlayMusic(int rank, bool bRepeat); + bool RestartMusic(); + void SuspendMusic(); + void StopMusic(); + bool IsPlayingMusic(); + + // plugin interface + char* PluginName(); + int PluginVersion(); + void InstallPlugin(); + void UninstallPlugin(); + + private: + void CleanUp(); + int RetPriority(Sound); + bool SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded); + + bool mEnabled; + bool m3D; + bool mMute; + int mAudioVolume; + ALCdevice* audioDevice; + ALCcontext* audioContext; + std::map mSounds; + std::map mChannels; +}; diff --git a/src/sound/plugins/oalsound/buffer.cpp b/src/sound/plugins/oalsound/buffer.cpp new file mode 100644 index 0000000..37211e9 --- /dev/null +++ b/src/sound/plugins/oalsound/buffer.cpp @@ -0,0 +1,80 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// buffer.cpp + +#include "buffer.h" + +Buffer::Buffer() { + mLoaded = false; + mDuration = 0; +} + + +Buffer::~Buffer() { + if (mLoaded) { + alDeleteBuffers(1, &mBuffer); + if (alCheck()) + GetLogger()->Warn("Failed to unload buffer. Code %d\n", alGetCode()); + } +} + + +bool Buffer::LoadFromFile(std::string filename, Sound sound) { + mSound = sound; + + GetLogger()->Info("Loading audio file: %s\n", filename.c_str()); + mBuffer = alutCreateBufferFromFile(filename.c_str()); + + ALenum error = alutGetError(); + if (error) { + GetLogger()->Warn("Failed to load file. Reason: %s\n", alutGetErrorString(error)); + mLoaded = false; + return false; + } + + ALint size, bits, channels, freq; + + alGetBufferi(mBuffer, AL_SIZE, &size); + alGetBufferi(mBuffer, AL_BITS, &bits); + alGetBufferi(mBuffer, AL_CHANNELS, &channels); + alGetBufferi(mBuffer, AL_FREQUENCY, &freq); + + mDuration = (ALfloat)size / channels / bits / 8 / (ALfloat)freq; + + mLoaded = true; + return true; +} + + +Sound Buffer::GetSoundType() { + return mSound; +} + + +ALuint Buffer::GetBuffer() { + return mBuffer; +} + + +bool Buffer::IsLoaded() { + return mLoaded; +} + + +float Buffer::GetDuration() { + return mDuration; +} diff --git a/src/sound/plugins/oalsound/buffer.h b/src/sound/plugins/oalsound/buffer.h new file mode 100644 index 0000000..6eefe72 --- /dev/null +++ b/src/sound/plugins/oalsound/buffer.h @@ -0,0 +1,48 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// buffer.h + +#pragma once + +#include + +#include + +#include +#include + +#include "check.h" + +class Buffer +{ + public: + Buffer(); + ~Buffer(); + + bool LoadFromFile(std::string, Sound); + bool IsLoaded(); + + Sound GetSoundType(); + ALuint GetBuffer(); + float GetDuration(); + + private: + ALuint mBuffer; + Sound mSound; + bool mLoaded; + float mDuration; +}; diff --git a/src/sound/plugins/oalsound/channel.cpp b/src/sound/plugins/oalsound/channel.cpp new file mode 100644 index 0000000..4476dee --- /dev/null +++ b/src/sound/plugins/oalsound/channel.cpp @@ -0,0 +1,304 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// channel.cpp + +#include "channel.h" + + +Channel::Channel() { + alGenSources(1, &mSource); + + if (alCheck()) { + GetLogger()->Warn("Failed to create sound source. Code: %d\n", alGetCode()); + mReady = false; + } else { + mReady = true; + } + + mPriority = 0; + mBuffer = nullptr; +} + + +Channel::~Channel() { + if (mReady) { + alSourcei(mSource, AL_BUFFER, 0); + alDeleteSources(1, &mSource); + if (alCheck()) + GetLogger()->Warn("Failed to delete sound source. Code: %s\n", alGetCode()); + } +} + + +bool Channel::Play() { + if (!mReady) + return false; + + alSourcePlay(mSource); + if (alCheck()) + GetLogger()->Warn("Could not play audio sound source. Code: %s\n", alGetCode()); + return true; +} + + +bool Channel::SetPosition(Math::Vector pos) { + if (!mReady) + return false; + + alSource3f(mSource, AL_POSITION, pos.x, pos.y, pos.z); + if (alCheck()) { + GetLogger()->Warn("Could not set sound position. Code: %s\n", alGetCode()); + return false; + } + return true; +} + + +bool Channel::SetFrequency(float freq) +{ + if (!mReady) + return false; + + alSourcef(mSource, AL_PITCH, freq); + if (alCheck()) { + GetLogger()->Warn("Could not set sound pitch. Code: %s\n", alGetCode()); + return false; + } + return true; +} + + +float Channel::GetFrequency() +{ + ALfloat freq; + if (!mReady) + return 0; + + alGetSourcef(mSource, AL_PITCH, &freq); + if (alCheck()) { + GetLogger()->Warn("Could not get sound pitch. Code: %s\n", alGetCode()); + return 0; + } + + return freq; +} + + +bool Channel::SetVolume(float vol) +{ + if (!mReady || vol < 0) + return false; + + alSourcef(mSource, AL_GAIN, vol / MAXVOLUME); + if (alCheck()) { + GetLogger()->Warn("Could not set sound volume. Code: %s\n", alGetCode()); + return false; + } + return true; +} + + +float Channel::GetVolume() +{ + ALfloat vol; + if (!mReady) + return 0; + + alGetSourcef(mSource, AL_GAIN, &vol); + if (alCheck()) { + GetLogger()->Warn("Could not get sound volume. Code: %s\n", alGetCode()); + return 0; + } + + return vol * MAXVOLUME; +} + + +int Channel::GetPriority() +{ + return mPriority; +} + + +void Channel::SetPriority(int pri) +{ + mPriority = pri; +} + + +void Channel::SetStartAmplitude(float gain) +{ + mStartAmplitude = gain; +} + + +void Channel::SetStartFrequency(float freq) +{ + mStartFrequency = freq; +} + + +void Channel::SetChangeFrequency(float freq) +{ + mChangeFrequency = freq; +} + + +void Channel::SetInitFrequency(float freq) +{ + mInitFrequency = freq; +} + + +float Channel::GetStartAmplitude() +{ + return mStartAmplitude; +} + + +float Channel::GetStartFrequency() +{ + return mStartFrequency; +} + + +float Channel::GetChangeFrequency() +{ + return mChangeFrequency; +} + + +float Channel::GetInitFrequency() +{ + return mInitFrequency; +} + + +void Channel::AddOper(SoundOper oper) +{ + mOper.push_back(oper); +} + + +void Channel::ResetOper() +{ + mOper.clear(); +} + + +Sound Channel::GetSoundType() { + return mBuffer->GetSoundType(); +} + + +bool Channel::SetBuffer(Buffer *buffer) { + if (!mReady) + return false; + + assert(buffer); + mBuffer = buffer; + alSourcei(mSource, AL_BUFFER, buffer->GetBuffer()); + if (alCheck()) { + GetLogger()->Warn("Could not set sound buffer. Code: %s\n", alGetCode()); + return false; + } + mInitFrequency = GetFrequency(); + return true; +} + + +void Channel::AdjustFrequency(float freq) { + SetFrequency(freq * mInitFrequency); +} + + +void Channel::AdjustVolume(float volume) { + SetVolume(mStartAmplitude * (float) volume); +} + + +bool Channel::IsPlaying() { + ALint status; + if (!mReady) return false; + + alGetSourcei(mSource, AL_SOURCE_STATE, &status); + if (alCheck()) { + GetLogger()->Warn("Could not get sound status. Code: %s\n", alGetCode()); + return false; + } + + return status == AL_PLAYING; +} + + +bool Channel::IsReady() { + return mReady; +} + + +bool Channel::Stop() { + alSourceStop(mSource); + if (alCheck()) { + GetLogger()->Warn("Could not stop sound. Code: %s\n", alGetCode()); + return false; + } + return true; +} + + +float Channel::GetCurrentTime() +{ + ALfloat current; + alGetSourcef(mSource, AL_SEC_OFFSET, ¤t); + if (alCheck()) { + GetLogger()->Warn("Could not get source current play time. Code: %s\n", alGetCode()); + return 0.0f; + } + return current; +} + + +void Channel::SetCurrentTime(float current) +{ + alSourcef(mSource, AL_SEC_OFFSET, current); + if (alCheck()) + GetLogger()->Warn("Could not get source current play time. Code: %s\n", alGetCode()); +} + + +float Channel::GetDuration() +{ + return mBuffer->GetDuration(); +} + + +bool Channel::HasEnvelope() +{ + return mOper.size() > 0; +} + + +SoundOper& Channel::GetEnvelope() +{ + return mOper.front(); +} + + +void Channel::PopEnvelope() +{ + mOper.pop_front(); +} diff --git a/src/sound/plugins/oalsound/channel.h b/src/sound/plugins/oalsound/channel.h new file mode 100644 index 0000000..3099931 --- /dev/null +++ b/src/sound/plugins/oalsound/channel.h @@ -0,0 +1,99 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// channel.h + +#pragma once + +#include +#include +#include + +#include +#include + +#include + +#include "buffer.h" +#include "check.h" + +struct SoundOper +{ + float finalAmplitude; + float finalFrequency; + float totalTime; + SoundNext nextOper; +}; + + +class Channel +{ + public: + Channel(); + ~Channel(); + + bool Play(); + bool Stop(); + bool SetPosition(Math::Vector); + + bool SetFrequency(float); + float GetFrequency(); + + float GetCurrentTime(); + void SetCurrentTime(float); + float GetDuration(); + + bool SetVolume(float); + float GetVolume(); + bool IsPlaying(); + bool IsReady(); + + bool SetBuffer(Buffer *); + bool HasEnvelope(); + SoundOper& GetEnvelope(); + void PopEnvelope(); + + int GetPriority(); + void SetPriority(int); + + void SetStartAmplitude(float); + void SetStartFrequency(float); + void SetChangeFrequency(float); + void SetInitFrequency(float); + + float GetStartAmplitude(); + float GetStartFrequency(); + float GetChangeFrequency(); + float GetInitFrequency(); + + void AddOper(SoundOper); + void ResetOper(); + Sound GetSoundType(); + void AdjustFrequency(float); + void AdjustVolume(float); + + private: + Buffer *mBuffer; + ALuint mSource; + + int mPriority; + float mStartAmplitude; + float mStartFrequency; + float mChangeFrequency; + float mInitFrequency; + std::deque mOper; + bool mReady; +}; diff --git a/src/sound/plugins/oalsound/check.h b/src/sound/plugins/oalsound/check.h new file mode 100644 index 0000000..cb6b4a1 --- /dev/null +++ b/src/sound/plugins/oalsound/check.h @@ -0,0 +1,39 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// check.h + +#pragma once + +#include +#include + +#include + +static ALenum CODE = AL_NO_ERROR; + +inline bool alCheck() +{ + CODE = alGetError(); + return CODE != AL_NO_ERROR; +} + +inline ALenum alGetCode() +{ + ALenum ret = CODE; + CODE = AL_NO_ERROR; + return ret; +} diff --git a/src/sound/plugins/oalsound/test/CMakeLists.txt b/src/sound/plugins/oalsound/test/CMakeLists.txt new file mode 100644 index 0000000..d10169b --- /dev/null +++ b/src/sound/plugins/oalsound/test/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 2.8) + +set(CMAKE_BUILD_TYPE debug) +set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0 -std=c++11 -rdynamic") + +add_executable(plugin_test plugin_test.cpp ../../../../common/iman.cpp ../../../../common/logger.cpp ../../../../plugins/pluginloader.cpp) + +include_directories(".") +include_directories("../../../../") + +target_link_libraries(plugin_test ltdl) diff --git a/src/sound/plugins/oalsound/test/plugin_test.cpp b/src/sound/plugins/oalsound/test/plugin_test.cpp new file mode 100644 index 0000000..40c1cd2 --- /dev/null +++ b/src/sound/plugins/oalsound/test/plugin_test.cpp @@ -0,0 +1,40 @@ +#include +#include +#include + +#include +#include +#include +#include + + +int main() { + new CLogger(); + new CInstanceManager(); + + lt_dlinit(); + + CPluginLoader *plugin = new CPluginLoader("libopenalsound"); + if (plugin->LoadPlugin()) { + CSoundInterface *sound = static_cast(CInstanceManager::GetInstancePointer()->SearchInstance(CLASS_SOUND)); + + sound->Create(true); + sound->CacheAll(); + sound->Play((Sound)8); + sound->Play((Sound)18); + + sleep(10); + /* + while (1) + { + // just a test, very slow + plugin->FrameMove(0); + //if ('n' == getchar()) + // break; + }*/ + plugin->UnloadPlugin(); + } + + lt_dlexit(); + return 0; +} -- cgit v1.2.3-1-g7c22 From 62b545128f37746c343760e464872655b5523c6f Mon Sep 17 00:00:00 2001 From: erihel Date: Sun, 12 Aug 2012 18:37:11 +0200 Subject: * Final changes to plugin interface * Added doxygen comments to plugin manager and plugin loader --- src/plugins/plugininterface.h | 34 ++++++++++++++++++++++++--- src/plugins/pluginloader.cpp | 17 +++++++++++--- src/plugins/pluginloader.h | 42 +++++++++++++++++++++++++++++++++- src/plugins/pluginmanager.cpp | 22 +++++++++++++----- src/plugins/pluginmanager.h | 33 ++++++++++++++++++++++++++ src/plugins/test/manager_test.cpp | 7 ++++++ src/sound/plugins/oalsound/alsound.cpp | 9 ++++---- src/sound/plugins/oalsound/alsound.h | 4 ++-- src/sound/sound.h | 8 +++---- 9 files changed, 153 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/plugins/plugininterface.h b/src/plugins/plugininterface.h index bf4e040..b8adddc 100644 --- a/src/plugins/plugininterface.h +++ b/src/plugins/plugininterface.h @@ -16,22 +16,50 @@ // plugininterface.h +/** + * @file plugin/plugininterface.h + * @brief Generic plugin interface + */ #pragma once +#include #define PLUGIN_INTERFACE(class_type) \ static class_type* Plugin##class_type; \ extern "C" void InstallPluginEntry() { Plugin##class_type = new class_type(); Plugin##class_type->InstallPlugin(); } \ - extern "C" void UninstallPluginEntry() { Plugin##class_type->UninstallPlugin(); delete Plugin##class_type; } \ + extern "C" bool UninstallPluginEntry(std::string &reason) { bool result = Plugin##class_type->UninstallPlugin(reason); \ + if (!result) \ + return false; \ + delete Plugin##class_type; \ + return true; } \ extern "C" CPluginInterface* GetPluginInterfaceEntry() { return static_cast(Plugin##class_type); } +/** +* @class CPluginInterface +* +* @brief Generic plugin interface. All plugins that will be managed by plugin manager have to derive from this class. +* +*/ class CPluginInterface { public: - virtual char* PluginName() = 0; + /** Function to get plugin name or description + * @return returns plugin name + */ + virtual std::string PluginName() = 0; + + /** Function to get plugin version. 1 means version 0.01, 2 means 0.02 etc. + * @return number indicating plugin version + */ virtual int PluginVersion() = 0; + + /** Function to initialize plugin + */ virtual void InstallPlugin() = 0; - virtual void UninstallPlugin() = 0; + + /** Function called before removing plugin + */ + virtual bool UninstallPlugin(std::string &) = 0; }; diff --git a/src/plugins/pluginloader.cpp b/src/plugins/pluginloader.cpp index 8893b56..fd8ce74 100644 --- a/src/plugins/pluginloader.cpp +++ b/src/plugins/pluginloader.cpp @@ -28,11 +28,11 @@ CPluginLoader::CPluginLoader(std::string filename) } -char* CPluginLoader::GetName() +std::string CPluginLoader::GetName() { if (mLoaded) return mInterface->PluginName(); - return nullptr; + return "(not loaded)"; } @@ -57,12 +57,18 @@ bool CPluginLoader::UnloadPlugin() return true; } - void (*uninstall)() = (void (*)()) lt_dlsym(mHandle, "UninstallPluginEntry"); + bool (*uninstall)(std::string &) = (bool (*)(std::string &)) lt_dlsym(mHandle, "UninstallPluginEntry"); if (!uninstall) { GetLogger()->Error("Error getting UninstallPluginEntry for plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); return false; } + std::string reason; + if (!uninstall(reason)) { + GetLogger()->Error("Could not unload plugin %s: %s\n", mFilename.c_str(), reason.c_str()); + return false; + } + lt_dlclose(mHandle); mLoaded = false; return true; @@ -71,6 +77,11 @@ bool CPluginLoader::UnloadPlugin() bool CPluginLoader::LoadPlugin() { + if (mFilename.length() == 0) { + GetLogger()->Warn("No plugin filename specified.\n"); + return false; + } + mHandle = lt_dlopenext(mFilename.c_str()); if (!mHandle) { GetLogger()->Error("Error loading plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); diff --git a/src/plugins/pluginloader.h b/src/plugins/pluginloader.h index 873d30a..40b19da 100644 --- a/src/plugins/pluginloader.h +++ b/src/plugins/pluginloader.h @@ -16,6 +16,10 @@ // pluginloader.h +/** + * @file plugin/pluginloader.h + * @brief Plugin loader interface + */ #pragma once @@ -27,16 +31,52 @@ #include "plugininterface.h" +/** +* @class CPluginLoader +* +* @brief Plugin loader interface. Plugin manager uses this class to load plugins. +* +*/ class CPluginLoader { public: + /** Class contructor + * @param std::string plugin filename + */ CPluginLoader(std::string); - char* GetName(); + /** Function to get plugin name or description + * @return returns plugin name + */ + std::string GetName(); + + /** Function to get plugin version + * @return returns plugin version + */ int GetVersion(); + + /** Function to unload plugin + * @return returns true on success + */ bool UnloadPlugin(); + + /** Function to load plugin + * @return returns true on success + */ bool LoadPlugin(); + + /** Function to check if plugin is loaded + * @return returns true if plugin is loaded + */ bool IsLoaded(); + + /** Function to set plugin filename + * @return returns true on success. Action can fail if plugin was loaded and cannot be unloaded + */ bool SetFilename(std::string); + + /** Function to get plugin filename + * @return returns plugin filename + */ std::string GetFilename(); diff --git a/src/plugins/pluginmanager.cpp b/src/plugins/pluginmanager.cpp index ab9d8ad..470ac2f 100644 --- a/src/plugins/pluginmanager.cpp +++ b/src/plugins/pluginmanager.cpp @@ -60,7 +60,7 @@ bool CPluginManager::LoadPlugin(std::string filename) loader->SetFilename(dir + "/" + filename); result = loader->LoadPlugin(); if (result) { - GetLogger()->Info("Plugin %s (%s) version %0.2f loaded!\n", filename.c_str(), loader->GetName(), loader->GetVersion() / 100.0f); + GetLogger()->Info("Plugin %s (%s) version %0.2f loaded!\n", filename.c_str(), loader->GetName().c_str(), loader->GetVersion() / 100.0f); m_plugins.push_back(loader); break; } @@ -102,13 +102,23 @@ bool CPluginManager::RemoveSearchDirectory(std::string dir) bool CPluginManager::UnloadAllPlugins() { - for (CPluginLoader *plugin : m_plugins) { - GetLogger()->Info("Trying to unload plugin %s (%s)...\n", plugin->GetFilename().c_str(), plugin->GetName()); - plugin->UnloadPlugin(); + bool allOk = true; + std::vector::iterator it; + for (it = m_plugins.begin(); it != m_plugins.end(); it++) { + CPluginLoader *plugin = *it; + bool result; + + GetLogger()->Info("Trying to unload plugin %s (%s)...\n", plugin->GetFilename().c_str(), plugin->GetName().c_str()); + result = plugin->UnloadPlugin(); + if (!result) { + allOk = false; + continue; + } delete plugin; + m_plugins.erase(it); } - m_plugins.clear(); - return true; + + return allOk; } diff --git a/src/plugins/pluginmanager.h b/src/plugins/pluginmanager.h index d267238..e425c62 100644 --- a/src/plugins/pluginmanager.h +++ b/src/plugins/pluginmanager.h @@ -16,6 +16,10 @@ // pluginmanager.h +/** + * @file plugin/pluginmanager.h + * @brief Plugin manager class. + */ #pragma once @@ -31,19 +35,48 @@ #include "pluginloader.h" +/** +* @class CPluginManager +* +* @brief Plugin manager class. Plugin manager can load plugins from colobot.ini or manually specified files. +* +*/ class CPluginManager : public CSingleton { public: CPluginManager(); ~CPluginManager(); + /** Function loads plugin list and path list from profile file + */ void LoadFromProfile(); + /** Function loads specified plugin + * @param std::string plugin filename + * @return returns true on success + */ bool LoadPlugin(std::string); + + /** Function unloads specified plugin + * @param std::string plugin filename + * @return returns true on success + */ bool UnloadPlugin(std::string); + /** Function adds path to be checked when searching for plugin file. If path was already added it will be ignored + * @param std::string plugin search path + * @return returns true on success + */ bool AddSearchDirectory(std::string); + + /** Function removes path from list + * @param std::string plugin search path + * @return returns true on success + */ bool RemoveSearchDirectory(std::string); + /** Function tries to unload all plugins + * @return returns true on success + */ bool UnloadAllPlugins(); private: diff --git a/src/plugins/test/manager_test.cpp b/src/plugins/test/manager_test.cpp index 9b3f472..d921c1d 100644 --- a/src/plugins/test/manager_test.cpp +++ b/src/plugins/test/manager_test.cpp @@ -15,8 +15,15 @@ int main() { GetLogger()->Error("Config not found!\n"); return 1; } + mgr->LoadFromProfile(); CSoundInterface *sound = static_cast(CInstanceManager::GetInstancePointer()->SearchInstance(CLASS_SOUND)); + + if (!sound) { + GetLogger()->Error("Sound not loaded!\n"); + return 2; + } + sound->Create(true); mgr->UnloadAllPlugins(); diff --git a/src/sound/plugins/oalsound/alsound.cpp b/src/sound/plugins/oalsound/alsound.cpp index a1d4801..8cd8221 100644 --- a/src/sound/plugins/oalsound/alsound.cpp +++ b/src/sound/plugins/oalsound/alsound.cpp @@ -27,15 +27,15 @@ PLUGIN_INTERFACE(ALSound) -char* ALSound::PluginName() +std::string ALSound::PluginName() { - return const_cast("Sound plugin using OpenAL library to play sounds."); + return "Sound plugin using OpenAL library to play sounds."; } int ALSound::PluginVersion() { - return 1; + return 2; } @@ -47,12 +47,13 @@ void ALSound::InstallPlugin() } -void ALSound::UninstallPlugin() +bool ALSound::UninstallPlugin(std::string &reason) { auto pointer = CInstanceManager::GetInstancePointer(); if (pointer != nullptr) CInstanceManager::GetInstancePointer()->DeleteInstance(CLASS_SOUND, this); CleanUp(); + return true; } diff --git a/src/sound/plugins/oalsound/alsound.h b/src/sound/plugins/oalsound/alsound.h index 9265e2c..c1cdb81 100644 --- a/src/sound/plugins/oalsound/alsound.h +++ b/src/sound/plugins/oalsound/alsound.h @@ -74,10 +74,10 @@ class ALSound : public CSoundInterface bool IsPlayingMusic(); // plugin interface - char* PluginName(); + std::string PluginName(); int PluginVersion(); void InstallPlugin(); - void UninstallPlugin(); + bool UninstallPlugin(std::string &); private: void CleanUp(); diff --git a/src/sound/sound.h b/src/sound/sound.h index f18a76a..45ec7e1 100644 --- a/src/sound/sound.h +++ b/src/sound/sound.h @@ -15,10 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// soundinterface.h +// sound.h /** - * @file sound/soundinterface.h + * @file sound/sound.h * @brief Sound plugin interface */ @@ -39,7 +39,7 @@ /** * \public - * \enum Sound sound/soundinterface.h + * \enum Sound sound/sound.h * \brief Sound enum representing sound file **/ enum Sound @@ -131,7 +131,7 @@ enum Sound /** * \public - * \enum SoundNext sound/soundinterface.h + * \enum SoundNext sound/sound.h * \brief Enum representing operation that will be performend on a sound at given time **/ enum SoundNext -- cgit v1.2.3-1-g7c22