Merge pull request #7066 from IntelOrca/refactor/memory-operations

Refactor memory operations 1
This commit is contained in:
Ted John 2018-01-26 11:41:19 +00:00 committed by GitHub
commit 8f1100c986
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 485 additions and 527 deletions

View File

@ -14,14 +14,15 @@
*****************************************************************************/
#pragma endregion
#include <algorithm>
#include <list>
#include <vector>
#include <openrct2/common.h>
#include <SDL.h>
#include <speex/speex_resampler.h>
#include <list>
#include <openrct2/Context.h>
#include <openrct2/core/Guard.hpp>
#include <openrct2/core/Math.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/core/Util.hpp>
#include <openrct2/audio/audio.h>
#include <openrct2/audio/AudioChannel.h>
@ -37,38 +38,6 @@
namespace OpenRCT2 { namespace Audio
{
struct Buffer
{
private:
void * _data = nullptr;
size_t _capacity = 0;
public:
void * GetData() const { return _data; }
void * GetData() { return _data; }
size_t GetCapacity() const { return _capacity; }
~Buffer()
{
Free();
}
void Free()
{
SafeFree(_data);
_capacity = 0;
}
void EnsureCapacity(size_t capacity)
{
if (_capacity < capacity)
{
_capacity = capacity;
_data = Memory::Reallocate(_data, capacity);
}
}
};
class AudioMixerImpl final : public IAudioMixer
{
private:
@ -86,9 +55,9 @@ namespace OpenRCT2 { namespace Audio
IAudioSource * _css1Sources[SOUND_MAXID] = { nullptr };
IAudioSource * _musicSources[PATH_ID_END] = { nullptr };
Buffer _channelBuffer;
Buffer _convertBuffer;
Buffer _effectBuffer;
std::vector<uint8> _channelBuffer;
std::vector<uint8> _convertBuffer;
std::vector<uint8> _effectBuffer;
public:
AudioMixerImpl()
@ -159,9 +128,12 @@ namespace OpenRCT2 { namespace Audio
}
// Free buffers
_channelBuffer.Free();
_convertBuffer.Free();
_effectBuffer.Free();
_channelBuffer.clear();
_channelBuffer.shrink_to_fit();
_convertBuffer.clear();
_convertBuffer.shrink_to_fit();
_effectBuffer.clear();
_effectBuffer.shrink_to_fit();
}
void Lock() override
@ -252,7 +224,7 @@ namespace OpenRCT2 { namespace Audio
UpdateAdjustedSound();
// Zero the output buffer
Memory::Set(dst, 0, length);
std::fill_n(dst, length, 0);
// Mix channels onto output buffer
auto it = _channels.begin();
@ -318,15 +290,15 @@ namespace OpenRCT2 { namespace Audio
// Read raw PCM from channel
sint32 readSamples = (sint32)(numSamples * rate);
size_t readLength = (size_t)(readSamples / cvt.len_ratio) * byteRate;
_channelBuffer.EnsureCapacity(readLength);
size_t bytesRead = channel->Read(_channelBuffer.GetData(), readLength);
_channelBuffer.resize(readLength);
size_t bytesRead = channel->Read(_channelBuffer.data(), readLength);
// Convert data to required format if necessary
void * buffer = nullptr;
size_t bufferLen = 0;
if (mustConvert)
{
if (Convert(&cvt, _channelBuffer.GetData(), bytesRead))
if (Convert(&cvt, _channelBuffer.data(), bytesRead))
{
buffer = cvt.buf;
bufferLen = cvt.len_cvt;
@ -338,7 +310,7 @@ namespace OpenRCT2 { namespace Audio
}
else
{
buffer = _channelBuffer.GetData();
buffer = _channelBuffer.data();
bufferLen = bytesRead;
}
@ -352,9 +324,9 @@ namespace OpenRCT2 { namespace Audio
inRate = _format.freq;
outRate = _format.freq * (1 / rate);
}
_effectBuffer.EnsureCapacity(length);
_effectBuffer.resize(length);
bufferLen = ApplyResample(channel, buffer, (sint32)(bufferLen / byteRate), numSamples, inRate, outRate);
buffer = _effectBuffer.GetData();
buffer = _effectBuffer.data();
}
// Apply panning and volume
@ -391,7 +363,7 @@ namespace OpenRCT2 { namespace Audio
resampler,
(const spx_int16_t *)srcBuffer,
&inLen,
(spx_int16_t *)_effectBuffer.GetData(),
(spx_int16_t *)_effectBuffer.data(),
&outLen);
return outLen * byteRate;
@ -523,11 +495,11 @@ namespace OpenRCT2 { namespace Audio
if (len != 0 && cvt->len_mult != 0)
{
size_t reqConvertBufferCapacity = len * cvt->len_mult;
_convertBuffer.EnsureCapacity(reqConvertBufferCapacity);
Memory::Copy(_convertBuffer.GetData(), src, len);
_convertBuffer.resize(reqConvertBufferCapacity);
std::copy_n((const uint8 *)src, len, _convertBuffer.data());
cvt->len = (sint32)len;
cvt->buf = (uint8 *)_convertBuffer.GetData();
cvt->buf = (uint8 *)_convertBuffer.data();
if (SDL_ConvertAudio(cvt) >= 0)
{
result = true;

View File

@ -14,10 +14,11 @@
*****************************************************************************/
#pragma endregion
#include <algorithm>
#include <vector>
#include <openrct2/common.h>
#include <SDL.h>
#include <openrct2/core/Math.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/audio/AudioMixer.h>
#include <openrct2/audio/AudioSource.h>
#include "AudioContext.h"
@ -32,10 +33,15 @@ namespace OpenRCT2 { namespace Audio
class MemoryAudioSource final : public ISDLAudioSource
{
private:
AudioFormat _format = { 0 };
uint8 * _data = nullptr;
size_t _length = 0;
bool _isSDLWav = false;
AudioFormat _format = { 0 };
std::vector<uint8> _data;
uint8 * _dataSDL = nullptr;
size_t _length = 0;
const uint8 * GetData()
{
return _dataSDL != nullptr ? _dataSDL : _data.data();
}
public:
~MemoryAudioSource()
@ -59,7 +65,12 @@ namespace OpenRCT2 { namespace Audio
if (offset < _length)
{
bytesToRead = (size_t)Math::Min<uint64>(len, _length - offset);
Memory::Copy<void>(dst, _data + offset, bytesToRead);
auto src = GetData();
if (src != nullptr)
{
std::copy_n(src + offset, bytesToRead, (uint8 *)dst);
}
}
return bytesToRead;
}
@ -76,14 +87,13 @@ namespace OpenRCT2 { namespace Audio
{
SDL_AudioSpec audiospec = { 0 };
uint32 audioLen;
SDL_AudioSpec * spec = SDL_LoadWAV_RW(rw, false, &audiospec, &_data, &audioLen);
SDL_AudioSpec * spec = SDL_LoadWAV_RW(rw, false, &audiospec, &_dataSDL, &audioLen);
if (spec != nullptr)
{
_format.freq = spec->freq;
_format.format = spec->format;
_format.channels = spec->channels;
_length = audioLen;
_isSDLWav = true;
result = true;
}
else
@ -129,13 +139,13 @@ namespace OpenRCT2 { namespace Audio
_format.format = AUDIO_S16LSB;
_format.channels = waveFormat.channels;
_data = new (std::nothrow) uint8[_length];
if (_data != nullptr)
try
{
SDL_RWread(rw, _data, _length, 1);
_data.resize(_length);
SDL_RWread(rw, _data.data(), _length, 1);
result = true;
}
else
catch (const std::bad_alloc &)
{
log_verbose("Unable to allocate data");
}
@ -156,21 +166,21 @@ namespace OpenRCT2 { namespace Audio
SDL_AudioCVT cvt;
if (SDL_BuildAudioCVT(&cvt, _format.format, _format.channels, _format.freq, format->format, format->channels, format->freq) >= 0)
{
auto src = GetData();
auto cvtBuffer = std::vector<uint8>(_length * cvt.len_mult);
std::copy_n(src, _length, cvtBuffer.data());
cvt.len = (sint32)_length;
cvt.buf = new uint8[cvt.len * cvt.len_mult];
Memory::Copy(cvt.buf, _data, _length);
cvt.buf = cvtBuffer.data();
if (SDL_ConvertAudio(&cvt) >= 0)
{
cvtBuffer.resize(cvt.len_cvt);
Unload();
_data = cvt.buf;
_data = std::move(cvtBuffer);
_length = cvt.len_cvt;
_format = *format;
return true;
}
else
{
delete[] cvt.buf;
}
}
}
return false;
@ -179,19 +189,14 @@ namespace OpenRCT2 { namespace Audio
private:
void Unload()
{
if (_data != nullptr)
{
if (_isSDLWav)
{
SDL_FreeWAV(_data);
}
else
{
delete[] _data;
}
_data = nullptr;
}
_isSDLWav = false;
// Free our data
_data.clear();
_data.shrink_to_fit();
// Free SDL2's data
SDL_FreeWAV(_dataSDL);
_dataSDL = nullptr;
_length = 0;
}
};

View File

@ -14,18 +14,17 @@
*****************************************************************************/
#pragma endregion
#include <algorithm>
#include <openrct2/common.h>
#include <SDL.h>
#include <openrct2/config/Config.h>
#include <openrct2/core/Guard.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/drawing/IDrawingEngine.h>
#include <openrct2/drawing/X8DrawingEngine.h>
#include <openrct2/Game.h>
#include <openrct2/ui/UiContext.h>
#include "DrawingEngines.h"
#include <openrct2/Game.h>
using namespace OpenRCT2;
using namespace OpenRCT2::Drawing;
using namespace OpenRCT2::Ui;
@ -121,7 +120,7 @@ private:
}
// Copy pixels from the virtual screen buffer to the surface
Memory::Copy<void>(_surface->pixels, _bits, _surface->pitch * _surface->h);
std::copy_n(_bits, _surface->pitch * _surface->h, (uint8 *)_surface->pixels);
// Unlock the surface
if (SDL_MUSTLOCK(_surface))

View File

@ -16,33 +16,29 @@
#ifndef DISABLE_OPENGL
#include <algorithm>
#include <cmath>
#include <unordered_map>
#include <SDL.h>
#include <openrct2/config/Config.h>
#include <openrct2/core/Console.hpp>
#include <openrct2/core/Math.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/drawing/Drawing.h>
#include <openrct2/drawing/IDrawingContext.h>
#include <openrct2/drawing/IDrawingEngine.h>
#include <openrct2/drawing/LightFX.h>
#include <openrct2/drawing/Rain.h>
#include <openrct2/interface/Screenshot.h>
#include <openrct2/ui/UiContext.h>
#include <openrct2-ui/interface/Window.h>
#include <openrct2/Intro.h>
#include <openrct2/drawing/Drawing.h>
#include <openrct2/drawing/LightFX.h>
#include <openrct2-ui/interface/Window.h>
#include <openrct2/ui/UiContext.h>
#include "../DrawingEngines.h"
#include "GLSLTypes.h"
#include "OpenGLAPI.h"
#include "OpenGLFramebuffer.h"
#include "ApplyPaletteShader.h"
#include "DrawCommands.h"
#include "DrawLineShader.h"
#include "DrawRectShader.h"
#include "GLSLTypes.h"
#include "OpenGLAPI.h"
#include "OpenGLFramebuffer.h"
#include "SwapFramebuffer.h"
#include "TextureCache.h"
#include "TransparencyDepth.h"
@ -346,27 +342,27 @@ private:
uint8 * newBits = new uint8[newBitsSize];
if (_bits == nullptr)
{
Memory::Set(newBits, 0, newBitsSize);
std::fill_n(newBits, newBitsSize, 0);
}
else
{
if (_pitch == pitch)
{
Memory::Copy(newBits, _bits, Math::Min(_bitsSize, newBitsSize));
std::copy_n(_bits, std::min(_bitsSize, newBitsSize), newBits);
}
else
{
uint8 * src = _bits;
uint8 * dst = newBits;
uint32 minWidth = Math::Min(_width, width);
uint32 minHeight = Math::Min(_height, height);
uint32 minWidth = std::min(_width, width);
uint32 minHeight = std::min(_height, height);
for (uint32 y = 0; y < minHeight; y++)
{
Memory::Copy(dst, src, minWidth);
std::copy_n(src, minWidth, dst);
if (pitch - minWidth > 0)
{
Memory::Set(dst + minWidth, 0, pitch - minWidth);
std::fill_n(dst + minWidth, pitch - minWidth, 0);
}
src += _pitch;
dst += pitch;
@ -716,8 +712,8 @@ void OpenGLDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskIm
sint32 drawOffsetX = g1ElementMask->x_offset;
sint32 drawOffsetY = g1ElementMask->y_offset;
sint32 drawWidth = Math::Min(g1ElementMask->width, g1ElementColour->width);
sint32 drawHeight = Math::Min(g1ElementMask->height, g1ElementColour->height);
sint32 drawWidth = std::min(g1ElementMask->width, g1ElementColour->width);
sint32 drawHeight = std::min(g1ElementMask->height, g1ElementColour->height);
sint32 left = x + drawOffsetX;
sint32 top = y + drawOffsetY;

View File

@ -16,9 +16,10 @@
#ifndef DISABLE_OPENGL
#include <algorithm>
#include <memory>
#include <openrct2/common.h>
#include <SDL_video.h>
#include <openrct2/core/Memory.hpp>
#include "OpenGLFramebuffer.h"
constexpr GLuint BACKBUFFER_ID = 0;
@ -94,21 +95,20 @@ void OpenGLFramebuffer::GetPixels(rct_drawpixelinfo &dpi) const
{
assert(dpi.width == _width && dpi.height == _height);
uint8 * pixels = Memory::Allocate<uint8>(_width * _height);
auto pixels = std::make_unique<uint8[]>(_width * _height);
glBindTexture(GL_TEXTURE_2D, _texture);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels.get());
// Flip pixels vertically on copy
uint8 * src = pixels + ((_height - 1) * _width);
uint8 * src = pixels.get() + ((_height - 1) * _width);
uint8 * dst = dpi.bits;
for (sint32 y = 0; y < _height; y++)
{
Memory::Copy(dst, src, _width);
std::copy_n(src, _width, dst);
src -= _width;
dst += dpi.width + dpi.pitch;
}
Memory::Free(pixels);
}
void OpenGLFramebuffer::SwapColourBuffer(OpenGLFramebuffer &other)

View File

@ -16,29 +16,28 @@
#ifndef DISABLE_OPENGL
#include <openrct2/Context.h>
#include <openrct2/core/Console.hpp>
#include <openrct2/core/FileStream.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/core/Path.hpp>
#include <openrct2/core/String.hpp>
#include <openrct2/PlatformEnvironment.h>
#include "OpenGLShaderProgram.h"
#include <openrct2/platform/platform.h>
using namespace OpenRCT2;
OpenGLShader::OpenGLShader(const char * name, GLenum type)
{
_type = type;
utf8 path[MAX_PATH];
GetPath(path, sizeof(path), name);
char * sourceCode = ReadSourceCode(path);
auto path = GetPath(name);
auto sourceCode = ReadSourceCode(path);
auto sourceCodeStr = sourceCode.c_str();
_id = glCreateShader(type);
glShaderSource(_id, 1, (const GLchar**)&sourceCode, nullptr);
glShaderSource(_id, 1, (const GLchar * *)&sourceCodeStr, nullptr);
glCompileShader(_id);
Memory::Free(sourceCode);
GLint status;
glGetShaderiv(_id, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE)
@ -47,7 +46,7 @@ OpenGLShader::OpenGLShader(const char * name, GLenum type)
glGetShaderInfoLog(_id, sizeof(buffer), nullptr, buffer);
glDeleteShader(_id);
Console::Error::WriteLine("Error compiling %s", path);
Console::Error::WriteLine("Error compiling %s", path.c_str());
Console::Error::WriteLine(buffer);
throw std::runtime_error("Error compiling shader.");
@ -64,22 +63,23 @@ GLuint OpenGLShader::GetShaderId()
return _id;
}
void OpenGLShader::GetPath(char * buffer, size_t bufferSize, const char * name)
std::string OpenGLShader::GetPath(const std::string &name)
{
platform_get_openrct_data_path(buffer, bufferSize);
Path::Append(buffer, bufferSize, "shaders");
Path::Append(buffer, bufferSize, name);
auto env = GetContext()->GetPlatformEnvironment();
auto shadersPath = env->GetDirectoryPath(DIRBASE::OPENRCT2, DIRID::SHADER);
auto path = Path::Combine(shadersPath, name);
if (_type == GL_VERTEX_SHADER)
{
String::Append(buffer, bufferSize, ".vert");
path += ".vert";
}
else
{
String::Append(buffer, bufferSize, ".frag");
path += ".frag";
}
return path;
}
char * OpenGLShader::ReadSourceCode(const utf8 * path)
std::string OpenGLShader::ReadSourceCode(const std::string &path)
{
auto fs = FileStream(path, FILE_MODE_OPEN);
@ -89,9 +89,8 @@ char * OpenGLShader::ReadSourceCode(const utf8 * path)
throw IOException("Shader source too large.");
}
utf8 * fileData = Memory::Allocate<utf8>((size_t)fileLength + 1);
fs.Read(fileData, fileLength);
fileData[fileLength] = '\0';
auto fileData = std::string((size_t)fileLength + 1, '\0');
fs.Read((void *)fileData.data(), fileLength);
return fileData;
}

View File

@ -16,6 +16,7 @@
#pragma once
#include <string>
#include <openrct2/common.h>
#include "OpenGLAPI.h"
@ -34,8 +35,8 @@ public:
GLuint GetShaderId();
private:
void GetPath(char * buffer, size_t bufferSize, const char * name);
static char * ReadSourceCode(const utf8 * path);
std::string GetPath(const std::string &name);
static std::string ReadSourceCode(const std::string &path);
};
class OpenGLShaderProgram

View File

@ -16,12 +16,11 @@
#ifndef DISABLE_OPENGL
#include <vector>
#include <algorithm>
#include <stdexcept>
#include <openrct2/core/Memory.hpp>
#include "TextureCache.h"
#include <vector>
#include <openrct2/drawing/Drawing.h>
#include "TextureCache.h"
constexpr uint32 UNUSED_INDEX = 0xFFFFFFFF;
@ -95,7 +94,7 @@ BasicTextureInfo TextureCache::GetOrLoadGlyphTexture(uint32 image, uint8 * palet
{
GlyphId glyphId;
glyphId.Image = image;
Memory::Copy<void>(&glyphId.Palette, palette, sizeof(glyphId.Palette));
std::copy_n(palette, sizeof(glyphId.Palette), (uint8 *)&glyphId.Palette);
auto kvp = _glyphTextureMap.find(glyphId);
if (kvp != _glyphTextureMap.end())
@ -290,8 +289,8 @@ void TextureCache::FreeTextures()
rct_drawpixelinfo TextureCache::CreateDPI(sint32 width, sint32 height)
{
size_t numPixels = width * height;
uint8 * pixels8 = Memory::Allocate<uint8>(numPixels);
Memory::Set(pixels8, 0, numPixels);
auto pixels8 = new uint8[numPixels];
std::fill_n(pixels8, numPixels, 0);
rct_drawpixelinfo dpi;
dpi.bits = pixels8;
@ -306,7 +305,7 @@ rct_drawpixelinfo TextureCache::CreateDPI(sint32 width, sint32 height)
void TextureCache::DeleteDPI(rct_drawpixelinfo dpi)
{
Memory::Free(dpi.bits);
delete dpi.bits;
}
GLuint TextureCache::GetAtlasesTexture()

View File

@ -19,7 +19,6 @@
#include <openrct2/core/Console.hpp>
#include <openrct2/core/File.h>
#include <openrct2/core/FileStream.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/core/Path.hpp>
#include <openrct2/core/String.hpp>
#include <openrct2/PlatformEnvironment.h>

View File

@ -14,16 +14,20 @@
*****************************************************************************/
#pragma endregion
#include <fstream>
#include <vector>
#include <openrct2/Context.h>
#include <openrct2/OpenRCT2.h>
#include <openrct2/core/Math.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2-ui/windows/Window.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2/core/String.hpp>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/OpenRCT2.h>
#include <openrct2/platform/platform.h>
#include <openrct2/PlatformEnvironment.h>
#include <openrct2/util/Util.h>
#include <openrct2-ui/windows/Window.h>
#include <openrct2-ui/interface/Widget.h>
using namespace OpenRCT2;
enum {
WIDX_BACKGROUND,
@ -89,10 +93,8 @@ static rct_window_event_list window_changelog_events = {
static bool window_changelog_read_file();
static void window_changelog_dispose_file();
static char *_changelogText = nullptr;
static size_t _changelogTextSize = 0;
static char **_changelogLines = nullptr;
static sint32 _changelogNumLines = 0;
static std::string _changelogText;
static std::vector<const char *> _changelogLines;
static sint32 _changelogLongestLineWidth = 0;
rct_window * window_changelog_open()
@ -164,7 +166,7 @@ static void window_changelog_resize(rct_window *w)
static void window_changelog_scrollgetsize(rct_window *w, sint32 scrollIndex, sint32 *width, sint32 *height)
{
*width = _changelogLongestLineWidth + 4;
*height = _changelogNumLines * 11;
*height = (sint32)(_changelogLines.size() * 11);
}
static void window_changelog_invalidate(rct_window *w)
@ -192,73 +194,85 @@ static void window_changelog_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi,
sint32 x = 3;
sint32 y = 3;
for (sint32 i = 0; i < _changelogNumLines; i++) {
gfx_draw_string(dpi, _changelogLines[i], w->colours[0], x, y);
for (auto line : _changelogLines)
{
gfx_draw_string(dpi, (char *)line, w->colours[0], x, y);
y += 11;
}
}
static std::string GetChangelogPath()
{
auto env = GetContext()->GetPlatformEnvironment();
return env->GetFilePath(PATHID::CHANGELOG);
}
static std::string GetChangelogText()
{
auto path = GetChangelogPath();
#if defined(_WIN32) && !defined(__MINGW32__)
auto pathW = String::ToUtf16(path);
auto fs = std::ifstream(pathW, std::ios::in);
#else
auto fs = std::ifstream(path, std::ios::in);
#endif
if (!fs.is_open())
{
throw std::runtime_error("Unable to open " + path);
}
return std::string((std::istreambuf_iterator<char>(fs)), std::istreambuf_iterator<char>());
}
static bool window_changelog_read_file()
{
window_changelog_dispose_file();
utf8 path[MAX_PATH];
platform_get_changelog_path(path, sizeof(path));
if (!readentirefile(path, (void**)&_changelogText, &_changelogTextSize)) {
try
{
_changelogText = GetChangelogText();
}
catch (const std::bad_alloc &)
{
log_error("Unable to allocate memory for changelog.txt");
return false;
}
catch (const std::exception &)
{
log_error("Unable to read changelog.txt");
return false;
}
void* new_memory = realloc(_changelogText, _changelogTextSize + 1);
if (new_memory == nullptr) {
log_error("Failed to reallocate memory for changelog text");
return false;
}
_changelogText = (char*)new_memory;
_changelogText[_changelogTextSize++] = 0;
char *start = _changelogText;
if (_changelogTextSize >= 3 && utf8_is_bom(_changelogText))
// Non-const cast required until C++17 is enabled
auto * start = (char *)_changelogText.data();
if (_changelogText.size() >= 3 && utf8_is_bom(start))
{
start += 3;
}
sint32 changelogLinesCapacity = 8;
_changelogLines = Memory::Allocate<utf8*>(changelogLinesCapacity * sizeof(char*));
_changelogLines[0] = start;
_changelogNumLines = 1;
char *ch = start;
while (*ch != 0) {
_changelogLines.clear();
_changelogLines.push_back(start);
auto ch = start;
while (*ch != '\0')
{
uint8 c = *ch;
if (c == '\n') {
if (c == '\n')
{
*ch++ = 0;
_changelogNumLines++;
if (_changelogNumLines > changelogLinesCapacity) {
changelogLinesCapacity *= 2;
new_memory = realloc(_changelogLines, changelogLinesCapacity * sizeof(char*));
if (new_memory == nullptr) {
log_error("Failed to reallocate memory for change log lines");
return false;
}
_changelogLines = (char**)new_memory;
}
_changelogLines[_changelogNumLines - 1] = ch;
} else if (c < 32 || c > 122) {
// A character that won't be drawn or change state.
_changelogLines.push_back(ch);
}
else if (utf8_is_format_code(c))
{
*ch++ = FORMAT_OUTLINE_OFF;
} else {
}
else
{
ch++;
}
}
new_memory = realloc(_changelogLines, _changelogNumLines * sizeof(char*));
if (new_memory == nullptr) {
log_error("Failed to reallocate memory for change log lines");
return false;
}
_changelogLines = (char**)new_memory;
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
_changelogLongestLineWidth = 0;
for (sint32 i = 0; i < _changelogNumLines; i++) {
sint32 width = gfx_get_string_width(_changelogLines[i]);
for (auto line : _changelogLines)
{
auto width = gfx_get_string_width(line);
_changelogLongestLineWidth = Math::Max(width, _changelogLongestLineWidth);
}
return true;
@ -266,8 +280,7 @@ static bool window_changelog_read_file()
static void window_changelog_dispose_file()
{
SafeFree(_changelogText);
SafeFree(_changelogLines);
_changelogTextSize = 0;
_changelogNumLines = 0;
_changelogText = std::string();
_changelogLines.clear();
_changelogLines.shrink_to_fit();
}

View File

@ -14,32 +14,31 @@
*****************************************************************************/
#pragma endregion
#include <openrct2-ui/windows/Window.h>
#include <algorithm>
#include <cctype>
#include <string>
#include <vector>
#include <openrct2/audio/audio.h>
#include <openrct2/config/Config.h>
#include <openrct2/Context.h>
#include <openrct2/core/Memory.hpp>
#include <openrct2/Editor.h>
#include <openrct2/EditorObjectSelectionSession.h>
#include <openrct2/Game.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/object/ObjectList.h>
#include <openrct2/object/ObjectManager.h>
#include <openrct2/object/ObjectRepository.h>
#include <openrct2/object/RideObject.h>
#include <openrct2/object/StexObject.h>
#include <openrct2/object/ObjectList.h>
#include <openrct2/OpenRCT2.h>
#include <openrct2/platform/platform.h>
#include <openrct2/ride/RideGroupManager.h>
#include <openrct2/sprites.h>
#include <openrct2/util/Util.h>
#include <openrct2-ui/interface/Dropdown.h>
#include <openrct2/windows/Intent.h>
#include <openrct2-ui/interface/Dropdown.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/windows/Window.h>
enum {
FILTER_RCT2 = (1 << 0),
@ -270,42 +269,34 @@ typedef struct list_item {
static rct_string_id get_ride_type_string_id(const ObjectRepositoryItem * item);
typedef sint32(*sortFunc_t)(const void *, const void *);
typedef bool (*sortFunc_t)(const list_item &, const list_item &);
static sint32 _numListItems = 0;
static list_item *_listItems = nullptr;
static std::vector<list_item> _listItems;
static sint32 _listSortType = RIDE_SORT_TYPE;
static bool _listSortDescending = false;
static void * _loadedObject = nullptr;
static void visible_list_dispose()
{
SafeFree(_listItems);
_numListItems = 0;
_listItems.clear();
_listItems.shrink_to_fit();
}
static sint32 visible_list_sort_ride_name(const void *rawA, const void *rawB)
static bool visible_list_sort_ride_name(const list_item &a, const list_item &b)
{
list_item *a = (list_item*)rawA;
list_item *b = (list_item*)rawB;
const char *nameA = a->repositoryItem->Name;
const char *nameB = b->repositoryItem->Name;
return strcmp(nameA, nameB);
auto nameA = a.repositoryItem->Name;
auto nameB = b.repositoryItem->Name;
return strcmp(nameA, nameB) < 0;
}
static sint32 visible_list_sort_ride_type(const void *rawA, const void *rawB)
static bool visible_list_sort_ride_type(const list_item &a, const list_item &b)
{
list_item *a = (list_item*)rawA;
list_item *b = (list_item*)rawB;
const char *rideTypeA = language_get_string(get_ride_type_string_id(a->repositoryItem));
const char *rideTypeB = language_get_string(get_ride_type_string_id(b->repositoryItem));
auto rideTypeA = language_get_string(get_ride_type_string_id(a.repositoryItem));
auto rideTypeB = language_get_string(get_ride_type_string_id(b.repositoryItem));
sint32 result = strcmp(rideTypeA, rideTypeB);
if (result != 0)
return result;
return visible_list_sort_ride_name(rawA, rawB);
return result != 0 ?
result < 0 :
visible_list_sort_ride_name(a, b);
}
static void visible_list_refresh(rct_window *w)
@ -314,10 +305,7 @@ static void visible_list_refresh(rct_window *w)
visible_list_dispose();
w->selected_list_item = -1;
_listItems = Memory::AllocateArray<list_item>(numObjects);
_numListItems = 0;
list_item *currentListItem = &_listItems[0];
const ObjectRepositoryItem *items = object_repository_get_items();
for (sint32 i = 0; i < numObjects; i++) {
uint8 selectionFlags = _objectSelectionFlags[i];
@ -333,29 +321,25 @@ static void visible_list_refresh(rct_window *w)
filter->ride.category[0] = 0;
filter->ride.category[1] = 0;
filter->ride.ride_type = 0;
currentListItem->repositoryItem = item;
currentListItem->entry = (rct_object_entry *)&item->ObjectEntry;
currentListItem->filter = filter;
currentListItem->flags = &_objectSelectionFlags[i];
currentListItem++;
_numListItems++;
list_item currentListItem;
currentListItem.repositoryItem = item;
currentListItem.entry = (rct_object_entry *)&item->ObjectEntry;
currentListItem.filter = filter;
currentListItem.flags = &_objectSelectionFlags[i];
_listItems.push_back(std::move(currentListItem));
}
}
if (_numListItems == 0)
if (_listItems.size() == 0)
{
visible_list_dispose();
window_invalidate(w);
return;
}
_listItems = Memory::ReallocateArray(_listItems, _numListItems);
if (_listItems == nullptr) {
_numListItems = 0;
log_error("Unable to reallocate list items");
} else {
else
{
sortFunc_t sortFunc = nullptr;
switch (_listSortType) {
switch (_listSortType)
{
case RIDE_SORT_TYPE:
sortFunc = visible_list_sort_ride_type;
break;
@ -364,17 +348,14 @@ static void visible_list_refresh(rct_window *w)
break;
default:
log_warning("Wrong sort type %d, leaving list as-is.", _listSortType);
window_invalidate(w);
return;
break;
}
qsort(_listItems, _numListItems, sizeof(list_item), sortFunc);
if (_listSortDescending) {
for (sint32 i = 0; i < _numListItems / 2; i++) {
sint32 ri = _numListItems - i - 1;
list_item temp = _listItems[i];
_listItems[i] = _listItems[ri];
_listItems[ri] = temp;
if (sortFunc != nullptr)
{
std::sort(_listItems.begin(), _listItems.end(), sortFunc);
if (_listSortDescending)
{
std::reverse(_listItems.begin(), _listItems.end());
}
}
}
@ -681,7 +662,7 @@ static void window_editor_object_selection_dropdown(rct_window *w, rct_widgetind
*/
static void window_editor_object_selection_scrollgetsize(rct_window *w, sint32 scrollIndex, sint32 *width, sint32 *height)
{
*height = _numListItems * 12;
*height = (sint32)(_listItems.size() * 12);
}
/**
@ -1110,7 +1091,7 @@ static void window_editor_object_selection_paint(rct_window *w, rct_drawpixelinf
*/
static void window_editor_object_selection_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32 scrollIndex)
{
sint32 x, y, i, colour, colour2;
sint32 x, y, colour, colour2;
bool ridePage = (w->selected_tab == WINDOW_OBJECT_SELECTION_PAGE_RIDE_VEHICLES_ATTRACTIONS);
@ -1118,27 +1099,26 @@ static void window_editor_object_selection_scrollpaint(rct_window *w, rct_drawpi
gfx_clear(dpi, paletteIndex);
y = 0;
for (i = 0; i < _numListItems; i++) {
list_item *listItem = &_listItems[i];
for (const auto &listItem : _listItems)
{
if (y + 12 >= dpi->y && y <= dpi->y + dpi->height) {
// Draw checkbox
if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) && !(*listItem->flags & 0x20))
if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) && !(*listItem.flags & 0x20))
gfx_fill_rect_inset(dpi, 2, y, 11, y + 10, w->colours[1], INSET_RECT_F_E0);
// Highlight background
colour = COLOUR_BRIGHT_GREEN | COLOUR_FLAG_TRANSLUCENT;
if (listItem->entry == w->object_entry && !(*listItem->flags & OBJECT_SELECTION_FLAG_6)) {
if (listItem.entry == w->object_entry && !(*listItem.flags & OBJECT_SELECTION_FLAG_6)) {
gfx_filter_rect(dpi, 0, y, w->width, y + 11, PALETTE_DARKEN_1);
colour = COLOUR_BRIGHT_GREEN;
}
// Draw checkmark
if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) && (*listItem->flags & OBJECT_SELECTION_FLAG_SELECTED)) {
if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) && (*listItem.flags & OBJECT_SELECTION_FLAG_SELECTED)) {
x = 2;
gCurrentFontSpriteBase = colour == COLOUR_BRIGHT_GREEN ? FONT_SPRITE_BASE_MEDIUM_EXTRA_DARK : FONT_SPRITE_BASE_MEDIUM_DARK;
colour2 = NOT_TRANSLUCENT(w->colours[1]);
if (*listItem->flags & (OBJECT_SELECTION_FLAG_IN_USE | OBJECT_SELECTION_FLAG_ALWAYS_REQUIRED))
if (*listItem.flags & (OBJECT_SELECTION_FLAG_IN_USE | OBJECT_SELECTION_FLAG_ALWAYS_REQUIRED))
colour2 |= COLOUR_FLAG_INSET;
gfx_draw_string(dpi, (char*)CheckBoxMarkString, colour2, x, y);
@ -1148,7 +1128,7 @@ static void window_editor_object_selection_scrollpaint(rct_window *w, rct_drawpi
char *bufferWithColour = gCommonStringFormatBuffer;
char *buffer = utf8_write_codepoint(bufferWithColour, colour);
if (*listItem->flags & OBJECT_SELECTION_FLAG_6) {
if (*listItem.flags & OBJECT_SELECTION_FLAG_6) {
colour = w->colours[1] & 0x7F;
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM_DARK;
}
@ -1159,14 +1139,14 @@ static void window_editor_object_selection_scrollpaint(rct_window *w, rct_drawpi
if (ridePage) {
// Draw ride type
rct_string_id rideTypeStringId = get_ride_type_string_id(listItem->repositoryItem);
rct_string_id rideTypeStringId = get_ride_type_string_id(listItem.repositoryItem);
safe_strcpy(buffer, language_get_string(rideTypeStringId), 256 - (buffer - bufferWithColour));
gfx_draw_string(dpi, bufferWithColour, colour, x, y);
x = w->widgets[WIDX_LIST_SORT_RIDE].left - w->widgets[WIDX_LIST].left;
}
// Draw text
safe_strcpy(buffer, listItem->repositoryItem->Name, 256 - (buffer - bufferWithColour));
safe_strcpy(buffer, listItem.repositoryItem->Name, 256 - (buffer - bufferWithColour));
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) {
while (*buffer != 0 && *buffer != 9)
buffer++;
@ -1221,7 +1201,7 @@ static void window_editor_object_selection_set_pressed_tab(rct_window *w)
static sint32 get_object_from_object_selection(uint8 object_type, sint32 y)
{
sint32 listItemIndex = y / 12;
if (listItemIndex < 0 || listItemIndex >= _numListItems)
if (listItemIndex < 0 || (size_t)listItemIndex >= _listItems.size())
return -1;
return listItemIndex;

View File

@ -14,11 +14,13 @@
*****************************************************************************/
#pragma endregion
#include <string>
#include <vector>
#include <openrct2/Context.h>
#include <openrct2/object/ObjectManager.h>
#include <openrct2/ride/TrackDesignRepository.h>
#include <openrct2/core/Math.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2-ui/windows/Window.h>
#include <openrct2/audio/audio.h>
@ -94,10 +96,10 @@ static rct_window_event_list window_install_track_events = {
nullptr
};
static rct_track_td6 *_trackDesign;
static utf8 *_trackPath;
static utf8 *_trackName;
static uint8 *_trackDesignPreviewPixels;
static rct_track_td6 * _trackDesign;
static std::string _trackPath;
static std::string _trackName;
static std::vector<uint8> _trackDesignPreviewPixels;
static void window_install_track_update_preview();
static void window_install_track_design(rct_window *w);
@ -142,9 +144,9 @@ rct_window * window_install_track_open(const utf8 *path)
w->track_list.track_list_being_updated = false;
window_push_others_right(w);
_trackPath = _strdup(path);
_trackName = track_repository_get_name_from_path(path);
_trackDesignPreviewPixels = Memory::AllocateArray<uint8>(4 * TRACK_PREVIEW_IMAGE_SIZE);
_trackPath = path;
_trackName = GetNameFromTrackPath(path);
_trackDesignPreviewPixels.resize(4 * TRACK_PREVIEW_IMAGE_SIZE);
window_install_track_update_preview();
window_invalidate(w);
@ -158,9 +160,10 @@ rct_window * window_install_track_open(const utf8 *path)
*/
static void window_install_track_close(rct_window *w)
{
SafeFree(_trackPath);
SafeFree(_trackName);
SafeFree(_trackDesignPreviewPixels);
_trackPath.clear();
_trackName.clear();
_trackDesignPreviewPixels.clear();
_trackDesignPreviewPixels.shrink_to_fit();
track_design_dispose(_trackDesign);
_trackDesign = nullptr;
}
@ -229,7 +232,7 @@ static void window_install_track_paint(rct_window *w, rct_drawpixelinfo *dpi)
gfx_fill_rect(dpi, x, y, x + 369, y + 216, colour);
rct_g1_element g1temp = { nullptr };
g1temp.offset = _trackDesignPreviewPixels + (_currentTrackPieceDirection * TRACK_PREVIEW_IMAGE_SIZE);
g1temp.offset = _trackDesignPreviewPixels.data() + (_currentTrackPieceDirection * TRACK_PREVIEW_IMAGE_SIZE);
g1temp.width = 370;
g1temp.height = 217;
g1temp.flags = G1_FLAG_BMP;
@ -400,15 +403,14 @@ static void window_install_track_text_input(rct_window *w, rct_widgetindex widge
return;
}
free(_trackName);
_trackName = _strdup(text);
_trackName = text;
window_event_mouse_up_call(w, WIDX_INSTALL);
}
static void window_install_track_update_preview()
{
track_design_draw_preview(_trackDesign, _trackDesignPreviewPixels);
track_design_draw_preview(_trackDesign, _trackDesignPreviewPixels.data());
}
static void window_install_track_design(rct_window *w)
@ -422,7 +424,7 @@ static void window_install_track_design(rct_window *w)
return;
}
safe_strcat_path(destPath, _trackName, sizeof(destPath));
safe_strcat_path(destPath, _trackName.c_str(), sizeof(destPath));
path_append_extension(destPath, ".td6", sizeof(destPath));
if (platform_file_exists(destPath)) {
@ -433,11 +435,11 @@ static void window_install_track_design(rct_window *w)
WIDX_INSTALL,
STR_SELECT_NEW_NAME_FOR_TRACK_DESIGN,
STR_AN_EXISTING_TRACK_DESIGN_ALREADY_HAS_THIS_NAME,
_trackName,
_trackName.c_str(),
255
);
} else {
if (track_repository_install(_trackPath)) {
if (track_repository_install(_trackPath.c_str())) {
window_close(w);
} else {
context_show_error(STR_CANT_SAVE_TRACK_DESIGN, STR_NONE);

View File

@ -14,24 +14,24 @@
*****************************************************************************/
#pragma endregion
#include <openrct2/OpenRCT2.h>
#include <openrct2/core/Math.hpp>
#include <openrct2/core/Util.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/Context.h>
#include <algorithm>
#include <vector>
#include <openrct2/audio/audio.h>
#include <openrct2/Cheats.h>
#include <openrct2/Context.h>
#include <openrct2/core/Math.hpp>
#include <openrct2/core/Util.hpp>
#include <openrct2/Game.h>
#include <openrct2/Input.h>
#include <openrct2-ui/interface/Viewport.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/OpenRCT2.h>
#include <openrct2/ride/Track.h>
#include <openrct2/world/Entrance.h>
#include <openrct2/world/Footpath.h>
#include <openrct2/world/Scenery.h>
#include <openrct2-ui/interface/LandTool.h>
#include <openrct2-ui/interface/Viewport.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/windows/Window.h>
#define MAP_COLOUR_2(colourA, colourB) ((colourA << 8) | colourB)
@ -175,7 +175,7 @@ static uint8 _activeTool;
static uint32 _currentLine;
/** rct2: 0x00F1AD68 */
static uint8 (*_mapImageData)[MAP_WINDOW_MAP_SIZE][MAP_WINDOW_MAP_SIZE];
static std::vector<uint8> _mapImageData;
static sint32 _nextPeepSpawnIndex = 0;
@ -217,8 +217,12 @@ rct_window * window_map_open()
return w;
}
_mapImageData = Memory::Allocate<uint8[MAP_WINDOW_MAP_SIZE][MAP_WINDOW_MAP_SIZE]>();
if (_mapImageData == nullptr) {
try
{
_mapImageData.resize(MAP_WINDOW_MAP_SIZE * MAP_WINDOW_MAP_SIZE);
}
catch (const std::bad_alloc &)
{
return nullptr;
}
@ -284,7 +288,8 @@ void window_map_reset()
*/
static void window_map_close(rct_window *w)
{
free(_mapImageData);
_mapImageData.clear();
_mapImageData.shrink_to_fit();
if ((input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) &&
gCurrentToolWidget.window_classification == w->classification &&
gCurrentToolWidget.window_number == w->number) {
@ -889,7 +894,7 @@ static void window_map_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32
gfx_clear(dpi, PALETTE_INDEX_10);
rct_g1_element g1temp = { nullptr };
g1temp.offset = (uint8 *)_mapImageData;
g1temp.offset = _mapImageData.data();
g1temp.width = MAP_WINDOW_MAP_SIZE;
g1temp.height = MAP_WINDOW_MAP_SIZE;
g1temp.x_offset = -8;
@ -914,7 +919,7 @@ static void window_map_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32
*/
static void window_map_init_map()
{
memset(_mapImageData, PALETTE_INDEX_10, sizeof(*_mapImageData));
std::fill(_mapImageData.begin(), _mapImageData.end(), PALETTE_INDEX_10);
_currentLine = 0;
}
@ -1653,12 +1658,11 @@ static uint16 map_window_get_pixel_colour_ride(sint32 x, sint32 y)
static void map_window_set_pixels(rct_window *w)
{
uint16 colour = 0;
uint8 *destination;
sint32 x = 0, y = 0, dx = 0, dy = 0;
sint32 pos = (_currentLine * (MAP_WINDOW_MAP_SIZE - 1)) + MAXIMUM_MAP_SIZE_TECHNICAL - 1;
LocationXY16 destinationPosition = MakeXY16(pos % MAP_WINDOW_MAP_SIZE, pos / MAP_WINDOW_MAP_SIZE);
destination = &(*_mapImageData)[destinationPosition.y][destinationPosition.x];
auto destination = _mapImageData.data() + (destinationPosition.y * MAP_WINDOW_MAP_SIZE) + destinationPosition.x;
switch (get_current_rotation()) {
case 0:
x = _currentLine * 32;
@ -1709,7 +1713,7 @@ static void map_window_set_pixels(rct_window *w)
destinationPosition.x++;
destinationPosition.y++;
destination = &(*_mapImageData)[destinationPosition.y][destinationPosition.x];
destination = _mapImageData.data() + (destinationPosition.y * MAP_WINDOW_MAP_SIZE) + destinationPosition.x;
}
_currentLine++;
if (_currentLine >= MAXIMUM_MAP_SIZE_TECHNICAL)

View File

@ -14,13 +14,13 @@
*****************************************************************************/
#pragma endregion
#include <openrct2-ui/windows/Window.h>
#include <openrct2/core/Memory.hpp>
#include <openrct2-ui/interface/Widget.h>
#include <string>
#include <vector>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/object/ObjectManager.h>
#include <openrct2/platform/platform.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/windows/Window.h>
enum WINDOW_OBJECT_LOAD_ERROR_WIDGET_IDX {
WIDX_BACKGROUND,
@ -96,9 +96,9 @@ static rct_window_event_list window_object_load_error_events = {
window_object_load_error_scrollpaint
};
static rct_object_entry * _invalid_entries = nullptr;
static std::vector<rct_object_entry> _invalid_entries;
static sint32 highlighted_index = -1;
static utf8 * file_path = nullptr;
static std::string file_path;
/**
* Returns an rct_string_id that represents an rct_object_entry's type.
@ -187,9 +187,7 @@ static void copy_object_names_to_clipboard(rct_window *w)
rct_window * window_object_load_error_open(utf8 * path, size_t numMissingObjects, const rct_object_entry * missingObjects)
{
size_t missingObjectsSize = numMissingObjects * sizeof(rct_object_entry);
_invalid_entries = Memory::AllocateArray<rct_object_entry>(numMissingObjects);
memcpy(_invalid_entries, missingObjects, missingObjectsSize);
_invalid_entries = std::vector<rct_object_entry>(missingObjects, missingObjects + numMissingObjects);
// Check if window is already open
rct_window * window = window_bring_to_front_by_class(WC_OBJECT_LOAD_ERROR);
@ -213,7 +211,7 @@ rct_window * window_object_load_error_open(utf8 * path, size_t numMissingObjects
// Refresh list items and path
window->no_list_items = (uint16)numMissingObjects;
file_path = strndup(path, strnlen(path, MAX_PATH));
file_path = path;
window_invalidate(window);
return window;
@ -221,7 +219,8 @@ rct_window * window_object_load_error_open(utf8 * path, size_t numMissingObjects
static void window_object_load_error_close(rct_window *w)
{
SafeFree(_invalid_entries);
_invalid_entries.clear();
_invalid_entries.shrink_to_fit();
}
static void window_object_load_error_update(rct_window *w)
@ -303,7 +302,7 @@ static void window_object_load_error_paint(rct_window *w, rct_drawpixelinfo *dpi
// Draw file name
set_format_arg(0, rct_string_id, STR_OBJECT_ERROR_WINDOW_FILE);
set_format_arg(2, utf8*, file_path);
set_format_arg(2, utf8*, file_path.c_str());
gfx_draw_string_left_clipped(dpi, STR_BLACK_STRING, gCommonFormatArgs, COLOUR_BLACK, w->x + 5, w->y + 43, WW-5);
}

View File

@ -141,7 +141,7 @@ static rct_window_event_list window_title_command_editor_events = {
nullptr,
nullptr,
nullptr,
window_title_command_editor_tool_down,
window_title_command_editor_tool_down,
nullptr,
nullptr,
nullptr,

View File

@ -14,42 +14,45 @@
*****************************************************************************/
#pragma endregion
#include <openrct2/config/Config.h>
#include <openrct2/scenario/ScenarioRepository.h>
#include <openrct2/scenario/ScenarioSources.h>
#include <openrct2/core/Memory.hpp>
#include <openrct2-ui/windows/Window.h>
#include <vector>
#include <openrct2/audio/audio.h>
#include <openrct2/config/Config.h>
#include <openrct2/interface/themes.h>
#include <openrct2/localisation/Date.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/scenario/ScenarioRepository.h>
#include <openrct2/scenario/ScenarioSources.h>
#include <openrct2/sprites.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2/interface/themes.h>
#include <openrct2/util/Util.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/windows/Window.h>
#define INITIAL_NUM_UNLOCKED_SCENARIOS 5
enum {
LIST_ITEM_TYPE_HEADING,
LIST_ITEM_TYPE_SCENARIO,
LIST_ITEM_TYPE_END,
enum class LIST_ITEM_TYPE : uint8
{
HEADING,
SCENARIO,
};
typedef struct sc_list_item {
uint8 type;
union {
struct {
struct sc_list_item
{
LIST_ITEM_TYPE type;
union
{
struct
{
rct_string_id string_id;
} heading;
struct {
const scenario_index_entry *scenario;
struct
{
const scenario_index_entry * scenario;
bool is_locked;
} scenario;
};
} sc_list_item;
};
static sc_list_item *_listItems = nullptr;
static std::vector<sc_list_item> _listItems;
enum {
WIDX_BACKGROUND,
@ -250,7 +253,8 @@ static void window_scenarioselect_init_tabs(rct_window *w)
static void window_scenarioselect_close(rct_window *w)
{
SafeFree(_listItems);
_listItems.clear();
_listItems.shrink_to_fit();
}
static void window_scenarioselect_mouseup(rct_window *w, rct_widgetindex widgetIndex)
@ -277,12 +281,14 @@ static void window_scenarioselect_mousedown(rct_window *w, rct_widgetindex widge
static void window_scenarioselect_scrollgetsize(rct_window *w, sint32 scrollIndex, sint32 *width, sint32 *height)
{
sint32 y = 0;
for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) {
switch (listItem->type) {
case LIST_ITEM_TYPE_HEADING:
for (const auto &listItem : _listItems)
{
switch (listItem.type)
{
case LIST_ITEM_TYPE::HEADING:
y += 18;
break;
case LIST_ITEM_TYPE_SCENARIO:
case LIST_ITEM_TYPE::SCENARIO:
y += 24;
break;
}
@ -296,17 +302,19 @@ static void window_scenarioselect_scrollgetsize(rct_window *w, sint32 scrollInde
*/
static void window_scenarioselect_scrollmousedown(rct_window *w, sint32 scrollIndex, sint32 x, sint32 y)
{
for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) {
switch (listItem->type) {
case LIST_ITEM_TYPE_HEADING:
for (const auto &listItem : _listItems)
{
switch (listItem.type)
{
case LIST_ITEM_TYPE::HEADING:
y -= 18;
break;
case LIST_ITEM_TYPE_SCENARIO:
case LIST_ITEM_TYPE::SCENARIO:
y -= 24;
if (y < 0 && !listItem->scenario.is_locked) {
if (y < 0 && !listItem.scenario.is_locked) {
audio_play_sound(SOUND_CLICK_1, 0, w->x + (w->width / 2));
gFirstTimeSaving = true;
_callback(listItem->scenario.scenario->path);
_callback(listItem.scenario.scenario->path);
if (_titleEditor)
{
window_close(w);
@ -329,18 +337,20 @@ static void window_scenarioselect_scrollmouseover(rct_window *w, sint32 scrollIn
bool originalShowLockedInformation = _showLockedInformation;
_showLockedInformation = false;
const scenario_index_entry *selected = nullptr;
for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) {
switch (listItem->type) {
case LIST_ITEM_TYPE_HEADING:
for (const auto &listItem : _listItems)
{
switch (listItem.type)
{
case LIST_ITEM_TYPE::HEADING:
y -= 18;
break;
case LIST_ITEM_TYPE_SCENARIO:
case LIST_ITEM_TYPE::SCENARIO:
y -= 24;
if (y < 0) {
if (listItem->scenario.is_locked) {
if (listItem.scenario.is_locked) {
_showLockedInformation = true;
} else {
selected = listItem->scenario.scenario;
selected = listItem.scenario.scenario;
}
}
break;
@ -483,30 +493,32 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo *
sint32 listWidth = listWidget->right - listWidget->left - 12;
sint32 y = 0;
for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) {
for (const auto &listItem : _listItems)
{
if (y > dpi->y + dpi->height) {
continue;
}
switch (listItem->type) {
case LIST_ITEM_TYPE_HEADING:
switch (listItem.type)
{
case LIST_ITEM_TYPE::HEADING:
{
const sint32 horizontalRuleMargin = 4;
draw_category_heading(w, dpi, horizontalRuleMargin, listWidth - horizontalRuleMargin, y + 2, listItem->heading.string_id);
draw_category_heading(w, dpi, horizontalRuleMargin, listWidth - horizontalRuleMargin, y + 2, listItem.heading.string_id);
y += 18;
break;
}
case LIST_ITEM_TYPE_SCENARIO:
case LIST_ITEM_TYPE::SCENARIO:
{
// Draw hover highlight
const scenario_index_entry *scenario = listItem->scenario.scenario;
const scenario_index_entry *scenario = listItem.scenario.scenario;
bool isHighlighted = w->highlighted_scenario == scenario;
if (isHighlighted) {
gfx_filter_rect(dpi, 0, y, w->width, y + 23, PALETTE_DARKEN_1);
}
bool isCompleted = scenario->highscore != nullptr;
bool isDisabled = listItem->scenario.is_locked;
bool isDisabled = listItem.scenario.is_locked;
// Draw scenario name
char buffer[64];
@ -574,12 +586,8 @@ static void draw_category_heading(rct_window *w, rct_drawpixelinfo *dpi, sint32
static void initialise_list_items(rct_window *w)
{
SafeFree(_listItems);
size_t numScenarios = scenario_repository_get_count();
size_t capacity = numScenarios + 16;
size_t length = 0;
_listItems = Memory::AllocateArray<sc_list_item>(capacity);
_listItems.clear();
// Mega park unlock
const uint32 rct1RequiredCompletedScenarios = (1 << SC_MEGA_PARK) - 1;
@ -596,8 +604,6 @@ static void initialise_list_items(rct_window *w)
if (_titleEditor && scenario->source_game == SCENARIO_SOURCE_OTHER)
continue;
sc_list_item *listItem;
// Category heading
rct_string_id headingStringId = STR_NONE;
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN || _titleEditor) {
@ -623,70 +629,69 @@ static void initialise_list_items(rct_window *w)
}
}
if (headingStringId != STR_NONE) {
// Ensure list capacity
if (length == capacity) {
capacity += 32;
_listItems = Memory::ReallocateArray(_listItems, capacity);
}
listItem = &_listItems[length++];
listItem->type = LIST_ITEM_TYPE_HEADING;
listItem->heading.string_id = headingStringId;
if (headingStringId != STR_NONE)
{
sc_list_item headerItem;
headerItem.type = LIST_ITEM_TYPE::HEADING;
headerItem.heading.string_id = headingStringId;
_listItems.push_back(std::move(headerItem));
}
// Ensure list capacity
if (length == capacity) {
capacity += 32;
_listItems = Memory::ReallocateArray(_listItems, capacity);
}
listItem = &_listItems[length++];
// Scenario
listItem->type = LIST_ITEM_TYPE_SCENARIO;
listItem->scenario.scenario = scenario;
if (is_locking_enabled(w)) {
listItem->scenario.is_locked = numUnlocks <= 0;
if (scenario->highscore == nullptr) {
sc_list_item scenarioItem;
scenarioItem.type = LIST_ITEM_TYPE::SCENARIO;
scenarioItem.scenario.scenario = scenario;
if (is_locking_enabled(w))
{
scenarioItem.scenario.is_locked = numUnlocks <= 0;
if (scenario->highscore == nullptr)
{
numUnlocks--;
} else {
}
else
{
// Mark RCT1 scenario as completed
if (scenario->sc_id < SC_MEGA_PARK) {
if (scenario->sc_id < SC_MEGA_PARK)
{
rct1CompletedScenarios |= 1 << scenario->sc_id;
}
}
// If scenario is Mega Park, keep a reference to it
if (scenario->sc_id == SC_MEGA_PARK) {
megaParkListItemIndex = length - 1;
if (scenario->sc_id == SC_MEGA_PARK)
{
megaParkListItemIndex = _listItems.size() - 1;
}
} else {
listItem->scenario.is_locked = false;
}
else
{
scenarioItem.scenario.is_locked = false;
}
_listItems.push_back(std::move(scenarioItem));
}
length++;
_listItems = Memory::ReallocateArray(_listItems, capacity);
_listItems[length - 1].type = LIST_ITEM_TYPE_END;
// Mega park handling
if (megaParkListItemIndex != SIZE_MAX) {
if (megaParkListItemIndex != SIZE_MAX)
{
bool megaParkLocked = (rct1CompletedScenarios & rct1RequiredCompletedScenarios) != rct1RequiredCompletedScenarios;
_listItems[megaParkListItemIndex].scenario.is_locked = megaParkLocked;
if (megaParkLocked && gConfigGeneral.scenario_hide_mega_park) {
if (megaParkLocked && gConfigGeneral.scenario_hide_mega_park)
{
// Remove mega park
size_t remainingItems = length - megaParkListItemIndex - 1;
memmove(&_listItems[megaParkListItemIndex], &_listItems[megaParkListItemIndex + 1], remainingItems);
_listItems.pop_back();
// Remove empty headings
sint32 i = 0;
for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) {
if (listItem->type == LIST_ITEM_TYPE_HEADING && (listItem + 1)->type != LIST_ITEM_TYPE_SCENARIO) {
remainingItems = length - i - 1;
memmove(&_listItems[i], &_listItems[i + 1], remainingItems);
listItem--;
} else {
i++;
for (auto it = _listItems.begin(); it != _listItems.end(); it++)
{
const auto &listItem = *it;
if (listItem.type == LIST_ITEM_TYPE::HEADING)
{
if ((it + 1) == _listItems.end() ||
(it + 1)->type == LIST_ITEM_TYPE::HEADING)
{
_listItems.erase(it);
it--;
}
}
}
}

View File

@ -14,23 +14,23 @@
*****************************************************************************/
#pragma endregion
#include <openrct2-ui/windows/Window.h>
#include <algorithm>
#include <vector>
#include <openrct2/audio/audio.h>
#include <openrct2/Cheats.h>
#include <openrct2/Context.h>
#include <openrct2/core/Math.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/Game.h>
#include <openrct2/Input.h>
#include <openrct2-ui/interface/Viewport.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/ride/Track.h>
#include <openrct2/ride/TrackData.h>
#include <openrct2/ride/TrackDesignRepository.h>
#include <openrct2/sprites.h>
#include <openrct2/windows/Intent.h>
#include <openrct2-ui/interface/Viewport.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/windows/Window.h>
#define TRACK_MINI_PREVIEW_WIDTH 168
#define TRACK_MINI_PREVIEW_HEIGHT 78
@ -104,7 +104,7 @@ static rct_window_event_list window_track_place_events = {
nullptr
};
static uint8 *_window_track_place_mini_preview;
static std::vector<uint8> _window_track_place_mini_preview;
static sint16 _window_track_place_last_x;
static sint16 _window_track_place_last_y;
@ -135,7 +135,7 @@ static uint8 *draw_mini_preview_get_pixel_ptr(LocationXY16 pixel);
*/
static void window_track_place_clear_mini_preview()
{
memset(_window_track_place_mini_preview, PALETTE_INDEX_TRANSPARENT, TRACK_MINI_PREVIEW_SIZE);
std::fill(_window_track_place_mini_preview.begin(), _window_track_place_mini_preview.end(), PALETTE_INDEX_TRANSPARENT);
}
#define swap(x, y) x = x ^ y; y = x ^ y; x = x ^ y;
@ -153,7 +153,7 @@ rct_window * window_track_place_open(const track_design_file_ref *tdFileRef)
window_close_construction_windows();
_window_track_place_mini_preview = Memory::Allocate<uint8>(TRACK_MINI_PREVIEW_SIZE);
_window_track_place_mini_preview.resize(TRACK_MINI_PREVIEW_SIZE);
rct_window *w = window_create(
0,
@ -198,7 +198,8 @@ static void window_track_place_close(rct_window *w)
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_CONSTRUCT;
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_ARROW;
hide_gridlines();
SafeFree(_window_track_place_mini_preview);
_window_track_place_mini_preview.clear();
_window_track_place_mini_preview.shrink_to_fit();
track_design_dispose(_trackDesign);
_trackDesign = nullptr;
}
@ -468,7 +469,7 @@ static void window_track_place_paint(rct_window *w, rct_drawpixelinfo *dpi)
rct_drawpixelinfo clippedDpi;
if (clip_drawpixelinfo(&clippedDpi, dpi, w->x + 4, w->y + 18, 168, 78)) {
rct_g1_element g1temp = { nullptr };
g1temp.offset = _window_track_place_mini_preview;
g1temp.offset = _window_track_place_mini_preview.data();
g1temp.width = TRACK_MINI_PREVIEW_WIDTH;
g1temp.height = TRACK_MINI_PREVIEW_HEIGHT;
gfx_set_g1_element(SPR_TEMP, &g1temp);

View File

@ -14,12 +14,10 @@
*****************************************************************************/
#pragma endregion
#include <openrct2-ui/windows/Window.h>
#include <vector>
#include <openrct2/audio/audio.h>
#include <openrct2/Context.h>
#include <openrct2/core/Math.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/core/String.hpp>
#include <openrct2/drawing/IDrawingEngine.h>
#include <openrct2/Editor.h>
@ -30,7 +28,7 @@
#include <openrct2/ride/TrackDesignRepository.h>
#include <openrct2/sprites.h>
#include <openrct2/windows/Intent.h>
#include <vector>
#include <openrct2-ui/windows/Window.h>
enum {
WIDX_BACKGROUND,
@ -108,13 +106,12 @@ static rct_window_event_list window_track_list_events = {
ride_list_item _window_track_list_item;
static track_design_file_ref * _trackDesigns = nullptr;
static size_t _trackDesignsCount = 0;
static std::vector<track_design_file_ref> _trackDesigns;
static utf8 _filterString[USER_STRING_MAX_LENGTH];
static std::vector<uint16> _filteredTrackIds;
static uint16 _loadedTrackDesignIndex;
static rct_track_td6 * _loadedTrackDesign;
static uint8 * _trackDesignPreviewPixels;
static std::vector<uint8> _trackDesignPreviewPixels;
static void track_list_load_designs(ride_list_item item);
static bool track_list_load_design_for_preview(utf8 *path);
@ -171,7 +168,7 @@ rct_window * window_track_list_open(ride_list_item item)
// Start with first track highlighted
w->selected_list_item = 0;
if (_trackDesignsCount != 0 && !(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER)) {
if (_trackDesigns.size() != 0 && !(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER)) {
w->selected_list_item = 1;
}
@ -179,7 +176,7 @@ rct_window * window_track_list_open(ride_list_item item)
window_push_others_right(w);
_currentTrackPieceDirection = 2;
_trackDesignPreviewPixels = Memory::AllocateArray<uint8>(4 * TRACK_PREVIEW_IMAGE_SIZE);
_trackDesignPreviewPixels.resize(4 * TRACK_PREVIEW_IMAGE_SIZE);
_loadedTrackDesign = nullptr;
_loadedTrackDesignIndex = TRACK_DESIGN_INDEX_UNLOADED;
@ -194,7 +191,7 @@ static void window_track_list_filter_list()
// Nothing to filter, so fill the list with all indices
if (String::LengthOf(_filterString) == 0)
{
for (uint16 i = 0; i < _trackDesignsCount; i++)
for (uint16 i = 0; i < _trackDesigns.size(); i++)
_filteredTrackIds.push_back(i);
return;
@ -207,7 +204,7 @@ static void window_track_list_filter_list()
filterStringLower[i] = (utf8)tolower(filterStringLower[i]);
// Fill the set with indices for tracks that match the filter
for (uint16 i = 0; i < _trackDesignsCount; i++)
for (uint16 i = 0; i < _trackDesigns.size(); i++)
{
utf8 trackNameLower[USER_STRING_MAX_LENGTH];
String::Set(trackNameLower, sizeof(trackNameLower), _trackDesigns[i].name);
@ -230,15 +227,16 @@ static void window_track_list_close(rct_window *w)
// Dispose track design and preview
track_design_dispose(_loadedTrackDesign);
_loadedTrackDesign = nullptr;
SafeFree(_trackDesignPreviewPixels);
_trackDesignPreviewPixels.clear();
_trackDesignPreviewPixels.shrink_to_fit();
// Dispose track list
for (size_t i = 0; i < _trackDesignsCount; i++) {
free(_trackDesigns[i].name);
free(_trackDesigns[i].path);
for (auto &trackDesign : _trackDesigns)
{
free(trackDesign.name);
free(trackDesign.path);
}
SafeFree(_trackDesigns);
_trackDesignsCount = 0;
_trackDesigns.clear();
// If gScreenAge is zero, we're already in the process
// of loading the track manager, so we shouldn't try
@ -501,7 +499,7 @@ static void window_track_list_paint(rct_window *w, rct_drawpixelinfo *dpi)
sint32 listItemIndex = w->selected_list_item;
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER)
{
if (_trackDesignsCount == 0 || listItemIndex == -1)
if (_trackDesigns.size() == 0 || listItemIndex == -1)
return;
}
else {
@ -538,7 +536,7 @@ static void window_track_list_paint(rct_window *w, rct_drawpixelinfo *dpi)
}
rct_g1_element g1temp = { nullptr };
g1temp.offset = _trackDesignPreviewPixels + (_currentTrackPieceDirection * TRACK_PREVIEW_IMAGE_SIZE);
g1temp.offset = _trackDesignPreviewPixels.data() + (_currentTrackPieceDirection * TRACK_PREVIEW_IMAGE_SIZE);
g1temp.width = 370;
g1temp.height = 217;
g1temp.flags = G1_FLAG_BMP;
@ -684,7 +682,7 @@ static void window_track_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi,
sint32 y = 0;
size_t listIndex = 0;
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) {
if (_trackDesignsCount == 0) {
if (_trackDesigns.size() == 0) {
// No track designs
gfx_draw_string_left(dpi, STR_NO_TRACK_DESIGNS_OF_THIS_TYPE, nullptr, COLOUR_BLACK, x, y - 1);
return;
@ -735,6 +733,7 @@ static void window_track_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi,
static void track_list_load_designs(ride_list_item item)
{
auto repo = GetTrackDesignRepository();
if (!RideGroupManager::RideTypeHasRideGroups(item.type))
{
char entry[9];
@ -747,13 +746,14 @@ static void track_list_load_designs(ride_list_item item)
entryPtr = entry;
}
}
_trackDesignsCount = track_repository_get_items_for_ride(&_trackDesigns, item.type, entryPtr);
_trackDesigns = repo->GetItemsForObjectEntry(item.type, String::ToStd(entryPtr));
}
else
{
rct_ride_entry *rideEntry = get_ride_entry(item.entry_index);
const RideGroup * rideGroup = RideGroupManager::GetRideGroup(item.type, rideEntry);
_trackDesignsCount = track_repository_get_items_for_ride_group(&_trackDesigns, item.type, rideGroup);
auto rideEntry = get_ride_entry(item.entry_index);
auto rideGroup = RideGroupManager::GetRideGroup(item.type, rideEntry);
_trackDesigns = repo->GetItemsForRideGroup(item.type, rideGroup);
}
window_track_list_filter_list();
@ -767,7 +767,7 @@ static bool track_list_load_design_for_preview(utf8 *path)
_loadedTrackDesign = track_design_open(path);
if (_loadedTrackDesign != nullptr && drawing_engine_get_type() != DRAWING_ENGINE_OPENGL) {
track_design_draw_preview(_loadedTrackDesign, _trackDesignPreviewPixels);
track_design_draw_preview(_loadedTrackDesign, _trackDesignPreviewPixels.data());
return true;
}
return false;

View File

@ -99,6 +99,8 @@ private:
return DIRBASE::RCT1;
case PATHID::SCORES_RCT2:
return DIRBASE::RCT2;
case PATHID::CHANGELOG:
return DIRBASE::DOCUMENTATION;
case PATHID::NETWORK_GROUPS:
case PATHID::NETWORK_SERVERS:
case PATHID::NETWORK_USERS:
@ -134,6 +136,7 @@ IPlatformEnvironment * OpenRCT2::CreatePlatformEnvironment()
basePaths[(size_t)DIRBASE::USER] = Path::Combine(Platform::GetFolderPath(SPECIAL_FOLDER::USER_DATA), subDirectory);
basePaths[(size_t)DIRBASE::CONFIG] = Path::Combine(Platform::GetFolderPath(SPECIAL_FOLDER::USER_CONFIG), subDirectory);
basePaths[(size_t)DIRBASE::CACHE] = Path::Combine(Platform::GetFolderPath(SPECIAL_FOLDER::USER_CACHE), subDirectory);
basePaths[(size_t)DIRBASE::DOCUMENTATION] = Platform::GetDocsPath();
// Override paths that have been specified via the command line
if (!String::IsNullOrEmpty(gCustomRCT2DataPath))
@ -151,6 +154,11 @@ IPlatformEnvironment * OpenRCT2::CreatePlatformEnvironment()
basePaths[(size_t)DIRBASE::CACHE] = gCustomUserDataPath;
}
if (basePaths[(size_t)DIRBASE::DOCUMENTATION].empty())
{
basePaths[(size_t)DIRBASE::DOCUMENTATION] = basePaths[(size_t)DIRBASE::OPENRCT2];
}
auto env = OpenRCT2::CreatePlatformEnvironment(basePaths);
// Now load the config so we can get the RCT1 and RCT2 paths
@ -206,7 +214,7 @@ const char * PlatformEnvironment::DirectoryNamesOpenRCT2[] =
"scenario", // SCENARIO
"screenshot", // SCREENSHOT
"sequence", // SEQUENCE
"shader", // SHADER
"shaders", // SHADER
"themes", // THEME
"track", // TRACK
};
@ -225,5 +233,6 @@ const char * PlatformEnvironment::FileNames[] =
"highscores.dat", // SCORES
"scores.dat", // SCORES (LEGACY)
"Saved Games" PATH_SEPARATOR "scores.dat", // SCORES (RCT2)
"changelog.txt" // CHANGELOG
};
// clang-format on

View File

@ -31,8 +31,9 @@ namespace OpenRCT2
USER, // Base directory for OpenRCT2 user content.
CONFIG, // Base directory for OpenRCT2 configuration.
CACHE, // Base directory for OpenRCT2 cache files.
DOCUMENTATION, // Base directory for OpenRCT2 doc files.
};
constexpr sint32 DIRBASE_COUNT = 6;
constexpr sint32 DIRBASE_COUNT = 7;
using DIRBASE_VALUES = std::string[DIRBASE_COUNT];
enum class DIRID
@ -67,6 +68,7 @@ namespace OpenRCT2
SCORES, // Scenario scores (highscores.dat).
SCORES_LEGACY, // Scenario scores, legacy (scores.dat).
SCORES_RCT2, // Scenario scores, rct2 (\Saved Games\scores.dat).
CHANGELOG, // Notable changes to the game between versions, distributed with the game.
};
/**

View File

@ -69,11 +69,6 @@ float platform_get_default_scale() {
return displayScale;
}
void platform_get_changelog_path(utf8 *outPath, size_t outSize)
{
STUB();
}
bool platform_get_steam_path(utf8 * outPath, size_t outSize)
{
return false;

View File

@ -108,27 +108,6 @@ void platform_posix_sub_resolve_openrct_data_path(utf8 *out, size_t size) {
}
}
/**
* Default directory fallback is:
* - <exePath>/doc
* - /usr/share/doc/openrct2
*/
static void platform_posix_sub_resolve_openrct_doc_path(utf8 *out, size_t size) {
static const utf8 *searchLocations[] = {
"./doc",
"/usr/share/doc/openrct2",
};
for (auto searchLocation : searchLocations)
{
log_verbose("Looking for OpenRCT2 doc path at %s", searchLocation);
if (platform_directory_exists(searchLocation))
{
safe_strcpy(out, searchLocation, size);
return;
}
}
}
uint16 platform_get_locale_language(){
const char *langString = setlocale(LC_MESSAGES, "");
if(langString != NULL){
@ -218,12 +197,6 @@ uint8 platform_get_locale_measurement_format(){
return MEASUREMENT_FORMAT_METRIC;
}
void platform_get_changelog_path(utf8 *outPath, size_t outSize)
{
platform_posix_sub_resolve_openrct_doc_path(outPath, outSize);
safe_strcat_path(outPath, "changelog.txt", outSize);
}
bool platform_get_steam_path(utf8 * outPath, size_t outSize)
{
const char * steamRoot = getenv("STEAMROOT");

View File

@ -34,6 +34,11 @@ namespace Platform
return std::string();
}
}
std::string GetDocsPath()
{
return std::string();
}
}
#endif

View File

@ -18,6 +18,7 @@
#include <pwd.h>
#include "../core/Path.hpp"
#include "platform.h"
#include "Platform2.h"
namespace Platform
@ -44,6 +45,24 @@ namespace Platform
return std::string();
}
}
std::string GetDocsPath()
{
static const utf8 * searchLocations[] =
{
"./doc",
"/usr/share/doc/openrct2",
};
for (auto searchLocation : searchLocations)
{
log_verbose("Looking for OpenRCT2 doc path at %s", searchLocation);
if (platform_directory_exists(searchLocation))
{
return searchLocation;
}
}
return std::string();
}
}
#endif

View File

@ -147,6 +147,11 @@ namespace Platform
return path;
}
std::string GetDocsPath()
{
return std::string();
}
static SYSTEMTIME TimeToSystemTime(std::time_t timestamp)
{
LONGLONG ll = Int32x32To64(timestamp, 10000000) + 116444736000000000;

View File

@ -39,6 +39,11 @@ namespace Platform
return std::string();
}
}
std::string GetDocsPath()
{
return std::string();
}
}
#endif

View File

@ -36,6 +36,7 @@ namespace Platform
std::string GetEnvironmentVariable(const std::string &name);
std::string GetFolderPath(SPECIAL_FOLDER folder);
std::string GetInstallPath();
std::string GetDocsPath();
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__)
std::string GetEnvironmentPath(const char * name);

View File

@ -244,12 +244,6 @@ void platform_get_openrct_data_path(utf8 *outPath, size_t outSize)
safe_strcpy(outPath, _openrctDataDirectoryPath, outSize);
}
void platform_get_changelog_path(utf8 *outPath, size_t outSize)
{
safe_strcpy(outPath, gExePath, outSize);
safe_strcat_path(outPath, "changelog.txt", outSize);
}
bool platform_get_steam_path(utf8 * outPath, size_t outSize)
{
wchar_t * wSteamPath;

View File

@ -127,7 +127,6 @@ uint8 platform_get_locale_measurement_format();
uint8 platform_get_locale_temperature_format();
uint8 platform_get_locale_date_format();
bool platform_process_is_elevated();
void platform_get_changelog_path(utf8 *outPath, size_t outSize);
bool platform_get_steam_path(utf8 * outPath, size_t outSize);
#ifndef NO_TTF

View File

@ -114,7 +114,7 @@ rct_track_td6 * track_design_open(const utf8 * path)
if (td6 != nullptr)
{
td6->name = track_repository_get_name_from_path(path);
td6->name = String::Duplicate(GetNameFromTrackPath(path).c_str());
return td6;
}
}

View File

@ -49,7 +49,7 @@ enum TRACK_REPO_ITEM_FLAGS
TRIF_READ_ONLY = (1 << 0),
};
static std::string GetNameFromTrackPath(const std::string &path)
std::string GetNameFromTrackPath(const std::string &path)
{
std::string name = Path::GetFileNameWithoutExtension(path);
//The track name should be the file name until the first instance of a dot
@ -222,7 +222,7 @@ public:
* @param entry The entry name to build a track list for. Leave empty to build track list for the non-separated types (e.g. Hyper-Twister, Car Ride)
* @return
*/
size_t GetItemsForObjectEntry(track_design_file_ref * * outRefs, uint8 rideType, const std::string &entry) const override
std::vector<track_design_file_ref> GetItemsForObjectEntry(uint8 rideType, const std::string &entry) const override
{
std::vector<track_design_file_ref> refs;
const IObjectRepository * repo = GetObjectRepository();
@ -252,11 +252,10 @@ public:
}
}
*outRefs = Collections::ToArray(refs);
return refs.size();
return refs;
}
size_t GetItemsForRideGroup(track_design_file_ref **outRefs, uint8 rideType, const RideGroup * rideGroup) const override
std::vector<track_design_file_ref> GetItemsForRideGroup(uint8 rideType, const RideGroup * rideGroup) const override
{
std::vector<track_design_file_ref> refs;
const IObjectRepository * repo = GetObjectRepository();
@ -281,8 +280,7 @@ public:
}
}
*outRefs = Collections::ToArray(refs);
return refs.size();
return refs;
}
void Scan() override
@ -418,18 +416,6 @@ extern "C"
repo->Scan();
}
size_t track_repository_get_items_for_ride(track_design_file_ref * * outRefs, uint8 rideType, const utf8 * entry)
{
ITrackDesignRepository * repo = GetTrackDesignRepository();
return repo->GetItemsForObjectEntry(outRefs, rideType, String::ToStd(entry));
}
size_t track_repository_get_items_for_ride_group(track_design_file_ref * * outRefs, uint8 rideType, const RideGroup * rideGroup)
{
ITrackDesignRepository * repo = GetTrackDesignRepository();
return repo->GetItemsForRideGroup(outRefs, rideType, rideGroup);
}
bool track_repository_delete(const utf8 * path)
{
ITrackDesignRepository * repo = GetTrackDesignRepository();
@ -449,9 +435,4 @@ extern "C"
std::string newPath = repo->Install(srcPath);
return !newPath.empty();
}
utf8 * track_repository_get_name_from_path(const utf8 * path)
{
return String::Duplicate(GetNameFromTrackPath(path));
}
}

View File

@ -42,12 +42,10 @@ interface ITrackDesignRepository
virtual size_t GetCount() const abstract;
virtual size_t GetCountForObjectEntry(uint8 rideType, const std::string &entry) const abstract;
virtual size_t GetCountForRideGroup(uint8 rideType, const RideGroup * rideGroup) const abstract;
virtual size_t GetItemsForObjectEntry(track_design_file_ref * * outRefs,
uint8 rideType,
const std::string &entry) const abstract;
virtual size_t GetItemsForRideGroup(track_design_file_ref **outRefs,
uint8 rideType,
const RideGroup * rideGroup) const abstract;
virtual std::vector<track_design_file_ref> GetItemsForObjectEntry(uint8 rideType,
const std::string &entry) const abstract;
virtual std::vector<track_design_file_ref> GetItemsForRideGroup(uint8 rideType,
const RideGroup * rideGroup) const abstract;
virtual void Scan() abstract;
virtual bool Delete(const std::string &path) abstract;
@ -57,6 +55,7 @@ interface ITrackDesignRepository
ITrackDesignRepository * CreateTrackDesignRepository(OpenRCT2::IPlatformEnvironment * env);
ITrackDesignRepository * GetTrackDesignRepository();
std::string GetNameFromTrackPath(const std::string &path);
#endif
@ -65,9 +64,6 @@ extern "C"
{
#endif
void track_repository_scan();
size_t track_repository_get_items_for_ride(track_design_file_ref * * outRefs, uint8 rideType, const utf8 * entry);
size_t track_repository_get_items_for_ride_group(track_design_file_ref * * outRefs, uint8 rideType, const RideGroup * rideGroup);
utf8 * track_repository_get_name_from_path(const utf8 *path);
bool track_repository_delete(const utf8 *path);
bool track_repository_rename(const utf8 *path, const utf8 *newName);
bool track_repository_install(const utf8 *srcPath);