Merge branch 'master' of github.com:supertuxkart/stk-code
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<stkgui>
|
||||
<div x="5%" y="5%" width="90%" height="90%" layout="vertical-row" >
|
||||
|
||||
<header id="title" width="80%" text="Race Setup" align="center" text_align="center" />
|
||||
<header id="title" width="100%" text="Race Setup" align="center" text_align="center" />
|
||||
|
||||
<spacer height="2%" width="1"/>
|
||||
|
||||
|
||||
@@ -15,13 +15,15 @@
|
||||
<spacer height="15" width="10"/>
|
||||
<div width="90%" align="center" layout="vertical-row" height="fit">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label width="40%" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
|
||||
<checkbox width="fit" id="online" I18N="In the login screen" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
<label proportion="1" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
|
||||
</div>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label width="40%" id="label_remember" height="100%" text_align="left"
|
||||
I18N="In the login screen" text="Remember password"/>
|
||||
<checkbox width="fit" id="remember-user" I18N="In the login screen" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
<label proportion="1" id="label_remember" height="100%" text_align="left"
|
||||
I18N="In the login screen" text="Remember password"/>
|
||||
</div>
|
||||
<!-- Disable guest accounts for now
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
|
||||
@@ -24,13 +24,15 @@
|
||||
<spacer height="15" width="10"/>
|
||||
<div width="90%" align="center" layout="vertical-row" height="fit">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label width="40%" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
|
||||
<checkbox width="fit" id="online" I18N="In the login screen" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
<label proportion="1" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
|
||||
</div>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="label_remember" width="40%" height="100%" text_align="left"
|
||||
I18N="In the login screen" text="Remember password"/>
|
||||
<checkbox width="fit" id="remember-user" I18N="In the login screen" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
<label id="label_remember" proportion="1" height="100%" text_align="left"
|
||||
I18N="In the login screen" text="Remember password"/>
|
||||
</div>
|
||||
<!-- Disable guest accounts for now
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
|
||||
30
data/shaders/primitive2dlist.vert
Normal file
30
data/shaders/primitive2dlist.vert
Normal file
@@ -0,0 +1,30 @@
|
||||
#if __VERSION__ >= 330
|
||||
layout(location = 0) in vec3 Position;
|
||||
layout(location = 1) in vec3 Normal;
|
||||
layout(location = 2) in vec4 Color;
|
||||
layout(location = 3) in vec2 Texcoord;
|
||||
layout(location = 4) in vec2 SecondTexcoord;
|
||||
layout(location = 5) in vec3 Tangent;
|
||||
layout(location = 6) in vec3 Bitangent;
|
||||
#else
|
||||
in vec3 Position;
|
||||
in vec3 Normal;
|
||||
in vec4 Color;
|
||||
in vec2 Texcoord;
|
||||
in vec2 SecondTexcoord;
|
||||
in vec3 Tangent;
|
||||
in vec3 Bitangent;
|
||||
#endif
|
||||
|
||||
out vec2 uv;
|
||||
out vec4 color;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
color = Color.zyxw;
|
||||
vec3 P = Position / vec3(screen, 1.);
|
||||
P = 2. * P - 1.;
|
||||
P.y *= -1;
|
||||
gl_Position = vec4(P, 1.);
|
||||
uv = Texcoord;
|
||||
}
|
||||
@@ -30,13 +30,16 @@
|
||||
class DummySFX : public SFXBase
|
||||
{
|
||||
public:
|
||||
DummySFX(SFXBuffer* buffer, bool positional, float gain) {}
|
||||
DummySFX(SFXBuffer* buffer, bool positional,
|
||||
float gain) {}
|
||||
virtual ~DummySFX() {}
|
||||
|
||||
/** Late creation, if SFX was initially disabled */
|
||||
virtual bool init() { return true; }
|
||||
|
||||
virtual bool init() { return true; }
|
||||
virtual bool isLooped() { return false; }
|
||||
virtual void updatePlayingSFX(float dt) {}
|
||||
virtual void setLoop(bool status) {}
|
||||
virtual void reallySetLoop(bool status) {}
|
||||
virtual void setPosition(const Vec3 &p) {}
|
||||
virtual void reallySetPosition(const Vec3 &p) {}
|
||||
virtual void play() {}
|
||||
@@ -52,10 +55,11 @@ public:
|
||||
virtual void reallySetSpeed(float factor) {}
|
||||
virtual void setVolume(float gain) {}
|
||||
virtual void reallySetVolume(float gain) {}
|
||||
virtual void setMasterVolume(float gain) {}
|
||||
virtual void reallySetMasterVolumeNow(float gain) {}
|
||||
virtual SFXStatus getStatus() { return SFX_STOPPED; }
|
||||
virtual void onSoundEnabledBack() {}
|
||||
virtual void setRolloff(float rolloff) {}
|
||||
virtual bool isPlaying() { return false; }
|
||||
virtual const SFXBuffer* getBuffer() const { return NULL; }
|
||||
|
||||
}; // DummySFX
|
||||
|
||||
@@ -46,35 +46,38 @@ public:
|
||||
enum SFXStatus
|
||||
{
|
||||
SFX_UNKNOWN = -1, SFX_STOPPED = 0, SFX_PAUSED = 1, SFX_PLAYING = 2,
|
||||
SFX_INITIAL = 3
|
||||
SFX_NOT_INITIALISED = 3
|
||||
};
|
||||
|
||||
virtual ~SFXBase() {}
|
||||
|
||||
/** Late creation, if SFX was initially disabled */
|
||||
virtual bool init() = 0;
|
||||
virtual void setPosition(const Vec3 &p) = 0;
|
||||
virtual void reallySetPosition(const Vec3 &p) = 0;
|
||||
virtual void setLoop(bool status) = 0;
|
||||
virtual bool isPlaying() = 0;
|
||||
virtual void play() = 0;
|
||||
virtual void reallyPlayNow() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual void reallyStopNow() = 0;
|
||||
virtual void pause() = 0;
|
||||
virtual void reallyPauseNow() = 0;
|
||||
virtual void resume() = 0;
|
||||
virtual void reallyResumeNow() = 0;
|
||||
virtual void deleteSFX() = 0;
|
||||
virtual void setSpeed(float factor) = 0;
|
||||
virtual void reallySetSpeed(float factor) = 0;
|
||||
virtual void setVolume(float gain) = 0;
|
||||
virtual void reallySetVolume(float gain) = 0;
|
||||
virtual void setMasterVolume(float gain) = 0;
|
||||
virtual void onSoundEnabledBack() = 0;
|
||||
virtual void setRolloff(float rolloff) = 0;
|
||||
virtual const SFXBuffer* getBuffer() const = 0;
|
||||
virtual SFXStatus getStatus() = 0;
|
||||
virtual bool init() = 0;
|
||||
virtual bool isLooped() = 0;
|
||||
virtual void updatePlayingSFX(float dt) = 0;
|
||||
virtual void setPosition(const Vec3 &p) = 0;
|
||||
virtual void reallySetPosition(const Vec3 &p) = 0;
|
||||
virtual void setLoop(bool status) = 0;
|
||||
virtual void reallySetLoop(bool status) = 0;
|
||||
virtual void play() = 0;
|
||||
virtual void reallyPlayNow() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual void reallyStopNow() = 0;
|
||||
virtual void pause() = 0;
|
||||
virtual void reallyPauseNow() = 0;
|
||||
virtual void resume() = 0;
|
||||
virtual void reallyResumeNow() = 0;
|
||||
virtual void deleteSFX() = 0;
|
||||
virtual void setSpeed(float factor) = 0;
|
||||
virtual void reallySetSpeed(float factor) = 0;
|
||||
virtual void setVolume(float gain) = 0;
|
||||
virtual void reallySetVolume(float gain) = 0;
|
||||
virtual void setMasterVolume(float gain) = 0;
|
||||
virtual void reallySetMasterVolumeNow(float gain) = 0;
|
||||
virtual void onSoundEnabledBack() = 0;
|
||||
virtual void setRolloff(float rolloff) = 0;
|
||||
virtual const SFXBuffer* getBuffer() const = 0;
|
||||
virtual SFXStatus getStatus() = 0;
|
||||
|
||||
}; // SFXBase
|
||||
|
||||
|
||||
@@ -101,13 +101,11 @@ SFXManager::SFXManager()
|
||||
delete m_thread_id.getData();
|
||||
m_thread_id.unlock();
|
||||
m_thread_id.setAtomic(0);
|
||||
Log::error("HTTP Manager", "Could not create thread, error=%d.",
|
||||
Log::error("SFXManager", "Could not create thread, error=%d.",
|
||||
errno);
|
||||
}
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
if (!sfxAllowed()) return;
|
||||
|
||||
setMasterSFXVolume( UserConfigParams::m_sfx_volume );
|
||||
m_sfx_commands.lock();
|
||||
m_sfx_commands.getData().clear();
|
||||
@@ -211,29 +209,34 @@ void SFXManager::queue(SFXCommands command, SFXBase *sfx, const Vec3 &p)
|
||||
void SFXManager::queueCommand(SFXCommand *command)
|
||||
{
|
||||
m_sfx_commands.lock();
|
||||
if(m_sfx_commands.getData().size() > 20*race_manager->getNumberOfKarts()+20)
|
||||
{
|
||||
if(command->m_command==SFX_POSITION || command->m_command==SFX_LOOP ||
|
||||
command->m_command==SFX_PLAY || command->m_command==SFX_SPEED )
|
||||
{
|
||||
delete command;
|
||||
static int count_messages = 0;
|
||||
if(count_messages < 5)
|
||||
{
|
||||
Log::warn("SFXManager", "Throttling sfx - queue size %d",
|
||||
m_sfx_commands.getData().size());
|
||||
count_messages++;
|
||||
}
|
||||
m_sfx_commands.unlock();
|
||||
return;
|
||||
} // if throttling
|
||||
}
|
||||
m_sfx_commands.getData().push_back(command);
|
||||
m_sfx_commands.unlock();
|
||||
} // queueCommand
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** Make sures that the sfx thread is started at least one per frame. It also
|
||||
* adds an update command for the music manager.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
void SFXManager::update(float dt)
|
||||
{
|
||||
queue(SFX_UPDATE_MUSIC, NULL, dt);
|
||||
// Wake up the sfx thread to handle all queued up audio commands.
|
||||
pthread_cond_signal(&m_cond_request);
|
||||
} // update
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** Puts a NULL request into the queue, which will trigger the thread to
|
||||
* exit.
|
||||
*/
|
||||
void SFXManager::stopThread()
|
||||
{
|
||||
queue(SFX_EXIT, NULL);
|
||||
queue(SFX_EXIT);
|
||||
// Make sure the thread wakes up.
|
||||
pthread_cond_signal(&m_cond_request);
|
||||
} // stopThread
|
||||
@@ -266,13 +269,11 @@ void* SFXManager::mainLoop(void *obj)
|
||||
pthread_cond_wait(&me->m_cond_request, me->m_sfx_commands.getMutex());
|
||||
empty = me->m_sfx_commands.getData().empty();
|
||||
}
|
||||
|
||||
SFXCommand *current = me->m_sfx_commands.getData().front();
|
||||
me->m_sfx_commands.getData().erase(me->m_sfx_commands.getData().begin());
|
||||
|
||||
if (current->m_command == SFX_EXIT)
|
||||
break;
|
||||
|
||||
me->m_sfx_commands.unlock();
|
||||
switch(current->m_command)
|
||||
{
|
||||
@@ -286,13 +287,18 @@ void* SFXManager::mainLoop(void *obj)
|
||||
current->m_parameter); break;
|
||||
case SFX_VOLUME: current->m_sfx->reallySetVolume(
|
||||
current->m_parameter.getX()); break;
|
||||
case SFX_MASTER_VOLUME:
|
||||
current->m_sfx->reallySetMasterVolumeNow(
|
||||
current->m_parameter.getX()); break;
|
||||
case SFX_LOOP: current->m_sfx->reallySetLoop(
|
||||
current->m_parameter.getX()!=0); break;
|
||||
case SFX_DELETE: {
|
||||
current->m_sfx->reallyStopNow();
|
||||
me->deleteSFX(current->m_sfx); break;
|
||||
}
|
||||
case SFX_LISTENER: me->reallyPositionListenerNow(); break;
|
||||
case SFX_UPDATE_MUSIC: music_manager->update(
|
||||
current->m_parameter.getX()); break;
|
||||
case SFX_PAUSE_ALL: me->reallyPauseAllNow(); break;
|
||||
case SFX_RESUME_ALL: me->reallyResumeAllNow(); break;
|
||||
case SFX_LISTENER: me->reallyPositionListenerNow(); break;
|
||||
case SFX_UPDATE: me->reallyUpdateNow(current); break;
|
||||
default: assert("Not yet supported.");
|
||||
}
|
||||
delete current;
|
||||
@@ -315,7 +321,7 @@ void* SFXManager::mainLoop(void *obj)
|
||||
* resumes all sound effects.
|
||||
* \param on If sound is switched on or off.
|
||||
*/
|
||||
void SFXManager::soundToggled(const bool on)
|
||||
void SFXManager::toggleSound(const bool on)
|
||||
{
|
||||
// When activating SFX, load all buffers
|
||||
if (on)
|
||||
@@ -327,7 +333,7 @@ void SFXManager::soundToggled(const bool on)
|
||||
buffer->load();
|
||||
}
|
||||
|
||||
resumeAll();
|
||||
reallyResumeAllNow();
|
||||
m_all_sfx.lock();
|
||||
const int sfx_amount = (int)m_all_sfx.getData().size();
|
||||
for (int n=0; n<sfx_amount; n++)
|
||||
@@ -338,9 +344,20 @@ void SFXManager::soundToggled(const bool on)
|
||||
}
|
||||
else
|
||||
{
|
||||
// First stop all sfx that are not looped
|
||||
const int sfx_amount = (int)m_all_sfx.getData().size();
|
||||
m_all_sfx.lock();
|
||||
for (int i=0; i<sfx_amount; i++)
|
||||
{
|
||||
if(!m_all_sfx.getData()[i]->isLooped())
|
||||
{
|
||||
m_all_sfx.getData()[i]->reallyStopNow();
|
||||
}
|
||||
}
|
||||
m_all_sfx.unlock();
|
||||
pauseAll();
|
||||
}
|
||||
} // soundToggled
|
||||
} // toggleSound
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** Returns if sfx can be played. This means sfx are enabled and
|
||||
@@ -440,7 +457,7 @@ SFXBuffer* SFXManager::addSingleSfx(const std::string &sfx_name,
|
||||
}
|
||||
|
||||
if (UserConfigParams::logMisc())
|
||||
Log::debug("SFXManager", "Loading SFX %s\n", sfx_file.c_str());
|
||||
Log::debug("SFXManager", "Loading SFX %s", sfx_file.c_str());
|
||||
|
||||
if (load && buffer->load()) return buffer;
|
||||
|
||||
@@ -460,7 +477,7 @@ SFXBuffer* SFXManager::loadSingleSfx(const XMLNode* node,
|
||||
if (node->get("filename", &filename) == 0)
|
||||
{
|
||||
Log::error("SFXManager",
|
||||
"/!\\ The 'filename' attribute is mandatory in the SFX XML file!\n");
|
||||
"The 'filename' attribute is mandatory in the SFX XML file!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -469,7 +486,7 @@ SFXBuffer* SFXManager::loadSingleSfx(const XMLNode* node,
|
||||
if(m_all_sfx_types.find(sfx_name)!=m_all_sfx_types.end())
|
||||
{
|
||||
Log::error("SFXManager",
|
||||
"There is already a sfx named '%s' installed - new one is ignored.\n",
|
||||
"There is already a sfx named '%s' installed - new one is ignored.",
|
||||
sfx_name.c_str());
|
||||
return NULL;
|
||||
}
|
||||
@@ -537,7 +554,7 @@ SFXBase* SFXManager::createSoundSource(const std::string &name,
|
||||
{
|
||||
Log::error("SFXManager",
|
||||
"SFXManager::createSoundSource could not find the "
|
||||
"requested sound effect : '%s'\n", name.c_str());
|
||||
"requested sound effect : '%s'.", name.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -575,6 +592,38 @@ void SFXManager::deleteSFXMapping(const std::string &name)
|
||||
|
||||
} // deleteSFXMapping
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** Make sures that the sfx thread is started at least one per frame. It also
|
||||
* adds an update command for the music manager.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
void SFXManager::update(float dt)
|
||||
{
|
||||
queue(SFX_UPDATE, NULL, dt);
|
||||
// Wake up the sfx thread to handle all queued up audio commands.
|
||||
pthread_cond_signal(&m_cond_request);
|
||||
} // update
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** Updates the status of all playing sfx (to test if they are finished).
|
||||
* This function is executed once per thread (triggered by the
|
||||
*/
|
||||
void SFXManager::reallyUpdateNow(SFXCommand *current)
|
||||
{
|
||||
assert(current->m_command==SFX_UPDATE);
|
||||
float dt = current->m_parameter.getX();
|
||||
music_manager->update(dt);
|
||||
m_all_sfx.lock();
|
||||
for (std::vector<SFXBase*>::iterator i = m_all_sfx.getData().begin();
|
||||
i != m_all_sfx.getData().end(); i++)
|
||||
{
|
||||
if((*i)->getStatus()==SFXBase::SFX_PLAYING)
|
||||
(*i)->updatePlayingSFX(dt);
|
||||
} // for i in m_all_sfx
|
||||
m_all_sfx.unlock();
|
||||
|
||||
} // reallyUpdateNow
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** Delete a sound effect object, and removes it from the internal list of
|
||||
* all SFXs. This call deletes the object, and removes it from the list of
|
||||
@@ -596,45 +645,63 @@ void SFXManager::deleteSFX(SFXBase *sfx)
|
||||
Log::warn("SFXManager",
|
||||
"SFXManager::deleteSFX : Warning: sfx '%s' %lx not found in list.",
|
||||
sfx->getBuffer()->getFileName().c_str(), sfx);
|
||||
m_all_sfx.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
m_all_sfx.getData().erase(i);
|
||||
delete sfx;
|
||||
|
||||
m_all_sfx.unlock();
|
||||
|
||||
delete sfx;
|
||||
} // deleteSFX
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** Pauses all looping SFXs. Non-looping SFX will be finished, since it's
|
||||
* otherwise not possible to determine which SFX must be resumed (i.e. were
|
||||
* actually playing at the time pause was called).
|
||||
*/
|
||||
void SFXManager::pauseAll()
|
||||
{
|
||||
if (!sfxAllowed()) return;
|
||||
queue(SFX_PAUSE_ALL);
|
||||
} // pauseAll
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** Pauses all looping SFXs. Non-looping SFX will be finished, since it's
|
||||
* otherwise not possible to determine which SFX must be resumed (i.e. were
|
||||
* actually playing at the time pause was called.
|
||||
*/
|
||||
void SFXManager::pauseAll()
|
||||
void SFXManager::reallyPauseAllNow()
|
||||
{
|
||||
m_all_sfx.lock();
|
||||
for (std::vector<SFXBase*>::iterator i= m_all_sfx.getData().begin();
|
||||
i!=m_all_sfx.getData().end(); i++)
|
||||
{
|
||||
(*i)->pause();
|
||||
(*i)->reallyPauseNow();
|
||||
} // for i in m_all_sfx
|
||||
m_all_sfx.unlock();
|
||||
} // pauseAll
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/**
|
||||
* Resumes all paused SFXs. If sound is disabled, does nothing.
|
||||
/** Resumes all paused SFXs. If sound is disabled, does nothing.
|
||||
*/
|
||||
void SFXManager::resumeAll()
|
||||
{
|
||||
// ignore unpausing if sound is disabled
|
||||
if (!sfxAllowed()) return;
|
||||
queue(SFX_RESUME_ALL);
|
||||
} // resumeAll
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** Resumes all paused SFXs. If sound is disabled, does nothing.
|
||||
*/
|
||||
void SFXManager::reallyResumeAllNow()
|
||||
{
|
||||
m_all_sfx.lock();
|
||||
for (std::vector<SFXBase*>::iterator i =m_all_sfx.getData().begin();
|
||||
i!=m_all_sfx.getData().end(); i++)
|
||||
{
|
||||
(*i)->resume();
|
||||
(*i)->reallyResumeNow();
|
||||
} // for i in m_all_sfx
|
||||
m_all_sfx.unlock();
|
||||
} // resumeAll
|
||||
@@ -727,7 +794,7 @@ void SFXManager::positionListener(const Vec3 &position, const Vec3 &front,
|
||||
m_listener_front = front;
|
||||
m_listener_up = up;
|
||||
m_listener_position.unlock();
|
||||
queue(SFX_LISTENER, NULL);
|
||||
queue(SFX_LISTENER);
|
||||
} // positionListener
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -65,13 +65,17 @@ public:
|
||||
SFX_PLAY = 1,
|
||||
SFX_STOP,
|
||||
SFX_PAUSE,
|
||||
SFX_PAUSE_ALL,
|
||||
SFX_RESUME,
|
||||
SFX_RESUME_ALL,
|
||||
SFX_DELETE,
|
||||
SFX_SPEED,
|
||||
SFX_POSITION,
|
||||
SFX_VOLUME,
|
||||
SFX_MASTER_VOLUME,
|
||||
SFX_LOOP,
|
||||
SFX_LISTENER,
|
||||
SFX_UPDATE_MUSIC,
|
||||
SFX_UPDATE,
|
||||
SFX_EXIT,
|
||||
}; // SFXCommands
|
||||
|
||||
@@ -180,7 +184,7 @@ private:
|
||||
public:
|
||||
static void create();
|
||||
static void destroy();
|
||||
void queue(SFXCommands command, SFXBase *sfx);
|
||||
void queue(SFXCommands command, SFXBase *sfx=NULL);
|
||||
void queue(SFXCommands command, SFXBase *sfx, float f);
|
||||
void queue(SFXCommands command, SFXBase *sfx, const Vec3 &p);
|
||||
// ------------------------------------------------------------------------
|
||||
@@ -206,15 +210,18 @@ public:
|
||||
const bool load = true);
|
||||
|
||||
SFXBase* createSoundSource(SFXBuffer* info,
|
||||
const bool addToSFXList=true,
|
||||
const bool add_to_SFX_list=true,
|
||||
const bool owns_buffer=false);
|
||||
SFXBase* createSoundSource(const std::string &name,
|
||||
const bool addToSFXList=true);
|
||||
|
||||
void deleteSFXMapping(const std::string &name);
|
||||
void pauseAll();
|
||||
void reallyPauseAllNow();
|
||||
void resumeAll();
|
||||
void reallyResumeAllNow();
|
||||
void update(float dt);
|
||||
void reallyUpdateNow(SFXCommand *current);
|
||||
bool soundExist(const std::string &name);
|
||||
void setMasterSFXVolume(float gain);
|
||||
float getMasterSFXVolume() const { return m_master_gain; }
|
||||
@@ -227,7 +234,7 @@ public:
|
||||
SFXBase* quickSound(const std::string &soundName);
|
||||
|
||||
/** Called when sound was muted/unmuted */
|
||||
void soundToggled(const bool newValue);
|
||||
void toggleSound(const bool newValue);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Prints the list of currently loaded sounds to stdout. Useful to
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2006-2013 Patrick Ammann <pammann@aro.ch>
|
||||
// Copyright (C) 2009-2013 Marianne Gagnon
|
||||
// Copyright (C) 2014 Joerg Henrichs
|
||||
// Copyright (C) 2006-2014 Patrick Ammann <pammann@aro.ch>
|
||||
// Copyright (C) 2009-2014 Marianne Gagnon
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
@@ -37,19 +38,20 @@
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
SFXOpenAL::SFXOpenAL(SFXBuffer* buffer, bool positional, float gain, bool owns_buffer) : SFXBase()
|
||||
SFXOpenAL::SFXOpenAL(SFXBuffer* buffer, bool positional, float gain,
|
||||
bool owns_buffer)
|
||||
: SFXBase()
|
||||
{
|
||||
m_sound_buffer = buffer;
|
||||
m_sound_source = 0;
|
||||
m_status = SFX_UNKNOWN;
|
||||
m_is_playing = false;
|
||||
m_status = SFX_NOT_INITIALISED;
|
||||
m_positional = positional;
|
||||
m_defaultGain = gain;
|
||||
m_default_gain = gain;
|
||||
m_loop = false;
|
||||
m_gain = -1.0f;
|
||||
m_master_gain = 1.0f;
|
||||
m_owns_buffer = owns_buffer;
|
||||
m_end_time = -1.0f;
|
||||
m_play_time = 0.0f;
|
||||
|
||||
// Don't initialise anything else if the sfx manager was not correctly
|
||||
// initialised. First of all the initialisation will not work, and it
|
||||
@@ -78,11 +80,15 @@ SFXOpenAL::~SFXOpenAL()
|
||||
} // ~SFXOpenAL
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** Initialises the sfx.
|
||||
*/
|
||||
bool SFXOpenAL::init()
|
||||
{
|
||||
m_status = SFX_UNKNOWN;
|
||||
|
||||
alGenSources(1, &m_sound_source );
|
||||
if (!SFXManager::checkError("generating a source")) return false;
|
||||
if (!SFXManager::checkError("generating a source"))
|
||||
return false;
|
||||
|
||||
assert( alIsBuffer(m_sound_buffer->getBufferID()) );
|
||||
assert( alIsSource(m_sound_source) );
|
||||
@@ -101,7 +107,7 @@ bool SFXOpenAL::init()
|
||||
|
||||
if (m_gain < 0.0f)
|
||||
{
|
||||
alSourcef (m_sound_source, AL_GAIN, m_defaultGain * m_master_gain);
|
||||
alSourcef (m_sound_source, AL_GAIN, m_default_gain * m_master_gain);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -113,27 +119,26 @@ bool SFXOpenAL::init()
|
||||
|
||||
alSourcei(m_sound_source, AL_LOOPING, m_loop ? AL_TRUE : AL_FALSE);
|
||||
|
||||
if(SFXManager::checkError("setting up the source"))
|
||||
m_status = SFX_INITIAL;
|
||||
if(!SFXManager::checkError("setting up the source"))
|
||||
return false;
|
||||
|
||||
return m_status==SFX_INITIAL;
|
||||
m_status = SFX_STOPPED;
|
||||
return true;
|
||||
} // init
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the status of this sfx. */
|
||||
SFXBase::SFXStatus SFXOpenAL::getStatus()
|
||||
/** Updates the status of a playing sfx. If the sound has been played long
|
||||
* enough, mark it to be finished. This avoid (a potentially costly)
|
||||
* call to openal.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
void SFXOpenAL::updatePlayingSFX(float dt)
|
||||
{
|
||||
if(m_status==SFX_PLAYING)
|
||||
{
|
||||
if(m_loop) return SFX_PLAYING;
|
||||
if(World::getWorld() && World::getWorld()->getTime() > m_end_time)
|
||||
{
|
||||
m_status = SFX_STOPPED;
|
||||
return m_status;
|
||||
}
|
||||
}
|
||||
return m_status;
|
||||
} // getStatus;
|
||||
assert(m_status==SFX_PLAYING);
|
||||
m_play_time += dt;
|
||||
if(!m_loop && m_play_time > m_sound_buffer->getDuration())
|
||||
m_status = SFX_STOPPED;
|
||||
} // updatePlayingSFX
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Queues up a change of the pitch of a sound effect to the sfx manager.
|
||||
@@ -141,7 +146,7 @@ SFXBase::SFXStatus SFXOpenAL::getStatus()
|
||||
*/
|
||||
void SFXOpenAL::setSpeed(float factor)
|
||||
{
|
||||
if(m_status==SFX_UNKNOWN) return;
|
||||
if(m_status==SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
|
||||
assert(!isnan(factor));
|
||||
SFXManager::get()->queue(SFXManager::SFX_SPEED, this, factor);
|
||||
} // setSpeed
|
||||
@@ -152,7 +157,13 @@ void SFXOpenAL::setSpeed(float factor)
|
||||
*/
|
||||
void SFXOpenAL::reallySetSpeed(float factor)
|
||||
{
|
||||
if(m_status==SFX_UNKNOWN) return;
|
||||
if(m_status==SFX_NOT_INITIALISED)
|
||||
{
|
||||
init();
|
||||
if(m_status==SFX_UNKNOWN)
|
||||
return;
|
||||
}
|
||||
|
||||
//OpenAL only accepts pitches in the range of 0.5 to 2.0
|
||||
if(factor > 2.0f)
|
||||
{
|
||||
@@ -171,7 +182,7 @@ void SFXOpenAL::reallySetSpeed(float factor)
|
||||
*/
|
||||
void SFXOpenAL::setVolume(float gain)
|
||||
{
|
||||
if(m_status==SFX_UNKNOWN) return;
|
||||
if(m_status==SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
|
||||
assert(!isnan(gain)) ;
|
||||
SFXManager::get()->queue(SFXManager::SFX_VOLUME, this, gain);
|
||||
} // setVolume
|
||||
@@ -182,45 +193,79 @@ void SFXOpenAL::setVolume(float gain)
|
||||
*/
|
||||
void SFXOpenAL::reallySetVolume(float gain)
|
||||
{
|
||||
if(m_status==SFX_UNKNOWN) return;
|
||||
m_gain = m_defaultGain * gain;
|
||||
m_gain = m_default_gain * gain;
|
||||
|
||||
if(m_status==SFX_UNKNOWN) return;
|
||||
|
||||
if(m_status==SFX_NOT_INITIALISED)
|
||||
{
|
||||
init();
|
||||
if(m_status==SFX_UNKNOWN)
|
||||
return;
|
||||
}
|
||||
|
||||
alSourcef(m_sound_source, AL_GAIN, m_gain * m_master_gain);
|
||||
} // reallySetVolume
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** Schedules setting of the master volume.
|
||||
* \param gain Gain value.
|
||||
*/
|
||||
void SFXOpenAL::setMasterVolume(float gain)
|
||||
{
|
||||
// This needs to be called even if sfx are disabled atm, so only exit
|
||||
// in case that the sfx could not be loaded in the first place.
|
||||
if(m_status==SFX_UNKNOWN) return;
|
||||
SFXManager::get()->queue(SFXManager::SFX_MASTER_VOLUME, this, gain);
|
||||
} // setMasterVolume
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets the master volume.
|
||||
* \param gain Master volume.
|
||||
*/
|
||||
void SFXOpenAL::reallySetMasterVolumeNow(float gain)
|
||||
{
|
||||
m_master_gain = gain;
|
||||
|
||||
if(m_status==SFX_UNKNOWN) return;
|
||||
if(m_status==SFX_UNKNOWN || m_status == SFX_NOT_INITIALISED) return;
|
||||
|
||||
alSourcef(m_sound_source, AL_GAIN,
|
||||
(m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain);
|
||||
(m_gain < 0.0f ? m_default_gain : m_gain) * m_master_gain);
|
||||
SFXManager::checkError("setting volume");
|
||||
} //setMasterVolume
|
||||
} // reallySetMasterVolumeNow
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Loops this sound effect.
|
||||
*/
|
||||
void SFXOpenAL::setLoop(bool status)
|
||||
{
|
||||
m_loop = status;
|
||||
if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
|
||||
SFXManager::get()->queue(SFXManager::SFX_LOOP, this, status ? 1.0f : 0.0f);
|
||||
} // setLoop
|
||||
|
||||
if(m_status==SFX_UNKNOWN) return;
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Loops this sound effect.
|
||||
*/
|
||||
void SFXOpenAL::reallySetLoop(bool status)
|
||||
{
|
||||
if(m_status==SFX_NOT_INITIALISED)
|
||||
{
|
||||
init();
|
||||
if(m_status==SFX_UNKNOWN)
|
||||
return;
|
||||
}
|
||||
m_loop = status;
|
||||
|
||||
alSourcei(m_sound_source, AL_LOOPING, status ? AL_TRUE : AL_FALSE);
|
||||
SFXManager::checkError("looping");
|
||||
} // loop
|
||||
} // reallySetLoop
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Queues a stop for this effect to the sound manager.
|
||||
*/
|
||||
void SFXOpenAL::stop()
|
||||
{
|
||||
if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
|
||||
SFXManager::get()->queue(SFXManager::SFX_STOP, this);
|
||||
} // stop
|
||||
|
||||
@@ -229,14 +274,14 @@ void SFXOpenAL::stop()
|
||||
*/
|
||||
void SFXOpenAL::reallyStopNow()
|
||||
{
|
||||
if(m_status==SFX_UNKNOWN) return;
|
||||
|
||||
m_is_playing = false;
|
||||
m_status = SFX_STOPPED;
|
||||
m_loop = false;
|
||||
alSourcei(m_sound_source, AL_LOOPING, AL_FALSE);
|
||||
alSourceStop(m_sound_source);
|
||||
SFXManager::checkError("stoping");
|
||||
if(m_status==SFX_PLAYING || m_status==SFX_PAUSED)
|
||||
{
|
||||
m_status = SFX_STOPPED;
|
||||
m_loop = false;
|
||||
alSourcei(m_sound_source, AL_LOOPING, AL_FALSE);
|
||||
alSourceStop(m_sound_source);
|
||||
SFXManager::checkError("stoping");
|
||||
}
|
||||
} // reallyStopNow
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -253,11 +298,9 @@ void SFXOpenAL::pause()
|
||||
*/
|
||||
void SFXOpenAL::reallyPauseNow()
|
||||
{
|
||||
// This updates the status, i.e. potentially switches from
|
||||
// playing to stopped.
|
||||
getStatus();
|
||||
if(m_status!=SFX_PLAYING) return;
|
||||
|
||||
// Need to be tested again here, since this function can be called
|
||||
// from pauseAll, and we have to make sure to only pause playing sfx.
|
||||
if (m_status != SFX_PLAYING || !SFXManager::get()->sfxAllowed()) return;
|
||||
m_status = SFX_PAUSED;
|
||||
alSourcePause(m_sound_source);
|
||||
SFXManager::checkError("pausing");
|
||||
@@ -268,6 +311,7 @@ void SFXOpenAL::reallyPauseNow()
|
||||
*/
|
||||
void SFXOpenAL::resume()
|
||||
{
|
||||
if (m_status != SFX_PLAYING || !SFXManager::get()->sfxAllowed()) return;
|
||||
SFXManager::get()->queue(SFXManager::SFX_RESUME, this);
|
||||
} // resume
|
||||
|
||||
@@ -276,8 +320,13 @@ void SFXOpenAL::resume()
|
||||
*/
|
||||
void SFXOpenAL::reallyResumeNow()
|
||||
{
|
||||
// Will init the sfx (lazy) if necessary.
|
||||
getStatus();
|
||||
if(m_status==SFX_NOT_INITIALISED)
|
||||
{
|
||||
init();
|
||||
if(m_status==SFX_UNKNOWN)
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_status==SFX_PAUSED)
|
||||
{
|
||||
alSourcePlay(m_sound_source);
|
||||
@@ -286,6 +335,98 @@ void SFXOpenAL::reallyResumeNow()
|
||||
}
|
||||
} // reallyResumeNow
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This actually queues up the sfx in the sfx manager. It will be started
|
||||
* from a separate thread later (in this frame).
|
||||
*/
|
||||
void SFXOpenAL::play()
|
||||
{
|
||||
if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
|
||||
|
||||
if(m_status==SFX_STOPPED)
|
||||
m_play_time = 0.0f;
|
||||
|
||||
// Technically the sfx is only playing after the sfx thread starts it,
|
||||
// but it is important to set this here since stk might decide to
|
||||
// delete a sfx if it has finished playing (i.e. is in stopped state)
|
||||
// - which can happen if the sfx thread had no time to actually start
|
||||
// it yet.
|
||||
m_status = SFX_PLAYING;
|
||||
SFXManager::get()->queue(SFXManager::SFX_PLAY, this);
|
||||
} // play
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Plays this sound effect.
|
||||
*/
|
||||
void SFXOpenAL::reallyPlayNow()
|
||||
{
|
||||
if (!SFXManager::get()->sfxAllowed()) return;
|
||||
if (m_status==SFX_NOT_INITIALISED)
|
||||
{
|
||||
// lazily create OpenAL source when needed
|
||||
init();
|
||||
|
||||
// creation of OpenAL source failed, giving up
|
||||
if (m_status==SFX_UNKNOWN) return;
|
||||
}
|
||||
|
||||
alSourcePlay(m_sound_source);
|
||||
SFXManager::checkError("playing");
|
||||
} // reallyPlayNow
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets the position where this sound effects is played.
|
||||
* \param position Position of the sound effect.
|
||||
*/
|
||||
void SFXOpenAL::setPosition(const Vec3 &position)
|
||||
{
|
||||
if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
|
||||
SFXManager::get()->queue(SFXManager::SFX_POSITION, this, position);
|
||||
|
||||
} // setPosition
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets the position where this sound effects is played.
|
||||
* \param position Position of the sound effect.
|
||||
*/
|
||||
void SFXOpenAL::reallySetPosition(const Vec3 &position)
|
||||
{
|
||||
if(m_status==SFX_NOT_INITIALISED)
|
||||
{
|
||||
init();
|
||||
if(m_status==SFX_UNKNOWN)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_positional)
|
||||
{
|
||||
// in multiplayer, all sounds are positional, so in this case don't
|
||||
// bug users with an error message if (note that 0 players is also
|
||||
// possible, in cutscenes)
|
||||
if (race_manager->getNumLocalPlayers() < 2)
|
||||
{
|
||||
Log::warn("SFX", "Position called on non-positional SFX");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
alSource3f(m_sound_source, AL_POSITION, (float)position.getX(),
|
||||
(float)position.getY(), (float)position.getZ());
|
||||
|
||||
if (SFXManager::get()->getListenerPos().distance(position)
|
||||
> m_sound_buffer->getMaxDist())
|
||||
{
|
||||
alSourcef(m_sound_source, AL_GAIN, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
alSourcef(m_sound_source, AL_GAIN,
|
||||
(m_gain < 0.0f ? m_default_gain : m_gain) * m_master_gain);
|
||||
}
|
||||
|
||||
SFXManager::checkError("positioning");
|
||||
} // reallySetPosition
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Queues up a delete request for this object. This is necessary to avoid
|
||||
* a crash if the sfx manager thread might be delayed and access this object
|
||||
@@ -296,118 +437,20 @@ void SFXOpenAL::deleteSFX()
|
||||
SFXManager::get()->queue(SFXManager::SFX_DELETE, this);
|
||||
} // deleteSFX
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This actually queues up the sfx in the sfx manager. It will be started
|
||||
* from a separate thread later (in this frame).
|
||||
*/
|
||||
void SFXOpenAL::play()
|
||||
{
|
||||
// Technically the sfx is only playing after the sfx thread starts it,
|
||||
// but for STK this is correct since we don't want to start the same
|
||||
// sfx twice.
|
||||
m_is_playing = true;
|
||||
SFXManager::get()->queue(SFXManager::SFX_PLAY, this);
|
||||
} // play
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Plays this sound effect.
|
||||
*/
|
||||
void SFXOpenAL::reallyPlayNow()
|
||||
{
|
||||
if (!SFXManager::get()->sfxAllowed()) return;
|
||||
if (m_status==SFX_UNKNOWN)
|
||||
{
|
||||
// lazily create OpenAL source when needed
|
||||
init();
|
||||
|
||||
// creation of OpenAL source failed, giving up
|
||||
if (m_status==SFX_UNKNOWN) return;
|
||||
}
|
||||
|
||||
alSourcePlay(m_sound_source);
|
||||
m_status = SFX_PLAYING;
|
||||
SFXManager::checkError("playing");
|
||||
|
||||
// At non-race time the end time is not important
|
||||
if(World::getWorld())
|
||||
m_end_time = World::getWorld()->getTime()+m_sound_buffer->getDuration();
|
||||
else
|
||||
m_end_time = 1.0f;
|
||||
} // reallyPlayNow
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns true if the sound effect is currently playing.
|
||||
*/
|
||||
bool SFXOpenAL::isPlaying()
|
||||
{
|
||||
return m_is_playing;
|
||||
} // isPlaying
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets the position where this sound effects is played.
|
||||
* \param position Position of the sound effect.
|
||||
*/
|
||||
void SFXOpenAL::setPosition(const Vec3 &position)
|
||||
{
|
||||
if (m_status == SFX_UNKNOWN) return;
|
||||
SFXManager::get()->queue(SFXManager::SFX_POSITION, this, position);
|
||||
|
||||
} // setPosition
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets the position where this sound effects is played.
|
||||
* \param position Position of the sound effect.
|
||||
*/
|
||||
void SFXOpenAL::reallySetPosition(const Vec3 &position)
|
||||
{
|
||||
if(!UserConfigParams::m_sfx)
|
||||
return;
|
||||
if (m_status==SFX_UNKNOWN)
|
||||
{
|
||||
Log::warn("SFX", "Position called on non-ok SFX <%s>",
|
||||
m_sound_buffer->getFileName().c_str());
|
||||
return;
|
||||
}
|
||||
if (!m_positional)
|
||||
{
|
||||
// in multiplayer, all sounds are positional, so in this case don't bug users with
|
||||
// an error message if (race_manager->getNumLocalPlayers() > 1)
|
||||
// (note that 0 players is also possible, in cutscenes)
|
||||
if (race_manager->getNumLocalPlayers() < 2)
|
||||
{
|
||||
Log::warn("SFX", "Position called on non-positional SFX");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
alSource3f(m_sound_source, AL_POSITION,
|
||||
(float)position.getX(), (float)position.getY(), (float)position.getZ());
|
||||
|
||||
if (SFXManager::get()->getListenerPos().distance(position) > m_sound_buffer->getMaxDist())
|
||||
{
|
||||
alSourcef(m_sound_source, AL_GAIN, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
alSourcef(m_sound_source, AL_GAIN, (m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain);
|
||||
}
|
||||
|
||||
SFXManager::checkError("positioning");
|
||||
} // reallySetPosition
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXOpenAL::onSoundEnabledBack()
|
||||
{
|
||||
if (m_loop)
|
||||
{
|
||||
if (m_status==SFX_UNKNOWN) init();
|
||||
if (m_status==SFX_NOT_INITIALISED) init();
|
||||
if (m_status!=SFX_UNKNOWN)
|
||||
{
|
||||
alSourcef(m_sound_source, AL_GAIN, 0);
|
||||
play();
|
||||
pause();
|
||||
alSourcef(m_sound_source, AL_GAIN, (m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain);
|
||||
alSourcef(m_sound_source, AL_GAIN,
|
||||
(m_gain < 0.0f ? m_default_gain : m_gain) * m_master_gain);
|
||||
}
|
||||
}
|
||||
} // onSoundEnabledBack
|
||||
|
||||
@@ -48,8 +48,11 @@ private:
|
||||
/** The status of this SFX. */
|
||||
SFXStatus m_status;
|
||||
|
||||
/** If the sfx is positional. */
|
||||
bool m_positional;
|
||||
float m_defaultGain;
|
||||
|
||||
/** Default gain value. */
|
||||
float m_default_gain;
|
||||
|
||||
/** The OpenAL source contains this info, but if audio is disabled initially then
|
||||
the sound source won't be created and we'll be left with no clue when enabling
|
||||
@@ -62,9 +65,6 @@ private:
|
||||
the sound source won't be created and we'll be left with no clue when enabling
|
||||
sounds later. */
|
||||
float m_gain;
|
||||
|
||||
/** True when the sfx is currently playing. */
|
||||
bool m_is_playing;
|
||||
|
||||
/** The master gain set in user preferences */
|
||||
float m_master_gain;
|
||||
@@ -72,20 +72,20 @@ private:
|
||||
/** If this sfx should also free the sound buffer. */
|
||||
bool m_owns_buffer;
|
||||
|
||||
/** Time at which a sfx ends playing. Used to avoid frequently getting
|
||||
* the openl status (which can slow down stk). */
|
||||
float m_end_time;
|
||||
/** How long the sfx has been playing. */
|
||||
float m_play_time;
|
||||
|
||||
public:
|
||||
SFXOpenAL(SFXBuffer* buffer, bool positional, float gain,
|
||||
bool owns_buffer = false);
|
||||
virtual ~SFXOpenAL();
|
||||
|
||||
virtual void updatePlayingSFX(float dt);
|
||||
virtual bool init();
|
||||
virtual void play();
|
||||
virtual void reallyPlayNow();
|
||||
virtual void setLoop(bool status);
|
||||
virtual bool isPlaying();
|
||||
virtual void reallySetLoop(bool status);
|
||||
virtual void stop();
|
||||
virtual void reallyStopNow();
|
||||
virtual void pause();
|
||||
@@ -100,9 +100,15 @@ public:
|
||||
virtual void setVolume(float gain);
|
||||
virtual void reallySetVolume(float gain);
|
||||
virtual void setMasterVolume(float gain);
|
||||
virtual void reallySetMasterVolumeNow(float gain);
|
||||
virtual void onSoundEnabledBack();
|
||||
virtual void setRolloff(float rolloff);
|
||||
virtual SFXStatus getStatus();
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if this sfx is looped or not. */
|
||||
virtual bool isLooped() { return m_loop; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the status of this sfx. */
|
||||
virtual SFXStatus getStatus() { return m_status; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the buffer associated with this sfx. */
|
||||
|
||||
@@ -68,6 +68,7 @@ SavedGrandPrix::SavedGrandPrix(unsigned int player_id,
|
||||
RaceManager::Difficulty difficulty,
|
||||
int player_karts,
|
||||
int last_track,
|
||||
int reverse_type,
|
||||
const std::vector<RaceManager::KartStatus> &kart_list)
|
||||
: m_savedgp_group("SavedGP",
|
||||
"Represents the saved state of a GP"),
|
||||
@@ -75,7 +76,8 @@ SavedGrandPrix::SavedGrandPrix(unsigned int player_id,
|
||||
m_gp_id(gp_id.c_str(), "gp_id", &m_savedgp_group),
|
||||
m_difficulty((int)difficulty,"difficulty", &m_savedgp_group),
|
||||
m_player_karts(player_karts,"player_karts", &m_savedgp_group),
|
||||
m_next_track(last_track,"last_track", &m_savedgp_group)
|
||||
m_next_track(last_track,"last_track", &m_savedgp_group),
|
||||
m_reverse_type(reverse_type,"reverse_type", &m_savedgp_group)
|
||||
{
|
||||
for(unsigned int i =0; i < kart_list.size(); i++)
|
||||
{
|
||||
@@ -94,18 +96,20 @@ SavedGrandPrix::SavedGrandPrix(unsigned int player_id,
|
||||
SavedGrandPrix::SavedGrandPrix(const XMLNode* node)
|
||||
: m_savedgp_group("SavedGP",
|
||||
"Represents the saved state of a GP"),
|
||||
m_player_id(0, "player_id", &m_savedgp_group),
|
||||
m_gp_id("-", "gp_id", &m_savedgp_group),
|
||||
m_difficulty(0,"difficulty", &m_savedgp_group),
|
||||
m_player_id (0, "player_id", &m_savedgp_group),
|
||||
m_gp_id ("-", "gp_id", &m_savedgp_group),
|
||||
m_difficulty (0,"difficulty", &m_savedgp_group),
|
||||
m_player_karts(0,"player_karts", &m_savedgp_group),
|
||||
m_next_track(0,"last_track", &m_savedgp_group)
|
||||
m_next_track (0,"last_track", &m_savedgp_group),
|
||||
m_reverse_type(0,"reverse_type", &m_savedgp_group)
|
||||
{
|
||||
//m_player_group.findYourDataInAChildOf(node);
|
||||
m_player_id.findYourDataInAnAttributeOf(node);
|
||||
m_gp_id.findYourDataInAnAttributeOf(node);
|
||||
m_difficulty.findYourDataInAnAttributeOf(node);
|
||||
m_player_id. findYourDataInAnAttributeOf(node);
|
||||
m_gp_id. findYourDataInAnAttributeOf(node);
|
||||
m_difficulty. findYourDataInAnAttributeOf(node);
|
||||
m_player_karts.findYourDataInAnAttributeOf(node);
|
||||
m_next_track.findYourDataInAnAttributeOf(node);
|
||||
m_next_track. findYourDataInAnAttributeOf(node);
|
||||
m_reverse_type.findYourDataInAnAttributeOf(node);
|
||||
|
||||
std::vector<XMLNode*> karts;
|
||||
node->getNodes("Kart", karts);
|
||||
@@ -140,35 +144,41 @@ void SavedGrandPrix::setKarts(const std::vector<RaceManager::KartStatus> &kart_l
|
||||
}
|
||||
} // setKarts
|
||||
|
||||
/* compares two KartStatus-objects for std::sort in the next function */
|
||||
bool cmp__l(RaceManager::KartStatus first, RaceManager::KartStatus second)
|
||||
{
|
||||
return (first.m_score > second.m_score);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SavedGrandPrix::loadKarts(std::vector<RaceManager::KartStatus> & kart_list)
|
||||
{
|
||||
//Fix aikarts
|
||||
|
||||
int aikarts = 0;
|
||||
for(unsigned int i = 0; i < m_karts.size(); i++)
|
||||
{
|
||||
const KartProperties *kp = kart_properties_manager->getKart(m_karts[i].m_ident);
|
||||
|
||||
if(m_karts[i].m_local_player_id == -1)
|
||||
if(m_karts[i].m_local_player_id == -1) // AI kart
|
||||
{
|
||||
//AI kart found
|
||||
if(kp) kart_list[aikarts].m_ident = m_karts[i].m_ident;
|
||||
kart_list[aikarts].m_score = m_karts[i].m_score;
|
||||
kart_list[aikarts].m_score = m_karts[i].m_score;
|
||||
kart_list[aikarts].m_overall_time = m_karts[i].m_overall_time;
|
||||
aikarts++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Get correct player
|
||||
// Get correct player
|
||||
for(unsigned int x = kart_list.size()-m_player_karts;
|
||||
x < kart_list.size(); x++)
|
||||
{
|
||||
if(kart_list[x].m_local_player_id == m_karts[i].m_local_player_id)
|
||||
{
|
||||
kart_list[x].m_score = m_karts[i].m_score;
|
||||
kart_list[x].m_score = m_karts[i].m_score;
|
||||
kart_list[x].m_overall_time = m_karts[i].m_overall_time;
|
||||
} // if kart_list[x].m_local_player_id == m_karts[i].,_local
|
||||
} // for x
|
||||
} // if m_local_player_id == -1
|
||||
} // for i
|
||||
|
||||
std::sort(kart_list.begin(), kart_list.end(), cmp__l);
|
||||
} // loadKarts
|
||||
|
||||
@@ -19,11 +19,13 @@
|
||||
#ifndef HEADER_SAVED_GRAND_PRIX_HPP
|
||||
#define HEADER_SAVED_GRAND_PRIX_HPP
|
||||
|
||||
#include <string>
|
||||
#include "config/user_config.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
class RaceManager;
|
||||
|
||||
// ============================================================================
|
||||
@@ -74,6 +76,9 @@ protected:
|
||||
/** Index of the next to run track. */
|
||||
IntUserConfigParam m_next_track;
|
||||
|
||||
/** GPReverseType of the GP as int */
|
||||
IntUserConfigParam m_reverse_type;
|
||||
|
||||
PtrVector<SavedGPKart> m_karts;
|
||||
|
||||
public:
|
||||
@@ -86,6 +91,7 @@ public:
|
||||
RaceManager::Difficulty difficulty,
|
||||
int player_karts,
|
||||
int last_track,
|
||||
int reverse_type,
|
||||
const std::vector<RaceManager::KartStatus> &kart_list);
|
||||
|
||||
/**
|
||||
@@ -120,6 +126,10 @@ public:
|
||||
/** Returns the index of the last track finished when this GP was saved. */
|
||||
int getNextTrack() const { return m_next_track; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the reverse Type. */
|
||||
int getReverseType() const { return m_reverse_type; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the index of the last track finished. */
|
||||
void setNextTrack(int next_track) { m_next_track = next_track; }
|
||||
@@ -135,29 +145,22 @@ public:
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Finds the right SavedGrandPrix given the specified data, or
|
||||
* NULL if no matching GP was found.
|
||||
*/
|
||||
* NULL if no matching GP was found. */
|
||||
static SavedGrandPrix* getSavedGP(unsigned int player,
|
||||
const std::string &gpid,
|
||||
int difficulty, int total_karts,
|
||||
int player_karts)
|
||||
const std::string &gpid,
|
||||
const unsigned int number_of_players)
|
||||
{
|
||||
for (unsigned int n=0; n<UserConfigParams::m_saved_grand_prix_list.size(); n++)
|
||||
{
|
||||
SavedGrandPrix* gp = &UserConfigParams::m_saved_grand_prix_list[n];
|
||||
|
||||
if ((gp->getGPID() == gpid) &&
|
||||
(gp->getPlayerID() == player) &&
|
||||
(gp->getDifficulty() == difficulty) &&
|
||||
(gp->getTotalKarts() == total_karts) &&
|
||||
(gp->getPlayerKarts() == player_karts)){
|
||||
if (gp->getGPID() == gpid &&
|
||||
gp->getPlayerID() == player &&
|
||||
gp->getPlayerKarts() == (int)number_of_players)
|
||||
return gp;
|
||||
} // if
|
||||
} // for n
|
||||
}
|
||||
return NULL;
|
||||
} // getSavedGP
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
}; // class SavedGrandPrix
|
||||
|
||||
#endif
|
||||
|
||||
338
src/graphics/2dutils.cpp
Normal file
338
src/graphics/2dutils.cpp
Normal file
@@ -0,0 +1,338 @@
|
||||
#include "2dutils.hpp"
|
||||
#include "glwrap.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
|
||||
#include "../../lib/irrlicht/source/Irrlicht/COpenGLTexture.h"
|
||||
|
||||
static void drawTexColoredQuad(const video::ITexture *texture, const video::SColor *col, float width, float height,
|
||||
float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
|
||||
float tex_width, float tex_height)
|
||||
{
|
||||
unsigned colors[] = {
|
||||
col[0].getRed(), col[0].getGreen(), col[0].getBlue(), col[0].getAlpha(),
|
||||
col[1].getRed(), col[1].getGreen(), col[1].getBlue(), col[1].getAlpha(),
|
||||
col[2].getRed(), col[2].getGreen(), col[2].getBlue(), col[2].getAlpha(),
|
||||
col[3].getRed(), col[3].getGreen(), col[3].getBlue(), col[3].getAlpha(),
|
||||
};
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, UIShader::ColoredTextureRectShader::getInstance()->colorvbo);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, 16 * sizeof(unsigned), colors);
|
||||
|
||||
glUseProgram(UIShader::ColoredTextureRectShader::getInstance()->Program);
|
||||
glBindVertexArray(UIShader::ColoredTextureRectShader::getInstance()->vao);
|
||||
|
||||
UIShader::ColoredTextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName()));
|
||||
UIShader::ColoredTextureRectShader::getInstance()->setUniforms(
|
||||
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
|
||||
core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height));
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glGetError();
|
||||
}
|
||||
|
||||
static
|
||||
void drawTexQuad(GLuint texture, float width, float height,
|
||||
float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
|
||||
float tex_width, float tex_height)
|
||||
{
|
||||
glUseProgram(UIShader::TextureRectShader::getInstance()->Program);
|
||||
glBindVertexArray(SharedObject::UIVAO);
|
||||
|
||||
UIShader::TextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(texture));
|
||||
UIShader::TextureRectShader::getInstance()->setUniforms(
|
||||
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
|
||||
core::vector2df(tex_center_pos_x, tex_center_pos_y),
|
||||
core::vector2df(tex_width, tex_height));
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glGetError();
|
||||
}
|
||||
|
||||
static void
|
||||
getSize(unsigned texture_width, unsigned texture_height, bool textureisRTT,
|
||||
const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect,
|
||||
float &width, float &height,
|
||||
float ¢er_pos_x, float ¢er_pos_y,
|
||||
float &tex_width, float &tex_height,
|
||||
float &tex_center_pos_x, float &tex_center_pos_y
|
||||
)
|
||||
{
|
||||
core::dimension2d<u32> frame_size =
|
||||
irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
|
||||
const int screen_w = frame_size.Width;
|
||||
const int screen_h = frame_size.Height;
|
||||
center_pos_x = float(destRect.UpperLeftCorner.X + destRect.LowerRightCorner.X);
|
||||
center_pos_x /= screen_w;
|
||||
center_pos_x -= 1.;
|
||||
center_pos_y = float(destRect.UpperLeftCorner.Y + destRect.LowerRightCorner.Y);
|
||||
center_pos_y /= screen_h;
|
||||
center_pos_y = float(1.f - center_pos_y);
|
||||
width = float(destRect.LowerRightCorner.X - destRect.UpperLeftCorner.X);
|
||||
width /= screen_w;
|
||||
height = float(destRect.LowerRightCorner.Y - destRect.UpperLeftCorner.Y);
|
||||
height /= screen_h;
|
||||
|
||||
tex_center_pos_x = float(sourceRect.UpperLeftCorner.X + sourceRect.LowerRightCorner.X);
|
||||
tex_center_pos_x /= texture_width * 2.f;
|
||||
tex_center_pos_y = float(sourceRect.UpperLeftCorner.Y + sourceRect.LowerRightCorner.Y);
|
||||
tex_center_pos_y /= texture_height * 2.f;
|
||||
tex_width = float(sourceRect.LowerRightCorner.X - sourceRect.UpperLeftCorner.X);
|
||||
tex_width /= texture_width * 2.f;
|
||||
tex_height = float(sourceRect.LowerRightCorner.Y - sourceRect.UpperLeftCorner.Y);
|
||||
tex_height /= texture_height * 2.f;
|
||||
|
||||
if (textureisRTT)
|
||||
tex_height = -tex_height;
|
||||
|
||||
const f32 invW = 1.f / static_cast<f32>(texture_width);
|
||||
const f32 invH = 1.f / static_cast<f32>(texture_height);
|
||||
const core::rect<f32> tcoords(
|
||||
sourceRect.UpperLeftCorner.X * invW,
|
||||
sourceRect.UpperLeftCorner.Y * invH,
|
||||
sourceRect.LowerRightCorner.X * invW,
|
||||
sourceRect.LowerRightCorner.Y *invH);
|
||||
}
|
||||
|
||||
void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
|
||||
const video::SColor &colors, bool useAlphaChannelOfTexture)
|
||||
{
|
||||
if (!irr_driver->isGLSL()) {
|
||||
video::SColor duplicatedArray[4] = {
|
||||
colors, colors, colors, colors
|
||||
};
|
||||
draw2DImage(texture, destRect, sourceRect, clipRect, duplicatedArray, useAlphaChannelOfTexture);
|
||||
return;
|
||||
}
|
||||
|
||||
float width, height,
|
||||
center_pos_x, center_pos_y,
|
||||
tex_width, tex_height,
|
||||
tex_center_pos_x, tex_center_pos_y;
|
||||
|
||||
getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
|
||||
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
|
||||
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
|
||||
|
||||
if (useAlphaChannelOfTexture)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
if (clipRect)
|
||||
{
|
||||
if (!clipRect->isValid())
|
||||
return;
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
|
||||
glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
|
||||
clipRect->getWidth(), clipRect->getHeight());
|
||||
}
|
||||
|
||||
glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
|
||||
glBindVertexArray(SharedObject::UIVAO);
|
||||
|
||||
UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName()));
|
||||
UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
|
||||
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height), colors);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
if (clipRect)
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glUseProgram(0);
|
||||
|
||||
glGetError();
|
||||
}
|
||||
|
||||
void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
|
||||
const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
|
||||
const video::SColor &colors, bool useAlphaChannelOfTexture)
|
||||
{
|
||||
if (useAlphaChannelOfTexture)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
float width, height,
|
||||
center_pos_x, center_pos_y,
|
||||
tex_width, tex_height,
|
||||
tex_center_pos_x, tex_center_pos_y;
|
||||
|
||||
getSize((int)texture_w, (int)texture_h, true,
|
||||
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
|
||||
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
|
||||
|
||||
glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
|
||||
glBindVertexArray(SharedObject::UIVAO);
|
||||
|
||||
UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(texture));
|
||||
UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
|
||||
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
|
||||
core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height),
|
||||
colors);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
|
||||
const video::SColor* const colors, bool useAlphaChannelOfTexture)
|
||||
{
|
||||
if (!irr_driver->isGLSL())
|
||||
{
|
||||
irr_driver->getVideoDriver()->draw2DImage(texture, destRect, sourceRect, clipRect, colors, useAlphaChannelOfTexture);
|
||||
return;
|
||||
}
|
||||
|
||||
float width, height,
|
||||
center_pos_x, center_pos_y,
|
||||
tex_width, tex_height,
|
||||
tex_center_pos_x, tex_center_pos_y;
|
||||
|
||||
getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
|
||||
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
|
||||
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
|
||||
|
||||
if (useAlphaChannelOfTexture)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
if (clipRect)
|
||||
{
|
||||
if (!clipRect->isValid())
|
||||
return;
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
|
||||
glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
|
||||
clipRect->getWidth(), clipRect->getHeight());
|
||||
}
|
||||
if (colors)
|
||||
drawTexColoredQuad(texture, colors, width, height, center_pos_x, center_pos_y,
|
||||
tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
|
||||
else
|
||||
drawTexQuad(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName(), width, height, center_pos_x, center_pos_y,
|
||||
tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
|
||||
if (clipRect)
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glUseProgram(0);
|
||||
|
||||
glGetError();
|
||||
}
|
||||
|
||||
void draw2DVertexPrimitiveList(video::ITexture *tex, const void* vertices,
|
||||
u32 vertexCount, const void* indexList, u32 primitiveCount,
|
||||
video::E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, video::E_INDEX_TYPE iType)
|
||||
{
|
||||
if (!irr_driver->isGLSL())
|
||||
{
|
||||
irr_driver->getVideoDriver()->draw2DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType);
|
||||
return;
|
||||
}
|
||||
GLuint tmpvao, tmpvbo, tmpibo;
|
||||
primitiveCount += 2;
|
||||
glGenVertexArrays(1, &tmpvao);
|
||||
glBindVertexArray(tmpvao);
|
||||
glGenBuffers(1, &tmpvbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, tmpvbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertexCount * getVertexPitchFromType(vType), vertices, GL_STREAM_DRAW);
|
||||
glGenBuffers(1, &tmpibo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tmpibo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, primitiveCount * sizeof(u16), indexList, GL_STREAM_DRAW);
|
||||
|
||||
VertexUtils::bindVertexArrayAttrib(vType);
|
||||
|
||||
glUseProgram(UIShader::Primitive2DList::getInstance()->Program);
|
||||
UIShader::Primitive2DList::getInstance()->setUniforms();
|
||||
const video::SOverrideMaterial &m = irr_driver->getVideoDriver()->getOverrideMaterial();
|
||||
compressTexture(tex, false);
|
||||
UIShader::Primitive2DList::getInstance()->SetTextureUnits({ getTextureGLuint(tex) });
|
||||
glDrawElements(GL_TRIANGLE_FAN, primitiveCount, GL_UNSIGNED_SHORT, 0);
|
||||
|
||||
glDeleteVertexArrays(1, &tmpvao);
|
||||
glDeleteBuffers(1, &tmpvbo);
|
||||
glDeleteBuffers(1, &tmpibo);
|
||||
|
||||
}
|
||||
|
||||
void GL32_draw2DRectangle(video::SColor color, const core::rect<s32>& position,
|
||||
const core::rect<s32>* clip)
|
||||
{
|
||||
|
||||
if (!irr_driver->isGLSL())
|
||||
{
|
||||
irr_driver->getVideoDriver()->draw2DRectangle(color, position, clip);
|
||||
return;
|
||||
}
|
||||
|
||||
core::dimension2d<u32> frame_size =
|
||||
irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
|
||||
const int screen_w = frame_size.Width;
|
||||
const int screen_h = frame_size.Height;
|
||||
float center_pos_x = float(position.UpperLeftCorner.X + position.LowerRightCorner.X);
|
||||
center_pos_x /= screen_w;
|
||||
center_pos_x -= 1;
|
||||
float center_pos_y = float(position.UpperLeftCorner.Y + position.LowerRightCorner.Y);
|
||||
center_pos_y /= screen_h;
|
||||
center_pos_y = 1 - center_pos_y;
|
||||
float width = float(position.LowerRightCorner.X - position.UpperLeftCorner.X);
|
||||
width /= screen_w;
|
||||
float height = float(position.LowerRightCorner.Y - position.UpperLeftCorner.Y);
|
||||
height /= screen_h;
|
||||
|
||||
if (color.getAlpha() < 255)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
if (clip)
|
||||
{
|
||||
if (!clip->isValid())
|
||||
return;
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
|
||||
glScissor(clip->UpperLeftCorner.X, renderTargetSize.Height - clip->LowerRightCorner.Y,
|
||||
clip->getWidth(), clip->getHeight());
|
||||
}
|
||||
|
||||
glUseProgram(UIShader::ColoredRectShader::getInstance()->Program);
|
||||
glBindVertexArray(SharedObject::UIVAO);
|
||||
UIShader::ColoredRectShader::getInstance()->setUniforms(core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), color);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
if (clip)
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glUseProgram(0);
|
||||
|
||||
glGetError();
|
||||
}
|
||||
33
src/graphics/2dutils.hpp
Normal file
33
src/graphics/2dutils.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef UTILS2D_HPP
|
||||
#define UTILS2D_HPP
|
||||
|
||||
#include "gl_headers.hpp"
|
||||
#include <rect.h>
|
||||
#include <SColor.h>
|
||||
#include <S3DVertex.h>
|
||||
#include <SVertexIndex.h>
|
||||
#include <EPrimitiveTypes.h>
|
||||
#include <ITexture.h>
|
||||
#include <irrTypes.h>
|
||||
|
||||
void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
|
||||
const irr::core::rect<irr::s32>& destRect,
|
||||
const irr::core::rect<irr::s32>& sourceRect, const irr::core::rect<irr::s32>* clipRect,
|
||||
const irr::video::SColor &colors, bool useAlphaChannelOfTexture);
|
||||
|
||||
void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect<irr::s32>& destRect,
|
||||
const irr::core::rect<irr::s32>& sourceRect, const irr::core::rect<irr::s32>* clipRect,
|
||||
const irr::video::SColor &color, bool useAlphaChannelOfTexture);
|
||||
|
||||
void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect<irr::s32>& destRect,
|
||||
const irr::core::rect<irr::s32>& sourceRect, const irr::core::rect<irr::s32>* clipRect,
|
||||
const irr::video::SColor* const colors, bool useAlphaChannelOfTexture);
|
||||
|
||||
void draw2DVertexPrimitiveList(irr::video::ITexture *t, const void* vertices,
|
||||
irr::u32 vertexCount, const void* indexList, irr::u32 primitiveCount,
|
||||
irr::video::E_VERTEX_TYPE vType = irr::video::EVT_STANDARD, irr::scene::E_PRIMITIVE_TYPE pType = irr::scene::EPT_TRIANGLES, irr::video::E_INDEX_TYPE iType = irr::video::EIT_16BIT);
|
||||
|
||||
void GL32_draw2DRectangle(irr::video::SColor color, const irr::core::rect<irr::s32>& position,
|
||||
const irr::core::rect<irr::s32>* clip = 0);
|
||||
|
||||
#endif
|
||||
@@ -6,9 +6,6 @@
|
||||
#include "utils/profiler.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
|
||||
|
||||
#include "../../lib/irrlicht/source/Irrlicht/COpenGLTexture.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
@@ -122,159 +119,6 @@ void initGL()
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::string LoadHeader()
|
||||
{
|
||||
std::string result;
|
||||
std::ifstream Stream(file_manager->getAsset("shaders/header.txt").c_str(), std::ios::in);
|
||||
|
||||
if (Stream.is_open())
|
||||
{
|
||||
std::string Line = "";
|
||||
while (getline(Stream, Line))
|
||||
result += "\n" + Line;
|
||||
Stream.close();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Mostly from shader tutorial
|
||||
GLuint LoadShader(const char * file, unsigned type)
|
||||
{
|
||||
GLuint Id = glCreateShader(type);
|
||||
char versionString[20];
|
||||
sprintf(versionString, "#version %d\n", irr_driver->getGLSLVersion());
|
||||
std::string Code = versionString;
|
||||
if (irr_driver->hasVSLayerExtension())
|
||||
Code += "#extension GL_AMD_vertex_shader_layer : enable\n";
|
||||
if (UserConfigParams::m_azdo)
|
||||
Code += "#extension GL_ARB_bindless_texture : enable\n";
|
||||
else
|
||||
{
|
||||
Code += "#extension GL_ARB_bindless_texture : disable\n";
|
||||
Code += "#undef GL_ARB_bindless_texture\n";
|
||||
}
|
||||
std::ifstream Stream(file, std::ios::in);
|
||||
Code += "//" + std::string(file) + "\n";
|
||||
if (irr_driver->needUBOWorkaround())
|
||||
Code += "#define UBO_DISABLED\n";
|
||||
if (irr_driver->hasVSLayerExtension())
|
||||
Code += "#define VSLayer\n";
|
||||
if (irr_driver->needsRGBBindlessWorkaround())
|
||||
Code += "#define SRGBBindlessFix\n";
|
||||
Code += LoadHeader();
|
||||
if (Stream.is_open())
|
||||
{
|
||||
std::string Line = "";
|
||||
while (getline(Stream, Line))
|
||||
Code += "\n" + Line;
|
||||
Stream.close();
|
||||
}
|
||||
GLint Result = GL_FALSE;
|
||||
int InfoLogLength;
|
||||
Log::info("GLWrap", "Compiling shader : %s", file);
|
||||
char const * SourcePointer = Code.c_str();
|
||||
int length = (int)strlen(SourcePointer);
|
||||
glShaderSource(Id, 1, &SourcePointer, &length);
|
||||
glCompileShader(Id);
|
||||
|
||||
glGetShaderiv(Id, GL_COMPILE_STATUS, &Result);
|
||||
if (Result == GL_FALSE)
|
||||
{
|
||||
Log::error("GLWrap", "Error in shader %s", file);
|
||||
glGetShaderiv(Id, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
if(InfoLogLength<0)
|
||||
InfoLogLength = 1024;
|
||||
char *ErrorMessage = new char[InfoLogLength];
|
||||
ErrorMessage[0]=0;
|
||||
glGetShaderInfoLog(Id, InfoLogLength, NULL, ErrorMessage);
|
||||
Log::error("GLWrap", ErrorMessage);
|
||||
delete[] ErrorMessage;
|
||||
}
|
||||
|
||||
glGetError();
|
||||
|
||||
return Id;
|
||||
}
|
||||
|
||||
void setAttribute(AttributeType Tp, GLuint ProgramID)
|
||||
{
|
||||
switch (Tp)
|
||||
{
|
||||
case OBJECT:
|
||||
glBindAttribLocation(ProgramID, 0, "Position");
|
||||
glBindAttribLocation(ProgramID, 1, "Normal");
|
||||
glBindAttribLocation(ProgramID, 2, "Color");
|
||||
glBindAttribLocation(ProgramID, 3, "Texcoord");
|
||||
glBindAttribLocation(ProgramID, 4, "SecondTexcoord");
|
||||
glBindAttribLocation(ProgramID, 5, "Tangent");
|
||||
glBindAttribLocation(ProgramID, 6, "Bitangent");
|
||||
glBindAttribLocation(ProgramID, 7, "Origin");
|
||||
glBindAttribLocation(ProgramID, 8, "Orientation");
|
||||
glBindAttribLocation(ProgramID, 9, "Scale");
|
||||
break;
|
||||
case PARTICLES_SIM:
|
||||
glBindAttribLocation(ProgramID, 0, "particle_position");
|
||||
glBindAttribLocation(ProgramID, 1, "lifetime");
|
||||
glBindAttribLocation(ProgramID, 2, "particle_velocity");
|
||||
glBindAttribLocation(ProgramID, 3, "size");
|
||||
glBindAttribLocation(ProgramID, 4, "particle_position_initial");
|
||||
glBindAttribLocation(ProgramID, 5, "lifetime_initial");
|
||||
glBindAttribLocation(ProgramID, 6, "particle_velocity_initial");
|
||||
glBindAttribLocation(ProgramID, 7, "size_initial");
|
||||
break;
|
||||
case PARTICLES_RENDERING:
|
||||
glBindAttribLocation(ProgramID, 1, "lifetime");
|
||||
glBindAttribLocation(ProgramID, 2, "size");
|
||||
glBindAttribLocation(ProgramID, 4, "quadcorner");
|
||||
glBindAttribLocation(ProgramID, 5, "rotationvec");
|
||||
glBindAttribLocation(ProgramID, 6, "anglespeed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount)
|
||||
{
|
||||
GLuint Program = glCreateProgram();
|
||||
loadAndAttach(Program, GL_VERTEX_SHADER, vertex_file_path);
|
||||
if (irr_driver->getGLSLVersion() < 330)
|
||||
setAttribute(PARTICLES_SIM, Program);
|
||||
glTransformFeedbackVaryings(Program, varyingscount, varyings, GL_INTERLEAVED_ATTRIBS);
|
||||
glLinkProgram(Program);
|
||||
|
||||
GLint Result = GL_FALSE;
|
||||
int InfoLogLength;
|
||||
glGetProgramiv(Program, GL_LINK_STATUS, &Result);
|
||||
if (Result == GL_FALSE)
|
||||
{
|
||||
glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
char *ErrorMessage = new char[InfoLogLength];
|
||||
glGetProgramInfoLog(Program, InfoLogLength, NULL, ErrorMessage);
|
||||
Log::error("GLWrap", ErrorMessage);
|
||||
delete[] ErrorMessage;
|
||||
}
|
||||
|
||||
glGetError();
|
||||
|
||||
return Program;
|
||||
}
|
||||
|
||||
void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + TextureUnit);
|
||||
glBindTexture(GL_TEXTURE_2D, TextureId);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MagFilter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFilter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
int aniso = UserConfigParams::m_anisotropic;
|
||||
if (aniso == 0) aniso = 1;
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, allowAF ? (float)aniso : 1.0f);
|
||||
|
||||
glGetError();
|
||||
}
|
||||
|
||||
ScopedGPUTimer::ScopedGPUTimer(GPUTimer &t) : timer(t)
|
||||
{
|
||||
if (!UserConfigParams::m_profiler_enabled) return;
|
||||
@@ -417,304 +261,6 @@ void draw3DLine(const core::vector3df& start,
|
||||
glGetError();
|
||||
}
|
||||
|
||||
static void drawTexColoredQuad(const video::ITexture *texture, const video::SColor *col, float width, float height,
|
||||
float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
|
||||
float tex_width, float tex_height)
|
||||
{
|
||||
unsigned colors[] = {
|
||||
col[0].getRed(), col[0].getGreen(), col[0].getBlue(), col[0].getAlpha(),
|
||||
col[1].getRed(), col[1].getGreen(), col[1].getBlue(), col[1].getAlpha(),
|
||||
col[2].getRed(), col[2].getGreen(), col[2].getBlue(), col[2].getAlpha(),
|
||||
col[3].getRed(), col[3].getGreen(), col[3].getBlue(), col[3].getAlpha(),
|
||||
};
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, UIShader::ColoredTextureRectShader::getInstance()->colorvbo);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, 16 * sizeof(unsigned), colors);
|
||||
|
||||
glUseProgram(UIShader::ColoredTextureRectShader::getInstance()->Program);
|
||||
glBindVertexArray(UIShader::ColoredTextureRectShader::getInstance()->vao);
|
||||
|
||||
UIShader::ColoredTextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName()));
|
||||
UIShader::ColoredTextureRectShader::getInstance()->setUniforms(
|
||||
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
|
||||
core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height));
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glGetError();
|
||||
}
|
||||
|
||||
static
|
||||
void drawTexQuad(GLuint texture, float width, float height,
|
||||
float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
|
||||
float tex_width, float tex_height)
|
||||
{
|
||||
glUseProgram(UIShader::TextureRectShader::getInstance()->Program);
|
||||
glBindVertexArray(SharedObject::UIVAO);
|
||||
|
||||
UIShader::TextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(texture));
|
||||
UIShader::TextureRectShader::getInstance()->setUniforms(
|
||||
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
|
||||
core::vector2df(tex_center_pos_x, tex_center_pos_y),
|
||||
core::vector2df(tex_width, tex_height));
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glGetError();
|
||||
}
|
||||
|
||||
static void
|
||||
getSize(unsigned texture_width, unsigned texture_height, bool textureisRTT,
|
||||
const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect,
|
||||
float &width, float &height,
|
||||
float ¢er_pos_x, float ¢er_pos_y,
|
||||
float &tex_width, float &tex_height,
|
||||
float &tex_center_pos_x, float &tex_center_pos_y
|
||||
)
|
||||
{
|
||||
core::dimension2d<u32> frame_size =
|
||||
irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
|
||||
const int screen_w = frame_size.Width;
|
||||
const int screen_h = frame_size.Height;
|
||||
center_pos_x = float(destRect.UpperLeftCorner.X + destRect.LowerRightCorner.X);
|
||||
center_pos_x /= screen_w;
|
||||
center_pos_x -= 1.;
|
||||
center_pos_y = float(destRect.UpperLeftCorner.Y + destRect.LowerRightCorner.Y);
|
||||
center_pos_y /= screen_h;
|
||||
center_pos_y = float(1.f - center_pos_y);
|
||||
width = float(destRect.LowerRightCorner.X - destRect.UpperLeftCorner.X);
|
||||
width /= screen_w;
|
||||
height = float(destRect.LowerRightCorner.Y - destRect.UpperLeftCorner.Y);
|
||||
height /= screen_h;
|
||||
|
||||
tex_center_pos_x = float(sourceRect.UpperLeftCorner.X + sourceRect.LowerRightCorner.X);
|
||||
tex_center_pos_x /= texture_width * 2.f;
|
||||
tex_center_pos_y = float(sourceRect.UpperLeftCorner.Y + sourceRect.LowerRightCorner.Y);
|
||||
tex_center_pos_y /= texture_height * 2.f;
|
||||
tex_width = float(sourceRect.LowerRightCorner.X - sourceRect.UpperLeftCorner.X);
|
||||
tex_width /= texture_width * 2.f;
|
||||
tex_height = float(sourceRect.LowerRightCorner.Y - sourceRect.UpperLeftCorner.Y);
|
||||
tex_height /= texture_height * 2.f;
|
||||
|
||||
if (textureisRTT)
|
||||
tex_height = -tex_height;
|
||||
|
||||
const f32 invW = 1.f / static_cast<f32>(texture_width);
|
||||
const f32 invH = 1.f / static_cast<f32>(texture_height);
|
||||
const core::rect<f32> tcoords(
|
||||
sourceRect.UpperLeftCorner.X * invW,
|
||||
sourceRect.UpperLeftCorner.Y * invH,
|
||||
sourceRect.LowerRightCorner.X * invW,
|
||||
sourceRect.LowerRightCorner.Y *invH);
|
||||
}
|
||||
|
||||
void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
|
||||
const video::SColor &colors, bool useAlphaChannelOfTexture)
|
||||
{
|
||||
if (!irr_driver->isGLSL()) {
|
||||
video::SColor duplicatedArray[4] = {
|
||||
colors, colors, colors, colors
|
||||
};
|
||||
draw2DImage(texture, destRect, sourceRect, clipRect, duplicatedArray, useAlphaChannelOfTexture);
|
||||
return;
|
||||
}
|
||||
|
||||
float width, height,
|
||||
center_pos_x, center_pos_y,
|
||||
tex_width, tex_height,
|
||||
tex_center_pos_x, tex_center_pos_y;
|
||||
|
||||
getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
|
||||
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
|
||||
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
|
||||
|
||||
if (useAlphaChannelOfTexture)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
if (clipRect)
|
||||
{
|
||||
if (!clipRect->isValid())
|
||||
return;
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
|
||||
glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
|
||||
clipRect->getWidth(), clipRect->getHeight());
|
||||
}
|
||||
|
||||
glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
|
||||
glBindVertexArray(SharedObject::UIVAO);
|
||||
|
||||
UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName()));
|
||||
UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
|
||||
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height), colors);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
if (clipRect)
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glUseProgram(0);
|
||||
|
||||
glGetError();
|
||||
}
|
||||
|
||||
void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
|
||||
const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
|
||||
const video::SColor &colors, bool useAlphaChannelOfTexture)
|
||||
{
|
||||
if (useAlphaChannelOfTexture)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
float width, height,
|
||||
center_pos_x, center_pos_y,
|
||||
tex_width, tex_height,
|
||||
tex_center_pos_x, tex_center_pos_y;
|
||||
|
||||
getSize((int)texture_w, (int)texture_h, true,
|
||||
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
|
||||
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
|
||||
|
||||
glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
|
||||
glBindVertexArray(SharedObject::UIVAO);
|
||||
|
||||
UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(texture));
|
||||
UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
|
||||
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
|
||||
core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height),
|
||||
colors);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
|
||||
const video::SColor* const colors, bool useAlphaChannelOfTexture)
|
||||
{
|
||||
if (!irr_driver->isGLSL())
|
||||
{
|
||||
irr_driver->getVideoDriver()->draw2DImage(texture, destRect, sourceRect, clipRect, colors, useAlphaChannelOfTexture);
|
||||
return;
|
||||
}
|
||||
|
||||
float width, height,
|
||||
center_pos_x, center_pos_y,
|
||||
tex_width, tex_height,
|
||||
tex_center_pos_x, tex_center_pos_y;
|
||||
|
||||
getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
|
||||
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
|
||||
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
|
||||
|
||||
if (useAlphaChannelOfTexture)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
if (clipRect)
|
||||
{
|
||||
if (!clipRect->isValid())
|
||||
return;
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
|
||||
glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
|
||||
clipRect->getWidth(), clipRect->getHeight());
|
||||
}
|
||||
if (colors)
|
||||
drawTexColoredQuad(texture, colors, width, height, center_pos_x, center_pos_y,
|
||||
tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
|
||||
else
|
||||
drawTexQuad(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName(), width, height, center_pos_x, center_pos_y,
|
||||
tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
|
||||
if (clipRect)
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glUseProgram(0);
|
||||
|
||||
glGetError();
|
||||
}
|
||||
|
||||
void GL32_draw2DRectangle(video::SColor color, const core::rect<s32>& position,
|
||||
const core::rect<s32>* clip)
|
||||
{
|
||||
|
||||
if (!irr_driver->isGLSL())
|
||||
{
|
||||
irr_driver->getVideoDriver()->draw2DRectangle(color, position, clip);
|
||||
return;
|
||||
}
|
||||
|
||||
core::dimension2d<u32> frame_size =
|
||||
irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
|
||||
const int screen_w = frame_size.Width;
|
||||
const int screen_h = frame_size.Height;
|
||||
float center_pos_x = float(position.UpperLeftCorner.X + position.LowerRightCorner.X);
|
||||
center_pos_x /= screen_w;
|
||||
center_pos_x -= 1;
|
||||
float center_pos_y = float(position.UpperLeftCorner.Y + position.LowerRightCorner.Y);
|
||||
center_pos_y /= screen_h;
|
||||
center_pos_y = 1 - center_pos_y;
|
||||
float width = float(position.LowerRightCorner.X - position.UpperLeftCorner.X);
|
||||
width /= screen_w;
|
||||
float height = float(position.LowerRightCorner.Y - position.UpperLeftCorner.Y);
|
||||
height /= screen_h;
|
||||
|
||||
if (color.getAlpha() < 255)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
if (clip)
|
||||
{
|
||||
if (!clip->isValid())
|
||||
return;
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
|
||||
glScissor(clip->UpperLeftCorner.X, renderTargetSize.Height - clip->LowerRightCorner.Y,
|
||||
clip->getWidth(), clip->getHeight());
|
||||
}
|
||||
|
||||
glUseProgram(UIShader::ColoredRectShader::getInstance()->Program);
|
||||
glBindVertexArray(SharedObject::UIVAO);
|
||||
UIShader::ColoredRectShader::getInstance()->setUniforms(core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), color);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
if (clip)
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glUseProgram(0);
|
||||
|
||||
glGetError();
|
||||
}
|
||||
|
||||
bool hasGLExtension(const char* extension)
|
||||
{
|
||||
if (glGetStringi != NULL)
|
||||
|
||||
@@ -15,78 +15,7 @@ namespace HardwareStats
|
||||
}
|
||||
|
||||
void initGL();
|
||||
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount);
|
||||
video::ITexture* getUnicolorTexture(const video::SColor &c);
|
||||
void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF = false);
|
||||
GLuint LoadShader(const char * file, unsigned type);
|
||||
|
||||
template<typename ... Types>
|
||||
void loadAndAttach(GLint ProgramID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
template<typename ... Types>
|
||||
void loadAndAttach(GLint ProgramID, GLint ShaderType, const char *filepath, Types ... args)
|
||||
{
|
||||
GLint ShaderID = LoadShader(filepath, ShaderType);
|
||||
glAttachShader(ProgramID, ShaderID);
|
||||
glDeleteShader(ShaderID);
|
||||
loadAndAttach(ProgramID, args...);
|
||||
}
|
||||
|
||||
template<typename ...Types>
|
||||
void printFileList()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
template<typename ...Types>
|
||||
void printFileList(GLint ShaderType, const char *filepath, Types ... args)
|
||||
{
|
||||
Log::error("GLWrapp", filepath);
|
||||
printFileList(args...);
|
||||
}
|
||||
|
||||
enum AttributeType
|
||||
{
|
||||
OBJECT,
|
||||
PARTICLES_SIM,
|
||||
PARTICLES_RENDERING,
|
||||
};
|
||||
|
||||
void setAttribute(AttributeType Tp, GLuint ProgramID);
|
||||
|
||||
template<typename ... Types>
|
||||
GLint LoadProgram(AttributeType Tp, Types ... args)
|
||||
{
|
||||
GLint ProgramID = glCreateProgram();
|
||||
loadAndAttach(ProgramID, args...);
|
||||
if (irr_driver->getGLSLVersion() < 330)
|
||||
setAttribute(Tp, ProgramID);
|
||||
glLinkProgram(ProgramID);
|
||||
|
||||
GLint Result = GL_FALSE;
|
||||
int InfoLogLength;
|
||||
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
|
||||
if (Result == GL_FALSE) {
|
||||
Log::error("GLWrapp", "Error when linking these shaders :");
|
||||
printFileList(args...);
|
||||
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
char *ErrorMessage = new char[InfoLogLength];
|
||||
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, ErrorMessage);
|
||||
Log::error("GLWrapp", ErrorMessage);
|
||||
delete[] ErrorMessage;
|
||||
}
|
||||
|
||||
GLenum glErr = glGetError();
|
||||
if (glErr != GL_NO_ERROR)
|
||||
{
|
||||
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
|
||||
}
|
||||
|
||||
return ProgramID;
|
||||
}
|
||||
|
||||
class GPUTimer;
|
||||
|
||||
@@ -132,30 +61,74 @@ public:
|
||||
void BlitToDefault(size_t, size_t, size_t, size_t);
|
||||
};
|
||||
|
||||
// core::rect<s32> needs these includes
|
||||
#include <rect.h>
|
||||
class VertexUtils
|
||||
{
|
||||
public:
|
||||
static void bindVertexArrayAttrib(enum video::E_VERTEX_TYPE tp)
|
||||
{
|
||||
switch (tp)
|
||||
{
|
||||
case video::EVT_STANDARD:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)28);
|
||||
break;
|
||||
case video::EVT_2TCOORDS:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)28);
|
||||
// SecondTexcoord
|
||||
glEnableVertexAttribArray(4);
|
||||
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)36);
|
||||
break;
|
||||
case video::EVT_TANGENTS:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)28);
|
||||
// Tangent
|
||||
glEnableVertexAttribArray(5);
|
||||
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)36);
|
||||
// Bitangent
|
||||
glEnableVertexAttribArray(6);
|
||||
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)48);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#include "utils/vec3.hpp"
|
||||
#include "texturemanager.hpp"
|
||||
|
||||
void draw3DLine(const core::vector3df& start,
|
||||
const core::vector3df& end, irr::video::SColor color);
|
||||
|
||||
void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
|
||||
const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
|
||||
const video::SColor &colors, bool useAlphaChannelOfTexture);
|
||||
|
||||
void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect<s32>& destRect,
|
||||
const irr::core::rect<s32>& sourceRect, const irr::core::rect<s32>* clipRect,
|
||||
const irr::video::SColor &color, bool useAlphaChannelOfTexture);
|
||||
|
||||
void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect<s32>& destRect,
|
||||
const irr::core::rect<s32>& sourceRect, const irr::core::rect<s32>* clipRect,
|
||||
const irr::video::SColor* const colors, bool useAlphaChannelOfTexture);
|
||||
|
||||
void GL32_draw2DRectangle(irr::video::SColor color, const irr::core::rect<s32>& position,
|
||||
const irr::core::rect<s32>* clip = 0);
|
||||
|
||||
bool hasGLExtension(const char* extension);
|
||||
const std::string getGLExtensions();
|
||||
void getGLLimits(HardwareStats::Json *json);
|
||||
|
||||
@@ -65,6 +65,5 @@ void HitSFX::setPlayerKartHit()
|
||||
bool HitSFX::updateAndDelete(float dt)
|
||||
{
|
||||
SFXBase::SFXStatus status = m_sfx->getStatus();
|
||||
if(status==SFXBase::SFX_INITIAL) return false;
|
||||
return status!= SFXBase::SFX_PLAYING;
|
||||
} // updateAndDelete
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "graphics/callbacks.hpp"
|
||||
#include "graphics/camera.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/2dutils.hpp"
|
||||
#include "graphics/hardware_skinning.hpp"
|
||||
#include "graphics/lens_flare.hpp"
|
||||
#include "graphics/light.hpp"
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <IMeshBuffer.h>
|
||||
#include "utils/log.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
|
||||
void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max) {
|
||||
|
||||
@@ -325,7 +327,8 @@ bool MeshTools::isNormalMap(scene::IMeshBuffer* mb)
|
||||
{
|
||||
if (!irr_driver->isGLSL())
|
||||
return false;
|
||||
return (mb->getMaterial().MaterialType == irr_driver->getShader(ES_NORMAL_MAP));
|
||||
return (mb->getMaterial().MaterialType == irr_driver->getShader(ES_NORMAL_MAP) &&
|
||||
mb->getVertexType() != video::EVT_TANGENTS);
|
||||
}
|
||||
|
||||
// Copied from irrlicht
|
||||
@@ -385,28 +388,28 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh, bool(*predic
|
||||
{
|
||||
switch (vType)
|
||||
{
|
||||
case video::EVT_STANDARD:
|
||||
{
|
||||
const video::S3DVertex* v =
|
||||
(const video::S3DVertex*)original->getVertices();
|
||||
vNew = video::S3DVertexTangents(
|
||||
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
|
||||
}
|
||||
case video::EVT_STANDARD:
|
||||
{
|
||||
const video::S3DVertex* v =
|
||||
(const video::S3DVertex*)original->getVertices();
|
||||
vNew = video::S3DVertexTangents(
|
||||
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
|
||||
}
|
||||
break;
|
||||
case video::EVT_2TCOORDS:
|
||||
{
|
||||
const video::S3DVertex2TCoords* v =
|
||||
(const video::S3DVertex2TCoords*)original->getVertices();
|
||||
vNew = video::S3DVertexTangents(
|
||||
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
|
||||
}
|
||||
case video::EVT_2TCOORDS:
|
||||
{
|
||||
const video::S3DVertex2TCoords* v =
|
||||
(const video::S3DVertex2TCoords*)original->getVertices();
|
||||
vNew = video::S3DVertexTangents(
|
||||
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
|
||||
}
|
||||
break;
|
||||
case video::EVT_TANGENTS:
|
||||
{
|
||||
const video::S3DVertexTangents* v =
|
||||
(const video::S3DVertexTangents*)original->getVertices();
|
||||
vNew = v[idx[i]];
|
||||
}
|
||||
case video::EVT_TANGENTS:
|
||||
{
|
||||
const video::S3DVertexTangents* v =
|
||||
(const video::S3DVertexTangents*)original->getVertices();
|
||||
vNew = v[idx[i]];
|
||||
}
|
||||
break;
|
||||
}
|
||||
core::map<video::S3DVertexTangents, int>::Node* n = vertMap.find(vNew);
|
||||
@@ -435,8 +438,28 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh, bool(*predic
|
||||
if (calculateTangents)
|
||||
recalculateTangents(clone, recalculateNormals, smooth, angleWeighted);
|
||||
|
||||
int mbcount = clone->getMeshBufferCount();
|
||||
for (int i = 0; i < mbcount; i++)
|
||||
{
|
||||
scene::IMeshBuffer* mb = clone->getMeshBuffer(i);
|
||||
|
||||
for (int t = 0; t < video::MATERIAL_MAX_TEXTURES; t++)
|
||||
{
|
||||
video::ITexture* texture = mb->getMaterial().TextureLayer[t].Texture;
|
||||
if (texture != NULL)
|
||||
texture->grab();
|
||||
}
|
||||
}
|
||||
|
||||
scene::IMeshCache* meshCache = irr_driver->getSceneManager()->getMeshCache();
|
||||
io::SNamedPath path = meshCache->getMeshName(mesh);
|
||||
irr_driver->removeMeshFromCache(mesh);
|
||||
|
||||
scene::SAnimatedMesh* amesh = new scene::SAnimatedMesh(clone);
|
||||
meshCache->addMesh(path, amesh);
|
||||
|
||||
World::getWorld()->getTrack()->addCachedMesh(amesh);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
@@ -123,6 +123,145 @@ Shaders::Shaders()
|
||||
loadShaders();
|
||||
}
|
||||
|
||||
// Shader loading related hook
|
||||
|
||||
static std::string LoadHeader()
|
||||
{
|
||||
std::string result;
|
||||
std::ifstream Stream(file_manager->getAsset("shaders/header.txt").c_str(), std::ios::in);
|
||||
|
||||
if (Stream.is_open())
|
||||
{
|
||||
std::string Line = "";
|
||||
while (getline(Stream, Line))
|
||||
result += "\n" + Line;
|
||||
Stream.close();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Mostly from shader tutorial
|
||||
GLuint LoadShader(const char * file, unsigned type)
|
||||
{
|
||||
GLuint Id = glCreateShader(type);
|
||||
char versionString[20];
|
||||
sprintf(versionString, "#version %d\n", irr_driver->getGLSLVersion());
|
||||
std::string Code = versionString;
|
||||
if (irr_driver->hasVSLayerExtension())
|
||||
Code += "#extension GL_AMD_vertex_shader_layer : enable\n";
|
||||
if (UserConfigParams::m_azdo)
|
||||
Code += "#extension GL_ARB_bindless_texture : enable\n";
|
||||
else
|
||||
{
|
||||
Code += "#extension GL_ARB_bindless_texture : disable\n";
|
||||
Code += "#undef GL_ARB_bindless_texture\n";
|
||||
}
|
||||
std::ifstream Stream(file, std::ios::in);
|
||||
Code += "//" + std::string(file) + "\n";
|
||||
if (irr_driver->needUBOWorkaround())
|
||||
Code += "#define UBO_DISABLED\n";
|
||||
if (irr_driver->hasVSLayerExtension())
|
||||
Code += "#define VSLayer\n";
|
||||
if (irr_driver->needsRGBBindlessWorkaround())
|
||||
Code += "#define SRGBBindlessFix\n";
|
||||
Code += LoadHeader();
|
||||
if (Stream.is_open())
|
||||
{
|
||||
std::string Line = "";
|
||||
while (getline(Stream, Line))
|
||||
Code += "\n" + Line;
|
||||
Stream.close();
|
||||
}
|
||||
GLint Result = GL_FALSE;
|
||||
int InfoLogLength;
|
||||
Log::info("GLWrap", "Compiling shader : %s", file);
|
||||
char const * SourcePointer = Code.c_str();
|
||||
int length = (int)strlen(SourcePointer);
|
||||
glShaderSource(Id, 1, &SourcePointer, &length);
|
||||
glCompileShader(Id);
|
||||
|
||||
glGetShaderiv(Id, GL_COMPILE_STATUS, &Result);
|
||||
if (Result == GL_FALSE)
|
||||
{
|
||||
Log::error("GLWrap", "Error in shader %s", file);
|
||||
glGetShaderiv(Id, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
if (InfoLogLength<0)
|
||||
InfoLogLength = 1024;
|
||||
char *ErrorMessage = new char[InfoLogLength];
|
||||
ErrorMessage[0] = 0;
|
||||
glGetShaderInfoLog(Id, InfoLogLength, NULL, ErrorMessage);
|
||||
Log::error("GLWrap", ErrorMessage);
|
||||
delete[] ErrorMessage;
|
||||
}
|
||||
|
||||
glGetError();
|
||||
|
||||
return Id;
|
||||
}
|
||||
|
||||
void setAttribute(AttributeType Tp, GLuint ProgramID)
|
||||
{
|
||||
switch (Tp)
|
||||
{
|
||||
case OBJECT:
|
||||
glBindAttribLocation(ProgramID, 0, "Position");
|
||||
glBindAttribLocation(ProgramID, 1, "Normal");
|
||||
glBindAttribLocation(ProgramID, 2, "Color");
|
||||
glBindAttribLocation(ProgramID, 3, "Texcoord");
|
||||
glBindAttribLocation(ProgramID, 4, "SecondTexcoord");
|
||||
glBindAttribLocation(ProgramID, 5, "Tangent");
|
||||
glBindAttribLocation(ProgramID, 6, "Bitangent");
|
||||
glBindAttribLocation(ProgramID, 7, "Origin");
|
||||
glBindAttribLocation(ProgramID, 8, "Orientation");
|
||||
glBindAttribLocation(ProgramID, 9, "Scale");
|
||||
break;
|
||||
case PARTICLES_SIM:
|
||||
glBindAttribLocation(ProgramID, 0, "particle_position");
|
||||
glBindAttribLocation(ProgramID, 1, "lifetime");
|
||||
glBindAttribLocation(ProgramID, 2, "particle_velocity");
|
||||
glBindAttribLocation(ProgramID, 3, "size");
|
||||
glBindAttribLocation(ProgramID, 4, "particle_position_initial");
|
||||
glBindAttribLocation(ProgramID, 5, "lifetime_initial");
|
||||
glBindAttribLocation(ProgramID, 6, "particle_velocity_initial");
|
||||
glBindAttribLocation(ProgramID, 7, "size_initial");
|
||||
break;
|
||||
case PARTICLES_RENDERING:
|
||||
glBindAttribLocation(ProgramID, 1, "lifetime");
|
||||
glBindAttribLocation(ProgramID, 2, "size");
|
||||
glBindAttribLocation(ProgramID, 4, "quadcorner");
|
||||
glBindAttribLocation(ProgramID, 5, "rotationvec");
|
||||
glBindAttribLocation(ProgramID, 6, "anglespeed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount)
|
||||
{
|
||||
GLuint Program = glCreateProgram();
|
||||
loadAndAttach(Program, GL_VERTEX_SHADER, vertex_file_path);
|
||||
if (irr_driver->getGLSLVersion() < 330)
|
||||
setAttribute(PARTICLES_SIM, Program);
|
||||
glTransformFeedbackVaryings(Program, varyingscount, varyings, GL_INTERLEAVED_ATTRIBS);
|
||||
glLinkProgram(Program);
|
||||
|
||||
GLint Result = GL_FALSE;
|
||||
int InfoLogLength;
|
||||
glGetProgramiv(Program, GL_LINK_STATUS, &Result);
|
||||
if (Result == GL_FALSE)
|
||||
{
|
||||
glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
char *ErrorMessage = new char[InfoLogLength];
|
||||
glGetProgramInfoLog(Program, InfoLogLength, NULL, ErrorMessage);
|
||||
Log::error("GLWrap", ErrorMessage);
|
||||
delete[] ErrorMessage;
|
||||
}
|
||||
|
||||
glGetError();
|
||||
|
||||
return Program;
|
||||
}
|
||||
|
||||
GLuint quad_vbo, tri_vbo;
|
||||
|
||||
GLuint SharedObject::FullScreenQuadVAO = 0;
|
||||
@@ -1749,6 +1888,16 @@ namespace FullScreenShader
|
||||
|
||||
namespace UIShader
|
||||
{
|
||||
|
||||
Primitive2DList::Primitive2DList()
|
||||
{
|
||||
Program = LoadProgram(OBJECT,
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/primitive2dlist.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/transparent.frag").c_str());
|
||||
AssignUniforms();
|
||||
AssignSamplerNames(Program, 0, "tex");
|
||||
}
|
||||
|
||||
TextureRectShader::TextureRectShader()
|
||||
{
|
||||
Program = LoadProgram(OBJECT,
|
||||
|
||||
@@ -580,6 +580,13 @@ public:
|
||||
|
||||
namespace UIShader
|
||||
{
|
||||
|
||||
class Primitive2DList : public ShaderHelperSingleton<Primitive2DList>, public TextureRead < Bilinear_Filtered >
|
||||
{
|
||||
public:
|
||||
Primitive2DList();
|
||||
};
|
||||
|
||||
class TextureRectShader : public ShaderHelperSingleton<TextureRectShader, core::vector2df, core::vector2df, core::vector2df, core::vector2df>, public TextureRead<Bilinear_Filtered>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -12,6 +12,77 @@ bool needsUBO();
|
||||
|
||||
unsigned getGLSLVersion();
|
||||
|
||||
GLuint LoadShader(const char * file, unsigned type);
|
||||
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount);
|
||||
|
||||
template<typename ... Types>
|
||||
void loadAndAttach(GLint ProgramID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
template<typename ... Types>
|
||||
void loadAndAttach(GLint ProgramID, GLint ShaderType, const char *filepath, Types ... args)
|
||||
{
|
||||
GLint ShaderID = LoadShader(filepath, ShaderType);
|
||||
glAttachShader(ProgramID, ShaderID);
|
||||
glDeleteShader(ShaderID);
|
||||
loadAndAttach(ProgramID, args...);
|
||||
}
|
||||
|
||||
template<typename ...Types>
|
||||
void printFileList()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
template<typename ...Types>
|
||||
void printFileList(GLint ShaderType, const char *filepath, Types ... args)
|
||||
{
|
||||
Log::error("GLWrapp", filepath);
|
||||
printFileList(args...);
|
||||
}
|
||||
|
||||
enum AttributeType
|
||||
{
|
||||
OBJECT,
|
||||
PARTICLES_SIM,
|
||||
PARTICLES_RENDERING,
|
||||
};
|
||||
|
||||
void setAttribute(AttributeType Tp, GLuint ProgramID);
|
||||
|
||||
template<typename ... Types>
|
||||
GLint LoadProgram(AttributeType Tp, Types ... args)
|
||||
{
|
||||
GLint ProgramID = glCreateProgram();
|
||||
loadAndAttach(ProgramID, args...);
|
||||
if (getGLSLVersion() < 330)
|
||||
setAttribute(Tp, ProgramID);
|
||||
glLinkProgram(ProgramID);
|
||||
|
||||
GLint Result = GL_FALSE;
|
||||
int InfoLogLength;
|
||||
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
|
||||
if (Result == GL_FALSE) {
|
||||
Log::error("GLWrapp", "Error when linking these shaders :");
|
||||
printFileList(args...);
|
||||
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
char *ErrorMessage = new char[InfoLogLength];
|
||||
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, ErrorMessage);
|
||||
Log::error("GLWrapp", ErrorMessage);
|
||||
delete[] ErrorMessage;
|
||||
}
|
||||
|
||||
GLenum glErr = glGetError();
|
||||
if (glErr != GL_NO_ERROR)
|
||||
{
|
||||
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
|
||||
}
|
||||
|
||||
return ProgramID;
|
||||
}
|
||||
|
||||
struct UniformHelper
|
||||
{
|
||||
template<unsigned N = 0>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "vaomanager.hpp"
|
||||
#include "irr_driver.hpp"
|
||||
#include "stkmesh.hpp"
|
||||
#include "glwrap.hpp"
|
||||
|
||||
VAOManager::VAOManager()
|
||||
{
|
||||
@@ -121,61 +122,8 @@ void VAOManager::regenerateVAO(enum VTXTYPE tp)
|
||||
glGenVertexArrays(1, &vao[tp]);
|
||||
glBindVertexArray(vao[tp]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]);
|
||||
switch (tp)
|
||||
{
|
||||
case VTXTYPE_COUNT: break; // avoid compiler warning
|
||||
case VTXTYPE_STANDARD:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
|
||||
break;
|
||||
case VTXTYPE_TCOORD:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
|
||||
// SecondTexcoord
|
||||
glEnableVertexAttribArray(4);
|
||||
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36);
|
||||
break;
|
||||
case VTXTYPE_TANGENT:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
|
||||
// Tangent
|
||||
glEnableVertexAttribArray(5);
|
||||
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36);
|
||||
// Bitangent
|
||||
glEnableVertexAttribArray(6);
|
||||
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)48);
|
||||
break;
|
||||
}
|
||||
|
||||
VertexUtils::bindVertexArrayAttrib(getVertexType(tp));
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]);
|
||||
glBindVertexArray(0);
|
||||
@@ -319,6 +267,20 @@ VAOManager::VTXTYPE VAOManager::getVTXTYPE(video::E_VERTEX_TYPE type)
|
||||
}
|
||||
};
|
||||
|
||||
irr::video::E_VERTEX_TYPE VAOManager::getVertexType(enum VTXTYPE tp)
|
||||
{
|
||||
switch (tp)
|
||||
{
|
||||
default:
|
||||
case VTXTYPE_STANDARD:
|
||||
return video::EVT_STANDARD;
|
||||
case VTXTYPE_TCOORD:
|
||||
return video::EVT_2TCOORDS;
|
||||
case VTXTYPE_TANGENT:
|
||||
return video::EVT_TANGENTS;
|
||||
}
|
||||
}
|
||||
|
||||
void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp)
|
||||
{
|
||||
size_t old_vtx_cnt = last_vertex[tp];
|
||||
|
||||
@@ -154,6 +154,7 @@ class VAOManager : public Singleton<VAOManager>
|
||||
void regenerateInstancedVAO();
|
||||
size_t getVertexPitch(enum VTXTYPE) const;
|
||||
VTXTYPE getVTXTYPE(irr::video::E_VERTEX_TYPE type);
|
||||
irr::video::E_VERTEX_TYPE getVertexType(enum VTXTYPE tp);
|
||||
void append(irr::scene::IMeshBuffer *, VTXTYPE tp);
|
||||
public:
|
||||
VAOManager();
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "IVideoDriver.h"
|
||||
#include "ITexture.h"
|
||||
#include <cassert>
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/2dutils.hpp"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
@@ -657,7 +657,7 @@ namespace GUIEngine
|
||||
#include "guiengine/engine.hpp"
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/2dutils.hpp"
|
||||
#include "input/input_manager.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "guiengine/event_handler.hpp"
|
||||
|
||||
@@ -184,6 +184,15 @@ bool EventHandler::OnEvent (const SEvent &event)
|
||||
// FIXME? it may be a bit unclean that all input events go trough
|
||||
// the gui module
|
||||
const EventPropagation blockPropagation = input_manager->input(event);
|
||||
|
||||
if (event.EventType == EET_KEY_INPUT_EVENT &&
|
||||
event.KeyInput.Key == irr::KEY_TAB)
|
||||
{
|
||||
// block all tab events, if we let them go, irrlicht will try
|
||||
// to apply its own focus code
|
||||
return true; // EVENT_BLOCK
|
||||
}
|
||||
|
||||
return blockPropagation == EVENT_BLOCK;
|
||||
}
|
||||
else if (event.EventType == EET_LOG_TEXT_EVENT)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/2dutils.hpp"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/2dutils.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/modaldialog.hpp"
|
||||
#include "guiengine/scalable_font.hpp"
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
//#include "os.h"
|
||||
#include "Keycodes.h"
|
||||
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/2dutils.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
|
||||
@@ -1436,21 +1436,14 @@ void Kart::handleMaterialSFX(const Material *material)
|
||||
m_previous_terrain_sound->setLoop(false);
|
||||
|
||||
const std::string &s = material->getSFXName();
|
||||
if (s != "")
|
||||
|
||||
// In multiplayer mode sounds are NOT positional, because we have
|
||||
// multiple listeners. This would make the sounds of all AIs be
|
||||
// audible at all times. So silence AI karts.
|
||||
if (s.size()!=0 && (race_manager->getNumPlayers()==1 ||
|
||||
m_controller->isPlayerController() ) )
|
||||
{
|
||||
m_terrain_sound = SFXManager::get()->createSoundSource(s);
|
||||
|
||||
// In multiplayer mode sounds are NOT positional, because we have
|
||||
// multiple listeners. This would make the sounds of all AIs be
|
||||
// audible at all times. So silence AI karts.
|
||||
if (race_manager->getNumLocalPlayers() > 1)
|
||||
{
|
||||
if (!m_controller->isPlayerController())
|
||||
{
|
||||
m_terrain_sound->setVolume( 0.0f );
|
||||
}
|
||||
}
|
||||
|
||||
m_terrain_sound->play();
|
||||
m_terrain_sound->setLoop(true);
|
||||
}
|
||||
@@ -2017,10 +2010,10 @@ void Kart::updatePhysics(float dt)
|
||||
m_skidding->getSkidState() == Skidding::SKID_ACCUMULATE_RIGHT ) &&
|
||||
m_skidding->getGraphicalJumpOffset()==0)
|
||||
{
|
||||
if(!m_skid_sound->isPlaying() && !isWheeless())
|
||||
if(m_skid_sound->getStatus()!=SFXBase::SFX_PLAYING && !isWheeless())
|
||||
m_skid_sound->play();
|
||||
}
|
||||
else if(m_skid_sound->isPlaying())
|
||||
else if(m_skid_sound->getStatus()==SFXBase::SFX_PLAYING)
|
||||
{
|
||||
m_skid_sound->stop();
|
||||
}
|
||||
|
||||
@@ -622,9 +622,9 @@ void KartModel::loadWheelInfo(const XMLNode &node,
|
||||
// stk_config file is read (which has no model information).
|
||||
if(m_model_filename!="")
|
||||
{
|
||||
Log::error("Kart_Model", "Missing wheel information '%s' for model"
|
||||
Log::error("Kart_Model", "Missing wheel information '%s' for model "
|
||||
"'%s'.", wheel_name.c_str(), m_model_filename.c_str());
|
||||
Log::error("Kart_Model", "This can be ignored, but the wheels will"
|
||||
Log::error("Kart_Model", "This can be ignored, but the wheels will "
|
||||
"not rotate.");
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -138,7 +138,6 @@ void MainLoop::run()
|
||||
if (!m_abort && !ProfileWorld::isNoGraphics())
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("Music/input/GUI", 0x7F, 0x00, 0x00);
|
||||
SFXManager::get()->update(dt);
|
||||
input_manager->update(dt);
|
||||
|
||||
#ifdef ENABLE_WIIUSE
|
||||
@@ -152,6 +151,13 @@ void MainLoop::run()
|
||||
irr_driver->update(dt);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
// Update sfx and music after graphics, so that graphics code
|
||||
// can use as many threads as possible without interfering
|
||||
// with audia
|
||||
PROFILER_PUSH_CPU_MARKER("Music/input/GUI", 0x7F, 0x00, 0x00);
|
||||
SFXManager::get()->update(dt);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("Protocol manager update", 0x7F, 0x00, 0x7F);
|
||||
ProtocolManager::getInstance()->update();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
@@ -436,6 +436,11 @@ void SoccerWorld::initKartList()
|
||||
for(unsigned int n=0; n<kart_amount; n++)
|
||||
{
|
||||
SoccerTeam team = race_manager->getLocalKartInfo(n).getSoccerTeam();
|
||||
#ifdef DEBUG
|
||||
// In debug mode it's possible to play soccer with a single player
|
||||
// (in artist debug mode). Avoid overwriting memory in this case.
|
||||
if(team==SOCCER_TEAM_NONE) team=SOCCER_TEAM_RED;
|
||||
#endif
|
||||
m_karts[n]->setPosition(team_cur_position[team]);
|
||||
team_cur_position[team]++;
|
||||
} // next kart
|
||||
|
||||
@@ -39,8 +39,6 @@ WorldStatus::WorldStatus()
|
||||
m_start_sound = SFXManager::get()->createSoundSource("start_race");
|
||||
m_track_intro_sound = SFXManager::get()->createSoundSource("track_intro");
|
||||
|
||||
music_manager->stopMusic();
|
||||
|
||||
m_play_racestart_sounds = true;
|
||||
|
||||
IrrlichtDevice *device = irr_driver->getDevice();
|
||||
|
||||
@@ -70,6 +70,7 @@ void GrandPrixData::createRandomGP(const unsigned int number_of_tracks,
|
||||
m_name = "Random Grand Prix";
|
||||
m_editable = false;
|
||||
m_group = GP_NONE;
|
||||
m_reverse_type = use_reverse;
|
||||
|
||||
if(new_tracks)
|
||||
{
|
||||
@@ -155,6 +156,7 @@ void GrandPrixData::changeTrackNumber(const unsigned int number_of_tracks,
|
||||
*/
|
||||
void GrandPrixData::changeReverse(const GrandPrixData::GPReverseType use_reverse)
|
||||
{
|
||||
m_reverse_type = use_reverse;
|
||||
for (unsigned int i = 0; i < m_tracks.size(); i++)
|
||||
{
|
||||
if (use_reverse == GP_NO_REVERSE)
|
||||
|
||||
@@ -94,6 +94,9 @@ public:
|
||||
GP_DEFAULT_REVERSE = 3
|
||||
}; // GPReverseType
|
||||
|
||||
private:
|
||||
GPReverseType m_reverse_type;
|
||||
|
||||
public:
|
||||
#if (defined(WIN32) || defined(_WIN32)) && !defined(__MINGW32__)
|
||||
# pragma warning(disable:4290)
|
||||
@@ -145,22 +148,25 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** @return the (potentially translated) user-visible name of the Grand
|
||||
* Prix (apply fribidi as needed) */
|
||||
irr::core::stringw getName() const { return _LTR(m_name.c_str()); }
|
||||
irr::core::stringw getName() const { return _LTR(m_name.c_str()); }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** @return the internal indentifier of the Grand Prix (not translated) */
|
||||
const std::string& getId() const { return m_id; }
|
||||
const std::string& getId() const { return m_id; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if this GP is a random GP. */
|
||||
bool isRandomGP() const { return m_id=="random"; }
|
||||
bool isRandomGP() const { return m_id=="random"; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the filename of the grand prix xml file. */
|
||||
const std::string& getFilename() const { return m_filename; }
|
||||
const std::string& getFilename() const { return m_filename; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the group. */
|
||||
enum GPGroupType getGroup() const { return m_group; }
|
||||
enum GPGroupType getGroup() const { return m_group; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
enum GPReverseType getReverseType()
|
||||
const { return m_reverse_type; }
|
||||
}; // GrandPrixData
|
||||
|
||||
#endif
|
||||
|
||||
@@ -279,15 +279,42 @@ void RaceManager::computeRandomKartList()
|
||||
void RaceManager::startNew(bool from_overworld)
|
||||
{
|
||||
m_started_from_overworld = from_overworld;
|
||||
m_saved_gp = NULL; // There will be checks for this being NULL done later
|
||||
|
||||
if(m_major_mode==MAJOR_MODE_GRAND_PRIX)
|
||||
if (m_major_mode==MAJOR_MODE_GRAND_PRIX)
|
||||
{
|
||||
// GP: get tracks, laps and reverse info from grand prix
|
||||
m_tracks = m_grand_prix.getTrackNames();
|
||||
m_num_laps = m_grand_prix.getLaps();
|
||||
m_reverse_track = m_grand_prix.getReverse();
|
||||
|
||||
// We look if Player 1 has a saved version of this GP.
|
||||
m_saved_gp = SavedGrandPrix::getSavedGP(
|
||||
StateManager::get()
|
||||
->getActivePlayerProfile(0)
|
||||
->getUniqueID(),
|
||||
m_grand_prix.getId(),
|
||||
m_player_karts.size());
|
||||
|
||||
// Saved GP only in offline mode
|
||||
if (m_continue_saved_gp && !NetworkWorld::getInstance<NetworkWorld>()->isRunning())
|
||||
{
|
||||
if (m_saved_gp == NULL)
|
||||
{
|
||||
Log::error("Race Manager", "Can not continue Grand Prix '%s'"
|
||||
"because it could not exist",
|
||||
m_grand_prix.getId().c_str());
|
||||
m_continue_saved_gp = false; // simple and working
|
||||
}
|
||||
else
|
||||
{
|
||||
setNumKarts(m_saved_gp->getTotalKarts());
|
||||
setupPlayerKartInfo();
|
||||
m_grand_prix.changeReverse((GrandPrixData::GPReverseType)m_saved_gp->getReverseType());
|
||||
m_reverse_track = m_grand_prix.getReverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
//assert(m_player_karts.size() > 0);
|
||||
|
||||
// command line parameters: negative numbers=all karts
|
||||
if(m_num_karts < 0 ) m_num_karts = stk_config->m_max_karts;
|
||||
@@ -308,8 +335,8 @@ void RaceManager::startNew(bool from_overworld)
|
||||
race_manager->getMinorMode()==RaceManager::MINOR_MODE_FOLLOW_LEADER
|
||||
? -1
|
||||
: 0;
|
||||
const unsigned int ai_kart_count = (unsigned int) m_ai_kart_list.size();
|
||||
for(unsigned int i=0; i<ai_kart_count; i++)
|
||||
const unsigned int ai_kart_count = m_ai_kart_list.size();
|
||||
for(unsigned int i = 0; i < ai_kart_count; i++)
|
||||
{
|
||||
m_kart_status.push_back(KartStatus(m_ai_kart_list[i], i, -1, -1,
|
||||
init_gp_rank, KT_AI));
|
||||
@@ -323,7 +350,7 @@ void RaceManager::startNew(bool from_overworld)
|
||||
|
||||
// Then the players, which start behind the AI karts
|
||||
// -------------------------------------------------
|
||||
for(unsigned int i=0; i<(unsigned int)m_player_karts.size(); i++)
|
||||
for(unsigned int i = 0; i < m_player_karts.size(); i++)
|
||||
{
|
||||
KartType kt= m_player_karts[i].isNetworkPlayer() ? KT_NETWORK_PLAYER : KT_PLAYER;
|
||||
m_kart_status.push_back(KartStatus(m_player_karts[i].getKartName(), i,
|
||||
@@ -340,34 +367,20 @@ void RaceManager::startNew(bool from_overworld)
|
||||
}
|
||||
|
||||
m_track_number = 0;
|
||||
if(m_major_mode==MAJOR_MODE_GRAND_PRIX &&
|
||||
!NetworkWorld::getInstance<NetworkWorld>()->isRunning()) // offline mode only
|
||||
if (m_major_mode == MAJOR_MODE_GRAND_PRIX)
|
||||
{
|
||||
//We look if Player 1 has a saved version of this GP.
|
||||
// =================================================
|
||||
SavedGrandPrix* gp = SavedGrandPrix::getSavedGP( StateManager::get()
|
||||
->getActivePlayerProfile(0)
|
||||
->getUniqueID(),
|
||||
m_grand_prix.getId(),
|
||||
m_difficulty,
|
||||
m_num_karts,
|
||||
(int)m_player_karts.size());
|
||||
|
||||
// Start the race with the appropriate track
|
||||
// =========================================
|
||||
if(gp != NULL)
|
||||
if (m_continue_saved_gp)
|
||||
{
|
||||
if (m_continue_saved_gp)
|
||||
{
|
||||
m_track_number = gp->getNextTrack();
|
||||
gp->loadKarts(m_kart_status);
|
||||
}
|
||||
else
|
||||
{
|
||||
gp->remove();
|
||||
}
|
||||
m_track_number = m_saved_gp->getNextTrack();
|
||||
m_saved_gp->loadKarts(m_kart_status);
|
||||
}
|
||||
else if (m_saved_gp != NULL)
|
||||
{
|
||||
m_saved_gp->remove();
|
||||
m_saved_gp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
startNextRace();
|
||||
} // startNew
|
||||
|
||||
@@ -482,7 +495,6 @@ void RaceManager::startNextRace()
|
||||
} // startNextRace
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RaceManager::next()
|
||||
{
|
||||
World::deleteWorld();
|
||||
@@ -493,38 +505,18 @@ void RaceManager::next()
|
||||
{
|
||||
if(m_major_mode==MAJOR_MODE_GRAND_PRIX && !NetworkWorld::getInstance()->isRunning())
|
||||
{
|
||||
//Saving GP state
|
||||
//We look if Player 1 has already saved this GP.
|
||||
SavedGrandPrix* gp =
|
||||
SavedGrandPrix::getSavedGP(StateManager::get()
|
||||
->getActivePlayerProfile(0)
|
||||
->getUniqueID(),
|
||||
m_grand_prix.getId(),
|
||||
m_difficulty,
|
||||
m_num_karts,
|
||||
(int)m_player_karts.size());
|
||||
if(gp != NULL)
|
||||
// Saving GP state
|
||||
// If Player 1 has already saved a GP, we adapt it
|
||||
if(m_saved_gp != NULL)
|
||||
{
|
||||
//if so addept it
|
||||
gp->setKarts(m_kart_status);
|
||||
gp->setNextTrack(m_track_number);
|
||||
m_saved_gp->setKarts(m_kart_status);
|
||||
m_saved_gp->setNextTrack(m_track_number);
|
||||
user_config->saveConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
//create a new entry
|
||||
UserConfigParams::m_saved_grand_prix_list.push_back(
|
||||
new SavedGrandPrix(
|
||||
StateManager::get()->getActivePlayerProfile(0)
|
||||
->getUniqueID(),
|
||||
m_grand_prix.getId(),
|
||||
m_difficulty,
|
||||
(int)m_player_karts.size(),
|
||||
m_track_number,
|
||||
m_kart_status
|
||||
)
|
||||
);
|
||||
saveGP();
|
||||
}
|
||||
user_config->saveConfig();
|
||||
}
|
||||
startNextRace();
|
||||
}
|
||||
@@ -534,6 +526,24 @@ void RaceManager::next()
|
||||
}
|
||||
} // next
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::saveGP()
|
||||
{
|
||||
UserConfigParams::m_saved_grand_prix_list.push_back(
|
||||
new SavedGrandPrix(
|
||||
StateManager::get()->getActivePlayerProfile(0)
|
||||
->getUniqueID(),
|
||||
m_grand_prix.getId(),
|
||||
m_difficulty,
|
||||
(int)m_player_karts.size(),
|
||||
m_track_number,
|
||||
m_grand_prix.getReverseType(),
|
||||
m_kart_status
|
||||
)
|
||||
);
|
||||
user_config->saveConfig();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** This class is only used in computeGPRanks, but the C++ standard
|
||||
@@ -630,16 +640,8 @@ void RaceManager::exitRace(bool delete_world)
|
||||
PlayerManager::getCurrentPlayer()->grandPrixFinished();
|
||||
if(m_major_mode==MAJOR_MODE_GRAND_PRIX&& !NetworkWorld::getInstance()->isRunning())
|
||||
{
|
||||
//Delete saved GP
|
||||
SavedGrandPrix* gp =
|
||||
SavedGrandPrix::getSavedGP(StateManager::get()
|
||||
->getActivePlayerProfile(0)
|
||||
->getUniqueID(),
|
||||
m_grand_prix.getId(),
|
||||
m_difficulty,
|
||||
m_num_karts,
|
||||
(int)m_player_karts.size());
|
||||
if(gp != NULL) gp->remove();
|
||||
if(m_saved_gp != NULL)
|
||||
m_saved_gp->remove();
|
||||
}
|
||||
StateManager::get()->resetAndGoToScreen( MainMenuScreen::getInstance() );
|
||||
|
||||
@@ -717,6 +719,7 @@ void RaceManager::exitRace(bool delete_world)
|
||||
|
||||
if (delete_world) World::deleteWorld();
|
||||
|
||||
m_saved_gp = NULL;
|
||||
m_track_number = 0;
|
||||
} // exitRace
|
||||
|
||||
@@ -766,7 +769,6 @@ void RaceManager::startGP(const GrandPrixData &gp, bool from_overworld,
|
||||
{
|
||||
StateManager::get()->enterGameState();
|
||||
setGrandPrix(gp);
|
||||
setCoinTarget( 0 ); // Might still be set from a previous challenge
|
||||
race_manager->setupPlayerKartInfo();
|
||||
m_continue_saved_gp = continue_saved_gp;
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
class AbstractKart;
|
||||
class SavedGrandPrix;
|
||||
class Track;
|
||||
|
||||
static const std::string IDENT_STD ("STANDARD" );
|
||||
@@ -326,6 +327,7 @@ private:
|
||||
std::vector<std::string> m_ai_kart_list;
|
||||
int m_track_number;
|
||||
GrandPrixData m_grand_prix;
|
||||
SavedGrandPrix* m_saved_gp;
|
||||
int m_num_karts;
|
||||
unsigned int m_num_finished_karts;
|
||||
unsigned int m_num_finished_players;
|
||||
@@ -410,11 +412,13 @@ public:
|
||||
*/
|
||||
void setDifficulty(Difficulty diff);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
void setCoinTarget(int num) { m_coin_target = num; }
|
||||
// ------------------------------------------------------------------------
|
||||
void setGrandPrix(const GrandPrixData &gp)
|
||||
{
|
||||
m_grand_prix = gp;
|
||||
m_coin_target = 0;
|
||||
setCoinTarget(0);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void setAIKartOverride(const std::string& kart)
|
||||
@@ -453,8 +457,6 @@ public:
|
||||
m_ai_superpower = SUPERPOWER_NONE;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void setCoinTarget(int num) { m_coin_target = num; }
|
||||
// ------------------------------------------------------------------------
|
||||
void setTimeTarget(float num) { m_has_time_target = true;
|
||||
m_time_target = num; }
|
||||
/** \} */
|
||||
@@ -683,8 +685,11 @@ public:
|
||||
* \brief Higher-level method to start a GP without having to care about
|
||||
* the exact startup sequence
|
||||
*/
|
||||
void startGP(const GrandPrixData &gp, bool from_overworld,
|
||||
bool continue_saved_gp);
|
||||
void startGP(const GrandPrixData &gp, bool from_overworld,
|
||||
bool continue_saved_gp);
|
||||
|
||||
/** Saves the current GP to the config */
|
||||
void saveGP();
|
||||
|
||||
/**
|
||||
* \brief Higher-level method to start a GP without having to care about
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
#include "config/user_config.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/scalable_font.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/2dutils.hpp"
|
||||
#include "states_screens/cutscene_gui.hpp"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -203,8 +203,6 @@ void GPInfoDialog::addButtons()
|
||||
->getActivePlayerProfile(0)
|
||||
->getUniqueID(),
|
||||
m_gp.getId(),
|
||||
race_manager->getDifficulty(),
|
||||
race_manager->getNumberOfKarts(),
|
||||
race_manager->getNumLocalPlayers());
|
||||
|
||||
okBtn->m_properties[PROP_ID] = "start";
|
||||
|
||||
@@ -479,8 +479,9 @@ void UserInfoDialog::onUpdate(float dt)
|
||||
// It's unsafe to delete from inside the event handler so we do it here
|
||||
if (m_self_destroy)
|
||||
{
|
||||
bool enter_profile = m_enter_profile;
|
||||
ModalDialog::dismiss();
|
||||
if (m_enter_profile)
|
||||
if (enter_profile)
|
||||
StateManager::get()->replaceTopMostScreen(OnlineProfileAchievements::getInstance());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,11 @@ bool EditTrackScreen::getResult() const
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditTrackScreen::loadedFromFile()
|
||||
{
|
||||
static const int MAX_LABEL_LENGTH = 35;
|
||||
|
||||
DynamicRibbonWidget* tracks_widget = getWidget<DynamicRibbonWidget>("tracks");
|
||||
assert(tracks_widget != NULL);
|
||||
tracks_widget->setMaxLabelLength(MAX_LABEL_LENGTH);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -81,7 +81,7 @@ void GPInfoScreen::loadedFromFile()
|
||||
// Only init the number of tracks here, this way the previously selected
|
||||
// number of tracks will be the default.
|
||||
m_num_tracks_spinner->setValue(1);
|
||||
|
||||
|
||||
m_ai_kart_spinner = getWidget<SpinnerWidget>("ai-spinner");
|
||||
} // loadedFromFile
|
||||
|
||||
@@ -97,14 +97,14 @@ void GPInfoScreen::setGP(const std::string &gp_ident)
|
||||
{
|
||||
// Doesn't matter what kind of GP we create, it just gets the
|
||||
// right id ("random").
|
||||
m_gp.createRandomGP(1, "standard",
|
||||
m_gp.createRandomGP(1, "standard",
|
||||
m_reverse_spinner ? getReverse()
|
||||
: GrandPrixData::GP_NO_REVERSE);
|
||||
}
|
||||
} // setGP
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Converts the currently selected reverse status into a value of type
|
||||
/** Converts the currently selected reverse status into a value of type
|
||||
* GPReverseType .
|
||||
*/
|
||||
GrandPrixData::GPReverseType GPInfoScreen::getReverse() const
|
||||
@@ -130,8 +130,6 @@ void GPInfoScreen::beforeAddingWidget()
|
||||
SavedGrandPrix* saved_gp = SavedGrandPrix::getSavedGP(
|
||||
StateManager::get()->getActivePlayerProfile(0)->getUniqueID(),
|
||||
m_gp.getId(),
|
||||
race_manager->getDifficulty(),
|
||||
race_manager->getNumberOfKarts(),
|
||||
race_manager->getNumLocalPlayers());
|
||||
|
||||
RibbonWidget* ribbonButtons = getWidget<RibbonWidget>("buttons");
|
||||
@@ -194,10 +192,10 @@ void GPInfoScreen::init()
|
||||
else
|
||||
m_group_name = stringc(m_group_spinner->getStringValue().c_str()).c_str();
|
||||
|
||||
// If there are more tracks selected atm as in the group (which can
|
||||
// If there are more tracks selected atm as in the group (which can
|
||||
// happen if the group has been changed since last time this screen
|
||||
// was shown), adjust it:
|
||||
int max_num_tracks = m_group_name=="all"
|
||||
int max_num_tracks = m_group_name=="all"
|
||||
? track_manager->getNumberOfRaceTracks()
|
||||
: (int)track_manager->getTracksInGroup(m_group_name).size();
|
||||
m_num_tracks_spinner->setMax(max_num_tracks);
|
||||
@@ -207,7 +205,7 @@ void GPInfoScreen::init()
|
||||
}
|
||||
|
||||
// Now create the random GP:
|
||||
m_gp.createRandomGP(m_num_tracks_spinner->getValue(),
|
||||
m_gp.createRandomGP(m_num_tracks_spinner->getValue(),
|
||||
m_group_name, getReverse(), true);
|
||||
}
|
||||
else
|
||||
@@ -215,7 +213,7 @@ void GPInfoScreen::init()
|
||||
getWidget<LabelWidget>("name")->setText(m_gp.getName(), false);
|
||||
m_gp.checkConsistency();
|
||||
}
|
||||
|
||||
|
||||
// Number of AIs
|
||||
// -------------
|
||||
const bool has_AI = race_manager->hasAI();
|
||||
@@ -288,7 +286,7 @@ void GPInfoScreen::addScreenshot()
|
||||
m_screenshot_widget->m_h = screenshot_div->m_h;
|
||||
|
||||
|
||||
// Temporary icon, will replace it just after
|
||||
// Temporary icon, will replace it just after
|
||||
// (but it will be shown if the given icon is not found)
|
||||
m_screenshot_widget->m_properties[PROP_ICON] = "gui/main_help.png";
|
||||
m_screenshot_widget->add();
|
||||
@@ -336,7 +334,7 @@ void GPInfoScreen::eventCallback(Widget *, const std::string &name,
|
||||
// the current track. The current value in the Number-of-tracks-spinner
|
||||
// has to be updated, since otherwise the displayed (and used) value
|
||||
// can be bigger than the maximum. (Might be a TODO to fix this)
|
||||
int max_num_tracks = m_group_name=="all"
|
||||
int max_num_tracks = m_group_name=="all"
|
||||
? track_manager->getNumberOfRaceTracks()
|
||||
: (int)track_manager->getTracksInGroup(m_group_name).size();
|
||||
m_num_tracks_spinner->setMax(max_num_tracks);
|
||||
@@ -344,7 +342,7 @@ void GPInfoScreen::eventCallback(Widget *, const std::string &name,
|
||||
m_num_tracks_spinner->setValue(max_num_tracks);
|
||||
// Create a new (i.e. with new tracks) random gp, since the old
|
||||
// tracks might not all belong to the newly selected group.
|
||||
|
||||
|
||||
m_gp.createRandomGP(m_num_tracks_spinner->getValue(), m_group_name,
|
||||
getReverse(), /*new_tracks*/true);
|
||||
addTracks();
|
||||
@@ -359,11 +357,6 @@ void GPInfoScreen::eventCallback(Widget *, const std::string &name,
|
||||
const int num_ai = m_ai_kart_spinner->getValue();
|
||||
race_manager->setNumKarts( race_manager->getNumLocalPlayers() + num_ai );
|
||||
UserConfigParams::m_num_karts = race_manager->getNumLocalPlayers() + num_ai;
|
||||
|
||||
//Redraw scene because available buttons depend on current settings
|
||||
getWidget<RibbonWidget>("buttons")->setSelection(0, PLAYER_ID_GAME_MASTER);
|
||||
reshowCurrentScreen();
|
||||
m_ai_kart_spinner->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||
}
|
||||
else if(name=="back")
|
||||
{
|
||||
|
||||
@@ -62,7 +62,15 @@ void GrandPrixEditorScreen::beforeAddingWidget()
|
||||
// -----------------------------------------------------------------------------
|
||||
void GrandPrixEditorScreen::loadedFromFile()
|
||||
{
|
||||
static const int MAX_LABEL_LENGTH = 35;
|
||||
|
||||
DynamicRibbonWidget* gplist_widget = getWidget<DynamicRibbonWidget>("gplist");
|
||||
assert (gplist_widget != NULL);
|
||||
gplist_widget->setMaxLabelLength(MAX_LABEL_LENGTH);
|
||||
|
||||
DynamicRibbonWidget* tracks_widget = getWidget<DynamicRibbonWidget>("tracks");
|
||||
assert(tracks_widget != NULL);
|
||||
tracks_widget->setMaxLabelLength(MAX_LABEL_LENGTH);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "states_screens/online_profile_base.hpp"
|
||||
|
||||
#include "config/player_manager.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/scalable_font.hpp"
|
||||
#include "guiengine/screen.hpp"
|
||||
@@ -71,6 +72,8 @@ void OnlineProfileBase::beforeAddingWidget()
|
||||
m_visiting_profile = ProfileManager::get()->getVisitingProfile();
|
||||
if (!m_visiting_profile || !m_visiting_profile->isCurrentUser())
|
||||
m_settings_tab->setVisible(false);
|
||||
else
|
||||
m_settings_tab->setVisible(true);
|
||||
|
||||
// If not logged in, don't show profile or friends
|
||||
if (!m_visiting_profile)
|
||||
@@ -103,6 +106,19 @@ void OnlineProfileBase::init()
|
||||
|
||||
} // init
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
bool OnlineProfileBase::onEscapePressed()
|
||||
{
|
||||
//return to main menu if it's your profile
|
||||
if (!m_visiting_profile || m_visiting_profile->isCurrentUser())
|
||||
return true;
|
||||
|
||||
//return to your profile if it's another profile
|
||||
ProfileManager::get()->setVisiting(PlayerManager::getCurrentOnlineId());
|
||||
StateManager::get()->replaceTopMostScreen(OnlineProfileAchievements::getInstance());
|
||||
return false;
|
||||
} // onEscapePressed
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Called when an event occurs (i.e. user clicks on something).
|
||||
*/
|
||||
|
||||
@@ -62,6 +62,8 @@ public:
|
||||
/** \brief implement callback from parent class GUIEngine::Screen */
|
||||
virtual void init() OVERRIDE;
|
||||
|
||||
virtual bool onEscapePressed() OVERRIDE;
|
||||
|
||||
virtual void beforeAddingWidget() OVERRIDE;
|
||||
};
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ void OptionsScreenAudio::eventCallback(Widget* widget, const std::string& name,
|
||||
CheckBoxWidget* w = dynamic_cast<CheckBoxWidget*>(widget);
|
||||
|
||||
UserConfigParams::m_sfx = w->getState();
|
||||
SFXManager::get()->soundToggled(UserConfigParams::m_sfx);
|
||||
SFXManager::get()->toggleSound(UserConfigParams::m_sfx);
|
||||
|
||||
if (UserConfigParams::m_sfx)
|
||||
{
|
||||
|
||||
@@ -26,8 +26,8 @@ using namespace irr;
|
||||
#include "challenges/unlock_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/camera.hpp"
|
||||
#include "graphics/2dutils.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/material_manager.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/modaldialog.hpp"
|
||||
@@ -506,7 +506,7 @@ void RaceGUI::drawEnergyMeter(int x, int y, const AbstractKart *kart,
|
||||
m.setTexture(0, m_gauge_goal);
|
||||
m.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
irr_driver->getVideoDriver()->setMaterial(m);
|
||||
irr_driver->getVideoDriver()->draw2DVertexPrimitiveList(vertices, count,
|
||||
draw2DVertexPrimitiveList(m_gauge_goal, vertices, count,
|
||||
index, count-2, video::EVT_STANDARD, scene::EPT_TRIANGLE_FAN);
|
||||
|
||||
}
|
||||
@@ -594,7 +594,7 @@ void RaceGUI::drawEnergyMeter(int x, int y, const AbstractKart *kart,
|
||||
m.setTexture(0, m_gauge_full);
|
||||
m.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
irr_driver->getVideoDriver()->setMaterial(m);
|
||||
irr_driver->getVideoDriver()->draw2DVertexPrimitiveList(vertices, count,
|
||||
draw2DVertexPrimitiveList(m.getTexture(0), vertices, count,
|
||||
index, count-2, video::EVT_STANDARD, scene::EPT_TRIANGLE_FAN);
|
||||
|
||||
}
|
||||
@@ -800,7 +800,7 @@ void RaceGUI::drawSpeedEnergyRank(const AbstractKart* kart,
|
||||
m.setTexture(0, m_speed_bar_icon->getTexture());
|
||||
m.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
irr_driver->getVideoDriver()->setMaterial(m);
|
||||
irr_driver->getVideoDriver()->draw2DVertexPrimitiveList(vertices, count,
|
||||
draw2DVertexPrimitiveList(m_speed_bar_icon->getTexture(), vertices, count,
|
||||
index, count-2, video::EVT_STANDARD, scene::EPT_TRIANGLE_FAN);
|
||||
|
||||
} // drawSpeedEnergyRank
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "audio/music_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/camera.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/2dutils.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/material.hpp"
|
||||
#include "graphics/material_manager.hpp"
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
#include "config/player_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/camera.hpp"
|
||||
#include "graphics/2dutils.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/material_manager.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/modaldialog.hpp"
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "challenges/unlock_manager.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/2dutils.hpp"
|
||||
#include "graphics/material.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/modaldialog.hpp"
|
||||
@@ -393,6 +393,7 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
|
||||
|
||||
void RaceResultGUI::onConfirm()
|
||||
{
|
||||
race_manager->saveGP(); // Save the aborted GP
|
||||
GUIEngine::ModalDialog::dismiss();
|
||||
cleanupGPProgress();
|
||||
StateManager::get()->popMenu();
|
||||
|
||||
@@ -163,10 +163,13 @@ void BaseUserScreen::selectUser(int index)
|
||||
|
||||
m_players->setSelection(StringUtils::toString(index), PLAYER_ID_GAME_MASTER,
|
||||
/*focusIt*/ true);
|
||||
|
||||
m_username_tb->setText(profile->getLastOnlineName());
|
||||
// Delete a password that might have been typed for another user
|
||||
m_password_tb->setText("");
|
||||
|
||||
// Last game was not online, so make the offline settings the default
|
||||
// (i.e. unckeck online checkbox, and make entry fields invisible).
|
||||
|
||||
if (!profile->wasOnlineLastTime() || profile->getLastOnlineName() == "")
|
||||
{
|
||||
m_online_cb->setState(false);
|
||||
@@ -177,7 +180,6 @@ void BaseUserScreen::selectUser(int index)
|
||||
// Now last use was with online --> Display the saved data
|
||||
m_online_cb->setState(true);
|
||||
makeEntryFieldsVisible();
|
||||
m_username_tb->setText(profile->getLastOnlineName());
|
||||
getWidget<CheckBoxWidget>("remember-user")->setState(
|
||||
profile->rememberPassword());
|
||||
if(profile->getLastOnlineName().size()>0)
|
||||
@@ -231,14 +233,6 @@ void BaseUserScreen::makeEntryFieldsVisible()
|
||||
{
|
||||
getWidget<LabelWidget>("label_password")->setVisible(online);
|
||||
m_password_tb->setVisible(online);
|
||||
if(player && player->hasSavedSession())
|
||||
{
|
||||
// Even though this field is invisible we need to set
|
||||
// the name, otherwise in update a change of user name
|
||||
// will be detected, causing a clearing of this player
|
||||
// (which then removes the associated online user name).
|
||||
m_username_tb->setText(player->getLastOnlineName());
|
||||
}
|
||||
}
|
||||
} // makeEntryFieldsVisible
|
||||
|
||||
@@ -446,18 +440,6 @@ void BaseUserScreen::onUpdate(float dt)
|
||||
m_info_widget->setText(StringUtils::loadingDots(message.c_str()),
|
||||
false );
|
||||
}
|
||||
PlayerProfile *player = getSelectedPlayer();
|
||||
if(player)
|
||||
{
|
||||
// If the player changes the online name, clear the saved session
|
||||
// flag, and make the password field visible again.
|
||||
if (m_username_tb->getText()!=player->getLastOnlineName())
|
||||
{
|
||||
player->clearSession();
|
||||
makeEntryFieldsVisible();
|
||||
m_username_tb->setText(player->getLastOnlineName());
|
||||
}
|
||||
}
|
||||
} // onUpdate
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -122,3 +122,17 @@ scene::IMesh* ModelDefinitionLoader::getFirstMeshFor(const std::string& name)
|
||||
{
|
||||
return irr_driver->getMesh(m_lod_groups[name][0].m_model_file);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ModelDefinitionLoader::cleanLibraryNodesAfterLoad()
|
||||
{
|
||||
for (std::map<std::string, XMLNode*>::iterator it = m_library_nodes.begin();
|
||||
it != m_library_nodes.end(); it++)
|
||||
{
|
||||
delete it->second;
|
||||
|
||||
file_manager->popTextureSearchPath();
|
||||
file_manager->popModelSearchPath();
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ class LODNode;
|
||||
class Track;
|
||||
class STKInstancedSceneNode;
|
||||
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
@@ -68,12 +69,13 @@ struct ModelDefinition
|
||||
}
|
||||
};
|
||||
|
||||
/** Utility class to load level-of-detail nodes and instaincing nodes
|
||||
/** Utility class to load level-of-detail nodes and library nodes
|
||||
* \ingroup tracks
|
||||
*/
|
||||
class ModelDefinitionLoader
|
||||
{
|
||||
private:
|
||||
std::map<std::string, XMLNode*> m_library_nodes;
|
||||
std::map< std::string, std::vector< ModelDefinition > > m_lod_groups;
|
||||
std::map< std::string, STKInstancedSceneNode* > m_instancing_nodes;
|
||||
Track* m_track;
|
||||
@@ -86,8 +88,25 @@ public:
|
||||
|
||||
void clear();
|
||||
|
||||
|
||||
scene::IMesh* getFirstMeshFor(const std::string& name);
|
||||
|
||||
std::map<std::string, XMLNode*>& getLibraryNodes()
|
||||
{
|
||||
return m_library_nodes;
|
||||
}
|
||||
|
||||
void cleanLibraryNodesAfterLoad();
|
||||
|
||||
bool containsLibraryNode(const std::string& name) const
|
||||
{
|
||||
return m_library_nodes.find(name) != m_library_nodes.end();
|
||||
}
|
||||
|
||||
void addToLibrary(const std::string& name, XMLNode* xml)
|
||||
{
|
||||
assert(xml != NULL);
|
||||
m_library_nodes[name] = xml;
|
||||
}
|
||||
}; // ModelDefinitionLoader
|
||||
|
||||
#endif // HEADER_LOD_NODE_LOADER_HPP
|
||||
|
||||
@@ -1738,18 +1738,9 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, XMLNode*> library_nodes;
|
||||
loadObjects(root, path, model_def_loader, true, NULL, library_nodes);
|
||||
loadObjects(root, path, model_def_loader, true, NULL);
|
||||
|
||||
// Cleanup library nodes
|
||||
for (std::map<std::string, XMLNode*>::iterator it = library_nodes.begin();
|
||||
it != library_nodes.end(); it++)
|
||||
{
|
||||
delete it->second;
|
||||
|
||||
file_manager->popTextureSearchPath();
|
||||
file_manager->popModelSearchPath();
|
||||
}
|
||||
model_def_loader.cleanLibraryNodesAfterLoad();
|
||||
|
||||
// Init all track objects
|
||||
m_track_object_manager->init();
|
||||
@@ -1914,8 +1905,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void Track::loadObjects(const XMLNode* root, const std::string& path, ModelDefinitionLoader& model_def_loader,
|
||||
bool create_lod_definitions, scene::ISceneNode* parent,
|
||||
std::map<std::string, XMLNode*>& library_nodes)
|
||||
bool create_lod_definitions, scene::ISceneNode* parent)
|
||||
{
|
||||
unsigned int start_position_counter = 0;
|
||||
|
||||
@@ -1927,75 +1917,10 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, ModelDefin
|
||||
// The track object was already converted before the loop, and the
|
||||
// default start was already used, too - so ignore those.
|
||||
if (name == "track" || name == "default-start") continue;
|
||||
if (name == "object")
|
||||
if (name == "object" || name == "library")
|
||||
{
|
||||
m_track_object_manager->add(*node, parent, model_def_loader);
|
||||
}
|
||||
else if (name == "library")
|
||||
{
|
||||
std::string name;
|
||||
node->get("name", &name);
|
||||
|
||||
core::vector3df xyz;
|
||||
node->get("xyz", &xyz);
|
||||
|
||||
core::vector3df hpr;
|
||||
node->get("hpr", &hpr);
|
||||
|
||||
core::vector3df scale;
|
||||
node->get("scale", &scale);
|
||||
|
||||
XMLNode* libroot;
|
||||
std::string lib_path =
|
||||
file_manager->getAsset(FileManager::LIBRARY, name)+"/";
|
||||
bool create_lod_definitions = true;
|
||||
|
||||
if (library_nodes.find(name) == library_nodes.end())
|
||||
{
|
||||
std::string lib_node_path = lib_path+"node.xml";
|
||||
libroot = file_manager->createXMLTree(lib_node_path);
|
||||
if (libroot == NULL)
|
||||
{
|
||||
Log::error("Track", "Cannot find library '%s'", lib_node_path.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
file_manager->pushTextureSearchPath(lib_path + "/");
|
||||
file_manager->pushModelSearchPath (lib_path);
|
||||
material_manager->pushTempMaterial(lib_path + "/materials.xml");
|
||||
library_nodes[name] = libroot;
|
||||
|
||||
// Load LOD groups
|
||||
const XMLNode *lod_xml_node = libroot->getNode("lod");
|
||||
if (lod_xml_node != NULL)
|
||||
{
|
||||
for (unsigned int i = 0; i < lod_xml_node->getNumNodes(); i++)
|
||||
{
|
||||
const XMLNode* lod_group_xml = lod_xml_node->getNode(i);
|
||||
for (unsigned int j = 0; j < lod_group_xml->getNumNodes(); j++)
|
||||
{
|
||||
model_def_loader.addModelDefinition(lod_group_xml->getNode(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
libroot = library_nodes[name];
|
||||
create_lod_definitions = false; // LOD definitions are already created, don't create them again
|
||||
}
|
||||
|
||||
scene::ISceneNode* parent = irr_driver->getSceneManager()->addEmptySceneNode();
|
||||
#ifdef DEBUG
|
||||
parent->setName(("libnode_" + name).c_str());
|
||||
#endif
|
||||
parent->setPosition(xyz);
|
||||
parent->setRotation(hpr);
|
||||
parent->setScale(scale);
|
||||
parent->updateAbsolutePosition();
|
||||
loadObjects(libroot, lib_path, model_def_loader, create_lod_definitions, parent, library_nodes);
|
||||
//m_all_nodes.push_back(parent);
|
||||
}
|
||||
else if (name == "water")
|
||||
{
|
||||
createWater(*node);
|
||||
|
||||
@@ -412,9 +412,6 @@ private:
|
||||
std::vector<MusicInformation*>& m_music );
|
||||
void loadCurves(const XMLNode &node);
|
||||
void handleSky(const XMLNode &root, const std::string &filename);
|
||||
void loadObjects(const XMLNode* root, const std::string& path, ModelDefinitionLoader& lod_loader,
|
||||
bool create_lod_definitions, scene::ISceneNode* parent,
|
||||
std::map<std::string, XMLNode*>& library_nodes);
|
||||
|
||||
public:
|
||||
|
||||
@@ -472,6 +469,9 @@ public:
|
||||
/** Returns true if this track has easter eggs. */
|
||||
bool hasEasterEggs() const { return m_has_easter_eggs; }
|
||||
// ------------------------------------------------------------------------
|
||||
void loadObjects(const XMLNode* root, const std::string& path, ModelDefinitionLoader& lod_loader,
|
||||
bool create_lod_definitions, scene::ISceneNode* parent);
|
||||
// ------------------------------------------------------------------------
|
||||
bool isSoccer () const { return m_is_soccer; }
|
||||
// ------------------------------------------------------------------------
|
||||
void loadTrackModel (World* parent,
|
||||
|
||||
@@ -132,6 +132,10 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
|
||||
m_type = "light";
|
||||
m_presentation = new TrackObjectPresentationLight(xml_node, parent);
|
||||
}
|
||||
else if (xml_node.getName() == "library")
|
||||
{
|
||||
m_presentation = new TrackObjectPresentationLibraryNode(xml_node, model_def_loader);
|
||||
}
|
||||
else if (type == "sfx-emitter")
|
||||
{
|
||||
// FIXME: at this time sound emitters are just disabled in multiplayer
|
||||
|
||||
@@ -148,6 +148,77 @@ TrackObjectPresentationEmpty::~TrackObjectPresentationEmpty()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TrackObjectPresentationLibraryNode::TrackObjectPresentationLibraryNode(
|
||||
const XMLNode& xml_node,
|
||||
ModelDefinitionLoader& model_def_loader) :
|
||||
TrackObjectPresentationSceneNode(xml_node)
|
||||
{
|
||||
std::string name;
|
||||
xml_node.get("name", &name);
|
||||
|
||||
m_node = irr_driver->getSceneManager()->addEmptySceneNode();
|
||||
#ifdef DEBUG
|
||||
m_node->setName(("libnode_" + name).c_str());
|
||||
#endif
|
||||
|
||||
XMLNode* libroot;
|
||||
std::string lib_path =
|
||||
file_manager->getAsset(FileManager::LIBRARY, name) + "/";
|
||||
bool create_lod_definitions = true;
|
||||
|
||||
if (!model_def_loader.containsLibraryNode(name))
|
||||
{
|
||||
std::string lib_node_path = lib_path + "node.xml";
|
||||
libroot = file_manager->createXMLTree(lib_node_path);
|
||||
if (libroot == NULL)
|
||||
{
|
||||
Log::error("TrackObjectPresentationLibraryNode", "Cannot find library '%s'", lib_node_path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
file_manager->pushTextureSearchPath(lib_path + "/");
|
||||
file_manager->pushModelSearchPath(lib_path);
|
||||
material_manager->pushTempMaterial(lib_path + "/materials.xml");
|
||||
model_def_loader.addToLibrary(name, libroot);
|
||||
|
||||
// Load LOD groups
|
||||
const XMLNode *lod_xml_node = libroot->getNode("lod");
|
||||
if (lod_xml_node != NULL)
|
||||
{
|
||||
for (unsigned int i = 0; i < lod_xml_node->getNumNodes(); i++)
|
||||
{
|
||||
const XMLNode* lod_group_xml = lod_xml_node->getNode(i);
|
||||
for (unsigned int j = 0; j < lod_group_xml->getNumNodes(); j++)
|
||||
{
|
||||
model_def_loader.addModelDefinition(lod_group_xml->getNode(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
libroot = model_def_loader.getLibraryNodes()[name];
|
||||
assert(libroot != NULL);
|
||||
create_lod_definitions = false; // LOD definitions are already created, don't create them again
|
||||
}
|
||||
|
||||
m_node->setPosition(m_init_xyz);
|
||||
m_node->setRotation(m_init_hpr);
|
||||
m_node->setScale(m_init_scale);
|
||||
m_node->updateAbsolutePosition();
|
||||
|
||||
assert(libroot != NULL);
|
||||
World::getWorld()->getTrack()->loadObjects(libroot, lib_path, model_def_loader,
|
||||
create_lod_definitions, m_node);
|
||||
}
|
||||
|
||||
TrackObjectPresentationLibraryNode::~TrackObjectPresentationLibraryNode()
|
||||
{
|
||||
irr_driver->removeNode(m_node);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TrackObjectPresentationLOD::TrackObjectPresentationLOD(const XMLNode& xml_node,
|
||||
scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader) :
|
||||
TrackObjectPresentationSceneNode(xml_node)
|
||||
@@ -411,7 +482,8 @@ TrackObjectPresentationSound::TrackObjectPresentationSound(const XMLNode& xml_no
|
||||
xml_node.get("max_dist", &max_dist );
|
||||
|
||||
// first try track dir, then global dir
|
||||
std::string soundfile = file_manager->getAsset(FileManager::MODEL,sound);
|
||||
std::string soundfile = World::getWorld()->getTrack()->getTrackFile(sound);
|
||||
//std::string soundfile = file_manager->getAsset(FileManager::MODEL,sound);
|
||||
if (!file_manager->fileExists(soundfile))
|
||||
{
|
||||
soundfile = file_manager->getAsset(FileManager::SFX, sound);
|
||||
|
||||
@@ -152,6 +152,18 @@ public:
|
||||
virtual ~TrackObjectPresentationEmpty();
|
||||
};
|
||||
|
||||
/**
|
||||
* \ingroup tracks
|
||||
* A track object representation that is a library node
|
||||
*/
|
||||
class TrackObjectPresentationLibraryNode : public TrackObjectPresentationSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
TrackObjectPresentationLibraryNode(const XMLNode& xml_node,
|
||||
ModelDefinitionLoader& model_def_loader);
|
||||
virtual ~TrackObjectPresentationLibraryNode();
|
||||
};
|
||||
|
||||
/**
|
||||
* \ingroup tracks
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "profiler.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/2dutils.hpp"
|
||||
#include "guiengine/event_handler.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/scalable_font.hpp"
|
||||
|
||||
51
tools/ibl.py
Normal file
51
tools/ibl.py
Normal file
@@ -0,0 +1,51 @@
|
||||
import Image as img
|
||||
import numpy as np
|
||||
import pylab as pl
|
||||
|
||||
n = 4
|
||||
|
||||
# constant factor of Ylm
|
||||
c00 = 0.282095
|
||||
c1minus1 = 0.488603
|
||||
c10 = 0.488603
|
||||
c11 = 0.488603
|
||||
c2minus2 = 1.092548
|
||||
c2minus1 = 1.092548
|
||||
c21 = 1.092548
|
||||
c20 = 0.315392
|
||||
c22 = 0.546274
|
||||
|
||||
def computeYmlOnGrid(Xgrid, Ygrid, Zgrid):
|
||||
"compute Yml from Y00 to Y22 on Xgrid/Ygrid/Zgrid"
|
||||
"Xgrid/Ygrid/Zgrid must be normalised"
|
||||
Y00 = c00
|
||||
Y1minus1 = c1minus1 * Ygrid
|
||||
Y10 = c10 * Zgrid
|
||||
Y11 = c11 * Xgrid
|
||||
Y2minus2 = c2minus2 * Xgrid * Ygrid
|
||||
Y2minus1 = c2minus1 * Ygrid * Zgrid
|
||||
Y21= c21 * Xgrid * Zgrid
|
||||
Y20 = c20 * (3 * Zgrid * Zgrid - 1)
|
||||
Y22 = c22 * (Xgrid * Xgrid - Ygrid * Ygrid)
|
||||
return (Y00, Y1minus1, Y10, Y11, Y2minus2, Y2minus1, Y20, Y21, Y22)
|
||||
|
||||
|
||||
Grid0, Grid1 = np.meshgrid(np.linspace(-1, 1, n), np.linspace(-1, 1, n))
|
||||
|
||||
FaceGrid = [(np.ones((n,n)), Grid0, Grid1), #GL_TEXTURE_CUBE_MAP_POSITIVE_X
|
||||
(-1 * np.ones((n,n)), Grid0, Grid1), #GL_TEXTURE_CUBE_MAP_NEGATIVE_X
|
||||
(Grid0, np.ones((n,n)), Grid1), #GL_TEXTURE_CUBE_MAP_POSITIVE_Y
|
||||
(Grid0, -1 * np.ones((n,n)), Grid1), #GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
|
||||
(Grid0, Grid1, np.ones((n,n))), #GL_TEXTURE_CUBE_MAP_POSITIVE_Z
|
||||
(Grid0, Grid1, -1 * np.ones((n,n)))] #GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
|
||||
|
||||
res = []
|
||||
for (Xd, Yd, Zd) in FaceGrid:
|
||||
res.append(computeYmlOnGrid(Xd, Yd, Zd))
|
||||
|
||||
print(res)
|
||||
|
||||
I = img.open("C:/Users/vljn_000/Documents/GitHub/stk-assets/textures/ants.png")
|
||||
m = np.array(I)
|
||||
print(type(m))
|
||||
pl.imshow(m)
|
||||
Reference in New Issue
Block a user