Index: ps/trunk/source/gui/CSlider.cpp
===================================================================
--- ps/trunk/source/gui/CSlider.cpp (revision 23001)
+++ ps/trunk/source/gui/CSlider.cpp (revision 23002)
@@ -1,142 +1,143 @@
/* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#include "precompiled.h"
#include "CSlider.h"
#include "gui/CGUI.h"
+#include "maths/MathUtil.h"
CSlider::CSlider(CGUI& pGUI)
: IGUIObject(pGUI), m_IsPressed(false), m_ButtonSide(0)
{
AddSetting("value");
AddSetting("min_value");
AddSetting("max_value");
AddSetting("cell_id");
AddSetting("sprite");
AddSetting("sprite_bar");
AddSetting("button_width");
m_Value = GetSetting("value");
m_MinValue = GetSetting("min_value");
m_MaxValue = GetSetting("max_value");
m_ButtonSide = GetSetting("button_width");
m_Value = Clamp(m_Value, m_MinValue, m_MaxValue);
}
CSlider::~CSlider()
{
}
float CSlider::GetSliderRatio() const
{
return (m_MaxValue - m_MinValue) / (m_CachedActualSize.GetWidth() - m_ButtonSide);
}
void CSlider::IncrementallyChangeValue(const float difference)
{
m_Value = Clamp(m_Value + difference, m_MinValue, m_MaxValue);
UpdateValue();
}
void CSlider::HandleMessage(SGUIMessage& Message)
{
switch (Message.type)
{
case GUIM_SETTINGS_UPDATED:
{
m_Value = GetSetting("value");
m_MinValue = GetSetting("min_value");
m_MaxValue = GetSetting("max_value");
m_ButtonSide = GetSetting("button_width");
m_Value = Clamp(m_Value, m_MinValue, m_MaxValue);
break;
}
case GUIM_MOUSE_WHEEL_DOWN:
{
if (m_IsPressed)
break;
IncrementallyChangeValue(-0.01f);
break;
}
case GUIM_MOUSE_WHEEL_UP:
{
if (m_IsPressed)
break;
IncrementallyChangeValue(0.01f);
break;
}
case GUIM_MOUSE_PRESS_LEFT:
{
m_Mouse = m_pGUI.GetMousePos();
m_IsPressed = true;
IncrementallyChangeValue((m_Mouse.x - GetButtonRect().CenterPoint().x) * GetSliderRatio());
break;
}
case GUIM_MOUSE_RELEASE_LEFT:
{
m_IsPressed = false;
break;
}
case GUIM_MOUSE_MOTION:
{
if (!IsMouseOver())
m_IsPressed = false;
if (m_IsPressed)
{
float difference = float(m_pGUI.GetMousePos().x - m_Mouse.x) * GetSliderRatio();
m_Mouse = m_pGUI.GetMousePos();
IncrementallyChangeValue(difference);
}
break;
}
default:
break;
}
}
void CSlider::Draw()
{
CGUISpriteInstance& sprite = GetSetting("sprite_bar");
CGUISpriteInstance& sprite_button = GetSetting("sprite");
const int cell_id = GetSetting("cell_id");
CRect slider_line(m_CachedActualSize);
slider_line.left += m_ButtonSide / 2.0f;
slider_line.right -= m_ButtonSide / 2.0f;
float bz = GetBufferedZ();
m_pGUI.DrawSprite(sprite, cell_id, bz, slider_line);
m_pGUI.DrawSprite(sprite_button, cell_id, bz, GetButtonRect());
}
void CSlider::UpdateValue()
{
SetSetting("value", m_Value, true);
ScriptEvent("valuechange");
}
CRect CSlider::GetButtonRect() const
{
float ratio = m_MaxValue > m_MinValue ? (m_Value - m_MinValue) / (m_MaxValue - m_MinValue) : 0.0f;
float x = m_CachedActualSize.left + ratio * (m_CachedActualSize.GetWidth() - m_ButtonSide);
float y = m_CachedActualSize.top + (m_CachedActualSize.GetHeight() - m_ButtonSide) / 2.0;
return CRect(x, y, x + m_ButtonSide, y + m_ButtonSide);
}
Index: ps/trunk/source/lib/lib.h
===================================================================
--- ps/trunk/source/lib/lib.h (revision 23001)
+++ ps/trunk/source/lib/lib.h (revision 23002)
@@ -1,168 +1,160 @@
-/* Copyright (C) 2010 Wildfire Games.
+/* Copyright (C) 2019 Wildfire Games.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* various utility functions.
*/
/**
low-level aka "lib"
-------------------
this codebase was grown from modules shared between several projects,
i.e. my personal library; hence the name "lib". it has been expanded to
fit the needs of 0ad - in particular, resource loading.
owing to the dual-use situation, the 0ad coding conventions are not met;
also, major changes are ill-advised because they may break other projects.
design goals
------------
- fast and low-overhead, including startup time
- portable: must run on Win32, Mac OS X and Linux
- reusable across projects, i.e. no dependency on a
central 'manager' that ties modules together.
scope
-----
- POSIX definitions
- resource management
- debugging tools (including memory tracker)
- low-level helper functions, e.g. ADTs, endian conversion and timing
- platform-dependent system/feature detection
**/
#ifndef INCLUDED_LIB
#define INCLUDED_LIB
#include // fabsf
#include // numeric_limits
#include // out_of_range
-#include // min, max
-
-template
-T Clamp(T val, T min, T max)
-{
- ASSERT(min <= max);
- return std::max(min, std::min(val, max));
-}
template
T DivideRoundUp(T dividend, T divisor)
{
ASSERT(divisor != 0);
return (dividend + divisor-1) / divisor;
}
/**
* are the given floats nearly "equal"?
*
* @return whether the numbers are within "epsilon" of each other.
*
* notes:
* - the epsilon magic number varies with the magnitude of the inputs.
* we use a sane default, but don't use this routine for very
* large/small comparands.
* - floating-point numbers don't magically lose precision. addition,
* subtraction and multiplication results are precise up to the mantissa's
* least-significant bit. only division, sqrt, sin/cos and other
* transcendental operations introduce error.
**/
inline bool feq(double d1, double d2, double epsilon = 0.00001)
{
return fabs(d1 - d2) < epsilon;
}
inline bool feqf(float f1, float f2, float epsilon = 0.001f)
{
return fabsf(f1 - f2) < epsilon;
}
inline bool IsSimilarMagnitude(double d1, double d2, const double relativeErrorTolerance = 0.05)
{
const double relativeError = fabs(d1/d2 - 1.0);
if(relativeError > relativeErrorTolerance)
return false;
return true;
}
//-----------------------------------------------------------------------------
// type conversion
// note: these avoid a common mistake in using >> (ANSI requires
// shift count be less than the bit width of the type).
extern u32 u64_hi(u64 x); /// return upper 32-bits
extern u32 u64_lo(u64 x); /// return lower 32-bits
extern u16 u32_hi(u32 x); /// return upper 16-bits
extern u16 u32_lo(u32 x); /// return lower 16-bits
extern u64 u64_from_u32(u32 hi, u32 lo); /// assemble u64 from u32
extern u32 u32_from_u16(u16 hi, u16 lo); /// assemble u32 from u16
// safe downcasters: cast from any integral type to u32 or u16;
// issues warning if larger than would fit in the target type.
//
// these are generally useful but included here (instead of e.g. lib.h) for
// several reasons:
// - including implementation in lib.h doesn't work because the definition
// of ENSURE in turn requires lib.h's STMT.
// - separate compilation of templates via export isn't supported by
// most compilers.
template u8 u8_from_larger(T x)
{
const u8 max = std::numeric_limits::max();
if((u64)x > (u64)max)
throw std::out_of_range("u8_from_larger");
return (u8)(x & max);
}
template u16 u16_from_larger(T x)
{
const u16 max = std::numeric_limits::max();
if((u64)x > (u64)max)
throw std::out_of_range("u16_from_larger");
return (u16)(x & max);
}
template u32 u32_from_larger(T x)
{
const u32 max = std::numeric_limits::max();
if((u64)x > (u64)max)
throw std::out_of_range("u32_from_larger");
return (u32)(x & max);
}
/// convert double to u8; verifies number is in range.
extern u8 u8_from_double(double in);
/// convert double to u16; verifies number is in range.
extern u16 u16_from_double(double in);
#endif // #ifndef INCLUDED_LIB
Index: ps/trunk/source/maths/MathUtil.h
===================================================================
--- ps/trunk/source/maths/MathUtil.h (revision 23001)
+++ ps/trunk/source/maths/MathUtil.h (revision 23002)
@@ -1,46 +1,50 @@
-/* Copyright (C) 2010 Wildfire Games.
+/* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#ifndef INCLUDED_MATHUTIL
#define INCLUDED_MATHUTIL
#define DEGTORAD(a) ((a) * ((float)M_PI/180.0f))
#define RADTODEG(a) ((a) * (180.0f/(float)M_PI))
#define SQR(x) ((x) * (x))
template
-inline T Interpolate(const T& a, const T& b, float l)
+inline T Interpolate(const T& a, const T& b, float t)
{
- return a + (b - a) * l;
+ return a + (b - a) * t;
}
template
-inline T clamp(T value, T min, T max)
+inline T Clamp(T value, T min, T max)
{
- if (value <= min) return min;
- else if (value >= max) return max;
- else return value;
+ if (value <= min)
+ return min;
+ else if (value >= max)
+ return max;
+ return value;
}
inline float sgn(float a)
{
- if (a > 0.0f) return 1.0f;
- if (a < 0.0f) return -1.0f;
+ if (a > 0.0f)
+ return 1.0f;
+ if (a < 0.0f)
+ return -1.0f;
return 0.0f;
}
-#endif
+#endif // INCLUDED_MATHUTIL
Index: ps/trunk/source/soundmanager/data/ogg.cpp
===================================================================
--- ps/trunk/source/soundmanager/data/ogg.cpp (revision 23001)
+++ ps/trunk/source/soundmanager/data/ogg.cpp (revision 23002)
@@ -1,333 +1,332 @@
-/* Copyright (C) 2012 Wildfire Games.
+/* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#include "precompiled.h"
#include "ogg.h"
#if CONFIG2_AUDIO
+#include "lib/byte_order.h"
#include "lib/external_libraries/openal.h"
#include "lib/external_libraries/vorbis.h"
-
-#include "lib/byte_order.h"
-#include "lib/file/io/io.h"
#include "lib/file/file_system.h"
-
+#include "lib/file/io/io.h"
#include "lib/file/vfs/vfs_util.h"
+#include "maths/MathUtil.h"
#include "ps/CLogger.h"
#include "ps/Filesystem.h"
static Status LibErrorFromVorbis(int err)
{
switch(err)
{
case 0:
return INFO::OK;
case OV_HOLE:
return ERR::AGAIN;
case OV_EREAD:
return ERR::IO;
case OV_EFAULT:
return ERR::LOGIC;
case OV_EIMPL:
return ERR::NOT_SUPPORTED;
case OV_EINVAL:
return ERR::INVALID_PARAM;
case OV_ENOTVORBIS:
return ERR::NOT_SUPPORTED;
case OV_EBADHEADER:
return ERR::CORRUPTED;
case OV_EVERSION:
return ERR::INVALID_VERSION;
case OV_ENOTAUDIO:
return ERR::_1;
case OV_EBADPACKET:
return ERR::_2;
case OV_EBADLINK:
return ERR::_3;
case OV_ENOSEEK:
return ERR::_4;
default:
return ERR::FAIL;
}
}
//-----------------------------------------------------------------------------
class VorbisFileAdapter
{
public:
VorbisFileAdapter(const PFile& openedFile)
: file(openedFile)
, size(FileSize(openedFile->Pathname()))
, offset(0)
{
}
static size_t Read(void* bufferToFill, size_t itemSize, size_t numItems, void* context)
{
VorbisFileAdapter* adapter = static_cast(context);
const off_t sizeRequested = numItems*itemSize;
const off_t sizeRemaining = adapter->size - adapter->offset;
const size_t sizeToRead = (size_t)std::min(sizeRequested, sizeRemaining);
io::Operation op(*adapter->file.get(), bufferToFill, sizeToRead, adapter->offset);
if(io::Run(op) == INFO::OK)
{
adapter->offset += sizeToRead;
return sizeToRead;
}
errno = EIO;
return 0;
}
static int Seek(void* context, ogg_int64_t offset, int whence)
{
VorbisFileAdapter* adapter = static_cast(context);
off_t origin = 0;
switch(whence)
{
case SEEK_SET:
origin = 0;
break;
case SEEK_CUR:
origin = adapter->offset;
break;
case SEEK_END:
origin = adapter->size+1;
break;
NODEFAULT;
}
adapter->offset = Clamp(off_t(origin+offset), off_t(0), adapter->size);
return 0;
}
static int Close(void* context)
{
VorbisFileAdapter* adapter = static_cast(context);
adapter->file.reset();
return 0; // return value is ignored
}
static long Tell(void* context)
{
VorbisFileAdapter* adapter = static_cast(context);
return adapter->offset;
}
private:
PFile file;
off_t size;
off_t offset;
};
//-----------------------------------------------------------------------------
class VorbisBufferAdapter
{
public:
VorbisBufferAdapter(const shared_ptr& buffer, size_t size)
: buffer(buffer)
, size(size)
, offset(0)
{
}
static size_t Read(void* bufferToFill, size_t itemSize, size_t numItems, void* context)
{
VorbisBufferAdapter* adapter = static_cast(context);
const off_t sizeRequested = numItems*itemSize;
const off_t sizeRemaining = adapter->size - adapter->offset;
const size_t sizeToRead = (size_t)std::min(sizeRequested, sizeRemaining);
memcpy(bufferToFill, adapter->buffer.get() + adapter->offset, sizeToRead);
adapter->offset += sizeToRead;
return sizeToRead;
}
static int Seek(void* context, ogg_int64_t offset, int whence)
{
VorbisBufferAdapter* adapter = static_cast(context);
off_t origin = 0;
switch(whence)
{
case SEEK_SET:
origin = 0;
break;
case SEEK_CUR:
origin = adapter->offset;
break;
case SEEK_END:
origin = adapter->size+1;
break;
NODEFAULT;
}
adapter->offset = Clamp(off_t(origin+offset), off_t(0), adapter->size);
return 0;
}
static int Close(void* context)
{
VorbisBufferAdapter* adapter = static_cast(context);
adapter->buffer.reset();
return 0; // return value is ignored
}
static long Tell(void* context)
{
VorbisBufferAdapter* adapter = static_cast(context);
return adapter->offset;
}
private:
shared_ptr buffer;
off_t size;
off_t offset;
};
//-----------------------------------------------------------------------------
template
class OggStreamImpl : public OggStream
{
public:
OggStreamImpl(const Adapter& adapter)
: adapter(adapter)
{
m_fileEOF = false;
info = NULL;
}
Status Close()
{
ov_clear( &vf );
return 0;
}
Status Open()
{
ov_callbacks callbacks;
callbacks.read_func = Adapter::Read;
callbacks.close_func = Adapter::Close;
callbacks.seek_func = Adapter::Seek;
callbacks.tell_func = Adapter::Tell;
const int ret = ov_open_callbacks(&adapter, &vf, 0, 0, callbacks);
if(ret != 0)
WARN_RETURN(LibErrorFromVorbis(ret));
const int link = -1; // retrieve info for current bitstream
info = ov_info(&vf, link);
if(!info)
WARN_RETURN(ERR::INVALID_HANDLE);
return INFO::OK;
}
virtual ALenum Format()
{
return (info->channels == 1)? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
}
virtual ALsizei SamplingRate()
{
return info->rate;
}
virtual bool atFileEOF()
{
return m_fileEOF;
}
virtual Status ResetFile()
{
ov_time_seek( &vf, 0 );
m_fileEOF = false;
return INFO::OK;
}
virtual Status GetNextChunk(u8* buffer, size_t size)
{
// we may have to call ov_read multiple times because it
// treats the buffer size "as a limit and not a request"
size_t bytesRead = 0;
for(;;)
{
const int isBigEndian = (BYTE_ORDER == BIG_ENDIAN);
const int wordSize = sizeof(i16);
const int isSigned = 1;
int bitstream; // unused
const int ret = ov_read(&vf, (char*)buffer+bytesRead, int(size-bytesRead), isBigEndian, wordSize, isSigned, &bitstream);
if(ret == 0) { // EOF
m_fileEOF = true;
return (Status)bytesRead;
}
else if(ret < 0)
WARN_RETURN(LibErrorFromVorbis(ret));
else // success
{
bytesRead += ret;
if(bytesRead == size)
return (Status)bytesRead;
}
}
}
private:
Adapter adapter;
OggVorbis_File vf;
vorbis_info* info;
bool m_fileEOF;
};
//-----------------------------------------------------------------------------
Status OpenOggStream(const OsPath& pathname, OggStreamPtr& stream)
{
PFile file(new File);
RETURN_STATUS_IF_ERR(file->Open(pathname, L'r'));
shared_ptr > tmp(new OggStreamImpl(VorbisFileAdapter(file)));
RETURN_STATUS_IF_ERR(tmp->Open());
stream = tmp;
return INFO::OK;
}
Status OpenOggNonstream(const PIVFS& vfs, const VfsPath& pathname, OggStreamPtr& stream)
{
shared_ptr contents;
size_t size;
RETURN_STATUS_IF_ERR(vfs->LoadFile(pathname, contents, size));
shared_ptr > tmp(new OggStreamImpl(VorbisBufferAdapter(contents, size)));
RETURN_STATUS_IF_ERR(tmp->Open());
stream = tmp;
return INFO::OK;
}
#endif // CONFIG2_AUDIO