Preprocessor purge round 15: FONTEDITOR, RENDERER
This commit is contained in:
parent
b5f6ec0f6c
commit
f0ffa2eeb1
@ -378,7 +378,7 @@ if get_option('build_powder')
|
|||||||
powder_sha = shared_library(
|
powder_sha = shared_library(
|
||||||
app_exe,
|
app_exe,
|
||||||
sources: powder_files,
|
sources: powder_files,
|
||||||
include_directories: [ project_inc, powder_inc ],
|
include_directories: project_inc,
|
||||||
c_args: project_c_args,
|
c_args: project_c_args,
|
||||||
cpp_args: project_cpp_args,
|
cpp_args: project_cpp_args,
|
||||||
link_args: project_link_args,
|
link_args: project_link_args,
|
||||||
@ -389,7 +389,7 @@ if get_option('build_powder')
|
|||||||
executable(
|
executable(
|
||||||
app_exe,
|
app_exe,
|
||||||
sources: powder_files,
|
sources: powder_files,
|
||||||
include_directories: [ project_inc, powder_inc ],
|
include_directories: project_inc,
|
||||||
c_args: project_c_args,
|
c_args: project_c_args,
|
||||||
cpp_args: project_cpp_args,
|
cpp_args: project_cpp_args,
|
||||||
win_subsystem: is_debug ? 'console' : 'windows',
|
win_subsystem: is_debug ? 'console' : 'windows',
|
||||||
@ -414,7 +414,7 @@ if get_option('build_render')
|
|||||||
executable(
|
executable(
|
||||||
'render',
|
'render',
|
||||||
sources: render_files,
|
sources: render_files,
|
||||||
include_directories: [ project_inc, render_inc ],
|
include_directories: project_inc,
|
||||||
c_args: project_c_args,
|
c_args: project_c_args,
|
||||||
cpp_args: project_cpp_args,
|
cpp_args: project_cpp_args,
|
||||||
link_args: render_link_args,
|
link_args: render_link_args,
|
||||||
@ -434,7 +434,7 @@ if get_option('build_font')
|
|||||||
executable(
|
executable(
|
||||||
'font',
|
'font',
|
||||||
sources: font_files,
|
sources: font_files,
|
||||||
include_directories: [ project_inc, font_inc ],
|
include_directories: project_inc,
|
||||||
c_args: project_c_args,
|
c_args: project_c_args,
|
||||||
cpp_args: project_cpp_args,
|
cpp_args: project_cpp_args,
|
||||||
link_args: project_link_args,
|
link_args: project_link_args,
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
// Boolean macros (defined / not defined), would be great to get rid of them all.
|
// Boolean macros (defined / not defined), would be great to get rid of them all.
|
||||||
#mesondefine RENDERER
|
|
||||||
#mesondefine FONTEDITOR
|
|
||||||
#mesondefine DEBUG
|
#mesondefine DEBUG
|
||||||
#mesondefine LIN
|
#mesondefine LIN
|
||||||
#mesondefine AND
|
#mesondefine AND
|
||||||
@ -63,13 +61,9 @@ constexpr char BRUSH_DIR[] = "Brushes";
|
|||||||
|
|
||||||
constexpr float M_GRAV = 6.67300e-1f;
|
constexpr float M_GRAV = 6.67300e-1f;
|
||||||
|
|
||||||
#ifdef RENDERER
|
|
||||||
constexpr int MENUSIZE = 0;
|
|
||||||
constexpr int BARSIZE = 0;
|
|
||||||
#else
|
|
||||||
constexpr int MENUSIZE = 40;
|
constexpr int MENUSIZE = 40;
|
||||||
constexpr int BARSIZE = 17;
|
constexpr int BARSIZE = 17;
|
||||||
#endif
|
|
||||||
//CELL, the size of the pressure, gravity, and wall maps. Larger than 1 to prevent extreme lag
|
//CELL, the size of the pressure, gravity, and wall maps. Larger than 1 to prevent extreme lag
|
||||||
constexpr int CELL = 4;
|
constexpr int CELL = 4;
|
||||||
constexpr int XCELLS = 153;
|
constexpr int XCELLS = 153;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "Format.h"
|
#include "Format.h"
|
||||||
|
#include "graphics/Graphics.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -9,12 +9,6 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "graphics/Graphics.h"
|
|
||||||
|
|
||||||
#ifndef RENDERER
|
|
||||||
# include <SDL.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ByteString format::UnixtimeToDate(time_t unixtime, ByteString dateFormat)
|
ByteString format::UnixtimeToDate(time_t unixtime, ByteString dateFormat)
|
||||||
{
|
{
|
||||||
struct tm * timeData;
|
struct tm * timeData;
|
||||||
|
@ -103,13 +103,11 @@ Client::Client():
|
|||||||
|
|
||||||
void Client::Initialize()
|
void Client::Initialize()
|
||||||
{
|
{
|
||||||
#if !defined(FONTEDITOR) && !defined(RENDERER)
|
|
||||||
if (GetPrefBool("version.update", false))
|
if (GetPrefBool("version.update", false))
|
||||||
{
|
{
|
||||||
SetPref("version.update", false);
|
SetPref("version.update", false);
|
||||||
update_finish();
|
update_finish();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
//Read stamps library
|
//Read stamps library
|
||||||
std::ifstream stampsLib;
|
std::ifstream stampsLib;
|
||||||
@ -1650,3 +1648,30 @@ bool Client::DoInstallation()
|
|||||||
#endif
|
#endif
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AddCustomGol(String ruleString, String nameString, unsigned int highColor, unsigned int lowColor)
|
||||||
|
{
|
||||||
|
auto customGOLTypes = Client::Ref().GetPrefByteStringArray("CustomGOL.Types");
|
||||||
|
Json::Value newCustomGOLTypes(Json::arrayValue);
|
||||||
|
bool nameTaken = false;
|
||||||
|
for (auto gol : customGOLTypes)
|
||||||
|
{
|
||||||
|
auto parts = gol.FromUtf8().PartitionBy(' ');
|
||||||
|
if (parts.size())
|
||||||
|
{
|
||||||
|
if (parts[0] == nameString)
|
||||||
|
{
|
||||||
|
nameTaken = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newCustomGOLTypes.append(gol);
|
||||||
|
}
|
||||||
|
if (nameTaken)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
StringBuilder sb;
|
||||||
|
sb << nameString << " " << ruleString << " " << highColor << " " << lowColor;
|
||||||
|
newCustomGOLTypes.append(sb.Build().ToUtf8());
|
||||||
|
Client::Ref().SetPref("CustomGOL.Types", newCustomGOLTypes);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -177,3 +177,5 @@ public:
|
|||||||
void SetPref(ByteString property, std::vector<Json::Value> value);
|
void SetPref(ByteString property, std::vector<Json::Value> value);
|
||||||
void SetPrefUnicode(ByteString prop, String value);
|
void SetPrefUnicode(ByteString prop, String value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool AddCustomGol(String ruleString, String nameString, unsigned int highColor, unsigned int lowColor);
|
||||||
|
@ -692,7 +692,6 @@ void GameSave::readOPS(const std::vector<char> &data)
|
|||||||
fprintf(stderr, "Wrong type for %s\n", bson_iterator_key(&iter));
|
fprintf(stderr, "Wrong type for %s\n", bson_iterator_key(&iter));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifndef RENDERER
|
|
||||||
else if (!strcmp(bson_iterator_key(&iter), "authors"))
|
else if (!strcmp(bson_iterator_key(&iter), "authors"))
|
||||||
{
|
{
|
||||||
if (bson_iterator_type(&iter) == BSON_OBJECT)
|
if (bson_iterator_type(&iter) == BSON_OBJECT)
|
||||||
@ -707,7 +706,6 @@ void GameSave::readOPS(const std::vector<char> &data)
|
|||||||
fprintf(stderr, "Wrong type for %s\n", bson_iterator_key(&iter));
|
fprintf(stderr, "Wrong type for %s\n", bson_iterator_key(&iter));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Read wall and fan data
|
//Read wall and fan data
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
#include <memory>
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdio>
|
|
||||||
#include <cassert>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#ifdef WIN
|
#ifdef WIN
|
||||||
# ifndef NOMINMAX
|
# ifndef NOMINMAX
|
||||||
# define NOMINMAX
|
# define NOMINMAX
|
||||||
@ -29,9 +25,6 @@
|
|||||||
# include <mach-o/dyld.h>
|
# include <mach-o/dyld.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Misc.h"
|
|
||||||
#include "client/Client.h"
|
|
||||||
|
|
||||||
namespace Platform
|
namespace Platform
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -59,37 +52,6 @@ ByteString GetCwd()
|
|||||||
return cwd;
|
return cwd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoRestart()
|
|
||||||
{
|
|
||||||
ByteString exename = ExecutableName();
|
|
||||||
if (exename.length())
|
|
||||||
{
|
|
||||||
#ifdef WIN
|
|
||||||
int ret = int(INT_PTR(ShellExecuteW(NULL, NULL, WinWiden(exename).c_str(), NULL, NULL, SW_SHOWNORMAL)));
|
|
||||||
if (ret <= 32)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "cannot restart: ShellExecute(...) failed: code %i\n", ret);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
# if !defined(RENDERER) && !defined(FONTEDITOR)
|
|
||||||
Client::Ref().Shutdown(); // very ugly hack; will fix soon(tm)
|
|
||||||
# endif
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
#elif defined(LIN) || defined(MACOSX)
|
|
||||||
execl(exename.c_str(), exename.c_str(), NULL);
|
|
||||||
int ret = errno;
|
|
||||||
fprintf(stderr, "cannot restart: execl(...) failed: code %i\n", ret);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(stderr, "cannot restart: no executable name???\n");
|
|
||||||
}
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenURI(ByteString uri)
|
void OpenURI(ByteString uri)
|
||||||
{
|
{
|
||||||
#if defined(WIN)
|
#if defined(WIN)
|
||||||
@ -309,141 +271,6 @@ std::vector<ByteString> DirectorySearch(ByteString directory, ByteString search,
|
|||||||
return searchResults;
|
return searchResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
String DoMigration(ByteString fromDir, ByteString toDir)
|
|
||||||
{
|
|
||||||
if (fromDir.at(fromDir.length() - 1) != '/')
|
|
||||||
fromDir = fromDir + '/';
|
|
||||||
if (toDir.at(toDir.length() - 1) != '/')
|
|
||||||
toDir = toDir + '/';
|
|
||||||
|
|
||||||
std::ofstream logFile(fromDir + "/migrationlog.txt", std::ios::out);
|
|
||||||
logFile << "Running migration of data from " << fromDir + " to " << toDir << std::endl;
|
|
||||||
|
|
||||||
// Get lists of files to migrate
|
|
||||||
auto stamps = DirectorySearch(fromDir + "stamps", "", { ".stm" });
|
|
||||||
auto saves = DirectorySearch(fromDir + "Saves", "", { ".cps", ".stm" });
|
|
||||||
auto scripts = DirectorySearch(fromDir + "scripts", "", { ".lua", ".txt" });
|
|
||||||
auto downloadedScripts = DirectorySearch(fromDir + "scripts/downloaded", "", { ".lua" });
|
|
||||||
bool hasScriptinfo = FileExists(toDir + "scripts/downloaded/scriptinfo");
|
|
||||||
auto screenshots = DirectorySearch(fromDir, "screenshot", { ".png" });
|
|
||||||
bool hasAutorun = FileExists(fromDir + "autorun.lua");
|
|
||||||
bool hasPref = FileExists(fromDir + "powder.pref");
|
|
||||||
|
|
||||||
if (stamps.empty() && saves.empty() && scripts.empty() && downloadedScripts.empty() && screenshots.empty() && !hasAutorun && !hasPref)
|
|
||||||
{
|
|
||||||
logFile << "Nothing to migrate.";
|
|
||||||
return "Nothing to migrate. This button is used to migrate data from pre-96.0 TPT installations to the shared directory";
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder result;
|
|
||||||
std::stack<ByteString> dirsToDelete;
|
|
||||||
|
|
||||||
// Migrate a list of files
|
|
||||||
auto migrateList = [&](std::vector<ByteString> list, ByteString directory, String niceName) {
|
|
||||||
result << '\n' << niceName << ": ";
|
|
||||||
if (!list.empty() && !directory.empty())
|
|
||||||
MakeDirectory(toDir + directory);
|
|
||||||
int migratedCount = 0, failedCount = 0;
|
|
||||||
for (auto &item : list)
|
|
||||||
{
|
|
||||||
std::string from = fromDir + directory + "/" + item;
|
|
||||||
std::string to = toDir + directory + "/" + item;
|
|
||||||
if (!FileExists(to))
|
|
||||||
{
|
|
||||||
if (rename(from.c_str(), to.c_str()))
|
|
||||||
{
|
|
||||||
failedCount++;
|
|
||||||
logFile << "failed to move " << from << " to " << to << std::endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
migratedCount++;
|
|
||||||
logFile << "moved " << from << " to " << to << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logFile << "skipping " << from << "(already exists)" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dirsToDelete.push(directory);
|
|
||||||
result << "\bt" << migratedCount << " migratated\x0E, \br" << failedCount << " failed\x0E";
|
|
||||||
int duplicates = list.size() - migratedCount - failedCount;
|
|
||||||
if (duplicates)
|
|
||||||
result << ", " << list.size() - migratedCount - failedCount << " skipped (duplicate)";
|
|
||||||
};
|
|
||||||
|
|
||||||
// Migrate a single file
|
|
||||||
auto migrateFile = [&fromDir, &toDir, &result, &logFile](ByteString filename) {
|
|
||||||
ByteString from = fromDir + filename;
|
|
||||||
ByteString to = toDir + filename;
|
|
||||||
if (!FileExists(to))
|
|
||||||
{
|
|
||||||
if (rename(from.c_str(), to.c_str()))
|
|
||||||
{
|
|
||||||
logFile << "failed to move " << from << " to " << to << std::endl;
|
|
||||||
result << "\n\br" << filename.FromUtf8() << " migration failed\x0E";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logFile << "moved " << from << " to " << to << std::endl;
|
|
||||||
result << '\n' << filename.FromUtf8() << " migrated";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logFile << "skipping " << from << "(already exists)" << std::endl;
|
|
||||||
result << '\n' << filename.FromUtf8() << " skipped (already exists)";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!RemoveFile(fromDir + filename)) {
|
|
||||||
logFile << "failed to delete " << filename << std::endl;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Do actual migration
|
|
||||||
RemoveFile(fromDir + "stamps/stamps.def");
|
|
||||||
migrateList(stamps, "stamps", "Stamps");
|
|
||||||
migrateList(saves, "Saves", "Saves");
|
|
||||||
if (!scripts.empty())
|
|
||||||
migrateList(scripts, "scripts", "Scripts");
|
|
||||||
if (!hasScriptinfo && !downloadedScripts.empty())
|
|
||||||
{
|
|
||||||
migrateList(downloadedScripts, "scripts/downloaded", "Downloaded scripts");
|
|
||||||
migrateFile("scripts/downloaded/scriptinfo");
|
|
||||||
}
|
|
||||||
if (!screenshots.empty())
|
|
||||||
migrateList(screenshots, "", "Screenshots");
|
|
||||||
if (hasAutorun)
|
|
||||||
migrateFile("autorun.lua");
|
|
||||||
if (hasPref)
|
|
||||||
migrateFile("powder.pref");
|
|
||||||
|
|
||||||
// Delete leftover directories
|
|
||||||
while (!dirsToDelete.empty())
|
|
||||||
{
|
|
||||||
ByteString toDelete = dirsToDelete.top();
|
|
||||||
if (!DeleteDirectory(fromDir + toDelete)) {
|
|
||||||
logFile << "failed to delete " << toDelete << std::endl;
|
|
||||||
}
|
|
||||||
dirsToDelete.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// chdir into the new directory
|
|
||||||
chdir(toDir.c_str());
|
|
||||||
|
|
||||||
#if !defined(RENDERER) && !defined(FONTEDITOR)
|
|
||||||
if (scripts.size())
|
|
||||||
Client::Ref().RescanStamps();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
logFile << std::endl << std::endl << "Migration complete. Results: " << result.Build().ToUtf8();
|
|
||||||
logFile.close();
|
|
||||||
|
|
||||||
return result.Build();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WIN
|
#ifdef WIN
|
||||||
ByteString WinNarrow(const std::wstring &source)
|
ByteString WinNarrow(const std::wstring &source)
|
||||||
{
|
{
|
||||||
|
187
src/common/PlatformPowder.cpp
Normal file
187
src/common/PlatformPowder.cpp
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
#include "Platform.h"
|
||||||
|
#include "client/Client.h"
|
||||||
|
#ifdef WIN
|
||||||
|
# ifndef NOMINMAX
|
||||||
|
# define NOMINMAX
|
||||||
|
# endif
|
||||||
|
# include <direct.h>
|
||||||
|
# include <io.h>
|
||||||
|
# include <shlobj.h>
|
||||||
|
# include <shlwapi.h>
|
||||||
|
# include <shellapi.h>
|
||||||
|
# include <windows.h>
|
||||||
|
#else
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <ctime>
|
||||||
|
# include <sys/time.h>
|
||||||
|
# include <dirent.h>
|
||||||
|
#endif
|
||||||
|
#ifdef MACOSX
|
||||||
|
# include <mach-o/dyld.h>
|
||||||
|
#endif
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
namespace Platform
|
||||||
|
{
|
||||||
|
void DoRestart()
|
||||||
|
{
|
||||||
|
ByteString exename = ExecutableName();
|
||||||
|
if (exename.length())
|
||||||
|
{
|
||||||
|
#ifdef WIN
|
||||||
|
int ret = int(INT_PTR(ShellExecuteW(NULL, NULL, WinWiden(exename).c_str(), NULL, NULL, SW_SHOWNORMAL)));
|
||||||
|
if (ret <= 32)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "cannot restart: ShellExecute(...) failed: code %i\n", ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Client::Ref().Shutdown(); // very ugly hack; will fix soon(tm)
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
#elif defined(LIN) || defined(MACOSX)
|
||||||
|
execl(exename.c_str(), exename.c_str(), NULL);
|
||||||
|
int ret = errno;
|
||||||
|
fprintf(stderr, "cannot restart: execl(...) failed: code %i\n", ret);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "cannot restart: no executable name???\n");
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
String DoMigration(ByteString fromDir, ByteString toDir)
|
||||||
|
{
|
||||||
|
if (fromDir.at(fromDir.length() - 1) != '/')
|
||||||
|
fromDir = fromDir + '/';
|
||||||
|
if (toDir.at(toDir.length() - 1) != '/')
|
||||||
|
toDir = toDir + '/';
|
||||||
|
|
||||||
|
std::ofstream logFile(fromDir + "/migrationlog.txt", std::ios::out);
|
||||||
|
logFile << "Running migration of data from " << fromDir + " to " << toDir << std::endl;
|
||||||
|
|
||||||
|
// Get lists of files to migrate
|
||||||
|
auto stamps = DirectorySearch(fromDir + "stamps", "", { ".stm" });
|
||||||
|
auto saves = DirectorySearch(fromDir + "Saves", "", { ".cps", ".stm" });
|
||||||
|
auto scripts = DirectorySearch(fromDir + "scripts", "", { ".lua", ".txt" });
|
||||||
|
auto downloadedScripts = DirectorySearch(fromDir + "scripts/downloaded", "", { ".lua" });
|
||||||
|
bool hasScriptinfo = FileExists(toDir + "scripts/downloaded/scriptinfo");
|
||||||
|
auto screenshots = DirectorySearch(fromDir, "screenshot", { ".png" });
|
||||||
|
bool hasAutorun = FileExists(fromDir + "autorun.lua");
|
||||||
|
bool hasPref = FileExists(fromDir + "powder.pref");
|
||||||
|
|
||||||
|
if (stamps.empty() && saves.empty() && scripts.empty() && downloadedScripts.empty() && screenshots.empty() && !hasAutorun && !hasPref)
|
||||||
|
{
|
||||||
|
logFile << "Nothing to migrate.";
|
||||||
|
return "Nothing to migrate. This button is used to migrate data from pre-96.0 TPT installations to the shared directory";
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder result;
|
||||||
|
std::stack<ByteString> dirsToDelete;
|
||||||
|
|
||||||
|
// Migrate a list of files
|
||||||
|
auto migrateList = [&](std::vector<ByteString> list, ByteString directory, String niceName) {
|
||||||
|
result << '\n' << niceName << ": ";
|
||||||
|
if (!list.empty() && !directory.empty())
|
||||||
|
MakeDirectory(toDir + directory);
|
||||||
|
int migratedCount = 0, failedCount = 0;
|
||||||
|
for (auto &item : list)
|
||||||
|
{
|
||||||
|
std::string from = fromDir + directory + "/" + item;
|
||||||
|
std::string to = toDir + directory + "/" + item;
|
||||||
|
if (!FileExists(to))
|
||||||
|
{
|
||||||
|
if (rename(from.c_str(), to.c_str()))
|
||||||
|
{
|
||||||
|
failedCount++;
|
||||||
|
logFile << "failed to move " << from << " to " << to << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
migratedCount++;
|
||||||
|
logFile << "moved " << from << " to " << to << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logFile << "skipping " << from << "(already exists)" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dirsToDelete.push(directory);
|
||||||
|
result << "\bt" << migratedCount << " migratated\x0E, \br" << failedCount << " failed\x0E";
|
||||||
|
int duplicates = list.size() - migratedCount - failedCount;
|
||||||
|
if (duplicates)
|
||||||
|
result << ", " << list.size() - migratedCount - failedCount << " skipped (duplicate)";
|
||||||
|
};
|
||||||
|
|
||||||
|
// Migrate a single file
|
||||||
|
auto migrateFile = [&fromDir, &toDir, &result, &logFile](ByteString filename) {
|
||||||
|
ByteString from = fromDir + filename;
|
||||||
|
ByteString to = toDir + filename;
|
||||||
|
if (!FileExists(to))
|
||||||
|
{
|
||||||
|
if (rename(from.c_str(), to.c_str()))
|
||||||
|
{
|
||||||
|
logFile << "failed to move " << from << " to " << to << std::endl;
|
||||||
|
result << "\n\br" << filename.FromUtf8() << " migration failed\x0E";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logFile << "moved " << from << " to " << to << std::endl;
|
||||||
|
result << '\n' << filename.FromUtf8() << " migrated";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logFile << "skipping " << from << "(already exists)" << std::endl;
|
||||||
|
result << '\n' << filename.FromUtf8() << " skipped (already exists)";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RemoveFile(fromDir + filename)) {
|
||||||
|
logFile << "failed to delete " << filename << std::endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Do actual migration
|
||||||
|
RemoveFile(fromDir + "stamps/stamps.def");
|
||||||
|
migrateList(stamps, "stamps", "Stamps");
|
||||||
|
migrateList(saves, "Saves", "Saves");
|
||||||
|
if (!scripts.empty())
|
||||||
|
migrateList(scripts, "scripts", "Scripts");
|
||||||
|
if (!hasScriptinfo && !downloadedScripts.empty())
|
||||||
|
{
|
||||||
|
migrateList(downloadedScripts, "scripts/downloaded", "Downloaded scripts");
|
||||||
|
migrateFile("scripts/downloaded/scriptinfo");
|
||||||
|
}
|
||||||
|
if (!screenshots.empty())
|
||||||
|
migrateList(screenshots, "", "Screenshots");
|
||||||
|
if (hasAutorun)
|
||||||
|
migrateFile("autorun.lua");
|
||||||
|
if (hasPref)
|
||||||
|
migrateFile("powder.pref");
|
||||||
|
|
||||||
|
// Delete leftover directories
|
||||||
|
while (!dirsToDelete.empty())
|
||||||
|
{
|
||||||
|
ByteString toDelete = dirsToDelete.top();
|
||||||
|
if (!DeleteDirectory(fromDir + toDelete)) {
|
||||||
|
logFile << "failed to delete " << toDelete << std::endl;
|
||||||
|
}
|
||||||
|
dirsToDelete.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// chdir into the new directory
|
||||||
|
chdir(toDir.c_str());
|
||||||
|
|
||||||
|
if (scripts.size())
|
||||||
|
Client::Ref().RescanStamps();
|
||||||
|
|
||||||
|
logFile << std::endl << std::endl << "Migration complete. Results: " << result.Build().ToUtf8();
|
||||||
|
logFile.close();
|
||||||
|
|
||||||
|
return result.Build();
|
||||||
|
}
|
||||||
|
}
|
@ -4,3 +4,7 @@ common_files += files(
|
|||||||
'tpt-rand.cpp',
|
'tpt-rand.cpp',
|
||||||
'tpt-thread-local.cpp',
|
'tpt-thread-local.cpp',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
powder_files += files(
|
||||||
|
'PlatformPowder.cpp',
|
||||||
|
)
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
font_conf_data = conf_data
|
|
||||||
font_conf_data.set('FONTEDITOR', true)
|
|
||||||
font_conf_data.set('RENDERER', false)
|
|
||||||
configure_file(
|
|
||||||
input: config_template,
|
|
||||||
output: 'Config.h',
|
|
||||||
configuration: font_conf_data
|
|
||||||
)
|
|
||||||
font_inc = include_directories('.')
|
|
@ -1,9 +0,0 @@
|
|||||||
if get_option('build_powder')
|
|
||||||
subdir('powder')
|
|
||||||
endif
|
|
||||||
if get_option('build_render')
|
|
||||||
subdir('render')
|
|
||||||
endif
|
|
||||||
if get_option('build_font')
|
|
||||||
subdir('font')
|
|
||||||
endif
|
|
@ -1,9 +0,0 @@
|
|||||||
powder_conf_data = conf_data
|
|
||||||
powder_conf_data.set('FONTEDITOR', false)
|
|
||||||
powder_conf_data.set('RENDERER', false)
|
|
||||||
configure_file(
|
|
||||||
input: config_template,
|
|
||||||
output: 'Config.h',
|
|
||||||
configuration: powder_conf_data
|
|
||||||
)
|
|
||||||
powder_inc = include_directories('.')
|
|
@ -1,9 +0,0 @@
|
|||||||
render_conf_data = conf_data
|
|
||||||
render_conf_data.set('FONTEDITOR', false)
|
|
||||||
render_conf_data.set('RENDERER', true)
|
|
||||||
configure_file(
|
|
||||||
input: config_template,
|
|
||||||
output: 'Config.h',
|
|
||||||
configuration: render_conf_data
|
|
||||||
)
|
|
||||||
render_inc = include_directories('.')
|
|
@ -1,16 +0,0 @@
|
|||||||
int drawtext(int x, int y, String s, int r, int g, int b, int a);
|
|
||||||
int drawchar(int x, int y, String::value_type c, int r, int g, int b, int a);
|
|
||||||
int addchar(int x, int y, String::value_type c, int r, int g, int b, int a);
|
|
||||||
|
|
||||||
void xor_pixel(int x, int y);
|
|
||||||
void xor_line(int x, int y, int x2, int y2);
|
|
||||||
void xor_rect(int x, int y, int width, int height);
|
|
||||||
void xor_bitmap(unsigned char * bitmap, int x, int y, int w, int h);
|
|
||||||
|
|
||||||
void draw_line(int x, int y, int x2, int y2, int r, int g, int b, int a);
|
|
||||||
void drawrect(int x, int y, int width, int height, int r, int g, int b, int a);
|
|
||||||
void fillrect(int x, int y, int width, int height, int r, int g, int b, int a);
|
|
||||||
void clearrect(int x, int y, int width, int height);
|
|
||||||
void gradientrect(int x, int y, int width, int height, int r, int g, int b, int a, int r2, int g2, int b2, int a2);
|
|
||||||
|
|
||||||
void draw_image(pixel *img, int x, int y, int w, int h, int a);
|
|
@ -30,6 +30,4 @@ constexpr auto VIDYRES = WINDOWH;
|
|||||||
#define PIXELMETHODS_CLASS Graphics
|
#define PIXELMETHODS_CLASS Graphics
|
||||||
#define DO_CLIPCHECK
|
#define DO_CLIPCHECK
|
||||||
#include "RasterDrawMethods.inl"
|
#include "RasterDrawMethods.inl"
|
||||||
#undef VIDYRES
|
|
||||||
#undef VIDXRES
|
|
||||||
#undef PIXELMETHODS_CLASS
|
#undef PIXELMETHODS_CLASS
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,7 @@
|
|||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#include "Graphics.h"
|
#include "Graphics.h"
|
||||||
#include "gui/interface/Point.h"
|
#include "gui/interface/Point.h"
|
||||||
@ -31,6 +32,8 @@ struct gcache_item
|
|||||||
};
|
};
|
||||||
typedef struct gcache_item gcache_item;
|
typedef struct gcache_item gcache_item;
|
||||||
|
|
||||||
|
int HeatToColour(float temp);
|
||||||
|
|
||||||
class Renderer
|
class Renderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
532
src/graphics/RendererBasic.cpp
Normal file
532
src/graphics/RendererBasic.cpp
Normal file
@ -0,0 +1,532 @@
|
|||||||
|
#include "Renderer.h"
|
||||||
|
#include <cmath>
|
||||||
|
#include "gui/game/RenderPreset.h"
|
||||||
|
#include "simulation/Simulation.h"
|
||||||
|
#include "simulation/ElementGraphics.h"
|
||||||
|
#include "simulation/ElementClasses.h"
|
||||||
|
|
||||||
|
constexpr auto VIDXRES = WINDOWW;
|
||||||
|
constexpr auto VIDYRES = WINDOWH;
|
||||||
|
|
||||||
|
void Renderer::RenderBegin()
|
||||||
|
{
|
||||||
|
if(display_mode & DISPLAY_PERS)
|
||||||
|
{
|
||||||
|
std::copy(persistentVid, persistentVid+(VIDXRES*YRES), vid);
|
||||||
|
}
|
||||||
|
pixel * oldVid = NULL;
|
||||||
|
if(display_mode & DISPLAY_WARP)
|
||||||
|
{
|
||||||
|
oldVid = vid;
|
||||||
|
vid = warpVid;
|
||||||
|
std::fill(warpVid, warpVid+(VIDXRES*VIDYRES), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_air();
|
||||||
|
draw_grav();
|
||||||
|
DrawWalls();
|
||||||
|
render_parts();
|
||||||
|
|
||||||
|
if(display_mode & DISPLAY_PERS)
|
||||||
|
{
|
||||||
|
int i,r,g,b;
|
||||||
|
for (i = 0; i < VIDXRES*YRES; i++)
|
||||||
|
{
|
||||||
|
r = PIXR(vid[i]);
|
||||||
|
g = PIXG(vid[i]);
|
||||||
|
b = PIXB(vid[i]);
|
||||||
|
if (r>0)
|
||||||
|
r--;
|
||||||
|
if (g>0)
|
||||||
|
g--;
|
||||||
|
if (b>0)
|
||||||
|
b--;
|
||||||
|
persistentVid[i] = PIXRGB(r,g,b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render_fire();
|
||||||
|
draw_other();
|
||||||
|
draw_grav_zones();
|
||||||
|
DrawSigns();
|
||||||
|
|
||||||
|
if(display_mode & DISPLAY_WARP)
|
||||||
|
{
|
||||||
|
vid = oldVid;
|
||||||
|
}
|
||||||
|
|
||||||
|
FinaliseParts();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::RenderEnd()
|
||||||
|
{
|
||||||
|
RenderZoom();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::SetSample(int x, int y)
|
||||||
|
{
|
||||||
|
sampleColor = GetPixel(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::clearScreen(float alpha)
|
||||||
|
{
|
||||||
|
g->Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::FinaliseParts()
|
||||||
|
{
|
||||||
|
if(display_mode & DISPLAY_WARP)
|
||||||
|
{
|
||||||
|
render_gravlensing(warpVid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::RenderZoom()
|
||||||
|
{
|
||||||
|
if(!zoomEnabled)
|
||||||
|
return;
|
||||||
|
{
|
||||||
|
int x, y, i, j;
|
||||||
|
pixel pix;
|
||||||
|
pixel * img = vid;
|
||||||
|
clearrect(zoomWindowPosition.X-1, zoomWindowPosition.Y-1, zoomScopeSize*ZFACTOR+1, zoomScopeSize*ZFACTOR+1);
|
||||||
|
drawrect(zoomWindowPosition.X-2, zoomWindowPosition.Y-2, zoomScopeSize*ZFACTOR+3, zoomScopeSize*ZFACTOR+3, 192, 192, 192, 255);
|
||||||
|
drawrect(zoomWindowPosition.X-1, zoomWindowPosition.Y-1, zoomScopeSize*ZFACTOR+1, zoomScopeSize*ZFACTOR+1, 0, 0, 0, 255);
|
||||||
|
for (j=0; j<zoomScopeSize; j++)
|
||||||
|
for (i=0; i<zoomScopeSize; i++)
|
||||||
|
{
|
||||||
|
pix = img[(j+zoomScopePosition.Y)*(VIDXRES)+(i+zoomScopePosition.X)];
|
||||||
|
for (y=0; y<ZFACTOR-1; y++)
|
||||||
|
for (x=0; x<ZFACTOR-1; x++)
|
||||||
|
img[(j*ZFACTOR+y+zoomWindowPosition.Y)*(VIDXRES)+(i*ZFACTOR+x+zoomWindowPosition.X)] = pix;
|
||||||
|
}
|
||||||
|
if (zoomEnabled)
|
||||||
|
{
|
||||||
|
for (j=-1; j<=zoomScopeSize; j++)
|
||||||
|
{
|
||||||
|
xor_pixel(zoomScopePosition.X+j, zoomScopePosition.Y-1);
|
||||||
|
xor_pixel(zoomScopePosition.X+j, zoomScopePosition.Y+zoomScopeSize);
|
||||||
|
}
|
||||||
|
for (j=0; j<zoomScopeSize; j++)
|
||||||
|
{
|
||||||
|
xor_pixel(zoomScopePosition.X-1, zoomScopePosition.Y+j);
|
||||||
|
xor_pixel(zoomScopePosition.X+zoomScopeSize, zoomScopePosition.Y+j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::DrawBlob(int x, int y, unsigned char cr, unsigned char cg, unsigned char cb)
|
||||||
|
{
|
||||||
|
blendpixel(x+1, y, cr, cg, cb, 112);
|
||||||
|
blendpixel(x-1, y, cr, cg, cb, 112);
|
||||||
|
blendpixel(x, y+1, cr, cg, cb, 112);
|
||||||
|
blendpixel(x, y-1, cr, cg, cb, 112);
|
||||||
|
|
||||||
|
blendpixel(x+1, y-1, cr, cg, cb, 64);
|
||||||
|
blendpixel(x-1, y-1, cr, cg, cb, 64);
|
||||||
|
blendpixel(x+1, y+1, cr, cg, cb, 64);
|
||||||
|
blendpixel(x-1, y+1, cr, cg, cb, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::render_gravlensing(pixel * source)
|
||||||
|
{
|
||||||
|
int nx, ny, rx, ry, gx, gy, bx, by, co;
|
||||||
|
int r, g, b;
|
||||||
|
pixel t;
|
||||||
|
pixel *src = source;
|
||||||
|
pixel *dst = vid;
|
||||||
|
if (!dst)
|
||||||
|
return;
|
||||||
|
for(nx = 0; nx < XRES; nx++)
|
||||||
|
{
|
||||||
|
for(ny = 0; ny < YRES; ny++)
|
||||||
|
{
|
||||||
|
co = (ny/CELL)*XCELLS+(nx/CELL);
|
||||||
|
rx = (int)(nx-sim->gravx[co]*0.75f+0.5f);
|
||||||
|
ry = (int)(ny-sim->gravy[co]*0.75f+0.5f);
|
||||||
|
gx = (int)(nx-sim->gravx[co]*0.875f+0.5f);
|
||||||
|
gy = (int)(ny-sim->gravy[co]*0.875f+0.5f);
|
||||||
|
bx = (int)(nx-sim->gravx[co]+0.5f);
|
||||||
|
by = (int)(ny-sim->gravy[co]+0.5f);
|
||||||
|
if(rx >= 0 && rx < XRES && ry >= 0 && ry < YRES && gx >= 0 && gx < XRES && gy >= 0 && gy < YRES && bx >= 0 && bx < XRES && by >= 0 && by < YRES)
|
||||||
|
{
|
||||||
|
t = dst[ny*(VIDXRES)+nx];
|
||||||
|
r = PIXR(src[ry*(VIDXRES)+rx]) + PIXR(t);
|
||||||
|
g = PIXG(src[gy*(VIDXRES)+gx]) + PIXG(t);
|
||||||
|
b = PIXB(src[by*(VIDXRES)+bx]) + PIXB(t);
|
||||||
|
if (r>255)
|
||||||
|
r = 255;
|
||||||
|
if (g>255)
|
||||||
|
g = 255;
|
||||||
|
if (b>255)
|
||||||
|
b = 255;
|
||||||
|
dst[ny*(VIDXRES)+nx] = PIXRGB(r,g,b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float temp[CELL*3][CELL*3];
|
||||||
|
float fire_alphaf[CELL*3][CELL*3];
|
||||||
|
float glow_alphaf[11][11];
|
||||||
|
float blur_alphaf[7][7];
|
||||||
|
void Renderer::prepare_alpha(int size, float intensity)
|
||||||
|
{
|
||||||
|
//TODO: implement size
|
||||||
|
int x,y,i,j;
|
||||||
|
float multiplier = 255.0f*intensity;
|
||||||
|
|
||||||
|
memset(temp, 0, sizeof(temp));
|
||||||
|
for (x=0; x<CELL; x++)
|
||||||
|
for (y=0; y<CELL; y++)
|
||||||
|
for (i=-CELL; i<CELL; i++)
|
||||||
|
for (j=-CELL; j<CELL; j++)
|
||||||
|
temp[y+CELL+j][x+CELL+i] += expf(-0.1f*(i*i+j*j));
|
||||||
|
for (x=0; x<CELL*3; x++)
|
||||||
|
for (y=0; y<CELL*3; y++)
|
||||||
|
fire_alpha[y][x] = (int)(multiplier*temp[y][x]/(CELL*CELL));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::drawblob(int x, int y, unsigned char cr, unsigned char cg, unsigned char cb)
|
||||||
|
{
|
||||||
|
blendpixel(x+1, y, cr, cg, cb, 112);
|
||||||
|
blendpixel(x-1, y, cr, cg, cb, 112);
|
||||||
|
blendpixel(x, y+1, cr, cg, cb, 112);
|
||||||
|
blendpixel(x, y-1, cr, cg, cb, 112);
|
||||||
|
|
||||||
|
blendpixel(x+1, y-1, cr, cg, cb, 64);
|
||||||
|
blendpixel(x-1, y-1, cr, cg, cb, 64);
|
||||||
|
blendpixel(x+1, y+1, cr, cg, cb, 64);
|
||||||
|
blendpixel(x-1, y+1, cr, cg, cb, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel Renderer::GetPixel(int x, int y)
|
||||||
|
{
|
||||||
|
if (x<0 || y<0 || x>=VIDXRES || y>=VIDYRES)
|
||||||
|
return 0;
|
||||||
|
return vid[(y*VIDXRES)+x];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<pixel> Renderer::flameTable;
|
||||||
|
std::vector<pixel> Renderer::plasmaTable;
|
||||||
|
std::vector<pixel> Renderer::heatTable;
|
||||||
|
std::vector<pixel> Renderer::clfmTable;
|
||||||
|
std::vector<pixel> Renderer::firwTable;
|
||||||
|
static bool tablesPopulated = false;
|
||||||
|
static std::mutex tablesPopulatedMx;
|
||||||
|
void Renderer::PopulateTables()
|
||||||
|
{
|
||||||
|
std::lock_guard g(tablesPopulatedMx);
|
||||||
|
if (!tablesPopulated)
|
||||||
|
{
|
||||||
|
tablesPopulated = true;
|
||||||
|
flameTable = Graphics::Gradient({
|
||||||
|
{ 0x000000, 0.00f },
|
||||||
|
{ 0x60300F, 0.50f },
|
||||||
|
{ 0xDFBF6F, 0.90f },
|
||||||
|
{ 0xAF9F0F, 1.00f },
|
||||||
|
}, 200);
|
||||||
|
plasmaTable = Graphics::Gradient({
|
||||||
|
{ 0x000000, 0.00f },
|
||||||
|
{ 0x301040, 0.25f },
|
||||||
|
{ 0x301060, 0.50f },
|
||||||
|
{ 0xAFFFFF, 0.90f },
|
||||||
|
{ 0xAFFFFF, 1.00f },
|
||||||
|
}, 200);
|
||||||
|
heatTable = Graphics::Gradient({
|
||||||
|
{ 0x2B00FF, 0.00f },
|
||||||
|
{ 0x003CFF, 0.01f },
|
||||||
|
{ 0x00C0FF, 0.05f },
|
||||||
|
{ 0x00FFEB, 0.08f },
|
||||||
|
{ 0x00FF14, 0.19f },
|
||||||
|
{ 0x4BFF00, 0.25f },
|
||||||
|
{ 0xC8FF00, 0.37f },
|
||||||
|
{ 0xFFDC00, 0.45f },
|
||||||
|
{ 0xFF0000, 0.71f },
|
||||||
|
{ 0xFF00DC, 1.00f },
|
||||||
|
}, 1024);
|
||||||
|
clfmTable = Graphics::Gradient({
|
||||||
|
{ 0x000000, 0.00f },
|
||||||
|
{ 0x0A0917, 0.10f },
|
||||||
|
{ 0x19163C, 0.20f },
|
||||||
|
{ 0x28285E, 0.30f },
|
||||||
|
{ 0x343E77, 0.40f },
|
||||||
|
{ 0x49769A, 0.60f },
|
||||||
|
{ 0x57A0B4, 0.80f },
|
||||||
|
{ 0x5EC4C6, 1.00f },
|
||||||
|
}, 200);
|
||||||
|
firwTable = Graphics::Gradient({
|
||||||
|
{ 0xFF00FF, 0.00f },
|
||||||
|
{ 0x0000FF, 0.20f },
|
||||||
|
{ 0x00FFFF, 0.40f },
|
||||||
|
{ 0x00FF00, 0.60f },
|
||||||
|
{ 0xFFFF00, 0.80f },
|
||||||
|
{ 0xFF0000, 1.00f },
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer::Renderer(Graphics * g, Simulation * sim):
|
||||||
|
sim(NULL),
|
||||||
|
g(NULL),
|
||||||
|
render_mode(0),
|
||||||
|
colour_mode(0),
|
||||||
|
display_mode(0),
|
||||||
|
gravityZonesEnabled(false),
|
||||||
|
gravityFieldEnabled(false),
|
||||||
|
decorations_enable(1),
|
||||||
|
blackDecorations(false),
|
||||||
|
debugLines(false),
|
||||||
|
sampleColor(0xFFFFFFFF),
|
||||||
|
findingElement(0),
|
||||||
|
foundElements(0),
|
||||||
|
mousePos(0, 0),
|
||||||
|
zoomWindowPosition(0, 0),
|
||||||
|
zoomScopePosition(0, 0),
|
||||||
|
zoomScopeSize(32),
|
||||||
|
zoomEnabled(false),
|
||||||
|
ZFACTOR(8),
|
||||||
|
gridSize(0)
|
||||||
|
{
|
||||||
|
PopulateTables();
|
||||||
|
|
||||||
|
this->g = g;
|
||||||
|
this->sim = sim;
|
||||||
|
vid = g->vid;
|
||||||
|
persistentVid = new pixel[VIDXRES*YRES];
|
||||||
|
warpVid = new pixel[VIDXRES*VIDYRES];
|
||||||
|
|
||||||
|
memset(fire_r, 0, sizeof(fire_r));
|
||||||
|
memset(fire_g, 0, sizeof(fire_g));
|
||||||
|
memset(fire_b, 0, sizeof(fire_b));
|
||||||
|
|
||||||
|
//Set defauly display modes
|
||||||
|
ResetModes();
|
||||||
|
|
||||||
|
//Render mode presets. Possibly load from config in future?
|
||||||
|
renderModePresets.push_back({
|
||||||
|
"Alternative Velocity Display",
|
||||||
|
{ RENDER_EFFE, RENDER_BASC },
|
||||||
|
{ DISPLAY_AIRC },
|
||||||
|
0
|
||||||
|
});
|
||||||
|
renderModePresets.push_back({
|
||||||
|
"Velocity Display",
|
||||||
|
{ RENDER_EFFE, RENDER_BASC },
|
||||||
|
{ DISPLAY_AIRV },
|
||||||
|
0
|
||||||
|
});
|
||||||
|
renderModePresets.push_back({
|
||||||
|
"Pressure Display",
|
||||||
|
{ RENDER_EFFE, RENDER_BASC },
|
||||||
|
{ DISPLAY_AIRP },
|
||||||
|
0
|
||||||
|
});
|
||||||
|
renderModePresets.push_back({
|
||||||
|
"Persistent Display",
|
||||||
|
{ RENDER_EFFE, RENDER_BASC },
|
||||||
|
{ DISPLAY_PERS },
|
||||||
|
0
|
||||||
|
});
|
||||||
|
renderModePresets.push_back({
|
||||||
|
"Fire Display",
|
||||||
|
{ RENDER_FIRE, RENDER_SPRK, RENDER_EFFE, RENDER_BASC },
|
||||||
|
{ },
|
||||||
|
0
|
||||||
|
});
|
||||||
|
renderModePresets.push_back({
|
||||||
|
"Blob Display",
|
||||||
|
{ RENDER_FIRE, RENDER_SPRK, RENDER_EFFE, RENDER_BLOB },
|
||||||
|
{ },
|
||||||
|
0
|
||||||
|
});
|
||||||
|
renderModePresets.push_back({
|
||||||
|
"Heat Display",
|
||||||
|
{ RENDER_BASC },
|
||||||
|
{ DISPLAY_AIRH },
|
||||||
|
COLOUR_HEAT
|
||||||
|
});
|
||||||
|
renderModePresets.push_back({
|
||||||
|
"Fancy Display",
|
||||||
|
{ RENDER_FIRE, RENDER_SPRK, RENDER_GLOW, RENDER_BLUR, RENDER_EFFE, RENDER_BASC },
|
||||||
|
{ DISPLAY_WARP },
|
||||||
|
0
|
||||||
|
});
|
||||||
|
renderModePresets.push_back({
|
||||||
|
"Nothing Display",
|
||||||
|
{ RENDER_BASC },
|
||||||
|
{ },
|
||||||
|
0
|
||||||
|
});
|
||||||
|
renderModePresets.push_back({
|
||||||
|
"Heat Gradient Display",
|
||||||
|
{ RENDER_BASC },
|
||||||
|
{ },
|
||||||
|
COLOUR_GRAD
|
||||||
|
});
|
||||||
|
renderModePresets.push_back({
|
||||||
|
"Life Gradient Display",
|
||||||
|
{ RENDER_BASC },
|
||||||
|
{ },
|
||||||
|
COLOUR_LIFE
|
||||||
|
});
|
||||||
|
|
||||||
|
//Prepare the graphics cache
|
||||||
|
graphicscache = new gcache_item[PT_NUM];
|
||||||
|
std::fill(&graphicscache[0], &graphicscache[0] + PT_NUM, gcache_item());
|
||||||
|
|
||||||
|
prepare_alpha(CELL, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::CompileRenderMode()
|
||||||
|
{
|
||||||
|
int old_render_mode = render_mode;
|
||||||
|
render_mode = 0;
|
||||||
|
for (size_t i = 0; i < render_modes.size(); i++)
|
||||||
|
render_mode |= render_modes[i];
|
||||||
|
|
||||||
|
//If firemode is removed, clear the fire display
|
||||||
|
if(!(render_mode & FIREMODE) && (old_render_mode & FIREMODE))
|
||||||
|
{
|
||||||
|
ClearAccumulation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::ClearAccumulation()
|
||||||
|
{
|
||||||
|
std::fill(&fire_r[0][0], &fire_r[0][0] + NCELL, 0);
|
||||||
|
std::fill(&fire_g[0][0], &fire_g[0][0] + NCELL, 0);
|
||||||
|
std::fill(&fire_b[0][0], &fire_b[0][0] + NCELL, 0);
|
||||||
|
std::fill(persistentVid, persistentVid+(VIDXRES*YRES), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::AddRenderMode(unsigned int mode)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < render_modes.size(); i++)
|
||||||
|
{
|
||||||
|
if(render_modes[i] == mode)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render_modes.push_back(mode);
|
||||||
|
CompileRenderMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::RemoveRenderMode(unsigned int mode)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < render_modes.size(); i++)
|
||||||
|
{
|
||||||
|
if(render_modes[i] == mode)
|
||||||
|
{
|
||||||
|
render_modes.erase(render_modes.begin() + i);
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CompileRenderMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::SetRenderMode(std::vector<unsigned int> render)
|
||||||
|
{
|
||||||
|
render_modes = render;
|
||||||
|
CompileRenderMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned int> Renderer::GetRenderMode()
|
||||||
|
{
|
||||||
|
return render_modes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::CompileDisplayMode()
|
||||||
|
{
|
||||||
|
int old_display_mode = display_mode;
|
||||||
|
display_mode = 0;
|
||||||
|
for (size_t i = 0; i < display_modes.size(); i++)
|
||||||
|
display_mode |= display_modes[i];
|
||||||
|
if (!(display_mode & DISPLAY_PERS) && (old_display_mode & DISPLAY_PERS))
|
||||||
|
{
|
||||||
|
ClearAccumulation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::AddDisplayMode(unsigned int mode)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < display_modes.size(); i++)
|
||||||
|
{
|
||||||
|
if (display_modes[i] == mode)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (display_modes[i] & DISPLAY_AIR)
|
||||||
|
{
|
||||||
|
display_modes.erase(display_modes.begin()+i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
display_modes.push_back(mode);
|
||||||
|
CompileDisplayMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::RemoveDisplayMode(unsigned int mode)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < display_modes.size(); i++)
|
||||||
|
{
|
||||||
|
if (display_modes[i] == mode)
|
||||||
|
{
|
||||||
|
display_modes.erase(display_modes.begin() + i);
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CompileDisplayMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::SetDisplayMode(std::vector<unsigned int> display)
|
||||||
|
{
|
||||||
|
display_modes = display;
|
||||||
|
CompileDisplayMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned int> Renderer::GetDisplayMode()
|
||||||
|
{
|
||||||
|
return display_modes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::SetColourMode(unsigned int mode)
|
||||||
|
{
|
||||||
|
colour_mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Renderer::GetColourMode()
|
||||||
|
{
|
||||||
|
return colour_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::ResetModes()
|
||||||
|
{
|
||||||
|
SetRenderMode({ RENDER_BASC, RENDER_FIRE, RENDER_SPRK, RENDER_EFFE });
|
||||||
|
SetDisplayMode({ });
|
||||||
|
SetColourMode(COLOUR_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoBuffer Renderer::DumpFrame()
|
||||||
|
{
|
||||||
|
VideoBuffer newBuffer(XRES, YRES);
|
||||||
|
for(int y = 0; y < YRES; y++)
|
||||||
|
{
|
||||||
|
std::copy(vid+(y*WINDOWW), vid+(y*WINDOWW)+XRES, newBuffer.Buffer+(y*XRES));
|
||||||
|
}
|
||||||
|
return newBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer::~Renderer()
|
||||||
|
{
|
||||||
|
delete[] persistentVid;
|
||||||
|
delete[] warpVid;
|
||||||
|
delete[] graphicscache;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PIXELMETHODS_CLASS Renderer
|
||||||
|
#include "RasterDrawMethods.inl"
|
||||||
|
#undef PIXELMETHODS_CLASS
|
33
src/graphics/RendererFont.cpp
Normal file
33
src/graphics/RendererFont.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include "Renderer.h"
|
||||||
|
|
||||||
|
void Renderer::draw_air()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::draw_grav()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::DrawWalls()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::render_parts()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::render_fire()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::draw_other()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::draw_grav_zones()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::DrawSigns()
|
||||||
|
{
|
||||||
|
}
|
@ -1,11 +1,17 @@
|
|||||||
graphics_files = files(
|
graphics_files = files(
|
||||||
'Graphics.cpp',
|
'Graphics.cpp',
|
||||||
#'OpenGLGraphics.cpp', # this is defunct right now
|
|
||||||
'RasterGraphics.cpp',
|
'RasterGraphics.cpp',
|
||||||
'FontReader.cpp',
|
'FontReader.cpp',
|
||||||
|
)
|
||||||
|
powder_graphics_files = files(
|
||||||
|
'RendererBasic.cpp',
|
||||||
'Renderer.cpp',
|
'Renderer.cpp',
|
||||||
)
|
)
|
||||||
|
font_graphics_files = files(
|
||||||
|
'RendererBasic.cpp',
|
||||||
|
'RendererFont.cpp',
|
||||||
|
)
|
||||||
|
|
||||||
powder_files += graphics_files
|
powder_files += graphics_files + powder_graphics_files
|
||||||
render_files += graphics_files
|
render_files += graphics_files + powder_graphics_files
|
||||||
font_files += graphics_files
|
font_files += graphics_files + font_graphics_files
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "common/Platform.h"
|
#include "common/Platform.h"
|
||||||
#include "graphics/Graphics.h"
|
#include "graphics/Graphics.h"
|
||||||
|
#include "graphics/Renderer.h"
|
||||||
#include "gui/Style.h"
|
#include "gui/Style.h"
|
||||||
#include "simulation/ElementDefs.h"
|
#include "simulation/ElementDefs.h"
|
||||||
|
|
||||||
@ -438,7 +439,6 @@ void OptionsView::UpdateAmbientAirTempPreview(float airTemp, bool isValid)
|
|||||||
{
|
{
|
||||||
if (isValid)
|
if (isValid)
|
||||||
{
|
{
|
||||||
int HeatToColour(float temp);
|
|
||||||
int c = HeatToColour(airTemp);
|
int c = HeatToColour(airTemp);
|
||||||
ambientAirTempPreview->Appearance.BackgroundInactive = ui::Colour(PIXR(c), PIXG(c), PIXB(c));
|
ambientAirTempPreview->Appearance.BackgroundInactive = ui::Colour(PIXR(c), PIXG(c), PIXB(c));
|
||||||
ambientAirTempPreview->SetText("");
|
ambientAirTempPreview->SetText("");
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
config_template = files('Config.template.h')
|
configure_file(
|
||||||
subdir('config')
|
input: 'Config.template.h',
|
||||||
|
output: 'Config.h',
|
||||||
|
configuration: conf_data
|
||||||
|
)
|
||||||
|
|
||||||
powder_files = files(
|
powder_files = files(
|
||||||
'SDLCompat.cpp',
|
'SDLCompat.cpp',
|
||||||
|
720
src/simulation/Editing.cpp
Normal file
720
src/simulation/Editing.cpp
Normal file
@ -0,0 +1,720 @@
|
|||||||
|
#include "Simulation.h"
|
||||||
|
#include "client/Client.h"
|
||||||
|
#include "ElementClasses.h"
|
||||||
|
#include "graphics/Renderer.h"
|
||||||
|
#include "gui/game/Brush.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
void Simulation::ApplyDecoration(int x, int y, int colR_, int colG_, int colB_, int colA_, int mode)
|
||||||
|
{
|
||||||
|
int rp;
|
||||||
|
float tr, tg, tb, ta, colR = float(colR_), colG = float(colG_), colB = float(colB_), colA = float(colA_);
|
||||||
|
float strength = 0.01f;
|
||||||
|
rp = pmap[y][x];
|
||||||
|
if (!rp)
|
||||||
|
rp = photons[y][x];
|
||||||
|
if (!rp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ta = float((parts[ID(rp)].dcolour>>24)&0xFF);
|
||||||
|
tr = float((parts[ID(rp)].dcolour>>16)&0xFF);
|
||||||
|
tg = float((parts[ID(rp)].dcolour>>8)&0xFF);
|
||||||
|
tb = float((parts[ID(rp)].dcolour)&0xFF);
|
||||||
|
|
||||||
|
ta /= 255.0f; tr /= 255.0f; tg /= 255.0f; tb /= 255.0f;
|
||||||
|
colR /= 255.0f; colG /= 255.0f; colB /= 255.0f; colA /= 255.0f;
|
||||||
|
|
||||||
|
if (mode == DECO_DRAW)
|
||||||
|
{
|
||||||
|
ta = colA;
|
||||||
|
tr = colR;
|
||||||
|
tg = colG;
|
||||||
|
tb = colB;
|
||||||
|
}
|
||||||
|
else if (mode == DECO_CLEAR)
|
||||||
|
{
|
||||||
|
ta = tr = tg = tb = 0.0f;
|
||||||
|
}
|
||||||
|
else if (mode == DECO_ADD)
|
||||||
|
{
|
||||||
|
//ta += (colA*strength)*colA;
|
||||||
|
tr += (colR*strength)*colA;
|
||||||
|
tg += (colG*strength)*colA;
|
||||||
|
tb += (colB*strength)*colA;
|
||||||
|
}
|
||||||
|
else if (mode == DECO_SUBTRACT)
|
||||||
|
{
|
||||||
|
//ta -= (colA*strength)*colA;
|
||||||
|
tr -= (colR*strength)*colA;
|
||||||
|
tg -= (colG*strength)*colA;
|
||||||
|
tb -= (colB*strength)*colA;
|
||||||
|
}
|
||||||
|
else if (mode == DECO_MULTIPLY)
|
||||||
|
{
|
||||||
|
tr *= 1.0f+(colR*strength)*colA;
|
||||||
|
tg *= 1.0f+(colG*strength)*colA;
|
||||||
|
tb *= 1.0f+(colB*strength)*colA;
|
||||||
|
}
|
||||||
|
else if (mode == DECO_DIVIDE)
|
||||||
|
{
|
||||||
|
tr /= 1.0f+(colR*strength)*colA;
|
||||||
|
tg /= 1.0f+(colG*strength)*colA;
|
||||||
|
tb /= 1.0f+(colB*strength)*colA;
|
||||||
|
}
|
||||||
|
else if (mode == DECO_SMUDGE)
|
||||||
|
{
|
||||||
|
if (x >= CELL && x < XRES-CELL && y >= CELL && y < YRES-CELL)
|
||||||
|
{
|
||||||
|
float tas = 0.0f, trs = 0.0f, tgs = 0.0f, tbs = 0.0f;
|
||||||
|
|
||||||
|
int rx, ry;
|
||||||
|
float num = 0;
|
||||||
|
for (rx=-2; rx<3; rx++)
|
||||||
|
for (ry=-2; ry<3; ry++)
|
||||||
|
{
|
||||||
|
if (abs(rx)+abs(ry) > 2 && TYP(pmap[y+ry][x+rx]) && parts[ID(pmap[y+ry][x+rx])].dcolour)
|
||||||
|
{
|
||||||
|
Particle part = parts[ID(pmap[y+ry][x+rx])];
|
||||||
|
num += 1.0f;
|
||||||
|
float pa = ((float)((part.dcolour>>24)&0xFF)) / 255.f;
|
||||||
|
float pr = ((float)((part.dcolour>>16)&0xFF)) / 255.f;
|
||||||
|
float pg = ((float)((part.dcolour>> 8)&0xFF)) / 255.f;
|
||||||
|
float pb = ((float)((part.dcolour )&0xFF)) / 255.f;
|
||||||
|
switch (deco_space)
|
||||||
|
{
|
||||||
|
case 0: // sRGB
|
||||||
|
pa = (pa <= 0.04045f) ? (pa / 12.92f) : pow((pa + 0.055f) / 1.055f, 2.4f);
|
||||||
|
pr = (pr <= 0.04045f) ? (pr / 12.92f) : pow((pr + 0.055f) / 1.055f, 2.4f);
|
||||||
|
pg = (pg <= 0.04045f) ? (pg / 12.92f) : pow((pg + 0.055f) / 1.055f, 2.4f);
|
||||||
|
pb = (pb <= 0.04045f) ? (pb / 12.92f) : pow((pb + 0.055f) / 1.055f, 2.4f);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // linear
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // Gamma = 2.2
|
||||||
|
pa = pow(pa, 2.2f);
|
||||||
|
pr = pow(pr, 2.2f);
|
||||||
|
pg = pow(pg, 2.2f);
|
||||||
|
pb = pow(pb, 2.2f);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // Gamma = 1.8
|
||||||
|
pa = pow(pa, 1.8f);
|
||||||
|
pr = pow(pr, 1.8f);
|
||||||
|
pg = pow(pg, 1.8f);
|
||||||
|
pb = pow(pb, 1.8f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tas += pa;
|
||||||
|
trs += pr;
|
||||||
|
tgs += pg;
|
||||||
|
tbs += pb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (num == 0)
|
||||||
|
return;
|
||||||
|
ta = tas / num;
|
||||||
|
tr = trs / num;
|
||||||
|
tg = tgs / num;
|
||||||
|
tb = tbs / num;
|
||||||
|
switch (deco_space)
|
||||||
|
{
|
||||||
|
case 0: // sRGB
|
||||||
|
ta = (ta <= 0.0031308f) ? (ta * 12.92f) : (1.055f * pow(ta, 1.f / 2.4f) - 0.055f);
|
||||||
|
tr = (tr <= 0.0031308f) ? (tr * 12.92f) : (1.055f * pow(tr, 1.f / 2.4f) - 0.055f);
|
||||||
|
tg = (tg <= 0.0031308f) ? (tg * 12.92f) : (1.055f * pow(tg, 1.f / 2.4f) - 0.055f);
|
||||||
|
tb = (tb <= 0.0031308f) ? (tb * 12.92f) : (1.055f * pow(tb, 1.f / 2.4f) - 0.055f);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // linear
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // Gamma = 2.2
|
||||||
|
ta = pow(ta, 1.f / 2.2f);
|
||||||
|
tr = pow(tr, 1.f / 2.2f);
|
||||||
|
tg = pow(tg, 1.f / 2.2f);
|
||||||
|
tb = pow(tb, 1.f / 2.2f);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // Gamma = 1.8
|
||||||
|
ta = pow(ta, 1.f / 1.8f);
|
||||||
|
tr = pow(tr, 1.f / 1.8f);
|
||||||
|
tg = pow(tg, 1.f / 1.8f);
|
||||||
|
tb = pow(tb, 1.f / 1.8f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!parts[ID(rp)].dcolour)
|
||||||
|
ta -= 3/255.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ta *= 255.0f; tr *= 255.0f; tg *= 255.0f; tb *= 255.0f;
|
||||||
|
ta += .5f; tr += .5f; tg += .5f; tb += .5f;
|
||||||
|
|
||||||
|
colA_ = int(ta);
|
||||||
|
colR_ = int(tr);
|
||||||
|
colG_ = int(tg);
|
||||||
|
colB_ = int(tb);
|
||||||
|
|
||||||
|
if(colA_ > 255)
|
||||||
|
colA_ = 255;
|
||||||
|
else if(colA_ < 0)
|
||||||
|
colA_ = 0;
|
||||||
|
if(colR_ > 255)
|
||||||
|
colR_ = 255;
|
||||||
|
else if(colR_ < 0)
|
||||||
|
colR_ = 0;
|
||||||
|
if(colG_ > 255)
|
||||||
|
colG_ = 255;
|
||||||
|
else if(colG_ < 0)
|
||||||
|
colG_ = 0;
|
||||||
|
if(colB_ > 255)
|
||||||
|
colB_ = 255;
|
||||||
|
else if(colB_ < 0)
|
||||||
|
colB_ = 0;
|
||||||
|
parts[ID(rp)].dcolour = ((colA_<<24)|(colR_<<16)|(colG_<<8)|colB_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Simulation::ApplyDecorationPoint(int positionX, int positionY, int colR, int colG, int colB, int colA, int mode, Brush * cBrush)
|
||||||
|
{
|
||||||
|
if(cBrush)
|
||||||
|
{
|
||||||
|
int radiusX = cBrush->GetRadius().X, radiusY = cBrush->GetRadius().Y, sizeX = cBrush->GetSize().X, sizeY = cBrush->GetSize().Y;
|
||||||
|
unsigned char *bitmap = cBrush->GetBitmap();
|
||||||
|
|
||||||
|
for(int y = 0; y < sizeY; y++)
|
||||||
|
{
|
||||||
|
for(int x = 0; x < sizeX; x++)
|
||||||
|
{
|
||||||
|
if(bitmap[(y*sizeX)+x] && (positionX+(x-radiusX) >= 0 && positionY+(y-radiusY) >= 0 && positionX+(x-radiusX) < XRES && positionY+(y-radiusY) < YRES))
|
||||||
|
{
|
||||||
|
ApplyDecoration(positionX+(x-radiusX), positionY+(y-radiusY), colR, colG, colB, colA, mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Simulation::ApplyDecorationLine(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode, Brush * cBrush)
|
||||||
|
{
|
||||||
|
bool reverseXY = abs(y2-y1) > abs(x2-x1);
|
||||||
|
int x, y, dx, dy, sy, rx = 0, ry = 0;
|
||||||
|
float e = 0.0f, de;
|
||||||
|
|
||||||
|
if(cBrush)
|
||||||
|
{
|
||||||
|
rx = cBrush->GetRadius().X;
|
||||||
|
ry = cBrush->GetRadius().Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reverseXY)
|
||||||
|
{
|
||||||
|
y = x1;
|
||||||
|
x1 = y1;
|
||||||
|
y1 = y;
|
||||||
|
y = x2;
|
||||||
|
x2 = y2;
|
||||||
|
y2 = y;
|
||||||
|
}
|
||||||
|
if (x1 > x2)
|
||||||
|
{
|
||||||
|
y = x1;
|
||||||
|
x1 = x2;
|
||||||
|
x2 = y;
|
||||||
|
y = y1;
|
||||||
|
y1 = y2;
|
||||||
|
y2 = y;
|
||||||
|
}
|
||||||
|
dx = x2 - x1;
|
||||||
|
dy = abs(y2 - y1);
|
||||||
|
de = dx ? dy/(float)dx : 0.0f;
|
||||||
|
y = y1;
|
||||||
|
sy = (y1<y2) ? 1 : -1;
|
||||||
|
for (x=x1; x<=x2; x++)
|
||||||
|
{
|
||||||
|
if (reverseXY)
|
||||||
|
ApplyDecorationPoint(y, x, colR, colG, colB, colA, mode, cBrush);
|
||||||
|
else
|
||||||
|
ApplyDecorationPoint(x, y, colR, colG, colB, colA, mode, cBrush);
|
||||||
|
e += de;
|
||||||
|
if (e >= 0.5f)
|
||||||
|
{
|
||||||
|
y += sy;
|
||||||
|
if (!(rx+ry))
|
||||||
|
{
|
||||||
|
if (reverseXY)
|
||||||
|
ApplyDecorationPoint(y, x, colR, colG, colB, colA, mode, cBrush);
|
||||||
|
else
|
||||||
|
ApplyDecorationPoint(x, y, colR, colG, colB, colA, mode, cBrush);
|
||||||
|
}
|
||||||
|
e -= 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Simulation::ApplyDecorationBox(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (x1>x2)
|
||||||
|
{
|
||||||
|
i = x2;
|
||||||
|
x2 = x1;
|
||||||
|
x1 = i;
|
||||||
|
}
|
||||||
|
if (y1>y2)
|
||||||
|
{
|
||||||
|
j = y2;
|
||||||
|
y2 = y1;
|
||||||
|
y1 = j;
|
||||||
|
}
|
||||||
|
for (j=y1; j<=y2; j++)
|
||||||
|
for (i=x1; i<=x2; i++)
|
||||||
|
ApplyDecoration(i, j, colR, colG, colB, colA, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Simulation::ColorCompare(Renderer *ren, int x, int y, int replaceR, int replaceG, int replaceB)
|
||||||
|
{
|
||||||
|
pixel pix = ren->vid[x+y*WINDOWW];
|
||||||
|
int r = PIXR(pix);
|
||||||
|
int g = PIXG(pix);
|
||||||
|
int b = PIXB(pix);
|
||||||
|
int diff = std::abs(replaceR-r) + std::abs(replaceG-g) + std::abs(replaceB-b);
|
||||||
|
return diff < 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Simulation::ApplyDecorationFill(Renderer *ren, int x, int y, int colR, int colG, int colB, int colA, int replaceR, int replaceG, int replaceB)
|
||||||
|
{
|
||||||
|
int x1, x2;
|
||||||
|
char *bitmap = (char*)malloc(XRES*YRES); //Bitmap for checking
|
||||||
|
if (!bitmap)
|
||||||
|
return;
|
||||||
|
memset(bitmap, 0, XRES*YRES);
|
||||||
|
|
||||||
|
if (!ColorCompare(ren, x, y, replaceR, replaceG, replaceB)) {
|
||||||
|
free(bitmap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CoordStack& cs = getCoordStackSingleton();
|
||||||
|
cs.clear();
|
||||||
|
|
||||||
|
cs.push(x, y);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
cs.pop(x, y);
|
||||||
|
x1 = x2 = x;
|
||||||
|
// go left as far as possible
|
||||||
|
while (x1>0)
|
||||||
|
{
|
||||||
|
if (bitmap[(x1-1)+y*XRES] || !ColorCompare(ren, x1-1, y, replaceR, replaceG, replaceB))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
x1--;
|
||||||
|
}
|
||||||
|
// go right as far as possible
|
||||||
|
while (x2<XRES-1)
|
||||||
|
{
|
||||||
|
if (bitmap[(x1+1)+y*XRES] || !ColorCompare(ren, x2+1, y, replaceR, replaceG, replaceB))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
x2++;
|
||||||
|
}
|
||||||
|
// fill span
|
||||||
|
for (x=x1; x<=x2; x++)
|
||||||
|
{
|
||||||
|
ApplyDecoration(x, y, colR, colG, colB, colA, DECO_DRAW);
|
||||||
|
bitmap[x+y*XRES] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y >= 1)
|
||||||
|
for (x=x1; x<=x2; x++)
|
||||||
|
if (!bitmap[x+(y-1)*XRES] && ColorCompare(ren, x, y-1, replaceR, replaceG, replaceB))
|
||||||
|
cs.push(x, y-1);
|
||||||
|
|
||||||
|
if (y < YRES-1)
|
||||||
|
for (x=x1; x<=x2; x++)
|
||||||
|
if (!bitmap[x+(y+1)*XRES] && ColorCompare(ren, x, y+1, replaceR, replaceG, replaceB))
|
||||||
|
cs.push(x, y+1);
|
||||||
|
} while (cs.getSize() > 0);
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << e.what() << std::endl;
|
||||||
|
free(bitmap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
free(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Simulation::ToolBrush(int positionX, int positionY, int tool, Brush * cBrush, float strength)
|
||||||
|
{
|
||||||
|
if(cBrush)
|
||||||
|
{
|
||||||
|
int radiusX = cBrush->GetRadius().X, radiusY = cBrush->GetRadius().Y, sizeX = cBrush->GetSize().X, sizeY = cBrush->GetSize().Y;
|
||||||
|
unsigned char *bitmap = cBrush->GetBitmap();
|
||||||
|
for(int y = 0; y < sizeY; y++)
|
||||||
|
for(int x = 0; x < sizeX; x++)
|
||||||
|
if(bitmap[(y*sizeX)+x] && (positionX+(x-radiusX) >= 0 && positionY+(y-radiusY) >= 0 && positionX+(x-radiusX) < XRES && positionY+(y-radiusY) < YRES))
|
||||||
|
Tool(positionX + (x - radiusX), positionY + (y - radiusY), tool, positionX, positionY, strength);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Simulation::ToolLine(int x1, int y1, int x2, int y2, int tool, Brush * cBrush, float strength)
|
||||||
|
{
|
||||||
|
bool reverseXY = abs(y2-y1) > abs(x2-x1);
|
||||||
|
int x, y, dx, dy, sy, rx = cBrush->GetRadius().X, ry = cBrush->GetRadius().Y;
|
||||||
|
float e = 0.0f, de;
|
||||||
|
if (reverseXY)
|
||||||
|
{
|
||||||
|
y = x1;
|
||||||
|
x1 = y1;
|
||||||
|
y1 = y;
|
||||||
|
y = x2;
|
||||||
|
x2 = y2;
|
||||||
|
y2 = y;
|
||||||
|
}
|
||||||
|
if (x1 > x2)
|
||||||
|
{
|
||||||
|
y = x1;
|
||||||
|
x1 = x2;
|
||||||
|
x2 = y;
|
||||||
|
y = y1;
|
||||||
|
y1 = y2;
|
||||||
|
y2 = y;
|
||||||
|
}
|
||||||
|
dx = x2 - x1;
|
||||||
|
dy = abs(y2 - y1);
|
||||||
|
de = dx ? dy/(float)dx : 0.0f;
|
||||||
|
y = y1;
|
||||||
|
sy = (y1<y2) ? 1 : -1;
|
||||||
|
for (x=x1; x<=x2; x++)
|
||||||
|
{
|
||||||
|
if (reverseXY)
|
||||||
|
ToolBrush(y, x, tool, cBrush, strength);
|
||||||
|
else
|
||||||
|
ToolBrush(x, y, tool, cBrush, strength);
|
||||||
|
e += de;
|
||||||
|
if (e >= 0.5f)
|
||||||
|
{
|
||||||
|
y += sy;
|
||||||
|
if (!(rx+ry) && ((y1<y2) ? (y<=y2) : (y>=y2)))
|
||||||
|
{
|
||||||
|
if (reverseXY)
|
||||||
|
ToolBrush(y, x, tool, cBrush, strength);
|
||||||
|
else
|
||||||
|
ToolBrush(x, y, tool, cBrush, strength);
|
||||||
|
}
|
||||||
|
e -= 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Simulation::ToolBox(int x1, int y1, int x2, int y2, int tool, float strength)
|
||||||
|
{
|
||||||
|
int brushX, brushY;
|
||||||
|
brushX = ((x1 + x2) / 2);
|
||||||
|
brushY = ((y1 + y2) / 2);
|
||||||
|
int i, j;
|
||||||
|
if (x1>x2)
|
||||||
|
{
|
||||||
|
i = x2;
|
||||||
|
x2 = x1;
|
||||||
|
x1 = i;
|
||||||
|
}
|
||||||
|
if (y1>y2)
|
||||||
|
{
|
||||||
|
j = y2;
|
||||||
|
y2 = y1;
|
||||||
|
y1 = j;
|
||||||
|
}
|
||||||
|
for (j=y1; j<=y2; j++)
|
||||||
|
for (i=x1; i<=x2; i++)
|
||||||
|
Tool(i, j, tool, brushX, brushY, strength);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Simulation::CreateParts(int positionX, int positionY, int c, Brush * cBrush, int flags)
|
||||||
|
{
|
||||||
|
if (flags == -1)
|
||||||
|
flags = replaceModeFlags;
|
||||||
|
if (cBrush)
|
||||||
|
{
|
||||||
|
int radiusX = cBrush->GetRadius().X, radiusY = cBrush->GetRadius().Y, sizeX = cBrush->GetSize().X, sizeY = cBrush->GetSize().Y;
|
||||||
|
unsigned char *bitmap = cBrush->GetBitmap();
|
||||||
|
|
||||||
|
// special case for LIGH
|
||||||
|
if (c == PT_LIGH)
|
||||||
|
{
|
||||||
|
if (currentTick < lightningRecreate)
|
||||||
|
return 1;
|
||||||
|
int newlife = radiusX + radiusY;
|
||||||
|
if (newlife > 55)
|
||||||
|
newlife = 55;
|
||||||
|
c = PMAP(newlife, c);
|
||||||
|
lightningRecreate = currentTick + std::max(newlife / 4, 1);
|
||||||
|
return CreatePartFlags(positionX, positionY, c, flags);
|
||||||
|
}
|
||||||
|
else if (c == PT_TESC)
|
||||||
|
{
|
||||||
|
int newtmp = (radiusX*4+radiusY*4+7);
|
||||||
|
if (newtmp > 300)
|
||||||
|
newtmp = 300;
|
||||||
|
c = PMAP(newtmp, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int y = sizeY-1; y >=0; y--)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < sizeX; x++)
|
||||||
|
{
|
||||||
|
if (bitmap[(y*sizeX)+x] && (positionX+(x-radiusX) >= 0 && positionY+(y-radiusY) >= 0 && positionX+(x-radiusX) < XRES && positionY+(y-radiusY) < YRES))
|
||||||
|
{
|
||||||
|
CreatePartFlags(positionX+(x-radiusX), positionY+(y-radiusY), c, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Simulation::CreateParts(int x, int y, int rx, int ry, int c, int flags)
|
||||||
|
{
|
||||||
|
bool created = false;
|
||||||
|
|
||||||
|
if (flags == -1)
|
||||||
|
flags = replaceModeFlags;
|
||||||
|
|
||||||
|
// special case for LIGH
|
||||||
|
if (c == PT_LIGH)
|
||||||
|
{
|
||||||
|
if (currentTick < lightningRecreate)
|
||||||
|
return 1;
|
||||||
|
int newlife = rx + ry;
|
||||||
|
if (newlife > 55)
|
||||||
|
newlife = 55;
|
||||||
|
c = PMAP(newlife, c);
|
||||||
|
lightningRecreate = currentTick + std::max(newlife / 4, 1);
|
||||||
|
rx = ry = 0;
|
||||||
|
}
|
||||||
|
else if (c == PT_TESC)
|
||||||
|
{
|
||||||
|
int newtmp = (rx*4+ry*4+7);
|
||||||
|
if (newtmp > 300)
|
||||||
|
newtmp = 300;
|
||||||
|
c = PMAP(newtmp, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = -ry; j <= ry; j++)
|
||||||
|
for (int i = -rx; i <= rx; i++)
|
||||||
|
if (CreatePartFlags(x+i, y+j, c, flags))
|
||||||
|
created = true;
|
||||||
|
return !created;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Simulation::CreateLine(int x1, int y1, int x2, int y2, int c, Brush * cBrush, int flags)
|
||||||
|
{
|
||||||
|
int x, y, dx, dy, sy, rx = cBrush->GetRadius().X, ry = cBrush->GetRadius().Y;
|
||||||
|
bool reverseXY = abs(y2-y1) > abs(x2-x1);
|
||||||
|
float e = 0.0f, de;
|
||||||
|
if (reverseXY)
|
||||||
|
{
|
||||||
|
y = x1;
|
||||||
|
x1 = y1;
|
||||||
|
y1 = y;
|
||||||
|
y = x2;
|
||||||
|
x2 = y2;
|
||||||
|
y2 = y;
|
||||||
|
}
|
||||||
|
if (x1 > x2)
|
||||||
|
{
|
||||||
|
y = x1;
|
||||||
|
x1 = x2;
|
||||||
|
x2 = y;
|
||||||
|
y = y1;
|
||||||
|
y1 = y2;
|
||||||
|
y2 = y;
|
||||||
|
}
|
||||||
|
dx = x2 - x1;
|
||||||
|
dy = abs(y2 - y1);
|
||||||
|
de = dx ? dy/(float)dx : 0.0f;
|
||||||
|
y = y1;
|
||||||
|
sy = (y1<y2) ? 1 : -1;
|
||||||
|
for (x=x1; x<=x2; x++)
|
||||||
|
{
|
||||||
|
if (reverseXY)
|
||||||
|
CreateParts(y, x, c, cBrush, flags);
|
||||||
|
else
|
||||||
|
CreateParts(x, y, c, cBrush, flags);
|
||||||
|
e += de;
|
||||||
|
if (e >= 0.5f)
|
||||||
|
{
|
||||||
|
y += sy;
|
||||||
|
if (!(rx+ry) && ((y1<y2) ? (y<=y2) : (y>=y2)))
|
||||||
|
{
|
||||||
|
if (reverseXY)
|
||||||
|
CreateParts(y, x, c, cBrush, flags);
|
||||||
|
else
|
||||||
|
CreateParts(x, y, c, cBrush, flags);
|
||||||
|
}
|
||||||
|
e -= 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Simulation::CreateBox(int x1, int y1, int x2, int y2, int c, int flags)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
if (x1>x2)
|
||||||
|
{
|
||||||
|
i = x2;
|
||||||
|
x2 = x1;
|
||||||
|
x1 = i;
|
||||||
|
}
|
||||||
|
if (y1>y2)
|
||||||
|
{
|
||||||
|
j = y2;
|
||||||
|
y2 = y1;
|
||||||
|
y1 = j;
|
||||||
|
}
|
||||||
|
for (j=y2; j>=y1; j--)
|
||||||
|
for (i=x1; i<=x2; i++)
|
||||||
|
CreateParts(i, j, 0, 0, c, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Simulation::FloodParts(int x, int y, int fullc, int cm, int flags)
|
||||||
|
{
|
||||||
|
int c = TYP(fullc);
|
||||||
|
int x1, x2, dy = (c<PT_NUM)?1:CELL;
|
||||||
|
int coord_stack_limit = XRES*YRES;
|
||||||
|
unsigned short (*coord_stack)[2];
|
||||||
|
int coord_stack_size = 0;
|
||||||
|
int created_something = 0;
|
||||||
|
|
||||||
|
// Bitmap for checking where we've already looked
|
||||||
|
auto bitmapPtr = std::unique_ptr<char[]>(new char[XRES * YRES]);
|
||||||
|
char *bitmap = bitmapPtr.get();
|
||||||
|
std::fill(&bitmap[0], &bitmap[0] + XRES * YRES, 0);
|
||||||
|
|
||||||
|
if (cm==-1)
|
||||||
|
{
|
||||||
|
//if initial flood point is out of bounds, do nothing
|
||||||
|
if (c != 0 && (x < CELL || x >= XRES-CELL || y < CELL || y >= YRES-CELL || c == PT_SPRK))
|
||||||
|
return 1;
|
||||||
|
else if (x < 0 || x >= XRES || y < 0 || y >= YRES)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (c == 0)
|
||||||
|
{
|
||||||
|
cm = TYP(pmap[y][x]);
|
||||||
|
if (!cm)
|
||||||
|
{
|
||||||
|
cm = TYP(photons[y][x]);
|
||||||
|
if (!cm)
|
||||||
|
{
|
||||||
|
if (bmap[y/CELL][x/CELL])
|
||||||
|
return FloodWalls(x, y, WL_ERASE, -1);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cm = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c != 0 && IsWallBlocking(x, y, c))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!FloodFillPmapCheck(x, y, cm))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
coord_stack = (short unsigned int (*)[2])malloc(sizeof(unsigned short)*2*coord_stack_limit);
|
||||||
|
coord_stack[coord_stack_size][0] = x;
|
||||||
|
coord_stack[coord_stack_size][1] = y;
|
||||||
|
coord_stack_size++;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
coord_stack_size--;
|
||||||
|
x = coord_stack[coord_stack_size][0];
|
||||||
|
y = coord_stack[coord_stack_size][1];
|
||||||
|
x1 = x2 = x;
|
||||||
|
// go left as far as possible
|
||||||
|
while (c?x1>CELL:x1>0)
|
||||||
|
{
|
||||||
|
if (bitmap[(y * XRES) + x1 - 1] || !FloodFillPmapCheck(x1-1, y, cm) || (c != 0 && IsWallBlocking(x1-1, y, c)))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
x1--;
|
||||||
|
}
|
||||||
|
// go right as far as possible
|
||||||
|
while (c?x2<XRES-CELL-1:x2<XRES-1)
|
||||||
|
{
|
||||||
|
if (bitmap[(y * XRES) + x2 + 1] || !FloodFillPmapCheck(x2+1, y, cm) || (c != 0 && IsWallBlocking(x2+1, y, c)))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
x2++;
|
||||||
|
}
|
||||||
|
// fill span
|
||||||
|
for (x=x1; x<=x2; x++)
|
||||||
|
{
|
||||||
|
if (!fullc)
|
||||||
|
{
|
||||||
|
if (elements[cm].Properties&TYPE_ENERGY)
|
||||||
|
{
|
||||||
|
if (photons[y][x])
|
||||||
|
{
|
||||||
|
kill_part(ID(photons[y][x]));
|
||||||
|
created_something = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pmap[y][x])
|
||||||
|
{
|
||||||
|
kill_part(ID(pmap[y][x]));
|
||||||
|
created_something = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (CreateParts(x, y, 0, 0, fullc, flags))
|
||||||
|
created_something = 1;
|
||||||
|
bitmap[(y * XRES) + x] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c?y>=CELL+dy:y>=dy)
|
||||||
|
for (x=x1; x<=x2; x++)
|
||||||
|
if (!bitmap[((y - dy) * XRES) + x] && FloodFillPmapCheck(x, y-dy, cm) && (c == 0 || !IsWallBlocking(x, y-dy, c)))
|
||||||
|
{
|
||||||
|
coord_stack[coord_stack_size][0] = x;
|
||||||
|
coord_stack[coord_stack_size][1] = y-dy;
|
||||||
|
coord_stack_size++;
|
||||||
|
if (coord_stack_size>=coord_stack_limit)
|
||||||
|
{
|
||||||
|
free(coord_stack);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c?y<YRES-CELL-dy:y<YRES-dy)
|
||||||
|
for (x=x1; x<=x2; x++)
|
||||||
|
if (!bitmap[((y + dy) * XRES) + x] && FloodFillPmapCheck(x, y+dy, cm) && (c == 0 || !IsWallBlocking(x, y+dy, c)))
|
||||||
|
{
|
||||||
|
coord_stack[coord_stack_size][0] = x;
|
||||||
|
coord_stack[coord_stack_size][1] = y+dy;
|
||||||
|
coord_stack_size++;
|
||||||
|
if (coord_stack_size>=coord_stack_limit)
|
||||||
|
{
|
||||||
|
free(coord_stack);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (coord_stack_size>0);
|
||||||
|
free(coord_stack);
|
||||||
|
return created_something;
|
||||||
|
}
|
@ -94,32 +94,3 @@ String SerialiseGOLRule(int rule)
|
|||||||
}
|
}
|
||||||
return golName.Build();
|
return golName.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef RENDERER
|
|
||||||
bool AddCustomGol(String ruleString, String nameString, unsigned int highColor, unsigned int lowColor)
|
|
||||||
{
|
|
||||||
auto customGOLTypes = Client::Ref().GetPrefByteStringArray("CustomGOL.Types");
|
|
||||||
Json::Value newCustomGOLTypes(Json::arrayValue);
|
|
||||||
bool nameTaken = false;
|
|
||||||
for (auto gol : customGOLTypes)
|
|
||||||
{
|
|
||||||
auto parts = gol.FromUtf8().PartitionBy(' ');
|
|
||||||
if (parts.size())
|
|
||||||
{
|
|
||||||
if (parts[0] == nameString)
|
|
||||||
{
|
|
||||||
nameTaken = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newCustomGOLTypes.append(gol);
|
|
||||||
}
|
|
||||||
if (nameTaken)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
StringBuilder sb;
|
|
||||||
sb << nameString << " " << ruleString << " " << highColor << " " << lowColor;
|
|
||||||
newCustomGOLTypes.append(sb.Build().ToUtf8());
|
|
||||||
Client::Ref().SetPref("CustomGOL.Types", newCustomGOLTypes);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -6,4 +6,3 @@
|
|||||||
bool ValidateGOLName(const String &value);
|
bool ValidateGOLName(const String &value);
|
||||||
int ParseGOLString(const String &value);
|
int ParseGOLString(const String &value);
|
||||||
String SerialiseGOLRule(int rule);
|
String SerialiseGOLRule(int rule);
|
||||||
bool AddCustomGol(String ruleString, String nameString, unsigned int highColor, unsigned int lowColor);
|
|
||||||
|
@ -1,36 +1,19 @@
|
|||||||
#include "Simulation.h"
|
#include "Simulation.h"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <cmath>
|
|
||||||
#include <set>
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#include <intrin.h>
|
|
||||||
#else
|
|
||||||
#include <strings.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "Air.h"
|
#include "Air.h"
|
||||||
#include "Config.h"
|
|
||||||
#include "CoordStack.h"
|
|
||||||
#include "ElementClasses.h"
|
#include "ElementClasses.h"
|
||||||
#include "Gravity.h"
|
#include "Gravity.h"
|
||||||
#include "Sample.h"
|
#include "Sample.h"
|
||||||
#include "Snapshot.h"
|
#include "Snapshot.h"
|
||||||
|
|
||||||
#include "Misc.h"
|
|
||||||
#include "ToolClasses.h"
|
#include "ToolClasses.h"
|
||||||
#include "Config.h"
|
|
||||||
#include "SimulationData.h"
|
#include "SimulationData.h"
|
||||||
#include "GOLString.h"
|
#include "GOLString.h"
|
||||||
|
|
||||||
#include "graphics/Renderer.h"
|
|
||||||
|
|
||||||
#include "client/GameSave.h"
|
#include "client/GameSave.h"
|
||||||
#include "common/tpt-compat.h"
|
#include "common/tpt-compat.h"
|
||||||
#include "common/tpt-minmax.h"
|
|
||||||
#include "common/tpt-rand.h"
|
#include "common/tpt-rand.h"
|
||||||
#include "common/tpt-thread-local.h"
|
#include "common/tpt-thread-local.h"
|
||||||
#include "gui/game/Brush.h"
|
#include "gui/game/Brush.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
extern int Element_PPIP_ppip_changed;
|
extern int Element_PPIP_ppip_changed;
|
||||||
extern int Element_LOLZ_RuleTable[9][9];
|
extern int Element_LOLZ_RuleTable[9][9];
|
||||||
@ -1012,355 +995,6 @@ void Simulation::SetEdgeMode(int newEdgeMode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef RENDERER
|
|
||||||
void Simulation::ApplyDecoration(int x, int y, int colR_, int colG_, int colB_, int colA_, int mode)
|
|
||||||
{
|
|
||||||
int rp;
|
|
||||||
float tr, tg, tb, ta, colR = float(colR_), colG = float(colG_), colB = float(colB_), colA = float(colA_);
|
|
||||||
float strength = 0.01f;
|
|
||||||
rp = pmap[y][x];
|
|
||||||
if (!rp)
|
|
||||||
rp = photons[y][x];
|
|
||||||
if (!rp)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ta = float((parts[ID(rp)].dcolour>>24)&0xFF);
|
|
||||||
tr = float((parts[ID(rp)].dcolour>>16)&0xFF);
|
|
||||||
tg = float((parts[ID(rp)].dcolour>>8)&0xFF);
|
|
||||||
tb = float((parts[ID(rp)].dcolour)&0xFF);
|
|
||||||
|
|
||||||
ta /= 255.0f; tr /= 255.0f; tg /= 255.0f; tb /= 255.0f;
|
|
||||||
colR /= 255.0f; colG /= 255.0f; colB /= 255.0f; colA /= 255.0f;
|
|
||||||
|
|
||||||
if (mode == DECO_DRAW)
|
|
||||||
{
|
|
||||||
ta = colA;
|
|
||||||
tr = colR;
|
|
||||||
tg = colG;
|
|
||||||
tb = colB;
|
|
||||||
}
|
|
||||||
else if (mode == DECO_CLEAR)
|
|
||||||
{
|
|
||||||
ta = tr = tg = tb = 0.0f;
|
|
||||||
}
|
|
||||||
else if (mode == DECO_ADD)
|
|
||||||
{
|
|
||||||
//ta += (colA*strength)*colA;
|
|
||||||
tr += (colR*strength)*colA;
|
|
||||||
tg += (colG*strength)*colA;
|
|
||||||
tb += (colB*strength)*colA;
|
|
||||||
}
|
|
||||||
else if (mode == DECO_SUBTRACT)
|
|
||||||
{
|
|
||||||
//ta -= (colA*strength)*colA;
|
|
||||||
tr -= (colR*strength)*colA;
|
|
||||||
tg -= (colG*strength)*colA;
|
|
||||||
tb -= (colB*strength)*colA;
|
|
||||||
}
|
|
||||||
else if (mode == DECO_MULTIPLY)
|
|
||||||
{
|
|
||||||
tr *= 1.0f+(colR*strength)*colA;
|
|
||||||
tg *= 1.0f+(colG*strength)*colA;
|
|
||||||
tb *= 1.0f+(colB*strength)*colA;
|
|
||||||
}
|
|
||||||
else if (mode == DECO_DIVIDE)
|
|
||||||
{
|
|
||||||
tr /= 1.0f+(colR*strength)*colA;
|
|
||||||
tg /= 1.0f+(colG*strength)*colA;
|
|
||||||
tb /= 1.0f+(colB*strength)*colA;
|
|
||||||
}
|
|
||||||
else if (mode == DECO_SMUDGE)
|
|
||||||
{
|
|
||||||
if (x >= CELL && x < XRES-CELL && y >= CELL && y < YRES-CELL)
|
|
||||||
{
|
|
||||||
float tas = 0.0f, trs = 0.0f, tgs = 0.0f, tbs = 0.0f;
|
|
||||||
|
|
||||||
int rx, ry;
|
|
||||||
float num = 0;
|
|
||||||
for (rx=-2; rx<3; rx++)
|
|
||||||
for (ry=-2; ry<3; ry++)
|
|
||||||
{
|
|
||||||
if (abs(rx)+abs(ry) > 2 && TYP(pmap[y+ry][x+rx]) && parts[ID(pmap[y+ry][x+rx])].dcolour)
|
|
||||||
{
|
|
||||||
Particle part = parts[ID(pmap[y+ry][x+rx])];
|
|
||||||
num += 1.0f;
|
|
||||||
float pa = ((float)((part.dcolour>>24)&0xFF)) / 255.f;
|
|
||||||
float pr = ((float)((part.dcolour>>16)&0xFF)) / 255.f;
|
|
||||||
float pg = ((float)((part.dcolour>> 8)&0xFF)) / 255.f;
|
|
||||||
float pb = ((float)((part.dcolour )&0xFF)) / 255.f;
|
|
||||||
switch (deco_space)
|
|
||||||
{
|
|
||||||
case 0: // sRGB
|
|
||||||
pa = (pa <= 0.04045f) ? (pa / 12.92f) : pow((pa + 0.055f) / 1.055f, 2.4f);
|
|
||||||
pr = (pr <= 0.04045f) ? (pr / 12.92f) : pow((pr + 0.055f) / 1.055f, 2.4f);
|
|
||||||
pg = (pg <= 0.04045f) ? (pg / 12.92f) : pow((pg + 0.055f) / 1.055f, 2.4f);
|
|
||||||
pb = (pb <= 0.04045f) ? (pb / 12.92f) : pow((pb + 0.055f) / 1.055f, 2.4f);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: // linear
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2: // Gamma = 2.2
|
|
||||||
pa = pow(pa, 2.2f);
|
|
||||||
pr = pow(pr, 2.2f);
|
|
||||||
pg = pow(pg, 2.2f);
|
|
||||||
pb = pow(pb, 2.2f);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3: // Gamma = 1.8
|
|
||||||
pa = pow(pa, 1.8f);
|
|
||||||
pr = pow(pr, 1.8f);
|
|
||||||
pg = pow(pg, 1.8f);
|
|
||||||
pb = pow(pb, 1.8f);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tas += pa;
|
|
||||||
trs += pr;
|
|
||||||
tgs += pg;
|
|
||||||
tbs += pb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (num == 0)
|
|
||||||
return;
|
|
||||||
ta = tas / num;
|
|
||||||
tr = trs / num;
|
|
||||||
tg = tgs / num;
|
|
||||||
tb = tbs / num;
|
|
||||||
switch (deco_space)
|
|
||||||
{
|
|
||||||
case 0: // sRGB
|
|
||||||
ta = (ta <= 0.0031308f) ? (ta * 12.92f) : (1.055f * pow(ta, 1.f / 2.4f) - 0.055f);
|
|
||||||
tr = (tr <= 0.0031308f) ? (tr * 12.92f) : (1.055f * pow(tr, 1.f / 2.4f) - 0.055f);
|
|
||||||
tg = (tg <= 0.0031308f) ? (tg * 12.92f) : (1.055f * pow(tg, 1.f / 2.4f) - 0.055f);
|
|
||||||
tb = (tb <= 0.0031308f) ? (tb * 12.92f) : (1.055f * pow(tb, 1.f / 2.4f) - 0.055f);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: // linear
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2: // Gamma = 2.2
|
|
||||||
ta = pow(ta, 1.f / 2.2f);
|
|
||||||
tr = pow(tr, 1.f / 2.2f);
|
|
||||||
tg = pow(tg, 1.f / 2.2f);
|
|
||||||
tb = pow(tb, 1.f / 2.2f);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3: // Gamma = 1.8
|
|
||||||
ta = pow(ta, 1.f / 1.8f);
|
|
||||||
tr = pow(tr, 1.f / 1.8f);
|
|
||||||
tg = pow(tg, 1.f / 1.8f);
|
|
||||||
tb = pow(tb, 1.f / 1.8f);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!parts[ID(rp)].dcolour)
|
|
||||||
ta -= 3/255.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ta *= 255.0f; tr *= 255.0f; tg *= 255.0f; tb *= 255.0f;
|
|
||||||
ta += .5f; tr += .5f; tg += .5f; tb += .5f;
|
|
||||||
|
|
||||||
colA_ = int(ta);
|
|
||||||
colR_ = int(tr);
|
|
||||||
colG_ = int(tg);
|
|
||||||
colB_ = int(tb);
|
|
||||||
|
|
||||||
if(colA_ > 255)
|
|
||||||
colA_ = 255;
|
|
||||||
else if(colA_ < 0)
|
|
||||||
colA_ = 0;
|
|
||||||
if(colR_ > 255)
|
|
||||||
colR_ = 255;
|
|
||||||
else if(colR_ < 0)
|
|
||||||
colR_ = 0;
|
|
||||||
if(colG_ > 255)
|
|
||||||
colG_ = 255;
|
|
||||||
else if(colG_ < 0)
|
|
||||||
colG_ = 0;
|
|
||||||
if(colB_ > 255)
|
|
||||||
colB_ = 255;
|
|
||||||
else if(colB_ < 0)
|
|
||||||
colB_ = 0;
|
|
||||||
parts[ID(rp)].dcolour = ((colA_<<24)|(colR_<<16)|(colG_<<8)|colB_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Simulation::ApplyDecorationPoint(int positionX, int positionY, int colR, int colG, int colB, int colA, int mode, Brush * cBrush)
|
|
||||||
{
|
|
||||||
if(cBrush)
|
|
||||||
{
|
|
||||||
int radiusX = cBrush->GetRadius().X, radiusY = cBrush->GetRadius().Y, sizeX = cBrush->GetSize().X, sizeY = cBrush->GetSize().Y;
|
|
||||||
unsigned char *bitmap = cBrush->GetBitmap();
|
|
||||||
|
|
||||||
for(int y = 0; y < sizeY; y++)
|
|
||||||
{
|
|
||||||
for(int x = 0; x < sizeX; x++)
|
|
||||||
{
|
|
||||||
if(bitmap[(y*sizeX)+x] && (positionX+(x-radiusX) >= 0 && positionY+(y-radiusY) >= 0 && positionX+(x-radiusX) < XRES && positionY+(y-radiusY) < YRES))
|
|
||||||
{
|
|
||||||
ApplyDecoration(positionX+(x-radiusX), positionY+(y-radiusY), colR, colG, colB, colA, mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Simulation::ApplyDecorationLine(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode, Brush * cBrush)
|
|
||||||
{
|
|
||||||
bool reverseXY = abs(y2-y1) > abs(x2-x1);
|
|
||||||
int x, y, dx, dy, sy, rx = 0, ry = 0;
|
|
||||||
float e = 0.0f, de;
|
|
||||||
|
|
||||||
if(cBrush)
|
|
||||||
{
|
|
||||||
rx = cBrush->GetRadius().X;
|
|
||||||
ry = cBrush->GetRadius().Y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reverseXY)
|
|
||||||
{
|
|
||||||
y = x1;
|
|
||||||
x1 = y1;
|
|
||||||
y1 = y;
|
|
||||||
y = x2;
|
|
||||||
x2 = y2;
|
|
||||||
y2 = y;
|
|
||||||
}
|
|
||||||
if (x1 > x2)
|
|
||||||
{
|
|
||||||
y = x1;
|
|
||||||
x1 = x2;
|
|
||||||
x2 = y;
|
|
||||||
y = y1;
|
|
||||||
y1 = y2;
|
|
||||||
y2 = y;
|
|
||||||
}
|
|
||||||
dx = x2 - x1;
|
|
||||||
dy = abs(y2 - y1);
|
|
||||||
de = dx ? dy/(float)dx : 0.0f;
|
|
||||||
y = y1;
|
|
||||||
sy = (y1<y2) ? 1 : -1;
|
|
||||||
for (x=x1; x<=x2; x++)
|
|
||||||
{
|
|
||||||
if (reverseXY)
|
|
||||||
ApplyDecorationPoint(y, x, colR, colG, colB, colA, mode, cBrush);
|
|
||||||
else
|
|
||||||
ApplyDecorationPoint(x, y, colR, colG, colB, colA, mode, cBrush);
|
|
||||||
e += de;
|
|
||||||
if (e >= 0.5f)
|
|
||||||
{
|
|
||||||
y += sy;
|
|
||||||
if (!(rx+ry))
|
|
||||||
{
|
|
||||||
if (reverseXY)
|
|
||||||
ApplyDecorationPoint(y, x, colR, colG, colB, colA, mode, cBrush);
|
|
||||||
else
|
|
||||||
ApplyDecorationPoint(x, y, colR, colG, colB, colA, mode, cBrush);
|
|
||||||
}
|
|
||||||
e -= 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Simulation::ApplyDecorationBox(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
if (x1>x2)
|
|
||||||
{
|
|
||||||
i = x2;
|
|
||||||
x2 = x1;
|
|
||||||
x1 = i;
|
|
||||||
}
|
|
||||||
if (y1>y2)
|
|
||||||
{
|
|
||||||
j = y2;
|
|
||||||
y2 = y1;
|
|
||||||
y1 = j;
|
|
||||||
}
|
|
||||||
for (j=y1; j<=y2; j++)
|
|
||||||
for (i=x1; i<=x2; i++)
|
|
||||||
ApplyDecoration(i, j, colR, colG, colB, colA, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Simulation::ColorCompare(Renderer *ren, int x, int y, int replaceR, int replaceG, int replaceB)
|
|
||||||
{
|
|
||||||
pixel pix = ren->vid[x+y*WINDOWW];
|
|
||||||
int r = PIXR(pix);
|
|
||||||
int g = PIXG(pix);
|
|
||||||
int b = PIXB(pix);
|
|
||||||
int diff = std::abs(replaceR-r) + std::abs(replaceG-g) + std::abs(replaceB-b);
|
|
||||||
return diff < 15;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Simulation::ApplyDecorationFill(Renderer *ren, int x, int y, int colR, int colG, int colB, int colA, int replaceR, int replaceG, int replaceB)
|
|
||||||
{
|
|
||||||
int x1, x2;
|
|
||||||
char *bitmap = (char*)malloc(XRES*YRES); //Bitmap for checking
|
|
||||||
if (!bitmap)
|
|
||||||
return;
|
|
||||||
memset(bitmap, 0, XRES*YRES);
|
|
||||||
|
|
||||||
if (!ColorCompare(ren, x, y, replaceR, replaceG, replaceB)) {
|
|
||||||
free(bitmap);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
CoordStack& cs = getCoordStackSingleton();
|
|
||||||
cs.clear();
|
|
||||||
|
|
||||||
cs.push(x, y);
|
|
||||||
do
|
|
||||||
{
|
|
||||||
cs.pop(x, y);
|
|
||||||
x1 = x2 = x;
|
|
||||||
// go left as far as possible
|
|
||||||
while (x1>0)
|
|
||||||
{
|
|
||||||
if (bitmap[(x1-1)+y*XRES] || !ColorCompare(ren, x1-1, y, replaceR, replaceG, replaceB))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
x1--;
|
|
||||||
}
|
|
||||||
// go right as far as possible
|
|
||||||
while (x2<XRES-1)
|
|
||||||
{
|
|
||||||
if (bitmap[(x1+1)+y*XRES] || !ColorCompare(ren, x2+1, y, replaceR, replaceG, replaceB))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
x2++;
|
|
||||||
}
|
|
||||||
// fill span
|
|
||||||
for (x=x1; x<=x2; x++)
|
|
||||||
{
|
|
||||||
ApplyDecoration(x, y, colR, colG, colB, colA, DECO_DRAW);
|
|
||||||
bitmap[x+y*XRES] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y >= 1)
|
|
||||||
for (x=x1; x<=x2; x++)
|
|
||||||
if (!bitmap[x+(y-1)*XRES] && ColorCompare(ren, x, y-1, replaceR, replaceG, replaceB))
|
|
||||||
cs.push(x, y-1);
|
|
||||||
|
|
||||||
if (y < YRES-1)
|
|
||||||
for (x=x1; x<=x2; x++)
|
|
||||||
if (!bitmap[x+(y+1)*XRES] && ColorCompare(ren, x, y+1, replaceR, replaceG, replaceB))
|
|
||||||
cs.push(x, y+1);
|
|
||||||
} while (cs.getSize() > 0);
|
|
||||||
}
|
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << e.what() << std::endl;
|
|
||||||
free(bitmap);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
free(bitmap);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int Simulation::Tool(int x, int y, int tool, int brushX, int brushY, float strength)
|
int Simulation::Tool(int x, int y, int tool, int brushX, int brushY, float strength)
|
||||||
{
|
{
|
||||||
Particle * cpart = NULL;
|
Particle * cpart = NULL;
|
||||||
@ -1372,94 +1006,6 @@ int Simulation::Tool(int x, int y, int tool, int brushX, int brushY, float stren
|
|||||||
return tools[tool].Perform(this, cpart, x, y, brushX, brushY, strength);
|
return tools[tool].Perform(this, cpart, x, y, brushX, brushY, strength);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef RENDERER
|
|
||||||
int Simulation::ToolBrush(int positionX, int positionY, int tool, Brush * cBrush, float strength)
|
|
||||||
{
|
|
||||||
if(cBrush)
|
|
||||||
{
|
|
||||||
int radiusX = cBrush->GetRadius().X, radiusY = cBrush->GetRadius().Y, sizeX = cBrush->GetSize().X, sizeY = cBrush->GetSize().Y;
|
|
||||||
unsigned char *bitmap = cBrush->GetBitmap();
|
|
||||||
for(int y = 0; y < sizeY; y++)
|
|
||||||
for(int x = 0; x < sizeX; x++)
|
|
||||||
if(bitmap[(y*sizeX)+x] && (positionX+(x-radiusX) >= 0 && positionY+(y-radiusY) >= 0 && positionX+(x-radiusX) < XRES && positionY+(y-radiusY) < YRES))
|
|
||||||
Tool(positionX + (x - radiusX), positionY + (y - radiusY), tool, positionX, positionY, strength);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Simulation::ToolLine(int x1, int y1, int x2, int y2, int tool, Brush * cBrush, float strength)
|
|
||||||
{
|
|
||||||
bool reverseXY = abs(y2-y1) > abs(x2-x1);
|
|
||||||
int x, y, dx, dy, sy, rx = cBrush->GetRadius().X, ry = cBrush->GetRadius().Y;
|
|
||||||
float e = 0.0f, de;
|
|
||||||
if (reverseXY)
|
|
||||||
{
|
|
||||||
y = x1;
|
|
||||||
x1 = y1;
|
|
||||||
y1 = y;
|
|
||||||
y = x2;
|
|
||||||
x2 = y2;
|
|
||||||
y2 = y;
|
|
||||||
}
|
|
||||||
if (x1 > x2)
|
|
||||||
{
|
|
||||||
y = x1;
|
|
||||||
x1 = x2;
|
|
||||||
x2 = y;
|
|
||||||
y = y1;
|
|
||||||
y1 = y2;
|
|
||||||
y2 = y;
|
|
||||||
}
|
|
||||||
dx = x2 - x1;
|
|
||||||
dy = abs(y2 - y1);
|
|
||||||
de = dx ? dy/(float)dx : 0.0f;
|
|
||||||
y = y1;
|
|
||||||
sy = (y1<y2) ? 1 : -1;
|
|
||||||
for (x=x1; x<=x2; x++)
|
|
||||||
{
|
|
||||||
if (reverseXY)
|
|
||||||
ToolBrush(y, x, tool, cBrush, strength);
|
|
||||||
else
|
|
||||||
ToolBrush(x, y, tool, cBrush, strength);
|
|
||||||
e += de;
|
|
||||||
if (e >= 0.5f)
|
|
||||||
{
|
|
||||||
y += sy;
|
|
||||||
if (!(rx+ry) && ((y1<y2) ? (y<=y2) : (y>=y2)))
|
|
||||||
{
|
|
||||||
if (reverseXY)
|
|
||||||
ToolBrush(y, x, tool, cBrush, strength);
|
|
||||||
else
|
|
||||||
ToolBrush(x, y, tool, cBrush, strength);
|
|
||||||
}
|
|
||||||
e -= 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Simulation::ToolBox(int x1, int y1, int x2, int y2, int tool, float strength)
|
|
||||||
{
|
|
||||||
int brushX, brushY;
|
|
||||||
brushX = ((x1 + x2) / 2);
|
|
||||||
brushY = ((y1 + y2) / 2);
|
|
||||||
int i, j;
|
|
||||||
if (x1>x2)
|
|
||||||
{
|
|
||||||
i = x2;
|
|
||||||
x2 = x1;
|
|
||||||
x1 = i;
|
|
||||||
}
|
|
||||||
if (y1>y2)
|
|
||||||
{
|
|
||||||
j = y2;
|
|
||||||
y2 = y1;
|
|
||||||
y1 = j;
|
|
||||||
}
|
|
||||||
for (j=y1; j<=y2; j++)
|
|
||||||
for (i=x1; i<=x2; i++)
|
|
||||||
Tool(i, j, tool, brushX, brushY, strength);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int Simulation::CreateWalls(int x, int y, int rx, int ry, int wall, Brush * cBrush)
|
int Simulation::CreateWalls(int x, int y, int rx, int ry, int wall, Brush * cBrush)
|
||||||
{
|
{
|
||||||
if(cBrush)
|
if(cBrush)
|
||||||
@ -1647,135 +1193,6 @@ int Simulation::FloodWalls(int x, int y, int wall, int bm)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef RENDERER
|
|
||||||
int Simulation::CreateParts(int positionX, int positionY, int c, Brush * cBrush, int flags)
|
|
||||||
{
|
|
||||||
if (flags == -1)
|
|
||||||
flags = replaceModeFlags;
|
|
||||||
if (cBrush)
|
|
||||||
{
|
|
||||||
int radiusX = cBrush->GetRadius().X, radiusY = cBrush->GetRadius().Y, sizeX = cBrush->GetSize().X, sizeY = cBrush->GetSize().Y;
|
|
||||||
unsigned char *bitmap = cBrush->GetBitmap();
|
|
||||||
|
|
||||||
// special case for LIGH
|
|
||||||
if (c == PT_LIGH)
|
|
||||||
{
|
|
||||||
if (currentTick < lightningRecreate)
|
|
||||||
return 1;
|
|
||||||
int newlife = radiusX + radiusY;
|
|
||||||
if (newlife > 55)
|
|
||||||
newlife = 55;
|
|
||||||
c = PMAP(newlife, c);
|
|
||||||
lightningRecreate = currentTick + std::max(newlife / 4, 1);
|
|
||||||
return CreatePartFlags(positionX, positionY, c, flags);
|
|
||||||
}
|
|
||||||
else if (c == PT_TESC)
|
|
||||||
{
|
|
||||||
int newtmp = (radiusX*4+radiusY*4+7);
|
|
||||||
if (newtmp > 300)
|
|
||||||
newtmp = 300;
|
|
||||||
c = PMAP(newtmp, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int y = sizeY-1; y >=0; y--)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < sizeX; x++)
|
|
||||||
{
|
|
||||||
if (bitmap[(y*sizeX)+x] && (positionX+(x-radiusX) >= 0 && positionY+(y-radiusY) >= 0 && positionX+(x-radiusX) < XRES && positionY+(y-radiusY) < YRES))
|
|
||||||
{
|
|
||||||
CreatePartFlags(positionX+(x-radiusX), positionY+(y-radiusY), c, flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Simulation::CreateParts(int x, int y, int rx, int ry, int c, int flags)
|
|
||||||
{
|
|
||||||
bool created = false;
|
|
||||||
|
|
||||||
if (flags == -1)
|
|
||||||
flags = replaceModeFlags;
|
|
||||||
|
|
||||||
// special case for LIGH
|
|
||||||
if (c == PT_LIGH)
|
|
||||||
{
|
|
||||||
if (currentTick < lightningRecreate)
|
|
||||||
return 1;
|
|
||||||
int newlife = rx + ry;
|
|
||||||
if (newlife > 55)
|
|
||||||
newlife = 55;
|
|
||||||
c = PMAP(newlife, c);
|
|
||||||
lightningRecreate = currentTick + std::max(newlife / 4, 1);
|
|
||||||
rx = ry = 0;
|
|
||||||
}
|
|
||||||
else if (c == PT_TESC)
|
|
||||||
{
|
|
||||||
int newtmp = (rx*4+ry*4+7);
|
|
||||||
if (newtmp > 300)
|
|
||||||
newtmp = 300;
|
|
||||||
c = PMAP(newtmp, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = -ry; j <= ry; j++)
|
|
||||||
for (int i = -rx; i <= rx; i++)
|
|
||||||
if (CreatePartFlags(x+i, y+j, c, flags))
|
|
||||||
created = true;
|
|
||||||
return !created;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Simulation::CreateLine(int x1, int y1, int x2, int y2, int c, Brush * cBrush, int flags)
|
|
||||||
{
|
|
||||||
int x, y, dx, dy, sy, rx = cBrush->GetRadius().X, ry = cBrush->GetRadius().Y;
|
|
||||||
bool reverseXY = abs(y2-y1) > abs(x2-x1);
|
|
||||||
float e = 0.0f, de;
|
|
||||||
if (reverseXY)
|
|
||||||
{
|
|
||||||
y = x1;
|
|
||||||
x1 = y1;
|
|
||||||
y1 = y;
|
|
||||||
y = x2;
|
|
||||||
x2 = y2;
|
|
||||||
y2 = y;
|
|
||||||
}
|
|
||||||
if (x1 > x2)
|
|
||||||
{
|
|
||||||
y = x1;
|
|
||||||
x1 = x2;
|
|
||||||
x2 = y;
|
|
||||||
y = y1;
|
|
||||||
y1 = y2;
|
|
||||||
y2 = y;
|
|
||||||
}
|
|
||||||
dx = x2 - x1;
|
|
||||||
dy = abs(y2 - y1);
|
|
||||||
de = dx ? dy/(float)dx : 0.0f;
|
|
||||||
y = y1;
|
|
||||||
sy = (y1<y2) ? 1 : -1;
|
|
||||||
for (x=x1; x<=x2; x++)
|
|
||||||
{
|
|
||||||
if (reverseXY)
|
|
||||||
CreateParts(y, x, c, cBrush, flags);
|
|
||||||
else
|
|
||||||
CreateParts(x, y, c, cBrush, flags);
|
|
||||||
e += de;
|
|
||||||
if (e >= 0.5f)
|
|
||||||
{
|
|
||||||
y += sy;
|
|
||||||
if (!(rx+ry) && ((y1<y2) ? (y<=y2) : (y>=y2)))
|
|
||||||
{
|
|
||||||
if (reverseXY)
|
|
||||||
CreateParts(y, x, c, cBrush, flags);
|
|
||||||
else
|
|
||||||
CreateParts(x, y, c, cBrush, flags);
|
|
||||||
}
|
|
||||||
e -= 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int Simulation::CreatePartFlags(int x, int y, int c, int flags)
|
int Simulation::CreatePartFlags(int x, int y, int c, int flags)
|
||||||
{
|
{
|
||||||
if (x < 0 || y < 0 || x >= XRES || y >= YRES)
|
if (x < 0 || y < 0 || x >= XRES || y >= YRES)
|
||||||
@ -1880,160 +1297,6 @@ void Simulation::CreateLine(int x1, int y1, int x2, int y2, int c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef RENDERER
|
|
||||||
void Simulation::CreateBox(int x1, int y1, int x2, int y2, int c, int flags)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
if (x1>x2)
|
|
||||||
{
|
|
||||||
i = x2;
|
|
||||||
x2 = x1;
|
|
||||||
x1 = i;
|
|
||||||
}
|
|
||||||
if (y1>y2)
|
|
||||||
{
|
|
||||||
j = y2;
|
|
||||||
y2 = y1;
|
|
||||||
y1 = j;
|
|
||||||
}
|
|
||||||
for (j=y2; j>=y1; j--)
|
|
||||||
for (i=x1; i<=x2; i++)
|
|
||||||
CreateParts(i, j, 0, 0, c, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Simulation::FloodParts(int x, int y, int fullc, int cm, int flags)
|
|
||||||
{
|
|
||||||
int c = TYP(fullc);
|
|
||||||
int x1, x2, dy = (c<PT_NUM)?1:CELL;
|
|
||||||
int coord_stack_limit = XRES*YRES;
|
|
||||||
unsigned short (*coord_stack)[2];
|
|
||||||
int coord_stack_size = 0;
|
|
||||||
int created_something = 0;
|
|
||||||
|
|
||||||
// Bitmap for checking where we've already looked
|
|
||||||
auto bitmapPtr = std::unique_ptr<char[]>(new char[XRES * YRES]);
|
|
||||||
char *bitmap = bitmapPtr.get();
|
|
||||||
std::fill(&bitmap[0], &bitmap[0] + XRES * YRES, 0);
|
|
||||||
|
|
||||||
if (cm==-1)
|
|
||||||
{
|
|
||||||
//if initial flood point is out of bounds, do nothing
|
|
||||||
if (c != 0 && (x < CELL || x >= XRES-CELL || y < CELL || y >= YRES-CELL || c == PT_SPRK))
|
|
||||||
return 1;
|
|
||||||
else if (x < 0 || x >= XRES || y < 0 || y >= YRES)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (c == 0)
|
|
||||||
{
|
|
||||||
cm = TYP(pmap[y][x]);
|
|
||||||
if (!cm)
|
|
||||||
{
|
|
||||||
cm = TYP(photons[y][x]);
|
|
||||||
if (!cm)
|
|
||||||
{
|
|
||||||
if (bmap[y/CELL][x/CELL])
|
|
||||||
return FloodWalls(x, y, WL_ERASE, -1);
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cm = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c != 0 && IsWallBlocking(x, y, c))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (!FloodFillPmapCheck(x, y, cm))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
coord_stack = (short unsigned int (*)[2])malloc(sizeof(unsigned short)*2*coord_stack_limit);
|
|
||||||
coord_stack[coord_stack_size][0] = x;
|
|
||||||
coord_stack[coord_stack_size][1] = y;
|
|
||||||
coord_stack_size++;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
coord_stack_size--;
|
|
||||||
x = coord_stack[coord_stack_size][0];
|
|
||||||
y = coord_stack[coord_stack_size][1];
|
|
||||||
x1 = x2 = x;
|
|
||||||
// go left as far as possible
|
|
||||||
while (c?x1>CELL:x1>0)
|
|
||||||
{
|
|
||||||
if (bitmap[(y * XRES) + x1 - 1] || !FloodFillPmapCheck(x1-1, y, cm) || (c != 0 && IsWallBlocking(x1-1, y, c)))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
x1--;
|
|
||||||
}
|
|
||||||
// go right as far as possible
|
|
||||||
while (c?x2<XRES-CELL-1:x2<XRES-1)
|
|
||||||
{
|
|
||||||
if (bitmap[(y * XRES) + x2 + 1] || !FloodFillPmapCheck(x2+1, y, cm) || (c != 0 && IsWallBlocking(x2+1, y, c)))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
x2++;
|
|
||||||
}
|
|
||||||
// fill span
|
|
||||||
for (x=x1; x<=x2; x++)
|
|
||||||
{
|
|
||||||
if (!fullc)
|
|
||||||
{
|
|
||||||
if (elements[cm].Properties&TYPE_ENERGY)
|
|
||||||
{
|
|
||||||
if (photons[y][x])
|
|
||||||
{
|
|
||||||
kill_part(ID(photons[y][x]));
|
|
||||||
created_something = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pmap[y][x])
|
|
||||||
{
|
|
||||||
kill_part(ID(pmap[y][x]));
|
|
||||||
created_something = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (CreateParts(x, y, 0, 0, fullc, flags))
|
|
||||||
created_something = 1;
|
|
||||||
bitmap[(y * XRES) + x] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c?y>=CELL+dy:y>=dy)
|
|
||||||
for (x=x1; x<=x2; x++)
|
|
||||||
if (!bitmap[((y - dy) * XRES) + x] && FloodFillPmapCheck(x, y-dy, cm) && (c == 0 || !IsWallBlocking(x, y-dy, c)))
|
|
||||||
{
|
|
||||||
coord_stack[coord_stack_size][0] = x;
|
|
||||||
coord_stack[coord_stack_size][1] = y-dy;
|
|
||||||
coord_stack_size++;
|
|
||||||
if (coord_stack_size>=coord_stack_limit)
|
|
||||||
{
|
|
||||||
free(coord_stack);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c?y<YRES-CELL-dy:y<YRES-dy)
|
|
||||||
for (x=x1; x<=x2; x++)
|
|
||||||
if (!bitmap[((y + dy) * XRES) + x] && FloodFillPmapCheck(x, y+dy, cm) && (c == 0 || !IsWallBlocking(x, y+dy, c)))
|
|
||||||
{
|
|
||||||
coord_stack[coord_stack_size][0] = x;
|
|
||||||
coord_stack[coord_stack_size][1] = y+dy;
|
|
||||||
coord_stack_size++;
|
|
||||||
if (coord_stack_size>=coord_stack_limit)
|
|
||||||
{
|
|
||||||
free(coord_stack);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (coord_stack_size>0);
|
|
||||||
free(coord_stack);
|
|
||||||
return created_something;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void Simulation::orbitalparts_get(int block1, int block2, int resblock1[], int resblock2[])
|
void Simulation::orbitalparts_get(int block1, int block2, int resblock1[], int resblock2[])
|
||||||
{
|
{
|
||||||
resblock1[0] = (block1&0x000000FF);
|
resblock1[0] = (block1&0x000000FF);
|
||||||
|
@ -20,6 +20,9 @@ subdir('simtools')
|
|||||||
powder_files += simulation_files
|
powder_files += simulation_files
|
||||||
render_files += simulation_files
|
render_files += simulation_files
|
||||||
|
|
||||||
|
powder_files += files(
|
||||||
|
'Editing.cpp',
|
||||||
|
)
|
||||||
if enable_gravfft
|
if enable_gravfft
|
||||||
powder_files += files('FftGravity.cpp')
|
powder_files += files('FftGravity.cpp')
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user