diff --git a/Sources/Audio/ALFuncs.cpp b/Sources/Audio/ALFuncs.cpp
index e5b7800d..537986ce 100644
--- a/Sources/Audio/ALFuncs.cpp
+++ b/Sources/Audio/ALFuncs.cpp
@@ -1,21 +1,21 @@
/*
Copyright (c) 2013 yvt
-
+
This file is part of OpenSpades.
-
+
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see .
-
+
*/
#include "ALFuncs.h"
@@ -168,33 +168,33 @@ namespace al{
static void *GPA(const char *str)
{
if(!alLibrary){
- auto paths = spades::Split(s_alDriver, ";");
- std::string errors;
- for (const std::string &path: paths) {
- auto trimmedPath = spades::TrimSpaces(path);
- try {
- alLibrary = new spades::DynamicLibrary(trimmedPath.c_str());
- if (alLibrary) {
- SPLog("'%s' loaded", trimmedPath.c_str());
- break;
- }
- } catch (const std::exception &ex) {
- errors += trimmedPath;
- errors += ":\n";
- errors += ex.what();
- }
- }
- if (!alLibrary) {
- SPRaise("Failed to load a OpenAL driver.\n%s", errors.c_str());
- }
+ auto paths = spades::Split(s_alDriver, ";");
+ std::string errors;
+ for (const std::string &path: paths) {
+ auto trimmedPath = spades::TrimSpaces(path);
+ try {
+ alLibrary = new spades::DynamicLibrary(trimmedPath.c_str());
+ if (alLibrary) {
+ SPLog("'%s' loaded", trimmedPath.c_str());
+ break;
+ }
+ } catch (const std::exception &ex) {
+ errors += trimmedPath;
+ errors += ":\n";
+ errors += ex.what();
+ }
+ }
+ if (!alLibrary) {
+ SPRaise("Failed to load a OpenAL driver.\n%s", errors.c_str());
+ }
}
-
+
if(qalGetProcAddress){
void *v = qalGetProcAddress(str);
if(v)
return v;
}
-
+
return alLibrary->GetSymbol(str);
}
@@ -204,7 +204,7 @@ namespace al{
void InitEAX(void){
ALCdevice *pDevice = NULL;
ALCcontext *pContext = NULL;
-
+
pContext = qalcGetCurrentContext();
pDevice = qalcGetContextsDevice(pContext);
@@ -246,9 +246,9 @@ namespace al{
SPRaise("Extension not found: '%s'",
ALC_EXT_EFX_NAME);
}
-
+
}
-
+
void Link(void) {
SPLog("Linking with OpenAL library.");
L(alEnable);
@@ -306,7 +306,7 @@ namespace al{
L(alDopplerFactor);
L(alDopplerVelocity);
L(alDistanceModel);
-
+
L(alcCreateContext);
L(alcMakeContextCurrent);
L(alcProcessContext);
@@ -322,9 +322,9 @@ namespace al{
L(alcGetEnumValue);
L(alcGetString);
L(alcGetIntegerv);
-
+
}
-
+
const char *DescribeError(ALenum e){
switch(e){
case AL_NO_ERROR:
@@ -343,7 +343,7 @@ namespace al{
return "Unknown error";
}
}
-
+
void CheckError(void){
ALenum e;
e = qalGetError();
@@ -354,7 +354,7 @@ namespace al{
SPLog("OpenAL error %d: %s", (int)e, DescribeError(e));
}
}
-
+
void CheckError(const char *source, const char *fun, int line){
ALenum e;
e = qalGetError();
diff --git a/Sources/Client/ClientPlayer.cpp b/Sources/Client/ClientPlayer.cpp
index 2acd48d8..8976cf17 100644
--- a/Sources/Client/ClientPlayer.cpp
+++ b/Sources/Client/ClientPlayer.cpp
@@ -1,21 +1,21 @@
/*
Copyright (c) 2013 yvt
-
+
This file is part of OpenSpades.
-
+
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see .
-
+
*/
@@ -49,15 +49,15 @@ DEFINE_SPADES_SETTING(cg_animations, "1");
namespace spades {
namespace client {
-
+
class SandboxedRenderer : public IRenderer {
Handle base;
AABB3 clipBox;
bool allowDepthHack;
-
+
void OnProhibitedAction() {
}
-
+
bool CheckVisibility(const AABB3 &box) {
if (!clipBox.Contains(box) ||
!std::isfinite(box.min.x) || !std::isfinite(box.min.y) || !std::isfinite(box.min.z) ||
@@ -70,46 +70,46 @@ namespace spades {
protected:
~SandboxedRenderer(){}
public:
-
+
SandboxedRenderer(IRenderer *base) :
base(base) {}
-
+
void SetClipBox(const AABB3 &b)
{ clipBox = b; }
void SetAllowDepthHack(bool h)
{ allowDepthHack = h; }
-
+
void Init() { OnProhibitedAction(); }
void Shutdown() { OnProhibitedAction(); }
-
+
IImage *RegisterImage(const char *filename)
{ return base->RegisterImage(filename); }
IModel *RegisterModel(const char *filename)
{ return base->RegisterModel(filename); }
-
+
IImage *CreateImage(Bitmap *bmp)
{ return base->CreateImage(bmp); }
IModel *CreateModel(VoxelModel *m)
{ return base->CreateModel(m); }
-
+
void SetGameMap(GameMap *)
{ OnProhibitedAction(); }
-
+
void SetFogDistance(float)
{ OnProhibitedAction(); }
void SetFogColor(Vector3)
{ OnProhibitedAction(); }
-
+
void StartScene(const SceneDefinition&)
{ OnProhibitedAction(); }
-
+
void AddLight(const client::DynamicLightParam& light) {
Vector3 rad(light.radius, light.radius, light.radius);
if (CheckVisibility(AABB3(light.origin - rad, light.origin + rad))) {
base->AddLight(light);
}
}
-
+
void RenderModel(IModel *model, const ModelRenderParam& p) {
if (!model) {
SPInvalidArgument("model");
@@ -127,7 +127,7 @@ namespace spades {
void AddDebugLine(Vector3 a, Vector3 b, Vector4 color) {
OnProhibitedAction();
}
-
+
void AddSprite(IImage *image, Vector3 center, float radius, float rotation) {
Vector3 rad(radius * 1.5f, radius * 1.5f, radius * 1.5f);
if (CheckVisibility(AABB3(center - rad, center + rad))) {
@@ -144,11 +144,11 @@ namespace spades {
base->AddLongSprite(image, p1, p2, radius);
}
}
-
+
void EndScene() { OnProhibitedAction(); }
-
+
void MultiplyScreenColor(Vector3) { OnProhibitedAction(); }
-
+
/** Sets color for image drawing. Deprecated because
* some methods treats this as an alpha premultiplied, while
* others treats this as an alpha non-premultiplied.
@@ -156,12 +156,12 @@ namespace spades {
void SetColor(Vector4 col) {
base->SetColor(col);
}
-
+
/** Sets color for image drawing. Always alpha premultiplied. */
void SetColorAlphaPremultiplied(Vector4 col) {
base->SetColorAlphaPremultiplied(col);
}
-
+
void DrawImage(IImage *img, const Vector2& outTopLeft)
{
if (allowDepthHack)
@@ -197,28 +197,28 @@ namespace spades {
else
OnProhibitedAction();
}
-
+
void DrawFlatGameMap(const AABB2& outRect, const AABB2& inRect)
{ OnProhibitedAction(); }
-
+
void FrameDone()
{ OnProhibitedAction(); }
-
+
void Flip()
{ OnProhibitedAction(); }
-
+
Bitmap *ReadBitmap()
{ OnProhibitedAction(); return nullptr; }
-
+
float ScreenWidth() { return base->ScreenWidth(); }
float ScreenHeight() { return base->ScreenHeight(); }
};
-
+
ClientPlayer::ClientPlayer(Player *p,
Client *c):
player(p), client(c){
SPADES_MARK_FUNCTION();
-
+
sprintState = 0.f;
aimDownState = 0.f;
toolRaiseState = 0.f;
@@ -226,32 +226,32 @@ namespace spades {
localFireVibrationTime = -100.f;
time = 0.f;
viewWeaponOffset = MakeVector3(0, 0, 0);
-
+
ScriptContextHandle ctx;
IRenderer *renderer = client->GetRenderer();
IAudioDevice *audio = client->GetAudioDevice();
-
+
sandboxedRenderer.Set(new SandboxedRenderer(renderer), false);
renderer = sandboxedRenderer;
-
+
static ScriptFunction spadeFactory("ISpadeSkin@ CreateThirdPersonSpadeSkin(Renderer@, AudioDevice@)");
spadeSkin = initScriptFactory( spadeFactory, renderer, audio );
-
+
static ScriptFunction spadeViewFactory("ISpadeSkin@ CreateViewSpadeSkin(Renderer@, AudioDevice@)");
spadeViewSkin = initScriptFactory( spadeViewFactory, renderer, audio );
-
+
static ScriptFunction blockFactory("IBlockSkin@ CreateThirdPersonBlockSkin(Renderer@, AudioDevice@)");
blockSkin = initScriptFactory( blockFactory, renderer, audio );
-
+
static ScriptFunction blockViewFactory("IBlockSkin@ CreateViewBlockSkin(Renderer@, AudioDevice@)");
blockViewSkin = initScriptFactory( blockViewFactory, renderer, audio );
-
+
static ScriptFunction grenadeFactory("IGrenadeSkin@ CreateThirdPersonGrenadeSkin(Renderer@, AudioDevice@)");
grenadeSkin = initScriptFactory( grenadeFactory, renderer, audio );
-
+
static ScriptFunction grenadeViewFactory("IGrenadeSkin@ CreateViewGrenadeSkin(Renderer@, AudioDevice@)");
grenadeViewSkin = initScriptFactory( grenadeViewFactory, renderer, audio );
-
+
static ScriptFunction rifleFactory("IWeaponSkin@ CreateThirdPersonRifleSkin(Renderer@, AudioDevice@)");
static ScriptFunction smgFactory("IWeaponSkin@ CreateThirdPersonSMGSkin(Renderer@, AudioDevice@)");
static ScriptFunction shotgunFactory("IWeaponSkin@ CreateThirdPersonShotgunSkin(Renderer@, AudioDevice@)");
@@ -274,19 +274,19 @@ namespace spades {
default:
SPAssert(false);
}
-
+
}
ClientPlayer::~ClientPlayer() {
spadeSkin->Release();
blockSkin->Release();
weaponSkin->Release();
grenadeSkin->Release();
-
+
spadeViewSkin->Release();
blockViewSkin->Release();
weaponViewSkin->Release();
grenadeViewSkin->Release();
-
+
}
asIScriptObject* ClientPlayer::initScriptFactory( ScriptFunction& creator, IRenderer* renderer, IAudioDevice* audio )
@@ -303,12 +303,12 @@ namespace spades {
void ClientPlayer::Invalidate() {
player = NULL;
}
-
+
bool ClientPlayer::IsChangingTool() {
return currentTool != player->GetTool() ||
toolRaiseState < .999f;
}
-
+
float ClientPlayer::GetLocalFireVibration() {
float localFireVibration = 0.f;
localFireVibration = time - localFireVibrationTime;
@@ -317,10 +317,10 @@ namespace spades {
localFireVibration = 0.f;
return localFireVibration;
}
-
+
void ClientPlayer::Update(float dt) {
time += dt;
-
+
PlayerInput actualInput = player->GetInput();
WeaponInput actualWeapInput = player->GetWeaponInput();
Vector3 vel = player->GetVelocty();
@@ -335,29 +335,29 @@ namespace spades {
if(sprintState < 0.f)
sprintState = 0.f;
}
-
+
if(actualWeapInput.secondary && player->IsToolWeapon() &&
player->IsAlive()){
- // This is the only animation that can be turned off
- // here; others affect the gameplay directly and
- // turning them off would be considered cheating
- if (cg_animations) {
- aimDownState += dt * 8.f;
- if(aimDownState > 1.f)
- aimDownState = 1.f;
- } else {
- aimDownState = 1.f;
- }
- }else{
- if (cg_animations) {
- aimDownState -= dt * 3.f;
- if(aimDownState < 0.f)
- aimDownState = 0.f;
- } else {
- aimDownState = 0.f;
- }
+ // This is the only animation that can be turned off
+ // here; others affect the gameplay directly and
+ // turning them off would be considered cheating
+ if (cg_animations) {
+ aimDownState += dt * 8.f;
+ if(aimDownState > 1.f)
+ aimDownState = 1.f;
+ } else {
+ aimDownState = 1.f;
+ }
+ }else{
+ if (cg_animations) {
+ aimDownState -= dt * 3.f;
+ if(aimDownState < 0.f)
+ aimDownState = 0.f;
+ } else {
+ aimDownState = 0.f;
+ }
}
-
+
if(currentTool == player->GetTool()) {
toolRaiseState += dt * 4.f;
if(toolRaiseState > 1.f)
@@ -369,7 +369,7 @@ namespace spades {
if(toolRaiseState < 0.f){
toolRaiseState = 0.f;
currentTool = player->GetTool();
-
+
// play tool change sound
if(player->IsLocalPlayer()) {
auto *audioDevice = client->GetAudioDevice();
@@ -393,7 +393,7 @@ namespace spades {
c = audioDevice->RegisterSound("Sounds/Weapons/Shotgun/RaiseLocal.wav");
break;
}
-
+
break;
case Player::ToolGrenade:
c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/RaiseLocal.wav");
@@ -406,7 +406,7 @@ namespace spades {
toolRaiseState = 1.f;
}
}
-
+
{
float scale = dt;
Vector3 vel = player->GetVelocty();
@@ -418,13 +418,13 @@ namespace spades {
viewWeaponOffset.z += Vector3::Dot(vel, up) * scale;
if(dt > 0.f)
viewWeaponOffset *= powf(.02f, dt);
-
+
if(currentTool == Player::ToolWeapon &&
player->GetWeaponInput().secondary) {
-
+
if(dt > 0.f)
viewWeaponOffset *= powf(.01f, dt);
-
+
const float limitX = .003f;
const float limitY = .003f;
if(viewWeaponOffset.x < -limitX)
@@ -437,7 +437,7 @@ namespace spades {
viewWeaponOffset.z = Mix(viewWeaponOffset.z, limitY, .5f);
}
}
-
+
// FIXME: should do for non-active skins?
asIScriptObject *skin;
if(ShouldRenderInThirdPersonView()){
@@ -470,17 +470,17 @@ namespace spades {
interface.Update(dt);
}
}
-
+
Matrix4 ClientPlayer::GetEyeMatrix() {
Player *p = player;
return Matrix4::FromAxis(-p->GetRight(), p->GetFront(), -p->GetUp(), p->GetEye());
}
-
+
void ClientPlayer::SetSkinParameterForTool(Player::ToolType type,
asIScriptObject *skin) {
Player *p = player;
if(currentTool == Player::ToolSpade) {
-
+
ScriptISpadeSkin interface(skin);
WeaponInput inp = p->GetWeaponInput();
if(p->GetTool() != Player::ToolSpade){
@@ -499,7 +499,7 @@ namespace spades {
interface.SetActionProgress(0.f);
}
}else if(currentTool == Player::ToolBlock) {
-
+
// TODO: smooth ready state
ScriptIBlockSkin interface(skin);
if(p->GetTool() != Player::ToolBlock){
@@ -511,13 +511,13 @@ namespace spades {
}else{
interface.SetReadyState(0.f);
}
-
+
interface.SetBlockColor(MakeVector3(p->GetBlockColor()) / 255.f);
}else if(currentTool == Player::ToolGrenade) {
-
+
ScriptIGrenadeSkin interface(skin);
interface.SetReadyState(1.f - p->GetTimeToNextGrenade() / 0.5f);
-
+
WeaponInput inp = p->GetWeaponInput();
if(inp.primary) {
interface.SetCookTime(p->GetGrenadeCookTime());
@@ -525,7 +525,7 @@ namespace spades {
interface.SetCookTime(0.f);
}
}else if(currentTool == Player::ToolWeapon) {
-
+
Weapon *w = p->GetWeapon();
ScriptIWeaponSkin interface(skin);
interface.SetReadyState(1.f - w->TimeToNextFire() / w->GetDelay());
@@ -538,7 +538,7 @@ namespace spades {
SPInvalidEnum("currentTool", currentTool);
}
}
-
+
void ClientPlayer::SetCommonSkinParameter(asIScriptObject *skin){
asIScriptObject *curSkin;
if(ShouldRenderInThirdPersonView()){
@@ -566,7 +566,7 @@ namespace spades {
SPInvalidEnum("currentTool", currentTool);
}
}
-
+
float sprint = SmoothStep(sprintState);
float putdown = 1.f - toolRaiseState;
putdown *= putdown;
@@ -580,22 +580,22 @@ namespace spades {
interface.SetMuted(client->IsMuted());
}
}
-
+
void ClientPlayer::AddToSceneFirstPersonView() {
Player *p = player;
IRenderer *renderer = client->GetRenderer();
World *world = client->GetWorld();
Matrix4 eyeMatrix = GetEyeMatrix();
-
+
sandboxedRenderer->SetClipBox(AABB3(eyeMatrix.GetOrigin() - Vector3(20.f, 20.f, 20.f),
eyeMatrix.GetOrigin() + Vector3(20.f, 20.f, 20.f)));
sandboxedRenderer->SetAllowDepthHack(true);
-
+
if(client->flashlightOn){
float brightness;
brightness = client->time - client->flashlightOnTime;
brightness = 1.f - expf(-brightness * 5.f);
-
+
// add flash light
DynamicLightParam light;
light.origin = (eyeMatrix * MakeVector3(0, -0.05f, -0.1f)).GetXYZ();
@@ -608,26 +608,26 @@ namespace spades {
light.spotAxis[2] = p->GetFront();
light.image = renderer->RegisterImage("Gfx/Spotlight.png");
renderer->AddLight(light);
-
+
light.color *= .3f;
light.radius = 10.f;
light.type = DynamicLightTypePoint;
light.image = NULL;
renderer->AddLight(light);
-
+
// add glare
renderer->SetColorAlphaPremultiplied(MakeVector4(1, .7f, .5f, 0) * brightness * .3f);
renderer->AddSprite(renderer->RegisterImage("Gfx/Glare.png"), (eyeMatrix * MakeVector3(0, 0.3f, -0.3f)).GetXYZ(), .8f, 0.f);
}
-
+
Vector3 leftHand, rightHand;
leftHand = MakeVector3(0, 0, 0);
rightHand = MakeVector3(0, 0, 0);
-
+
// view weapon
-
+
Vector3 viewWeaponOffset = this->viewWeaponOffset;
-
+
// bobbing
{
float sp = 1.f - aimDownState;
@@ -638,19 +638,19 @@ namespace spades {
vl *= vl;
viewWeaponOffset.z += vl * 0.012f * sp;
}
-
+
// slow pulse
{
float sp = 1.f - aimDownState;
float vl = sinf(world->GetTime() * 1.f);
-
+
viewWeaponOffset.x += vl * 0.001f * sp;
viewWeaponOffset.y += vl * 0.0007f * sp;
viewWeaponOffset.z += vl * 0.003f * sp;
}
-
+
asIScriptObject *skin;
-
+
if(currentTool == Player::ToolSpade) {
skin = spadeViewSkin;
}else if(currentTool == Player::ToolBlock) {
@@ -662,11 +662,11 @@ namespace spades {
}else{
SPInvalidEnum("currentTool", currentTool);
}
-
+
SetSkinParameterForTool(currentTool, skin);
-
+
SetCommonSkinParameter(skin);
-
+
// common process
{
ScriptIViewToolSkin interface(skin);
@@ -682,23 +682,23 @@ namespace spades {
leftHand = interface.GetLeftHandPosition();
rightHand = interface.GetRightHandPosition();
}
-
+
// view hands
if(leftHand.GetPoweredLength() > 0.001f &&
rightHand.GetPoweredLength() > 0.001f){
-
-
+
+
ModelRenderParam param;
param.depthHack = true;
-
+
IModel *model = renderer->RegisterModel("Models/Player/Arm.kv6");
IModel *model2 = renderer->RegisterModel("Models/Player/UpperArm.kv6");
-
+
IntVector3 col = p->GetColor();
param.customColor = MakeVector3(col.x/255.f, col.y/255.f, col.z/255.f);
-
+
const float armlen = 0.5f;
-
+
Vector3 shoulders[] = {{0.4f, 0.0f, 0.25f},
{-0.4f, 0.0f, 0.25f}};
Vector3 hands[] = {leftHand, rightHand};
@@ -708,65 +708,65 @@ namespace spades {
Vector3 shoulder = shoulders[i];
Vector3 hand = hands[i];
Vector3 benddir = benddirs[i];
-
+
float len2 = (hand - shoulder).GetPoweredLength();
// len2/4 + x^2 = armlen^2
float bendlen = sqrtf(std::max(armlen*armlen - len2*.25f, 0.f));
-
+
Vector3 bend = Vector3::Cross(benddir, hand-shoulder);
bend = bend.Normalize();
-
+
if(bend.z < 0.f) bend.z = -bend.z;
-
+
Vector3 elbow = (hand + shoulder) * .5f;
elbow += bend * bendlen;
-
+
{
Vector3 axises[3];
axises[2] = (hand - elbow).Normalize();
axises[0] = MakeVector3(0, 0, 1);
axises[1] = Vector3::Cross(axises[2], axises[0]).Normalize();
axises[0] = Vector3::Cross(axises[1], axises[2]).Normalize();
-
+
Matrix4 mat = Matrix4::Scale(.05f);
mat = Matrix4::FromAxis(axises[0], axises[1], axises[2], elbow) * mat;
mat = eyeMatrix * mat;
-
+
param.matrix = mat;
renderer->RenderModel(model, param);
}
-
+
{
Vector3 axises[3];
axises[2] = (elbow - shoulder).Normalize();
axises[0] = MakeVector3(0, 0, 1);
axises[1] = Vector3::Cross(axises[2], axises[0]).Normalize();
axises[0] = Vector3::Cross(axises[1], axises[2]).Normalize();
-
+
Matrix4 mat = Matrix4::Scale(.05f);
mat = Matrix4::FromAxis(axises[0], axises[1], axises[2], shoulder) * mat;
mat = eyeMatrix * mat;
-
+
param.matrix = mat;
renderer->RenderModel(model2, param);
}
}
-
+
}
-
+
// --- local view ends
-
+
}
-
-
+
+
void ClientPlayer::AddToSceneThirdPersonView() {
Player *p = player;
IRenderer *renderer = client->GetRenderer();
World *world = client->GetWorld();
-
-
-
+
+
+
if(!p->IsAlive()){
if(!cg_ragdoll){
ModelRenderParam param;
@@ -774,21 +774,21 @@ namespace spades {
param.matrix = param.matrix * Matrix4::Scale(.1f);
IntVector3 col = p->GetColor();
param.customColor = MakeVector3(col.x/255.f, col.y/255.f, col.z/255.f);
-
+
IModel *model = renderer->RegisterModel("Models/Player/Dead.kv6");
renderer->RenderModel(model, param);
}
return;
}
-
+
auto origin = p->GetOrigin();
sandboxedRenderer->SetClipBox(AABB3(origin - Vector3(2.f, 2.f, 4.f),
origin + Vector3(2.f, 2.f, 2.f)));
sandboxedRenderer->SetAllowDepthHack(false);
-
+
// ready for tool rendering
asIScriptObject *skin;
-
+
if(currentTool == Player::ToolSpade) {
skin = spadeSkin;
}else if(currentTool == Player::ToolBlock) {
@@ -800,107 +800,107 @@ namespace spades {
}else{
SPInvalidEnum("currentTool", currentTool);
}
-
+
SetSkinParameterForTool(currentTool, skin);
-
+
SetCommonSkinParameter(skin);
-
+
float pitchBias;
{
ScriptIThirdPersonToolSkin interface(skin);
pitchBias = interface.GetPitchBias();
}
-
+
ModelRenderParam param;
IModel *model;
Vector3 front = p->GetFront();
IntVector3 col = p->GetColor();
param.customColor = MakeVector3(col.x/255.f, col.y/255.f, col.z/255.f);
-
+
float yaw = atan2(front.y, front.x) + M_PI * .5f;
float pitch = -atan2(front.z, sqrt(front.x * front.x + front.y * front.y));
-
+
// lower axis
Matrix4 lower = Matrix4::Translate(p->GetOrigin());
lower = lower * Matrix4::Rotate(MakeVector3(0,0,1), yaw);
-
+
Matrix4 scaler = Matrix4::Scale(0.1f);
scaler = scaler * Matrix4::Scale(-1,-1,1);
-
+
PlayerInput inp = p->GetInput();
-
+
// lower
Matrix4 torso, head, arms;
if(inp.crouch){
Matrix4 leg1 = Matrix4::Translate(-0.25f, 0.2f, -0.1f);
Matrix4 leg2 = Matrix4::Translate( 0.25f, 0.2f, -0.1f);
-
+
float ang = sinf(p->GetWalkAnimationProgress() * M_PI * 2.f) * 0.6f;
float walkVel = Vector3::Dot(p->GetVelocty(), p->GetFront2D()) * 4.f;
leg1 = leg1 * Matrix4::Rotate(MakeVector3(1,0,0), ang * walkVel);
leg2 = leg2 * Matrix4::Rotate(MakeVector3(1,0,0), -ang * walkVel);
-
+
walkVel = Vector3::Dot(p->GetVelocty(), p->GetRight()) * 3.f;
leg1 = leg1 * Matrix4::Rotate(MakeVector3(0,1,0), ang * walkVel);
leg2 = leg2 * Matrix4::Rotate(MakeVector3(0,1,0), -ang * walkVel);
-
+
leg1 = lower * leg1;
leg2 = lower * leg2;
-
+
model = renderer->RegisterModel("Models/Player/LegCrouch.kv6");
param.matrix = leg1 * scaler;
renderer->RenderModel(model, param);
param.matrix = leg2 * scaler;
renderer->RenderModel(model, param);
-
+
torso = Matrix4::Translate(0.f,0.f,-0.55f);
torso = lower * torso;
-
+
model = renderer->RegisterModel("Models/Player/TorsoCrouch.kv6");
param.matrix = torso * scaler;
renderer->RenderModel(model, param);
-
+
head = Matrix4::Translate(0.f,0.f,-0.0f);
head = torso * head;
-
+
arms = Matrix4::Translate(0.f,0.f,-0.0f);
arms = torso * arms;
}else{
Matrix4 leg1 = Matrix4::Translate(-0.25f, 0.f, -0.1f);
Matrix4 leg2 = Matrix4::Translate( 0.25f, 0.f, -0.1f);
-
+
float ang = sinf(p->GetWalkAnimationProgress() * M_PI * 2.f) * 0.6f;
float walkVel = Vector3::Dot(p->GetVelocty(), p->GetFront2D()) * 4.f;
leg1 = leg1 * Matrix4::Rotate(MakeVector3(1,0,0), ang * walkVel);
leg2 = leg2 * Matrix4::Rotate(MakeVector3(1,0,0), -ang * walkVel);
-
+
walkVel = Vector3::Dot(p->GetVelocty(), p->GetRight()) * 3.f;
leg1 = leg1 * Matrix4::Rotate(MakeVector3(0,1,0), ang * walkVel);
leg2 = leg2 * Matrix4::Rotate(MakeVector3(0,1,0), -ang * walkVel);
-
+
leg1 = lower * leg1;
leg2 = lower * leg2;
-
+
model = renderer->RegisterModel("Models/Player/Leg.kv6");
param.matrix = leg1 * scaler;
renderer->RenderModel(model, param);
param.matrix = leg2 * scaler;
renderer->RenderModel(model, param);
-
+
torso = Matrix4::Translate(0.f,0.f,-1.0f);
torso = lower * torso;
-
+
model = renderer->RegisterModel("Models/Player/Torso.kv6");
param.matrix = torso * scaler;
renderer->RenderModel(model, param);
-
+
head = Matrix4::Translate(0.f,0.f,-0.0f);
head = torso * head;
-
+
arms = Matrix4::Translate(0.f,0.f,0.1f);
arms = torso * arms;
}
-
+
float armPitch = pitch;
if(inp.sprint) {
armPitch -= .5f;
@@ -910,20 +910,20 @@ namespace spades {
armPitch = std::max(armPitch, -(float)M_PI * .5f);
armPitch *= .9f;
}
-
+
arms = arms * Matrix4::Rotate(MakeVector3(1,0,0), armPitch);
-
+
model = renderer->RegisterModel("Models/Player/Arms.kv6");
param.matrix = arms * scaler;
renderer->RenderModel(model, param);
-
-
+
+
head = head * Matrix4::Rotate(MakeVector3(1,0,0), pitch);
-
+
model = renderer->RegisterModel("Models/Player/Head.kv6");
param.matrix = head * scaler;
renderer->RenderModel(model, param);
-
+
// draw tool
{
ScriptIThirdPersonToolSkin interface(skin);
@@ -933,8 +933,8 @@ namespace spades {
ScriptIToolSkin interface(skin);
interface.AddToScene();
}
-
-
+
+
// draw intel in ctf
IGameMode* mode = world->GetMode();
if( mode && IGameMode::m_CTF == mode->ModeType() ){
@@ -943,35 +943,35 @@ namespace spades {
if(tId < 3){
CTFGameMode::Team& team = ctfMode->GetTeam(p->GetTeamId());
if(team.hasIntel && team.carrier == p->GetId()){
-
+
IntVector3 col2 = world->GetTeam(1-p->GetTeamId()).color;
param.customColor = MakeVector3(col2.x/255.f, col2.y/255.f, col2.z/255.f);
Matrix4 mIntel = torso * Matrix4::Translate(0,0.6f,0.5f);
-
+
model = renderer->RegisterModel("Models/MapObjects/Intel.kv6");
param.matrix = mIntel * scaler;
renderer->RenderModel(model, param);
-
+
param.customColor = MakeVector3(col.x/255.f, col.y/255.f, col.z/255.f);
}
}
}
-
+
// third person player rendering, done
}
-
+
void ClientPlayer::AddToScene() {
SPADES_MARK_FUNCTION();
-
+
Player *p = player;
IRenderer *renderer = client->GetRenderer();
const SceneDefinition& lastSceneDef = client->GetLastSceneDef();
-
+
if(p->GetTeamId() >= 2){
// spectator, or dummy player
return;
-
+
}
// debug
if(false){
@@ -979,23 +979,23 @@ namespace spades {
renderer->SetColorAlphaPremultiplied(MakeVector4(1, 0, 0, 0));
renderer->AddLongSprite(img, lastSceneDef.viewOrigin + MakeVector3(0, 0, 1), p->GetOrigin(), 0.5f);
}
-
+
float distancePowered = (p->GetOrigin() - lastSceneDef.viewOrigin).GetPoweredLength();
if(distancePowered > 140.f * 140.f){
return;
}
-
+
if(!ShouldRenderInThirdPersonView()){
AddToSceneFirstPersonView();
} else {
AddToSceneThirdPersonView();
}
}
-
+
void ClientPlayer::Draw2D() {
if(!ShouldRenderInThirdPersonView()) {
asIScriptObject *skin;
-
+
if(currentTool == Player::ToolSpade) {
skin = spadeViewSkin;
}else if(currentTool == Player::ToolBlock) {
@@ -1007,11 +1007,11 @@ namespace spades {
}else{
SPInvalidEnum("currentTool", currentTool);
}
-
+
SetSkinParameterForTool(currentTool, skin);
-
+
SetCommonSkinParameter(skin);
-
+
// common process
{
ScriptIViewToolSkin interface(skin);
@@ -1021,13 +1021,13 @@ namespace spades {
}
}
}
-
+
bool ClientPlayer::ShouldRenderInThirdPersonView() {
if(player != player->GetWorld()->GetLocalPlayer())
return true;
return client->ShouldRenderInThirdPersonView();
}
-
+
void ClientPlayer::FiredWeapon() {
World *world = player->GetWorld();
Vector3 muzzle;
@@ -1035,7 +1035,7 @@ namespace spades {
IRenderer *renderer = client->GetRenderer();
IAudioDevice *audioDevice = client->GetAudioDevice();
Player *p = player;
-
+
// make dlight
{
Vector3 vec;
@@ -1045,12 +1045,12 @@ namespace spades {
.5f,
0.2f);
mat = eyeMatrix * mat;
-
+
vec = (mat * MakeVector3(0, 1, 0)).GetXYZ();
muzzle = vec;
client->MuzzleFire(vec, player->GetFront(), player == world->GetLocalPlayer());
}
-
+
if(cg_ejectBrass){
float dist = (player->GetOrigin() - lastSceneDef.viewOrigin).GetPoweredLength();
if(dist < 130.f * 130.f) {
@@ -1083,7 +1083,7 @@ namespace spades {
if(model){
Vector3 origin;
origin = muzzle - p->GetFront() * 0.5f;
-
+
Vector3 vel;
vel = p->GetFront() * 0.5f + p->GetRight() +
p->GetUp() * 0.2f;
@@ -1097,17 +1097,17 @@ namespace spades {
default:
break;
}
-
+
ILocalEntity *ent;
ent = new GunCasing(client, model, snd, snd2,
origin, p->GetFront(),
vel);
client->AddLocalEntity(ent);
-
+
}
}
}
-
+
asIScriptObject *skin;
// FIXME: what if current tool isn't weapon?
if(ShouldRenderInThirdPersonView()){
@@ -1115,14 +1115,14 @@ namespace spades {
}else{
skin = weaponViewSkin;
}
-
+
{
ScriptIWeaponSkin interface(skin);
interface.WeaponFired();
}
-
+
}
-
+
void ClientPlayer::ReloadingWeapon() {
asIScriptObject *skin;
// FIXME: what if current tool isn't weapon?
@@ -1131,13 +1131,13 @@ namespace spades {
}else{
skin = weaponViewSkin;
}
-
+
{
ScriptIWeaponSkin interface(skin);
interface.ReloadingWeapon();
}
}
-
+
void ClientPlayer::ReloadedWeapon() {
asIScriptObject *skin;
// FIXME: what if current tool isn't weapon?
diff --git a/Sources/Client/Client_Input.cpp b/Sources/Client/Client_Input.cpp
index 72721787..bcc26892 100644
--- a/Sources/Client/Client_Input.cpp
+++ b/Sources/Client/Client_Input.cpp
@@ -1,22 +1,22 @@
/*
Copyright (c) 2013 yvt
based on code of pysnip (c) Mathias Kaerlev 2011-2012.
-
+
This file is part of OpenSpades.
-
+
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see .
-
+
*/
#include "Client.h"
@@ -90,18 +90,18 @@ DEFINE_SPADES_SETTING(cg_keyAutoFocus, "MiddleMouseButton");
namespace spades {
namespace client {
-
+
bool Client::WantsToBeClosed() {
return readyToClose;
}
-
+
bool FirstPersonSpectate = false;
-
+
void Client::Closing() {
SPADES_MARK_FUNCTION();
}
-
+
bool Client::NeedsAbsoluteMouseCoordinate() {
SPADES_MARK_FUNCTION();
if(scriptedUI->NeedsInput()) {
@@ -116,20 +116,20 @@ namespace spades {
}
return false;
}
-
+
void Client::MouseEvent(float x, float y) {
SPADES_MARK_FUNCTION();
-
+
if(scriptedUI->NeedsInput()) {
scriptedUI->MouseEvent(x, y);
return;
}
-
+
if(IsLimboViewActive()){
limbo->MouseEvent(x, y);
return;
}
-
+
if(IsFollowing()){
SPAssert(world != nullptr);
/*
@@ -140,11 +140,11 @@ namespace spades {
x = -x; y = -y;
}
*/
-
+
x = -x;
if (!cg_invertMouseY)
y = -y;
-
+
followYaw -= x * 0.003f;
followPitch -= y * 0.003f;
if(followPitch < -M_PI*.45f) followPitch = -static_cast(M_PI)*.45f;
@@ -156,7 +156,7 @@ namespace spades {
if(p->IsAlive()){
x /= GetAimDownZoomScale();
y /= GetAimDownZoomScale();
-
+
float rad = x * x + y * y;
if(rad > 0.f) {
if((float)cg_mouseExpPower < 0.001f ||
@@ -168,40 +168,40 @@ namespace spades {
factor *= factor;
rad /= factor;
rad = powf(rad, (float)cg_mouseExpPower * 0.5f - 0.5f);
-
+
// shouldn't happen...
if(isnan(rad)) rad = 1.f;
-
+
x *= rad;
y *= rad;
}
-
+
if(aimDownState > 0.f) {
float scale = cg_zoomedMouseSensScale;
scale = powf(scale, aimDownState);
x *= scale;
y *= scale;
}
-
+
x *= (float)cg_mouseSensitivity;
y *= (float)cg_mouseSensitivity;
-
+
if(cg_invertMouseY)
y = -y;
-
+
p->Turn(x * 0.003f, y * 0.003f);
}
}
}
-
+
void Client::WheelEvent(float x, float y) {
SPADES_MARK_FUNCTION();
-
+
if(scriptedUI->NeedsInput()) {
scriptedUI->WheelEvent(x, y);
return;
}
-
+
if(y > .5f) {
KeyEvent("WheelDown", true);
KeyEvent("WheelDown", false);
@@ -210,37 +210,37 @@ namespace spades {
KeyEvent("WheelUp", false);
}
}
-
+
void Client::TextInputEvent(const std::string &ch){
SPADES_MARK_FUNCTION();
-
+
if (scriptedUI->NeedsInput() && !scriptedUI->isIgnored(ch)) {
scriptedUI->TextInputEvent(ch);
return;
}
-
+
// we don't get "/" here anymore
}
-
+
void Client::TextEditingEvent(const std::string &ch,
int start, int len) {
SPADES_MARK_FUNCTION();
-
+
if (scriptedUI->NeedsInput() && !scriptedUI->isIgnored(ch)) {
scriptedUI->TextEditingEvent(ch, start, len);
return;
}
}
-
+
bool Client::AcceptsTextInput() {
SPADES_MARK_FUNCTION();
-
+
if(scriptedUI->NeedsInput()) {
return scriptedUI->AcceptsTextInput();
}
return false;
}
-
+
AABB2 Client::GetTextInputRect() {
SPADES_MARK_FUNCTION();
if(scriptedUI->NeedsInput()) {
@@ -248,7 +248,7 @@ namespace spades {
}
return AABB2();
}
-
+
static bool CheckKey(const std::string& cfg,
const std::string& input) {
if(cfg.empty())
@@ -272,10 +272,10 @@ namespace spades {
}
return false;
}
-
+
void Client::KeyEvent(const std::string& name, bool down){
SPADES_MARK_FUNCTION();
-
+
if(scriptedUI->NeedsInput()) {
if(!scriptedUI->isIgnored(name)) {
scriptedUI->KeyEvent(name, down);
@@ -286,7 +286,7 @@ namespace spades {
}
return;
}
-
+
if(name == "Escape"){
if(down){
if(inGameLimbo){
@@ -332,13 +332,13 @@ namespace spades {
}
if(world->GetLocalPlayer()){
Player *p = world->GetLocalPlayer();
-
+
if(p->IsAlive() && p->GetTool() == Player::ToolBlock && down) {
if(paletteView->KeyInput(name)){
return;
}
}
-
+
if(cg_debugCorpse){
if(name == "p" && down){
Corpse *corp;
@@ -346,7 +346,7 @@ namespace spades {
corp = new Corpse(renderer, map, victim);
corp->AddImpulse(victim->GetFront() * 32.f);
corpses.emplace_back(corp);
-
+
if(corpses.size() > corpseHardLimit){
corpses.pop_front();
}else if(corpses.size() > corpseSoftLimit){
@@ -412,14 +412,14 @@ namespace spades {
(!w->IsReloading()) &&
world->GetLocalPlayer()->GetTool() == Player::ToolWeapon){
if(world->GetLocalPlayer()->IsToolWeapon()){
- if(weapInput.secondary) {
- // if we send WeaponInput after sending Reload,
- // server might cancel the reload.
- // https://github.com/infogulch/pyspades/blob/895879ed14ddee47bb278a77be86d62c7580f8b7/pyspades/server.py#343
- hasDelayedReload = true;
- weapInput.secondary = false;
- return;
- }
+ if(weapInput.secondary) {
+ // if we send WeaponInput after sending Reload,
+ // server might cancel the reload.
+ // https://github.com/infogulch/pyspades/blob/895879ed14ddee47bb278a77be86d62c7580f8b7/pyspades/server.py#343
+ hasDelayedReload = true;
+ weapInput.secondary = false;
+ return;
+ }
}
world->GetLocalPlayer()->Reload();
net->SendReload();
@@ -590,8 +590,8 @@ namespace spades {
}
}
}
-
-
+
+
}
}
diff --git a/Sources/Client/Client_LocalEnts.cpp b/Sources/Client/Client_LocalEnts.cpp
index 4306c55b..16a4184c 100644
--- a/Sources/Client/Client_LocalEnts.cpp
+++ b/Sources/Client/Client_LocalEnts.cpp
@@ -1,22 +1,22 @@
/*
Copyright (c) 2013 yvt
based on code of pysnip (c) Mathias Kaerlev 2011-2012.
-
+
This file is part of OpenSpades.
-
+
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see .
-
+
*/
#include "Client.h"
@@ -60,28 +60,28 @@ DEFINE_SPADES_SETTING(cg_autoFocusSpeed, "0.4");
namespace spades {
namespace client {
-
-
+
+
#pragma mark - Local Entities / Effects
-
-
+
+
void Client::RemoveAllCorpses(){
SPADES_MARK_FUNCTION();
-
+
corpses.clear();
lastMyCorpse = nullptr;
}
-
-
+
+
void Client::RemoveAllLocalEntities(){
SPADES_MARK_FUNCTION();
-
+
localEntities.clear();
}
-
+
void Client::RemoveInvisibleCorpses(){
SPADES_MARK_FUNCTION();
-
+
decltype(corpses)::iterator it;
std::vector its;
int cnt = (int)corpses.size() - corpseSoftLimit;
@@ -96,13 +96,13 @@ namespace spades {
}
cnt--;
}
-
+
for(size_t i = 0; i < its.size(); i++)
corpses.erase(its[i]);
-
+
}
-
-
+
+
Player *Client::HotTrackedPlayer( hitTag_t* hitFlag ){
if(!world)
return nullptr;
@@ -114,10 +114,10 @@ namespace spades {
Vector3 origin = p->GetEye();
Vector3 dir = p->GetFront();
World::WeaponRayCastResult result = world->WeaponRayCast(origin, dir, p);
-
+
if(result.hit == false || result.player == nullptr)
return nullptr;
-
+
// don't hot track enemies (non-spectator only)
if(result.player->GetTeamId() != p->GetTeamId() &&
p->GetTeamId() < 2)
@@ -127,27 +127,27 @@ namespace spades {
}
return result.player;
}
-
+
bool Client::IsMuted() {
// prevent to play loud sound at connection
// caused by saved packets
return time < worldSetTime + .05f;
}
-
+
void Client::Bleed(spades::Vector3 v){
SPADES_MARK_FUNCTION();
-
+
if(!cg_blood)
return;
-
+
// distance cull
if((v - lastSceneDef.viewOrigin).GetPoweredLength() >
150.f * 150.f)
return;
-
- if ((int)cg_particles < 1)
- return;
-
+
+ if ((int)cg_particles < 1)
+ return;
+
Handle img = renderer->RegisterImage("Gfx/White.tga");
Vector4 color = {0.5f, 0.02f, 0.04f, 1.f};
for(int i = 0; i < 10; i++){
@@ -162,11 +162,11 @@ namespace spades {
ent->SetRadius(0.1f + GetRandom()*GetRandom()*0.2f);
ent->SetLifeTime(3.f, 0.f, 1.f);
localEntities.emplace_back(ent);
- }
-
- if((int) cg_particles < 2)
- return;
-
+ }
+
+ if((int) cg_particles < 2)
+ return;
+
color = MakeVector4(.7f, .35f, .37f, .6f);
for(int i = 0; i < 2; i++){
ParticleSpriteEntity *ent =
@@ -184,7 +184,7 @@ namespace spades {
ent->SetLifeTime(.20f + GetRandom() * .2f, 0.06f, .20f);
localEntities.emplace_back(ent);
}
-
+
color.w *= .1f;
for(int i = 0; i < 1; i++){
ParticleSpriteEntity *ent =
@@ -203,20 +203,20 @@ namespace spades {
localEntities.emplace_back(ent);
}
}
-
+
void Client::EmitBlockFragments(Vector3 origin,
IntVector3 c){
SPADES_MARK_FUNCTION();
-
+
// distance cull
float distPowered = (origin - lastSceneDef.viewOrigin).GetPoweredLength();
if(distPowered >
150.f * 150.f)
return;
-
- if ((int)cg_particles < 1)
- return;
-
+
+ if ((int)cg_particles < 1)
+ return;
+
Handle img = renderer->RegisterImage("Gfx/White.tga");
Vector4 color = {c.x / 255.f,
c.y / 255.f, c.z / 255.f, 1.f};
@@ -235,10 +235,10 @@ namespace spades {
ent->SetBlockHitAction(ParticleSpriteEntity::BounceWeak);
localEntities.emplace_back(ent);
}
-
- if ((int)cg_particles < 2)
- return;
-
+
+ if ((int)cg_particles < 2)
+ return;
+
if(distPowered <
32.f * 32.f){
for(int i = 0; i < 16; i++){
@@ -257,7 +257,7 @@ namespace spades {
localEntities.emplace_back(ent);
}
}
-
+
color += (MakeVector4(1, 1, 1, 1) - color) * .2f;
color.w *= .2f;
for(int i = 0; i < 2; i++){
@@ -275,23 +275,23 @@ namespace spades {
ent->SetBlockHitAction(ParticleSpriteEntity::Ignore);
localEntities.emplace_back(ent);
}
-
+
}
-
+
void Client::EmitBlockDestroyFragments(IntVector3 blk,
IntVector3 c){
SPADES_MARK_FUNCTION();
-
+
Vector3 origin = {blk.x + .5f, blk.y + .5f, blk.z + .5f};
-
+
// distance cull
if((origin - lastSceneDef.viewOrigin).GetPoweredLength() >
150.f * 150.f)
return;
-
- if ((int)cg_particles < 1)
- return;
-
+
+ if ((int)cg_particles < 1)
+ return;
+
Handle img = renderer->RegisterImage("Gfx/White.tga");
Vector4 color = {c.x / 255.f,
c.y / 255.f, c.z / 255.f, 1.f};
@@ -310,7 +310,7 @@ namespace spades {
localEntities.emplace_back(ent);
}
}
-
+
void Client::MuzzleFire(spades::Vector3 origin,
spades::Vector3 dir,
bool local) {
@@ -320,14 +320,14 @@ namespace spades {
l.type = DynamicLightTypePoint;
l.color = MakeVector3(3.f, 1.6f, 0.5f);
flashDlights.push_back(l);
-
- if ((int)cg_particles < 1)
- return;
-
+
+ if ((int)cg_particles < 1)
+ return;
+
Vector4 color;
Vector3 velBias = {0, 0, -0.5f};
color = MakeVector4( .8f, .8f, .8f, .3f);
-
+
// rapid smoke
for(int i = 0; i < 2; i++){
ParticleSpriteEntity *ent =
@@ -346,7 +346,7 @@ namespace spades {
localEntities.emplace_back(ent);
}
}
-
+
void Client::GrenadeExplosion(spades::Vector3 origin){
float dist = (origin - lastSceneDef.viewOrigin).GetLength();
if(dist > 170.f)
@@ -354,7 +354,7 @@ namespace spades {
grenadeVibration += 2.f / (dist + 5.f);
if(grenadeVibration > 1.f)
grenadeVibration = 1.f;
-
+
DynamicLightParam l;
l.origin = origin;
l.radius = 16.f;
@@ -362,10 +362,10 @@ namespace spades {
l.color = MakeVector3(3.f, 1.6f, 0.5f);
l.useLensFlare = true;
flashDlights.push_back(l);
-
- if ((int)cg_particles < 1)
- return;
-
+
+ if ((int)cg_particles < 1)
+ return;
+
Vector3 velBias = {0,0,0};
if(!map->ClipBox(origin.x, origin.y, origin.z)){
if(map->ClipBox(origin.x + 1.f, origin.y, origin.z)){
@@ -387,7 +387,7 @@ namespace spades {
velBias.z += 1.f;
}
}
-
+
Vector4 color;
color = MakeVector4( .6f, .6f, .6f, 1.f);
// rapid smoke
@@ -407,7 +407,7 @@ namespace spades {
ent->SetLifeTime(1.8f + GetRandom()*0.1f, 0.f, .20f);
localEntities.emplace_back(ent);
}
-
+
// slow smoke
color.w = .25f;
for(int i = 0; i < 8; i++){
@@ -422,21 +422,21 @@ namespace spades {
ent->SetRadius(1.5f + GetRandom()*GetRandom()*0.8f,
0.2f);
ent->SetBlockHitAction(ParticleSpriteEntity::Ignore);
- switch ((int) cg_particles) {
- case 1:
- ent->SetLifeTime(0.8f + GetRandom() * 1.f, 0.1f, 8.f);
- break;
- case 2:
- ent->SetLifeTime(1.5f + GetRandom() * 2.f, 0.1f, 8.f);
- break;
- case 3:
- default:
- ent->SetLifeTime(2.f + GetRandom() * 5.f, 0.1f, 8.f);
- break;
- }
+ switch ((int) cg_particles) {
+ case 1:
+ ent->SetLifeTime(0.8f + GetRandom() * 1.f, 0.1f, 8.f);
+ break;
+ case 2:
+ ent->SetLifeTime(1.5f + GetRandom() * 2.f, 0.1f, 8.f);
+ break;
+ case 3:
+ default:
+ ent->SetLifeTime(2.f + GetRandom() * 5.f, 0.1f, 8.f);
+ break;
+ }
localEntities.emplace_back(ent);
}
-
+
// fragments
Handle img = renderer->RegisterImage("Gfx/White.tga");
color = MakeVector4(0.01, 0.03, 0, 1.f);
@@ -457,7 +457,7 @@ namespace spades {
ent->SetBlockHitAction(ParticleSpriteEntity::BounceWeak);
localEntities.emplace_back(ent);
}
-
+
// fire smoke
color= MakeVector4(1.f, .7f, .4f, .2f) * 5.f;
for(int i = 0; i < 4; i++){
@@ -478,7 +478,7 @@ namespace spades {
localEntities.emplace_back(ent);
}
}
-
+
void Client::GrenadeExplosionUnderwater(spades::Vector3 origin){
float dist = (origin - lastSceneDef.viewOrigin).GetLength();
if(dist > 170.f)
@@ -486,18 +486,18 @@ namespace spades {
grenadeVibration += 1.5f / (dist + 5.f);
if(grenadeVibration > 1.f)
grenadeVibration = 1.f;
-
- if((int) cg_particles < 1)
- return;
-
+
+ if((int) cg_particles < 1)
+ return;
+
Vector3 velBias = {0,0,0};
-
+
Vector4 color;
color = MakeVector4( .95f, .95f, .95f, .6f);
// water1
- Handle img = renderer->RegisterImage("Textures/WaterExpl.png");
- if((int) cg_particles < 2)
- color.w = .3f;
+ Handle img = renderer->RegisterImage("Textures/WaterExpl.png");
+ if((int) cg_particles < 2)
+ color.w = .3f;
for(int i = 0; i < 7; i++){
ParticleSpriteEntity *ent =
new ParticleSpriteEntity(this, img, color);
@@ -513,12 +513,12 @@ namespace spades {
ent->SetLifeTime(3.f + GetRandom()*0.3f, 0.f, .60f);
localEntities.emplace_back(ent);
}
-
+
// water2
img = renderer->RegisterImage("Textures/Fluid.png");
color.w = .9f;
if((int) cg_particles < 2)
- color.w = .4f;
+ color.w = .4f;
for(int i = 0; i < 16; i++){
ParticleSpriteEntity *ent =
new ParticleSpriteEntity(this, img, color);
@@ -534,11 +534,11 @@ namespace spades {
ent->SetLifeTime(3.f + GetRandom()*0.3f, .7f, .60f);
localEntities.emplace_back(ent);
}
-
+
// slow smoke
- color.w = .4f;
- if((int) cg_particles < 2)
- color.w = .2f;
+ color.w = .4f;
+ if((int) cg_particles < 2)
+ color.w = .2f;
for(int i = 0; i < 8; i++){
ParticleSpriteEntity *ent =
new SmokeSpriteEntity(this, color, 20.f);
@@ -551,20 +551,20 @@ namespace spades {
ent->SetRadius(1.4f + GetRandom()*GetRandom()*0.8f,
0.2f);
ent->SetBlockHitAction(ParticleSpriteEntity::Ignore);
- switch ((int)cg_particles) {
- case 1:
- ent->SetLifeTime(3.f + GetRandom() * 5.f, 0.1f, 8.f);
- break;
- case 2:
- case 3:
- default:
- ent->SetLifeTime(6.f + GetRandom() * 5.f, 0.1f, 8.f);
- break;
-
- }
+ switch ((int)cg_particles) {
+ case 1:
+ ent->SetLifeTime(3.f + GetRandom() * 5.f, 0.1f, 8.f);
+ break;
+ case 2:
+ case 3:
+ default:
+ ent->SetLifeTime(6.f + GetRandom() * 5.f, 0.1f, 8.f);
+ break;
+
+ }
localEntities.emplace_back(ent);
}
-
+
// fragments
img = renderer->RegisterImage("Gfx/White.tga");
color = MakeVector4(1,1,1, 0.7f);
@@ -586,22 +586,22 @@ namespace spades {
ent->SetBlockHitAction(ParticleSpriteEntity::Delete);
localEntities.emplace_back(ent);
}
-
-
+
+
// TODO: wave?
}
-
-
+
+
void Client::BulletHitWaterSurface(spades::Vector3 origin){
float dist = (origin - lastSceneDef.viewOrigin).GetLength();
if(dist > 150.f)
return;
if(!cg_waterImpact)
return;
-
- if((int) cg_particles < 1)
- return;
-
+
+ if((int) cg_particles < 1)
+ return;
+
Vector4 color;
color = MakeVector4( .95f, .95f, .95f, .3f);
// water1
@@ -622,7 +622,7 @@ namespace spades {
ent->SetLifeTime(3.f + GetRandom()*0.3f, 0.1f, .60f);
localEntities.emplace_back(ent);
}
-
+
// water2
img = renderer->RegisterImage("Textures/Fluid.png");
color.w = .9f;
@@ -642,8 +642,8 @@ namespace spades {
ent->SetLifeTime(3.f + GetRandom()*0.3f, GetRandom() * 0.3f, .60f);
localEntities.emplace_back(ent);
}
-
-
+
+
// fragments
img = renderer->RegisterImage("Gfx/White.tga");
color = MakeVector4(1,1,1, 0.7f);
@@ -664,13 +664,13 @@ namespace spades {
ent->SetBlockHitAction(ParticleSpriteEntity::Delete);
localEntities.emplace_back(ent);
}
-
-
+
+
// TODO: wave?
}
-
+
#pragma mark - Camera Control
-
+
enum { AutoFocusPoints = 4 };
void Client::UpdateAutoFocus(float dt) {
if (autoFocusEnabled && world && (int)cg_manualFocus) {
@@ -681,7 +681,7 @@ namespace spades {
const Vector3 camDir = lastSceneDef.viewAxis[2].Normalize();
const Vector3 camX = lastSceneDef.viewAxis[0].Normalize() * measureRange;
const Vector3 camY = lastSceneDef.viewAxis[1].Normalize() * measureRange;
-
+
float distances[AutoFocusPoints * AutoFocusPoints];
std::size_t numValidDistances = 0;
Vector3 camDir1 = camDir - camX - camY;
@@ -691,43 +691,43 @@ namespace spades {
Vector3 camDir2 = camDir1;
for (int y = 0; y < AutoFocusPoints; ++y) {
float dist = RayCastForAutoFocus(camOrigin, camDir2);
-
+
dist *= lenScale;
-
+
if (std::isfinite(dist) && dist > 0.8f) {
distances[numValidDistances++] = dist;
}
-
+
camDir2 += camDY;
}
camDir1 += camDX;
}
-
+
if (numValidDistances > 0) {
// Take median
std::sort(distances, distances + numValidDistances);
-
+
float dist = (numValidDistances & 1) ?
distances[numValidDistances >> 1] :
(distances[numValidDistances >> 1] + distances[(numValidDistances >> 1) - 1]) * 0.5f;
-
+
targetFocalLength = dist;
-
+
}
}
-
+
// Change the actual focal length slowly
{
float dist = 1.f / targetFocalLength;
float curDist = 1.f / focalLength;
const float maxSpeed = cg_autoFocusSpeed;
-
+
if (dist > curDist) {
curDist = std::min(dist, curDist + maxSpeed * dt);
} else {
curDist = std::max(dist, curDist - maxSpeed * dt);
}
-
+
focalLength = 1.f / curDist;
}
}
@@ -735,7 +735,7 @@ namespace spades {
const Vector3 &direction)
{
SPAssert(world);
-
+
const auto &lastSceneDef = this->lastSceneDef;
World::WeaponRayCastResult result =
world->WeaponRayCast(origin,
@@ -744,7 +744,7 @@ namespace spades {
if (result.hit) {
return Vector3::Dot(result.hitPos - origin, lastSceneDef.viewAxis[2]);
}
-
+
return std::nan(nullptr);
}
diff --git a/Sources/Client/Client_Scene.cpp b/Sources/Client/Client_Scene.cpp
index 6a852b0c..feb07ff4 100644
--- a/Sources/Client/Client_Scene.cpp
+++ b/Sources/Client/Client_Scene.cpp
@@ -1,22 +1,22 @@
/*
Copyright (c) 2013 yvt
based on code of pysnip (c) Mathias Kaerlev 2011-2012.
-
+
This file is part of OpenSpades.
-
+
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see .
-
+
*/
#include "Client.h"
@@ -53,9 +53,9 @@ static float nextRandom() {
namespace spades {
namespace client {
-
+
#pragma mark - Drawing
-
+
bool Client::ShouldRenderInThirdPersonView() {
if(world && world->GetLocalPlayer()){
if(!world->GetLocalPlayer()->IsAlive())
@@ -66,7 +66,7 @@ namespace spades {
}
return false;
}
-
+
float Client::GetLocalFireVibration() {
float localFireVibration = 0.f;
localFireVibration = time - localFireVibrationTime;
@@ -75,7 +75,7 @@ namespace spades {
localFireVibration = 0.f;
return localFireVibration;
}
-
+
float Client::GetAimDownZoomScale(){
if(world == nullptr ||
world->GetLocalPlayer() == nullptr ||
@@ -97,27 +97,27 @@ namespace spades {
float aimDownState = GetAimDownState();
return 1.f + powf(aimDownState, 5.f) * delta;
}
-
+
SceneDefinition Client::CreateSceneDefinition() {
SPADES_MARK_FUNCTION();
-
- int shakeLevel = cg_shake;
-
+
+ int shakeLevel = cg_shake;
+
SceneDefinition def;
def.time = (unsigned int)(time * 1000.f);
- def.denyCameraBlur = true;
- def.zFar = 200.f;
-
+ def.denyCameraBlur = true;
+ def.zFar = 200.f;
+
if(world){
IntVector3 fogColor = world->GetFogColor();
renderer->SetFogColor(MakeVector3(fogColor.x / 255.f,
fogColor.y / 255.f,
fogColor.z / 255.f));
-
+
Player *player = world->GetLocalPlayer();
-
+
def.blurVignette = .0f;
-
+
if(IsFollowing()){
int limit = 100;
// if current following player has left,
@@ -133,7 +133,7 @@ namespace spades {
player = world->GetPlayer(followingPlayerId);
}
if(player){
-
+
float roll = 0.f;
float scale = 1.f;
float vibPitch = 0.f;
@@ -143,7 +143,7 @@ namespace spades {
Vector3 center = player->GetEye();
Vector3 playerFront = player->GetFront2D();
Vector3 up = MakeVector3(0,0,-1);
-
+
if((!player->IsAlive()) && lastMyCorpse &&
player == world->GetLocalPlayer()){
center = lastMyCorpse->GetCenter();
@@ -163,7 +163,7 @@ namespace spades {
}
}
}
-
+
float distance = 5.f;
if(player == world->GetLocalPlayer() &&
world->GetLocalPlayer()->GetTeamId() < 2 &&
@@ -172,14 +172,14 @@ namespace spades {
float elapsedTime = time - lastAliveTime;
distance -= 3.f * expf(-elapsedTime * 1.f);
}
-
+
Vector3 eye = center;
//eye -= playerFront * 5.f;
//eye += up * 2.0f;
eye.x += cosf(followYaw) * cosf(followPitch) * distance;
eye.y += sinf(followYaw) * cosf(followPitch) * distance;
eye.z -= sinf(followPitch) * distance;
-
+
if(false){
// settings for making limbo stuff
eye = center;
@@ -188,7 +188,7 @@ namespace spades {
eye += player->GetRight() *2.f;
scale *= .6f;
}
-
+
// try ray casting
GameMap::RayCastResult result;
result = map->CastRay2(center, (eye - center).Normalize(), 256);
@@ -201,10 +201,10 @@ namespace spades {
eye += (center - eye).Normalize() * diff;
}
}
-
+
Vector3 front = center - eye;
front = front.Normalize();
-
+
if(FirstPersonSpectate == false){
def.viewOrigin = eye;
def.viewAxis[0] = -Vector3::Cross(up, front).Normalize();
@@ -216,100 +216,100 @@ namespace spades {
def.viewAxis[1] = player->GetUp();
def.viewAxis[2] = player->GetFront();
}
-
+
def.fovY = (float)cg_fov * static_cast(M_PI) /180.f;
def.fovX = atanf(tanf(def.fovY * .5f) *
renderer->ScreenWidth() /
renderer->ScreenHeight()) * 2.f;
-
+
// update initial spectate pos
// this is not used now, but if the local player is
// is spectating, this is used when he/she's no
// longer following
followPos = def.viewOrigin;
followVel = MakeVector3(0, 0, 0);
-
+
}else if(player->GetTeamId() >= 2){
// spectator view (noclip view)
Vector3 center = followPos;
Vector3 front;
Vector3 up = {0, 0, -1};
-
+
front.x = -cosf(followYaw) * cosf(followPitch);
front.y = -sinf(followYaw) * cosf(followPitch);
front.z = sinf(followPitch);
-
+
def.viewOrigin = center;
def.viewAxis[0] = -Vector3::Cross(up, front).Normalize();
def.viewAxis[1] = -Vector3::Cross(front, def.viewAxis[0]).Normalize();
def.viewAxis[2] = front;
-
+
def.fovY = (float)cg_fov * static_cast(M_PI) /180.f;
def.fovX = atanf(tanf(def.fovY * .5f) *
renderer->ScreenWidth() /
renderer->ScreenHeight()) * 2.f;
-
+
// for 1st view, camera blur can be used
def.denyCameraBlur = false;
-
+
}else{
Vector3 front = player->GetFront();
Vector3 right = player->GetRight();
Vector3 up = player->GetUp();
-
- if (shakeLevel >= 1) {
- float localFireVibration = GetLocalFireVibration();
- localFireVibration *= localFireVibration;
-
- if(player->GetTool() == Player::ToolSpade) {
- localFireVibration *= 0.4f;
- }
-
- roll += (nextRandom() - nextRandom()) * 0.03f * localFireVibration;
- scale += nextRandom() * 0.04f * localFireVibration;
-
- vibPitch += localFireVibration * (1.f - localFireVibration) * 0.01f;
- vibYaw += sinf(localFireVibration * (float)M_PI * 2.f) * 0.001f;
-
- def.radialBlur += localFireVibration * 0.2f;
-
- // sprint bob
- {
- float sp = SmoothStep(GetSprintState());
- vibYaw += sinf(player->GetWalkAnimationProgress() * static_cast(M_PI) * 2.f) * 0.01f * sp;
- roll -= sinf(player->GetWalkAnimationProgress() * static_cast(M_PI) * 2.f) * 0.005f * (sp);
- float p = cosf(player->GetWalkAnimationProgress() * static_cast(M_PI) * 2.f);
- p = p * p; p *= p; p *= p; p *= p;
- vibPitch += p * 0.01f * sp;
- }
- }
-
+
+ if (shakeLevel >= 1) {
+ float localFireVibration = GetLocalFireVibration();
+ localFireVibration *= localFireVibration;
+
+ if(player->GetTool() == Player::ToolSpade) {
+ localFireVibration *= 0.4f;
+ }
+
+ roll += (nextRandom() - nextRandom()) * 0.03f * localFireVibration;
+ scale += nextRandom() * 0.04f * localFireVibration;
+
+ vibPitch += localFireVibration * (1.f - localFireVibration) * 0.01f;
+ vibYaw += sinf(localFireVibration * (float)M_PI * 2.f) * 0.001f;
+
+ def.radialBlur += localFireVibration * 0.2f;
+
+ // sprint bob
+ {
+ float sp = SmoothStep(GetSprintState());
+ vibYaw += sinf(player->GetWalkAnimationProgress() * static_cast(M_PI) * 2.f) * 0.01f * sp;
+ roll -= sinf(player->GetWalkAnimationProgress() * static_cast(M_PI) * 2.f) * 0.005f * (sp);
+ float p = cosf(player->GetWalkAnimationProgress() * static_cast(M_PI) * 2.f);
+ p = p * p; p *= p; p *= p; p *= p;
+ vibPitch += p * 0.01f * sp;
+ }
+ }
+
scale /= GetAimDownZoomScale();
-
+
def.viewOrigin = player->GetEye();
def.viewAxis[0] = right;
def.viewAxis[1] = up;
def.viewAxis[2] = front;
-
+
def.fovY = (float)cg_fov * static_cast(M_PI) /180.f;
def.fovX = atanf(tanf(def.fovY * .5f) *
renderer->ScreenWidth() /
renderer->ScreenHeight()) * 2.f;
-
+
// for 1st view, camera blur can be used
def.denyCameraBlur = false;
-
+
float aimDownState = GetAimDownState();
float per = aimDownState;
per *= per * per;
def.depthOfFieldFocalLength = per * 13.f + .054f;
-
+
def.blurVignette = .0f;
-
-
-
+
+
+
}
-
+
// add vibration for both 1st/3rd view
{
// add grenade vibration
@@ -322,100 +322,100 @@ namespace spades {
vibPitch += (nextRandom() - nextRandom()) * 0.1f * grenVib;
vibYaw += (nextRandom() - nextRandom()) * 0.1f * grenVib;
scale -= (nextRandom()-nextRandom()) * 0.1f * grenVib;
-
+
def.radialBlur += grenVib * 0.8f;
}
}
-
+
// add roll / scale
{
Vector3 right = def.viewAxis[0];
Vector3 up = def.viewAxis[1];
-
+
def.viewAxis[0] = right * cosf(roll) - up * sinf(roll);
def.viewAxis[1] = up * cosf(roll) + right * sinf(roll);
-
- def.fovX = atanf(tanf(def.fovX * .5f) * scale) * 2.f;
- def.fovY = atanf(tanf(def.fovY * .5f) * scale) * 2.f;
+
+ def.fovX = atanf(tanf(def.fovX * .5f) * scale) * 2.f;
+ def.fovY = atanf(tanf(def.fovY * .5f) * scale) * 2.f;
}
{
Vector3 u = def.viewAxis[1];
Vector3 v = def.viewAxis[2];
-
+
def.viewAxis[1] = u * cosf(vibPitch) - v * sinf(vibPitch);
def.viewAxis[2] = v * cosf(vibPitch) + u * sinf(vibPitch);
}
{
Vector3 u = def.viewAxis[0];
Vector3 v = def.viewAxis[2];
-
+
def.viewAxis[0] = u * cosf(vibYaw) - v * sinf(vibYaw);
def.viewAxis[2] = v * cosf(vibYaw) + u * sinf(vibYaw);
}
{
float wTime = world->GetTime();
if(wTime < lastHurtTime + .15f &&
- wTime >= lastHurtTime){
+ wTime >= lastHurtTime){
float per = 1.f - (wTime - lastHurtTime) / .15f;
per *= .5f - player->GetHealth() / 100.f * .3f;
def.blurVignette += per * 6.f;
}
if(wTime < lastHurtTime + .2f &&
- wTime >= lastHurtTime){
+ wTime >= lastHurtTime){
float per = 1.f - (wTime - lastHurtTime) / .2f;
per *= .5f - player->GetHealth() / 100.f * .3f;
def.saturation *= std::max(0.f, 1.f - per * 4.f);
}
}
-
+
def.zNear = 0.05f;
-
+
def.skipWorld = false;
}else{
def.viewOrigin = MakeVector3(256, 256, 4);
def.viewAxis[0] = MakeVector3(-1, 0, 0);
def.viewAxis[1] = MakeVector3(0, 1, 0);
def.viewAxis[2] = MakeVector3(0, 0, 1);
-
+
def.fovY = (float)cg_fov * static_cast(M_PI) /180.f;
def.fovX = atanf(tanf(def.fovY * .5f) *
renderer->ScreenWidth() /
renderer->ScreenHeight()) * 2.f;
-
+
def.zNear = 0.05f;
-
+
def.skipWorld = false;
}
-
+
}else{
def.viewOrigin = MakeVector3(0, 0, 0);
def.viewAxis[0] = MakeVector3(1, 0, 0);
def.viewAxis[1] = MakeVector3(0, 0, -1);
def.viewAxis[2] = MakeVector3(0, 0, 1);
-
+
def.fovY = (float)cg_fov * static_cast(M_PI) /180.f;
def.fovX = atanf(tanf(def.fovY * .5f) *
renderer->ScreenWidth() /
renderer->ScreenHeight()) * 2.f;
-
+
def.zNear = 0.05f;
-
+
def.skipWorld = true;
-
+
renderer->SetFogColor(MakeVector3(0,0,0));
}
-
- if (def.viewOrigin.z < 0.f) {
- // Need to move the far plane because there's no vertical fog
- def.zFar -= def.viewOrigin.z;
- }
-
+
+ if (def.viewOrigin.z < 0.f) {
+ // Need to move the far plane because there's no vertical fog
+ def.zFar -= def.viewOrigin.z;
+ }
+
SPAssert(!isnan(def.viewOrigin.x));
SPAssert(!isnan(def.viewOrigin.y));
SPAssert(!isnan(def.viewOrigin.z));
-
+
def.radialBlur = std::min(def.radialBlur, 1.f);
-
+
if ((int)cg_manualFocus) {
// Depth of field is manually controlled
def.depthOfFieldNearBlurStrength = def.depthOfFieldFarBlurStrength =
@@ -425,29 +425,29 @@ namespace spades {
def.depthOfFieldNearBlurStrength = cg_depthOfFieldAmount;
def.depthOfFieldFarBlurStrength = 0.f;
}
-
+
return def;
}
-
+
void Client::AddGrenadeToScene(spades::client::Grenade *g) {
SPADES_MARK_FUNCTION();
-
+
IModel *model;
model = renderer->RegisterModel("Models/Weapons/Grenade/Grenade.kv6");
-
+
if(g->GetPosition().z > 63.f) {
// work-around for water refraction problem
return;
}
-
+
ModelRenderParam param;
Matrix4 mat = Matrix4::Scale(0.03f);
mat = Matrix4::Translate(g->GetPosition()) * mat;
param.matrix = mat;
-
+
renderer->RenderModel(model, param);
}
-
+
void Client::AddDebugObjectToScene(const spades::OBB3 &obb, const Vector4& color) {
const Matrix4& mat = obb.m;
Vector3 v[2][2][2];
@@ -459,23 +459,23 @@ namespace spades {
v[1][0][1] = (mat * MakeVector3(1,0,1)).GetXYZ();
v[1][1][0] = (mat * MakeVector3(1,1,0)).GetXYZ();
v[1][1][1] = (mat * MakeVector3(1,1,1)).GetXYZ();
-
+
renderer->AddDebugLine(v[0][0][0], v[1][0][0], color);
renderer->AddDebugLine(v[0][0][1], v[1][0][1], color);
renderer->AddDebugLine(v[0][1][0], v[1][1][0], color);
renderer->AddDebugLine(v[0][1][1], v[1][1][1], color);
-
+
renderer->AddDebugLine(v[0][0][0], v[0][1][0], color);
renderer->AddDebugLine(v[0][0][1], v[0][1][1], color);
renderer->AddDebugLine(v[1][0][0], v[1][1][0], color);
renderer->AddDebugLine(v[1][0][1], v[1][1][1], color);
-
+
renderer->AddDebugLine(v[0][0][0], v[0][0][1], color);
renderer->AddDebugLine(v[0][1][0], v[0][1][1], color);
renderer->AddDebugLine(v[1][0][0], v[1][0][1], color);
renderer->AddDebugLine(v[1][1][0], v[1][1][1], color);
}
-
+
void Client::DrawCTFObjects() {
SPADES_MARK_FUNCTION();
CTFGameMode *mode = static_cast(world->GetMode());
@@ -488,15 +488,15 @@ namespace spades {
Vector3 color = {
col.x / 255.f, col.y / 255.f, col.z / 255.f
};
-
+
ModelRenderParam param;
param.customColor = color;
-
+
// draw base
param.matrix = Matrix4::Translate(team.basePos);
param.matrix = param.matrix * Matrix4::Scale(.3f);
renderer->RenderModel(base, param);
-
+
// draw flag
if(!mode->GetTeam(1-tId).hasIntel){
param.matrix = Matrix4::Translate(team.flagPos);
@@ -505,7 +505,7 @@ namespace spades {
}
}
}
-
+
void Client::DrawTCObjects() {
SPADES_MARK_FUNCTION();
TCGameMode *mode = static_cast(world->GetMode());
@@ -523,26 +523,26 @@ namespace spades {
Vector3 color = {
col.x / 255.f, col.y / 255.f, col.z / 255.f
};
-
+
ModelRenderParam param;
param.customColor = color;
-
+
// draw base
param.matrix = Matrix4::Translate(t->pos);
param.matrix = param.matrix * Matrix4::Scale(.3f);
renderer->RenderModel(base, param);
-
+
}
}
-
+
void Client::DrawScene(){
SPADES_MARK_FUNCTION();
-
+
renderer->StartScene(lastSceneDef);
-
+
if(world){
Player *p = world->GetLocalPlayer();
-
+
for(size_t i = 0; i < world->GetNumPlayerSlots(); i++)
if(world->GetPlayer(static_cast(i))){
SPAssert(clientPlayers[i]);
@@ -552,7 +552,7 @@ namespace spades {
for(size_t i = 0; i < nades.size(); i++){
AddGrenadeToScene(nades[i]);
}
-
+
{
for(auto& c: corpses){
Vector3 center = c->GetCenter();
@@ -561,19 +561,19 @@ namespace spades {
c->AddToScene();
}
}
-
+
if( IGameMode::m_CTF == world->GetMode()->ModeType() ){
DrawCTFObjects();
} else if( IGameMode::m_TC == world->GetMode()->ModeType() ){
DrawTCObjects();
}
-
+
{
for(auto& ent: localEntities){
ent->Render3D();
}
}
-
+
// draw block cursor
// FIXME: don't use debug line
if(p){
@@ -589,9 +589,9 @@ namespace spades {
}else{
blocks.push_back(p->GetBlockCursorPos());
}
-
+
bool active = p->IsBlockCursorActive();
-
+
Vector4 color = {1,1,1,1};
if(!active)
color = Vector4(1,1,0,1);
@@ -599,12 +599,12 @@ namespace spades {
color = MakeVector4(1,0,0,1);
if(!active)
color.w *= 0.5f;
-
+
for(size_t i = 0; i < blocks.size(); i++){
IntVector3& v = blocks[i];
-
+
if(active) {
-
+
renderer->AddDebugLine(MakeVector3(v.x, v.y, v.z),
MakeVector3(v.x+1, v.y, v.z),
color);
@@ -620,7 +620,7 @@ namespace spades {
renderer->AddDebugLine(MakeVector3(v.x, v.y, v.z),
MakeVector3(v.x+1, v.y, v.z),
color);
-
+
renderer->AddDebugLine(MakeVector3(v.x, v.y, v.z),
MakeVector3(v.x, v.y+1, v.z),
color);
@@ -633,7 +633,7 @@ namespace spades {
renderer->AddDebugLine(MakeVector3(v.x+1, v.y, v.z+1),
MakeVector3(v.x+1, v.y+1, v.z+1),
color);
-
+
renderer->AddDebugLine(MakeVector3(v.x, v.y, v.z),
MakeVector3(v.x, v.y, v.z+1),
color);
@@ -648,7 +648,7 @@ namespace spades {
color);
}else{
// not active
-
+
const float ln = 0.1f;
{
float xx = v.x, yy = v.y, zz = v.z;
@@ -698,20 +698,20 @@ namespace spades {
renderer->AddDebugLine(Vector3(xx, yy, zz), Vector3(xx, yy-ln, zz), color);
renderer->AddDebugLine(Vector3(xx, yy, zz), Vector3(xx, yy, zz-ln), color);
}
-
+
}
// --- one block drawn
} // end for
-
+
} // p->IsReadyToUseTool
}
}
-
+
for(size_t i = 0; i < flashDlights.size(); i++)
renderer->AddLight(flashDlights[i]);
flashDlightsOld.clear();
flashDlightsOld.swap(flashDlights);
-
+
// draw player hottrack
// FIXME: don't use debug line
{
@@ -721,7 +721,7 @@ namespace spades {
IntVector3 col = world->GetTeam(hottracked->GetTeamId()).color;
Vector4 color = Vector4::Make( col.x / 255.f, col.y / 255.f, col.z / 255.f, 1.f );
Vector4 color2 = Vector4::Make( 1, 1, 1, 1);
-
+
Player::HitBoxes hb = hottracked->GetHitBoxes();
AddDebugObjectToScene(hb.head, (tag & hit_Head) ? color2 : color );
AddDebugObjectToScene(hb.torso, (tag & hit_Torso) ? color2 : color );
@@ -730,29 +730,29 @@ namespace spades {
AddDebugObjectToScene(hb.limbs[2], (tag & hit_Arms) ? color2 : color );
}
}
-
+
renderer->EndScene();
}
-
+
Vector3 Client::Project(spades::Vector3 v){
v -= lastSceneDef.viewOrigin;
-
+
// transform to NDC
Vector3 v2;
v2.x = Vector3::Dot(v, lastSceneDef.viewAxis[0]);
v2.y = Vector3::Dot(v, lastSceneDef.viewAxis[1]);
v2.z = Vector3::Dot(v, lastSceneDef.viewAxis[2]);
-
+
float tanX = tanf(lastSceneDef.fovX * .5f);
float tanY = tanf(lastSceneDef.fovY * .5f);
-
+
v2.x /= tanX * v2.z;
v2.y /= tanY * v2.z;
-
+
// transform to IRenderer 2D coord
v2.x = (v2.x + 1.f) / 2.f * renderer->ScreenWidth();
v2.y = (-v2.y + 1.f) / 2.f * renderer->ScreenHeight();
-
+
return v2;
}
diff --git a/Sources/Client/Corpse.cpp b/Sources/Client/Corpse.cpp
index 0c9ae0f6..3cc57213 100644
--- a/Sources/Client/Corpse.cpp
+++ b/Sources/Client/Corpse.cpp
@@ -1,21 +1,21 @@
/*
Copyright (c) 2013 yvt
-
+
This file is part of OpenSpades.
-
+
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see .
-
+
*/
#include "Corpse.h"
@@ -38,29 +38,29 @@ namespace spades {
Player *p):
renderer(renderer), map(map) {
SPADES_MARK_FUNCTION();
-
+
IntVector3 col = p->GetWorld()->GetTeam(p->GetTeamId()).color;
color = MakeVector3(col.x / 255.f,
col.y / 255.f,
col.z / 255.f);
-
+
bool crouch = p->GetInput().crouch;
Vector3 front = p->GetFront();
-
+
float yaw = atan2(front.y, front.x) + static_cast(M_PI) * .5f;
//float pitch = -atan2(front.z, sqrt(front.x * front.x + front.y * front.y));
-
+
// lower axis
Matrix4 lower = Matrix4::Translate(p->GetOrigin());
lower = lower * Matrix4::Rotate(MakeVector3(0,0,1),
yaw);
-
+
Matrix4 torso;
-
+
if(crouch){
lower = lower * Matrix4::Translate(0, 0, -0.4f);
torso = lower * Matrix4::Translate(0, 0, -0.3f);
-
+
SetNode(Torso1,
torso*MakeVector3(0.4f, -.15f, 0.1f));
SetNode(Torso2,
@@ -69,20 +69,20 @@ namespace spades {
torso*MakeVector3(-0.4f, .8f, 0.7f));
SetNode(Torso4,
torso*MakeVector3(0.4f, .8f, 0.7f));
-
+
SetNode(Leg1,
lower*MakeVector3(-0.4f, .1f, 1.f));
SetNode(Leg2,
lower*MakeVector3(0.4f, .1f, 1.f));
-
+
SetNode(Arm1,
torso*MakeVector3(0.2f, -.4f, .2f));
SetNode(Arm2,
torso*MakeVector3(-0.2f, -.4f, .2f));
-
+
}else{
torso = lower * Matrix4::Translate(0, 0, -1.1f);
-
+
SetNode(Torso1,
torso*MakeVector3(0.4f, 0.f, 0.1f));
SetNode(Torso2,
@@ -91,29 +91,29 @@ namespace spades {
torso*MakeVector3(-0.4f, .0f, 1.f));
SetNode(Torso4,
torso*MakeVector3(0.4f, .0f, 1.f));
-
+
SetNode(Leg1,
lower*MakeVector3(-0.4f, .0f, 1.f));
SetNode(Leg2,
lower*MakeVector3(0.4f, .0f, 1.f));
-
+
SetNode(Arm1,
torso*MakeVector3(0.2f, -.4f, .2f));
SetNode(Arm2,
torso*MakeVector3(-0.2f, -.4f, .2f));
-
+
}
-
+
SetNode(Head, (nodes[Torso1].pos + nodes[Torso2].pos)
* .5f + MakeVector3(0,0,-0.6f));
-
-
+
+
}
-
+
static float VelNoise() {
return (GetRandom() - GetRandom()) * 2.f;
}
-
+
void Corpse::SetNode(NodeType n, spades::Vector3 v){
SPAssert(n >= 0); SPAssert(n < NodeCount);
nodes[n].pos = v;
@@ -122,16 +122,16 @@ namespace spades {
0.f);
nodes[n].lastPos = v;
nodes[n].lastForce = MakeVector3(0, 0,0);
-
+
}
void Corpse::SetNode(NodeType n, spades::Vector4 v){
SetNode(n, v.GetXYZ());
}
-
+
Corpse::~Corpse(){
-
+
}
-
+
void Corpse::Spring(NodeType n1,
NodeType n2,
float distance,
@@ -145,18 +145,18 @@ namespace spades {
float dist = diff.GetLength();
Vector3 force = diff.Normalize() * (distance - dist);
force *= dt * 50.f;
-
+
b.vel += force;
a.vel -= force;
-
+
b.pos += force / (dt * 50.f) * 0.5f;
a.pos -= force / (dt * 50.f) * 0.5f;
-
+
Vector3 velMid = (a.vel + b.vel) * .5f;
float dump = 1.f - powf(.1f, dt);
a.vel += (velMid - a.vel) * dump;
b.vel += (velMid - b.vel) * dump;
-
+
}
void Corpse::Spring(NodeType n1a,
NodeType n1b,
@@ -174,20 +174,20 @@ namespace spades {
float dist = diff.GetLength();
Vector3 force = diff.Normalize() * (distance - dist);
force *= dt * 50.f;
-
+
b.vel += force;
force *= .5f;
x.vel -= force;
y.vel -= force;
-
+
Vector3 velMid = (x.vel + y.vel) * .25f + b.vel * .5f;
float dump = 1.f - powf(.05f, dt);
x.vel += (velMid - x.vel) * dump;
y.vel += (velMid - y.vel) * dump;
b.vel += (velMid - b.vel) * dump;
-
+
}
-
+
static float MyACos(float v){
SPAssert(!isnan(v));
if(v >= 1.f) return 0.f;
@@ -214,48 +214,48 @@ namespace spades {
float ln1 = d1.GetLength();
float ln2 = d2.GetLength();
float dot = Vector3::Dot(d1, d2) / (ln1 * ln2 + 0.0000001f);
-
+
if(dot >= minDot && dot <= maxDot)
return;
-
+
Vector3 diff = n2.pos - n1.pos;
float strength = 0.f;
-
+
Vector3 a1 = Vector3::Cross(d1, diff);
a1 = Vector3::Cross(d1, a1).Normalize();
-
+
Vector3 a2 = Vector3::Cross(d2, diff);
a2 = Vector3::Cross(d2, a2).Normalize();
-
+
//a1=-a1; a2=-a2;
//a1 = -a1;
a2 = -a2;
-
+
if(dot > maxDot){
strength = MyACos(dot) - MyACos(maxDot);
}else if(dot < minDot){
strength = MyACos(dot) - MyACos(minDot);
}
-
+
SPAssert(!isnan(strength));
-
+
strength *= 20.f;
strength *= dt;
-
+
a1 *= strength;
a2 *= strength;
-
+
a2 *= 0.f;
-
+
n2.vel += a1;
n1.vel += a2;
nBase.vel -= a1 + a2;
-
+
/*
d1 += a1 * 0.01;
d2 += a2 * 0.01;
float nd = Vector3::Dot(d1, d2) / (d1.GetLength() * d2.GetLength());
-
+
if(dot > maxDot){
if(nd < dot)
printf("GOOD %f -> %f\n", dot, nd);
@@ -279,42 +279,42 @@ namespace spades {
Vector3 diff = n2.pos - n1.pos;
float ln1 = diff.GetLength();
float dot = Vector3::Dot(diff, dir) / (ln1 + 0.000000001f);
-
+
if(dot >= minDot && dot <= maxDot)
return;
-
+
float strength = 0.f;
-
+
Vector3 a1 = Vector3::Cross(dir, diff);
a1 = Vector3::Cross(diff, a1).Normalize();
-
+
Vector3 a2 = -a1;
//a1=-a1; a2=-a2;
//a1 = -a1;
-
+
if(dot > maxDot){
strength = MyACos(dot) - MyACos(maxDot);
}else if(dot < minDot){
strength = MyACos(dot) - MyACos(minDot);
}
-
+
SPAssert(!isnan(strength));
-
+
strength *= 100.f;
strength *= dt;
-
+
a1 *= strength;
a2 *= strength;
-
+
n2.vel += a1;
n1.vel += a2;
//nBase.vel -= a1 + a2;
-
+
/*
d1 += a1 * 0.01;
d2 += a2 * 0.01;
float nd = Vector3::Dot(d1, d2) / (d1.GetLength() * d2.GetLength());
-
+
if(dot > maxDot){
if(nd < dot)
printf("GOOD %f -> %f\n", dot, nd);
@@ -327,11 +327,11 @@ namespace spades {
printf("BAD %f -> %f\n", dot, nd);
}*/
}
-
+
static float fractf(float v){
return v - floorf(v);
}
-
+
static void CheckEscape(GameMap *map,
IntVector3 hitBlock,
IntVector3 a, IntVector3 b,
@@ -370,31 +370,31 @@ namespace spades {
SPAssert(false);
return;
}
-
+
if(dist < bestDist){
bestDist = dist;
bestDir = dir;
}
}
-
+
void Corpse::LineCollision(NodeType a, NodeType b, float dt){
if(!r_corpseLineCollision)
return;
Node& n1 = nodes[a];
Node& n2 = nodes[b];
-
+
IntVector3 hitBlock;
-
+
if(map->CastRay(n1.lastPos, n2.lastPos, 16.f, hitBlock)) {
GameMap::RayCastResult res1 = map->CastRay2(n1.lastPos, n2.lastPos - n1.lastPos, 8);
GameMap::RayCastResult res2 = map->CastRay2(n2.lastPos, n1.lastPos - n2.lastPos, 8);
-
+
if(!res1.hit) return;
if(!res2.hit) return;
if(res1.startSolid || res2.startSolid){
return;
}
-
+
// really hit?
if(Vector3::Dot(res1.hitPos - n1.lastPos, n2.lastPos - n1.lastPos)
> (n2.pos-n1.pos).GetPoweredLength()){
@@ -412,23 +412,23 @@ namespace spades {
< 0.f){
return;
}
-
+
Vector3 blockPos;
blockPos.x = hitBlock.x + .5f;
blockPos.y = hitBlock.y + .5f;
blockPos.z = hitBlock.z + .5f;
-
+
float inlen = (res1.hitPos - res2.hitPos).GetLength();
-
+
IntVector3 ivec = {0, 0, 0};
-
+
ivec.x += res1.normal.x;
ivec.y += res1.normal.y;
ivec.z += res1.normal.z;
ivec.x += res2.normal.x;
ivec.y += res2.normal.y;
ivec.z += res2.normal.z;
-
+
Vector3 dir = {0.f, 0.f, 0.f};
if(ivec.x == 0 && ivec.y == 0 && ivec.z == 0) {
// hanging. which direction to escape?
@@ -474,25 +474,25 @@ namespace spades {
dir.x = ivec.x;
dir.y = ivec.y;
dir.z = ivec.z;
-
+
Vector3 normDir = dir; // |D|
-
+
n1.vel -= normDir * std::min(Vector3::Dot(normDir, n1.vel), 0.f);
n2.vel -= normDir * std::min(Vector3::Dot(normDir, n2.vel), 0.f);
-
+
dir *= dt * inlen * 5.f;
-
+
n1.vel += dir;
n2.vel += dir;
-
+
// friction
n1.vel -= (n1.vel - normDir * Vector3::Dot(normDir, n1.vel)) * .2f;
n2.vel -= (n2.vel - normDir * Vector3::Dot(normDir, n2.vel)) * .2f;
-
+
}
-
+
}
-
+
void Corpse::AngularMomentum(int eId,
NodeType a,
NodeType b){
@@ -503,19 +503,19 @@ namespace spades {
e.node1 = a; e.node2 = b;
return;
}
-
+
Vector3 force = e.lastVelDiff - e.velDiff;
force *= .5f;
nodes[b].vel += force;
nodes[a].vel -= force;
-
+
e.lastVelDiff = e.velDiff;
}
void Corpse::ApplyConstraint(float dt) {
SPADES_MARK_FUNCTION();
-
-
+
+
AngularMomentum(0,
Torso1, Torso2);
AngularMomentum(1,
@@ -532,23 +532,23 @@ namespace spades {
Torso3, Leg1);
AngularMomentum(7,
Torso4, Leg2);
-
+
Spring(Torso1, Torso2,
0.8f, dt);
Spring(Torso3, Torso4,
0.8f, dt);
-
+
Spring(Torso1, Torso4,
0.9f, dt);
Spring(Torso2, Torso3,
0.9f, dt);
-
+
Spring(Torso1, Torso3,
1.204f, dt);
Spring(Torso2, Torso4,
1.204f, dt);
-
-
+
+
Spring(Arm1, Torso1,
1.f, dt);
Spring(Arm2, Torso2,
@@ -557,33 +557,33 @@ namespace spades {
1.f, dt);
Spring(Leg2, Torso4,
1.f, dt);
-
+
AngleSpring(Torso1,
Arm1, Torso3,
-1.f, 0.6f, dt);
AngleSpring(Torso2,
Arm2, Torso4,
-1.f, 0.6f, dt);
-
+
AngleSpring(Torso3,
Leg1, Torso2,
-1.f, -0.2f, dt);
AngleSpring(Torso4,
Leg2, Torso1,
-1.f, -0.2f, dt);
-
+
Spring(Torso1, Torso2, Head,
.6f, dt);
/*
AngleSpring(Torso1,
Torso2, Head,
0.5f, 1.f, dt);
-
+
AngleSpring(Torso2,
Torso1, Head,
0.5f, 1.f, dt);
*/
-
+
LineCollision(Torso1, Torso2, dt);
LineCollision(Torso2, Torso3, dt);
LineCollision(Torso3, Torso4, dt);
@@ -594,57 +594,57 @@ namespace spades {
LineCollision(Torso2, Arm2, dt);
LineCollision(Torso3, Leg1, dt);
LineCollision(Torso4, Leg2, dt);
-
-
+
+
return;
AngleSpring(Torso4,
Torso1, Head,
0.5f, 1.f, dt);
-
+
AngleSpring(Torso3,
Torso2, Head,
0.5f, 1.f, dt);
-
+
AngleSpring(Torso4,
Torso2, Head,
0.5f, 1.f, dt);
-
+
AngleSpring(Torso3,
Torso1, Head,
0.5f, 1.f, dt);
}
-
+
void Corpse::Update(float dt) {
SPADES_MARK_FUNCTION();
float damp = 1.f;
- float damp2 = 1.f;
+ float damp2 = 1.f;
if(dt > 0.f){
damp = powf(.9f, dt);
damp2 = powf(.371f, dt);
- }
+ }
//dt *= 0.1f;
-
+
for(int i = 0; i 63.f){
node.vel.z -= dt * 6.f; // buoyancy
node.vel *= damp;
}else{
- node.vel.z += dt * 32.f; // gravity
- node.vel.z *= damp2;
- }
-
+ node.vel.z += dt * 32.f; // gravity
+ node.vel.z *= damp2;
+ }
+
//node.vel *= damp;
-
+
if(!map->ClipBox(oldPos.x, oldPos.y, oldPos.z)){
-
+
if(map->ClipBox(node.pos.x,
oldPos.y,
oldPos.z)){
@@ -652,11 +652,11 @@ namespace spades {
if(fabsf(node.vel.x) < .3f)
node.vel.x = 0.f;
node.pos.x = oldPos.x;
-
+
node.vel.y *= .5f;
node.vel.z *= .5f;
}
-
+
if(map->ClipBox(node.pos.x,
node.pos.y,
oldPos.z)){
@@ -664,11 +664,11 @@ namespace spades {
if(fabsf(node.vel.y) < .3f)
node.vel.y = 0.f;
node.pos.y = oldPos.y;
-
+
node.vel.x *= .5f;
node.vel.z *= .5f;
}
-
+
if(map->ClipBox(node.pos.x,
node.pos.y,
node.pos.z)){
@@ -676,18 +676,18 @@ namespace spades {
if(fabsf(node.vel.z) < .3f)
node.vel.z = 0.f;
node.pos.z = oldPos.z;
-
+
node.vel.x *= .5f;
node.vel.y *= .5f;
}
-
+
if(map->ClipBox(node.pos.x, node.pos.y, node.pos.z)){
// TODO: getting out block
//node.pos = oldPos;
//node.vel *= .5f;
}
}
-
+
/*
if(map->ClipBox(node.pos.x,
node.pos.y,
@@ -718,23 +718,23 @@ namespace spades {
}
node.vel *= .8f;
//node.pos = oldPos;
-
+
if(node.vel.GetLength() < .02f){
node.vel *= 0.f;
}
}*/
-
+
node.lastPos = node.pos;
node.lastForce = node.vel;
}
ApplyConstraint(dt);
-
+
for(int i = 0; i AddDebugLine(nodes[Torso4].pos,
nodes[Torso1].pos,
col);
-
+
renderer->AddDebugLine(nodes[Torso2].pos,
nodes[Torso4].pos,
col);
renderer->AddDebugLine(nodes[Torso1].pos,
nodes[Torso3].pos,
col);
-
-
+
+
renderer->AddDebugLine(nodes[Torso1].pos,
nodes[Arm1].pos,
col);
renderer->AddDebugLine(nodes[Torso2].pos,
nodes[Arm2].pos,
col);
-
+
renderer->AddDebugLine(nodes[Torso3].pos,
nodes[Leg1].pos,
col);
renderer->AddDebugLine(nodes[Torso4].pos,
nodes[Leg2].pos,
col);
-
-
+
+
renderer->AddDebugLine((nodes[Torso1].pos+nodes[Torso2].pos)*.5f,
nodes[Head].pos,
col);
return;
}
-
+
ModelRenderParam param;
param.customColor = color;
-
+
IModel *model;
Matrix4 scaler = Matrix4::Scale(.1f);
-
+
// draw torso
Matrix4 torso;
Vector3 tX, tY;
@@ -801,9 +801,9 @@ namespace spades {
tY = Vector3::Cross(tX, tZ).Normalize();
Vector3 tOrigin = tY1 * .5f;
torso = Matrix4::FromAxis(tX, -tZ, -tY, tOrigin);
-
+
param.matrix = torso * scaler;
-
+
model = renderer->RegisterModel
("Models/Player/Torso.kv6");
renderer->RenderModel(model, param);
@@ -812,13 +812,13 @@ namespace spades {
{
Vector3 headBase =
(torso * MakeVector3(0.0f, 0.f, 0.f)).GetXYZ();
-
+
model = renderer->RegisterModel
("Models/Player/Head.kv6");
-
+
Vector3 aX, aY, aZ;
Vector3 center = (nodes[Torso1].pos + nodes[Torso2].pos) * .5f;
-
+
aZ = nodes[Head].pos - center;
aZ = -torso.GetAxis(2);
aZ = aZ.Normalize();
@@ -826,73 +826,73 @@ namespace spades {
aY = Vector3::Cross(aY, aZ).Normalize();
aX = Vector3::Cross(aY, aZ).Normalize();
param.matrix = Matrix4::FromAxis(-aX, aY, -aZ, headBase) * scaler;
-
+
renderer->RenderModel(model, param);
}
-
+
// draw Arms
{
Vector3 arm1Base =
(torso * MakeVector3(0.4f, 0.f, 0.2f)).GetXYZ();
Vector3 arm2Base =
(torso * MakeVector3(-0.4f, 0.f, 0.2f)).GetXYZ();
-
+
model = renderer->RegisterModel
("Models/Player/Arm.kv6");
-
+
Vector3 aX, aY, aZ;
-
+
aZ = nodes[Arm1].pos - nodes[Torso1].pos;
aZ = aZ.Normalize();
aY = nodes[Torso2].pos - nodes[Torso1].pos;
aY = Vector3::Cross(aY, aZ).Normalize();
aX = Vector3::Cross(aY, aZ).Normalize();
param.matrix = Matrix4::FromAxis(aX, aY, aZ, arm1Base) * scaler;
-
+
renderer->RenderModel(model, param);
-
+
aZ = nodes[Arm2].pos - nodes[Torso2].pos;
aZ = aZ.Normalize();
aY = nodes[Torso1].pos - nodes[Torso2].pos;
aY = Vector3::Cross(aY, aZ).Normalize();
aX = Vector3::Cross(aY, aZ).Normalize();
param.matrix = Matrix4::FromAxis(aX, aY, aZ, arm2Base) * scaler;
-
+
renderer->RenderModel(model, param);
}
-
+
// draw Leg
{
Vector3 leg1Base =
(torso * MakeVector3(0.25f, 0.f, 0.9f)).GetXYZ();
Vector3 leg2Base =
(torso * MakeVector3(-0.25f, 0.f, 0.9f)).GetXYZ();
-
+
model = renderer->RegisterModel
("Models/Player/Leg.kv6");
-
+
Vector3 aX, aY, aZ;
-
+
aZ = nodes[Leg1].pos - nodes[Torso3].pos;
aZ = aZ.Normalize();
aY = nodes[Torso1].pos - nodes[Torso2].pos;
aY = Vector3::Cross(aY, aZ).Normalize();
aX = Vector3::Cross(aY, aZ).Normalize();
param.matrix = Matrix4::FromAxis(aX, aY, aZ, leg1Base) * scaler;
-
+
renderer->RenderModel(model, param);
-
+
aZ = nodes[Leg2].pos - nodes[Torso4].pos;
aZ = aZ.Normalize();
aY = nodes[Torso1].pos - nodes[Torso2].pos;
aY = Vector3::Cross(aY, aZ).Normalize();
aX = Vector3::Cross(aY, aZ).Normalize();
param.matrix = Matrix4::FromAxis(aX, aY, aZ, leg2Base) * scaler;
-
+
renderer->RenderModel(model, param);
}
}
-
+
Vector3 Corpse::GetCenter() {
Vector3 v = {0,0,0};
for(int i = 0; i < NodeCount; i++)
@@ -900,12 +900,12 @@ namespace spades {
v *= 1.f / (float)NodeCount;
return v;
}
-
+
bool Corpse::IsVisibleFrom(spades::Vector3 eye){
// distance culled?
if((eye - GetCenter()).GetLength() > 150.f)
return false;
-
+
for(int i = 0; i < NodeCount; i++){
IntVector3 outBlk;
if(map->CastRay(eye, nodes[i].pos,
@@ -914,7 +914,7 @@ namespace spades {
}
return false;
}
-
+
void Corpse::AddImpulse(spades::Vector3 v){
for(int i = 0; i < NodeCount; i++)
nodes[i].vel += v;
diff --git a/Sources/Client/GameMapWrapper.cpp b/Sources/Client/GameMapWrapper.cpp
index f4d1244d..59a7695d 100644
--- a/Sources/Client/GameMapWrapper.cpp
+++ b/Sources/Client/GameMapWrapper.cpp
@@ -1,21 +1,21 @@
/*
Copyright (c) 2013 yvt
-
+
This file is part of OpenSpades.
-
+
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see .
-
+
*/
#include "GameMapWrapper.h"
@@ -31,51 +31,51 @@
namespace spades {
namespace client {
-
-
+
+
GameMapWrapper::GameMapWrapper(GameMap *mp):
map(mp) {
SPADES_MARK_FUNCTION();
-
+
width = mp->Width();
height = mp->Height();
depth = mp->Depth();
linkMap = new uint8_t[width*height*depth];
memset(linkMap, 0, width * height * depth);
}
-
+
GameMapWrapper::~GameMapWrapper() {
SPADES_MARK_FUNCTION();
delete[] linkMap;
}
-
+
void GameMapWrapper::Rebuild() {
SPADES_MARK_FUNCTION();
-
+
Stopwatch stopwatch;
-
+
GameMap *m = map;
memset(linkMap, 0, width * height * depth);
-
+
for(int x = 0; x < width; x++)
for(int y = 0; y < height; y++)
SetLink(x, y, depth - 1, Root);
-
+
Deque queue(width * height * 2);
-
+
for(int x = 0; x < width; x++)
for(int y = 0; y < height; y++)
if(m->IsSolid(x, y, depth - 2)){
SetLink(x, y, depth-2, PositiveZ);
queue.Push(CellPos(x, y, depth - 2));
}
-
+
while(!queue.IsEmpty()){
CellPos p = queue.Front();
queue.Shift();
-
+
int x = p.x, y = p.y, z = p.z;
-
+
if(p.x > 0 && m->IsSolid(x-1,y,z) && GetLink(x-1,y,z) == Invalid){
SetLink(x-1, y, z, PositiveX);
queue.Push(CellPos(x-1, y, z));
@@ -101,28 +101,28 @@ namespace spades {
queue.Push(CellPos(x, y, z+1));
}
}
-
+
SPLog("%.3f msecs to rebuild",
stopwatch.GetTime() * 1000.);
-
+
}
-
+
void GameMapWrapper::AddBlock(int x, int y, int z, uint32_t color){
SPADES_MARK_FUNCTION();
-
+
GameMap *m = map;
-
+
if(GetLink(x, y, z) != Invalid) {
SPAssert(m->IsSolid(x, y, z));
return;
}
-
+
m->Set(x, y, z, true, color);
-
+
if(GetLink(x, y, z) != Invalid) {
return;
}
-
+
LinkType l = Invalid;
if(x > 0 && m->IsSolid(x - 1, y, z) &&
GetLink(x-1, y, z) != Invalid){
@@ -155,7 +155,7 @@ namespace spades {
SPAssert(GetLink(x, y, z+1) != NegativeZ);
}
SetLink(x, y, z, l);
-
+
if(l == Invalid)
return;
// if there's invalid block around this block,
@@ -165,12 +165,12 @@ namespace spades {
while(!queue.IsEmpty()){
CellPos p = queue.Front();
queue.Shift();
-
+
int x = p.x, y = p.y, z = p.z;
SPAssert(m->IsSolid(x,y,z));
-
+
LinkType thisLink = GetLink(x, y, z);
-
+
if(p.x > 0 && m->IsSolid(x-1,y,z) && GetLink(x-1,y,z) == Invalid &&
thisLink != NegativeX){
SetLink(x-1, y, z, PositiveX);
@@ -202,50 +202,50 @@ namespace spades {
queue.Push(CellPos(x, y, z+1));
}
}
-
+
}
-
- template
- static inline bool EqualTwoCond(T a, T b, T c, bool cond) {
- return a == b || (cond && a == c);
- }
-
+
+ template
+ static inline bool EqualTwoCond(T a, T b, T c, bool cond) {
+ return a == b || (cond && a == c);
+ }
+
std::vector GameMapWrapper::RemoveBlocks(const std::vector& cells) {
SPADES_MARK_FUNCTION();
-
+
if(cells.empty())
return std::vector();
-
+
GameMap *m = map;
-
+
// solid, but unlinked cells
std::vector unlinkedCells;
Deque queue(1024);
-
+
// unlink children
for(size_t i = 0; i < cells.size(); i++){
CellPos pos = cells[i];
m->Set(pos.x, pos.y, pos.z, false, 0);
// if(GetLink(pos.x, pos.y, pos.z) == Invalid){
- // this block is already disconnected.
- // }
-
- if(GetLink(pos.x, pos.y, pos.z) == Marked){
- continue;
- }
+ // this block is already disconnected.
+ // }
+
+ if(GetLink(pos.x, pos.y, pos.z) == Marked){
+ continue;
+ }
SPAssert(GetLink(pos.x, pos.y, pos.z) != Root);
-
+
SetLink(pos.x, pos.y, pos.z, Invalid);
queue.Push(pos);
-
+
while(!queue.IsEmpty()){
pos = queue.Front();
queue.Shift();
-
+
if(m->IsSolid(pos.x, pos.y, pos.z))
unlinkedCells.push_back(pos);
// don't "continue;" when non-solid
-
+
int x = pos.x, y = pos.y, z = pos.z;
if(x > 0 && EqualTwoCond(GetLink(x-1,y,z), PositiveX, Invalid, m->IsSolid(x-1, y, z))){
SetLink(x-1, y, z, Marked);
@@ -272,18 +272,18 @@ namespace spades {
queue.Push(CellPos(x, y, z+1));
}
}
-
+
}
-
- // remove "visited" mark
+
+ // remove "visited" mark
for(size_t i = 0; i < unlinkedCells.size(); i++){
- const CellPos& pos = unlinkedCells[i];
- if(GetLink(pos.x, pos.y, pos.z) == Marked)
- SetLink(pos.x, pos.y, pos.z, Invalid);
- }
-
+ const CellPos& pos = unlinkedCells[i];
+ if(GetLink(pos.x, pos.y, pos.z) == Marked)
+ SetLink(pos.x, pos.y, pos.z, Invalid);
+ }
+
SPAssert(queue.IsEmpty());
-
+
// start relinking
for(size_t i = 0; i < unlinkedCells.size(); i++){
const CellPos& pos = unlinkedCells[i];
@@ -293,7 +293,7 @@ namespace spades {
// don't use SPAssert()
continue;
}
-
+
LinkType newLink = Invalid;
if(z < depth - 1 && GetLink(x,y,z+1) != Invalid){
newLink = PositiveZ;
@@ -308,21 +308,21 @@ namespace spades {
}else if(z > 0 && GetLink(x,y,z-1) != Invalid){
newLink = NegativeZ;
}
-
+
if(newLink != Invalid){
SetLink(x, y, z, newLink);
queue.Push(pos);
}
-
+
}
-
+
while(!queue.IsEmpty()){
CellPos p = queue.Front();
queue.Shift();
-
+
int x = p.x, y = p.y, z = p.z;
LinkType thisLink = GetLink(x,y,z);
-
+
if(p.x > 0 && m->IsSolid(x-1,y,z) && GetLink(x-1,y,z) == Invalid &&
thisLink != NegativeX){
SetLink(x-1, y, z, PositiveX);
@@ -354,10 +354,10 @@ namespace spades {
queue.Push(CellPos(x, y, z+1));
}
}
-
+
std::vector floatingBlocks;
floatingBlocks.reserve(unlinkedCells.size());
-
+
for(size_t i = 0; i < unlinkedCells.size(); i++){
const CellPos& p = unlinkedCells[i];
if(!m->IsSolid(p.x, p.y, p.z))
@@ -366,7 +366,7 @@ namespace spades {
floatingBlocks.push_back(p);
}
}
-
+
return floatingBlocks;
}
}
diff --git a/Sources/Client/MumbleLink.cpp b/Sources/Client/MumbleLink.cpp
index 65a40036..9d1c8b84 100644
--- a/Sources/Client/MumbleLink.cpp
+++ b/Sources/Client/MumbleLink.cpp
@@ -37,115 +37,115 @@ namespace spades {
#endif
};
- MumbleLink::MumbleLink() :
- metre_per_block(0.63),
+ MumbleLink::MumbleLink() :
+ metre_per_block(0.63),
mumbleLinkedMemory(nullptr),
priv(new MumbleLinkPrivate())
{}
- MumbleLink::~MumbleLink() {
- #ifdef WIN32
- UnmapViewOfFile(mumbleLinkedMemory);
- if (priv->obj != nullptr)
- CloseHandle(priv->obj);
- #else
- munmap(mumbleLinkedMemory, sizeof(*mumbleLinkedMemory));
- if (priv->fd > 0)
- close(priv->fd);
- #endif
- }
+ MumbleLink::~MumbleLink() {
+#ifdef WIN32
+ UnmapViewOfFile(mumbleLinkedMemory);
+ if (priv->obj != nullptr)
+ CloseHandle(priv->obj);
+#else
+ munmap(mumbleLinkedMemory, sizeof(*mumbleLinkedMemory));
+ if (priv->fd > 0)
+ close(priv->fd);
+#endif
+ }
- void MumbleLink::set_mumble_vector3(float mumble_vec[3],
- const spades::Vector3 &vec) {
- mumble_vec[0] = vec.x;
- mumble_vec[1] = vec.z;
- mumble_vec[2] = vec.y;
- }
+ void MumbleLink::set_mumble_vector3(float mumble_vec[3],
+ const spades::Vector3 &vec) {
+ mumble_vec[0] = vec.x;
+ mumble_vec[1] = vec.z;
+ mumble_vec[2] = vec.y;
+ }
- bool MumbleLink::init() {
- assert(mumbleLinkedMemory == nullptr);
- #ifdef WIN32
- priv->obj = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, L"MumbleLink");
- if (priv->obj == nullptr)
- return false;
+ bool MumbleLink::init() {
+ assert(mumbleLinkedMemory == nullptr);
+#ifdef WIN32
+ priv->obj = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, L"MumbleLink");
+ if (priv->obj == nullptr)
+ return false;
- mumbleLinkedMemory = static_cast(MapViewOfFile(
- priv->obj, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(*mumbleLinkedMemory)));
+ mumbleLinkedMemory = static_cast(MapViewOfFile(
+ priv->obj, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(*mumbleLinkedMemory)));
- if (mumbleLinkedMemory == nullptr) {
- CloseHandle(priv->obj);
- priv->obj = nullptr;
- return false;
- }
- #else
- std::string name = "/MumbleLink." + std::to_string(getuid());
+ if (mumbleLinkedMemory == nullptr) {
+ CloseHandle(priv->obj);
+ priv->obj = nullptr;
+ return false;
+ }
+#else
+ std::string name = "/MumbleLink." + std::to_string(getuid());
- priv->fd = shm_open(name.c_str(), O_RDWR, S_IRUSR | S_IWUSR);
+ priv->fd = shm_open(name.c_str(), O_RDWR, S_IRUSR | S_IWUSR);
- if (priv->fd < 0) {
- return false;
- }
+ if (priv->fd < 0) {
+ return false;
+ }
- mumbleLinkedMemory = static_cast(
- (mmap(nullptr, sizeof(*mumbleLinkedMemory), PROT_READ | PROT_WRITE,
- MAP_SHARED, priv->fd, 0)));
+ mumbleLinkedMemory = static_cast(
+ (mmap(nullptr, sizeof(*mumbleLinkedMemory), PROT_READ | PROT_WRITE,
+ MAP_SHARED, priv->fd, 0)));
- if (mumbleLinkedMemory == MAP_FAILED) {
- mumbleLinkedMemory = nullptr;
- return false;
- }
- #endif
- return true;
- }
+ if (mumbleLinkedMemory == MAP_FAILED) {
+ mumbleLinkedMemory = nullptr;
+ return false;
+ }
+#endif
+ return true;
+ }
- void MumbleLink::setContext(const std::string &context) {
- if (mumbleLinkedMemory == nullptr)
- return;
- size_t len(std::min(256, static_cast(context.size())));
- std::memcpy(mumbleLinkedMemory->context, context.c_str(), len);
- mumbleLinkedMemory->context_len = len;
- }
+ void MumbleLink::setContext(const std::string &context) {
+ if (mumbleLinkedMemory == nullptr)
+ return;
+ size_t len(std::min(256, static_cast(context.size())));
+ std::memcpy(mumbleLinkedMemory->context, context.c_str(), len);
+ mumbleLinkedMemory->context_len = len;
+ }
- void MumbleLink::setIdentity(const std::string &identity) {
- if (mumbleLinkedMemory == nullptr)
- return;
- std::wcsncpy(mumbleLinkedMemory->identity,
- std::wstring(identity.begin(), identity.end()).c_str(), 256);
- }
+ void MumbleLink::setIdentity(const std::string &identity) {
+ if (mumbleLinkedMemory == nullptr)
+ return;
+ std::wcsncpy(mumbleLinkedMemory->identity,
+ std::wstring(identity.begin(), identity.end()).c_str(), 256);
+ }
- void MumbleLink::update(spades::client::Player *player) {
- if (mumbleLinkedMemory == nullptr || player == nullptr)
- return;
+ void MumbleLink::update(spades::client::Player *player) {
+ if (mumbleLinkedMemory == nullptr || player == nullptr)
+ return;
- if (mumbleLinkedMemory->uiVersion != 2) {
- wcsncpy(mumbleLinkedMemory->name, L"OpenSpades", 256);
- wcsncpy(mumbleLinkedMemory->description, L"OpenSpades Link plugin.", 2048);
- mumbleLinkedMemory->uiVersion = 2;
- }
- mumbleLinkedMemory->uiTick++;
+ if (mumbleLinkedMemory->uiVersion != 2) {
+ wcsncpy(mumbleLinkedMemory->name, L"OpenSpades", 256);
+ wcsncpy(mumbleLinkedMemory->description, L"OpenSpades Link plugin.", 2048);
+ mumbleLinkedMemory->uiVersion = 2;
+ }
+ mumbleLinkedMemory->uiTick++;
- // Left handed coordinate system.
- // X positive towards "right".
- // Y positive towards "up".
- // Z positive towards "front".
- //
- // 1 unit = 1 meter
+ // Left handed coordinate system.
+ // X positive towards "right".
+ // Y positive towards "up".
+ // Z positive towards "front".
+ //
+ // 1 unit = 1 meter
- // Unit vector pointing out of the avatar's eyes aka "At"-vector.
- set_mumble_vector3(mumbleLinkedMemory->fAvatarFront, player->GetFront());
+ // Unit vector pointing out of the avatar's eyes aka "At"-vector.
+ set_mumble_vector3(mumbleLinkedMemory->fAvatarFront, player->GetFront());
- // Unit vector pointing out of the top of the avatar's head aka "Up"-vector
- // (here Top points straight up).
- set_mumble_vector3(mumbleLinkedMemory->fAvatarTop, player->GetUp());
+ // Unit vector pointing out of the top of the avatar's head aka "Up"-vector
+ // (here Top points straight up).
+ set_mumble_vector3(mumbleLinkedMemory->fAvatarTop, player->GetUp());
- // Position of the avatar (here standing slightly off the origin)
- set_mumble_vector3(mumbleLinkedMemory->fAvatarPosition,
- player->GetPosition() * metre_per_block);
+ // Position of the avatar (here standing slightly off the origin)
+ set_mumble_vector3(mumbleLinkedMemory->fAvatarPosition,
+ player->GetPosition() * metre_per_block);
- // Same as avatar but for the camera.
- set_mumble_vector3(mumbleLinkedMemory->fCameraPosition,
- player->GetPosition() * metre_per_block);
- set_mumble_vector3(mumbleLinkedMemory->fCameraFront, player->GetFront());
- set_mumble_vector3(mumbleLinkedMemory->fCameraTop, player->GetUp());
- }
+ // Same as avatar but for the camera.
+ set_mumble_vector3(mumbleLinkedMemory->fCameraPosition,
+ player->GetPosition() * metre_per_block);
+ set_mumble_vector3(mumbleLinkedMemory->fCameraFront, player->GetFront());
+ set_mumble_vector3(mumbleLinkedMemory->fCameraTop, player->GetUp());
+ }
}
diff --git a/Sources/Client/NetClient.cpp b/Sources/Client/NetClient.cpp
index 5bf317a3..441ba25f 100644
--- a/Sources/Client/NetClient.cpp
+++ b/Sources/Client/NetClient.cpp
@@ -1,22 +1,22 @@
/*
Copyright (c) 2013 yvt
based on code of pysnip (c) Mathias Kaerlev 2011-2012.
-
+
This file is part of OpenSpades.
-
+
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see .
-
+
*/
#include
@@ -47,9 +47,9 @@ DEFINE_SPADES_SETTING(cg_unicode, "1");
namespace spades {
namespace client {
-
+
static const char UtfSign = -1;
-
+
enum{
BLUE_FLAG = 0,
GREEN_FLAG = 1,
@@ -95,7 +95,7 @@ namespace spades {
PacketTypeVersionSend = 34, // C2S
};
-
+
static std::string EncodeString(std::string str) {
auto str2 = CP437::Encode(str, -1);
if(!cg_unicode) {
@@ -110,27 +110,27 @@ namespace spades {
}
return str;
}
-
+
static std::string DecodeString(std::string s) {
if(s.size() > 0 && s[0] == UtfSign){
return s.substr(1);
}
return CP437::Decode(s);
}
-
+
class NetPacketReader {
std::vector data;
size_t pos;
public:
NetPacketReader(ENetPacket *packet){
SPADES_MARK_FUNCTION();
-
+
data.resize(packet->dataLength);
memcpy(data.data(), packet->data, packet->dataLength);
enet_packet_destroy(packet);
pos = 1;
}
-
+
NetPacketReader(const std::vector inData){
data = inData;
pos = 1;
@@ -140,7 +140,7 @@ namespace spades {
}
uint32_t ReadInt() {
SPADES_MARK_FUNCTION();
-
+
uint32_t value = 0;
if(pos + 4 > data.size()){
SPRaise("Received packet truncated");
@@ -153,7 +153,7 @@ namespace spades {
}
uint16_t ReadShort() {
SPADES_MARK_FUNCTION();
-
+
uint32_t value = 0;
if(pos + 2 > data.size()){
SPRaise("Received packet truncated");
@@ -164,7 +164,7 @@ namespace spades {
}
uint8_t ReadByte() {
SPADES_MARK_FUNCTION();
-
+
if(pos >= data.size()){
SPRaise("Received packet truncated");
}
@@ -179,7 +179,7 @@ namespace spades {
v = ReadInt();
return f;
}
-
+
IntVector3 ReadIntColor() {
SPADES_MARK_FUNCTION();
IntVector3 col;
@@ -188,7 +188,7 @@ namespace spades {
col.x = ReadByte();
return col;
}
-
+
Vector3 ReadFloatColor() {
SPADES_MARK_FUNCTION();
Vector3 col;
@@ -197,11 +197,11 @@ namespace spades {
col.x = ReadByte() / 255.f;
return col;
}
-
+
std::vector GetData() {
return data;
}
-
+
std::string ReadData(size_t siz) {
if(pos + siz > data.size()){
SPRaise("Received packet truncated");
@@ -214,7 +214,7 @@ namespace spades {
return std::string(data.data() + pos,
data.size() - pos);
}
-
+
std::string ReadString(size_t siz){
// convert to C string once so that
// null-chars are removed
@@ -229,7 +229,7 @@ namespace spades {
s = DecodeString(s);
return s;
}
-
+
void DumpDebug() {
#if 1
char buf[1024];
@@ -245,20 +245,20 @@ namespace spades {
sprintf(buf, " %02x", (unsigned int)(unsigned char)data[i]);
str += buf;
}
-
-
+
+
SPLog("%s", str.c_str());
#endif
}
};
-
+
class NetPacketWriter {
std::vector data;
public:
NetPacketWriter(PacketType type){
data.push_back(type);
}
-
+
void Write(uint8_t v){
SPADES_MARK_FUNCTION_DEBUG();
data.push_back(v);
@@ -288,14 +288,14 @@ namespace spades {
Write((uint8_t)v.y);
Write((uint8_t)v.x);
}
-
+
void Write(std::string str){
str = EncodeString(str);
data.insert(data.end(),
str.begin(),
str.end());
}
-
+
void Write(std::string str, size_t fillLen){
str = EncodeString(str);
Write(str.substr(0, fillLen));
@@ -305,23 +305,23 @@ namespace spades {
sz++;
}
}
-
+
ENetPacket *CreatePacket(int flag = ENET_PACKET_FLAG_RELIABLE) {
return enet_packet_create(data.data(),
data.size(),
flag);
}
};
-
+
NetClient::NetClient(Client *c):
client(c),
host(nullptr),
peer(nullptr){
SPADES_MARK_FUNCTION();
-
+
enet_initialize();
SPLog("ENet initialized");
-
+
host = enet_host_create(NULL,
1, 1,
100000, 100000);
@@ -329,44 +329,44 @@ namespace spades {
if(!host){
SPRaise("Failed to create ENet host");
}
-
+
if(enet_host_compress_with_range_coder(host) < 0)
SPRaise("Failed to enable ENet Range coder.");
-
+
SPLog("ENet Range Coder Enabled");
-
+
peer = NULL;
status = NetClientStatusNotConnected;
-
+
lastPlayerInput = 0;
lastWeaponInput = 0;
-
+
savedPlayerPos.resize(32);
savedPlayerFront.resize(32);
savedPlayerTeam.resize(32);
playerPosRecords.resize(32);
-
+
std::fill(savedPlayerTeam.begin(),
savedPlayerTeam.end(), -1);
-
+
bandwidthMonitor.reset(new BandwidthMonitor(host));
}
NetClient::~NetClient(){
SPADES_MARK_FUNCTION();
-
+
Disconnect();
if(host)
enet_host_destroy(host);
bandwidthMonitor.reset();
SPLog("ENet host destroyed");
}
-
+
void NetClient::Connect(const ServerAddress& hostname) {
SPADES_MARK_FUNCTION();
-
+
Disconnect();
SPAssert(status == NetClientStatusNotConnected);
-
+
if( hostname.protocol() != ProtocolVersion::Unknown ) {
cg_protocolVersion = (int)hostname.protocol();
}
@@ -385,33 +385,33 @@ namespace spades {
ENetAddress addr = hostname.asAddress();
SPLog("Connecting to %u:%u", (unsigned int)addr.host, (unsigned int)addr.port);
-
+
savedPackets.clear();
-
+
peer = enet_host_connect(host, &addr, 1, (int)cg_protocolVersion);
if(peer == NULL){
SPRaise("Failed to create ENet peer");
}
-
+
status = NetClientStatusConnecting;
statusString = _Tr("NetClient", "Connecting to the server");
timeToTryMapLoad = 0;
-
+
protocolVersion = cg_protocolVersion;
}
-
+
void NetClient::Disconnect() {
SPADES_MARK_FUNCTION();
-
+
if(!peer)
return;
enet_peer_disconnect(peer, 0);
-
+
status = NetClientStatusNotConnected;
statusString = _Tr("NetClient", "Not connected");
-
+
savedPackets.clear();
-
+
ENetEvent event;
SPLog("Waiting for graceful disconnection");
while(enet_host_service(host, &event, 1000) > 0){
@@ -429,50 +429,50 @@ namespace spades {
// discard
}
}
-
-
+
+
SPLog("Connection terminated");
enet_peer_reset(peer);
// FXIME: release peer
peer = NULL;
}
-
+
int NetClient::GetPing() {
SPADES_MARK_FUNCTION();
-
+
if(status == NetClientStatusNotConnected)
return -1;
-
+
auto rtt = peer->roundTripTime;
if(rtt == 0) return -1;
return static_cast(rtt);
}
-
+
void NetClient::DoEvents(int timeout) {
SPADES_MARK_FUNCTION();
-
+
if(status == NetClientStatusNotConnected)
return;
-
+
// don't allow changin cg_protocolVersion
if((int)cg_protocolVersion != protocolVersion) {
cg_protocolVersion = protocolVersion;
}
-
+
if(bandwidthMonitor)
bandwidthMonitor->Update();
-
+
ENetEvent event;
while(enet_host_service(host, &event, timeout) > 0){
if(event.type == ENET_EVENT_TYPE_DISCONNECT) {
if(GetWorld()){
client->SetWorld(NULL);
}
-
+
enet_peer_reset(peer);
peer = NULL;
status = NetClientStatusNotConnected;
-
+
SPLog("Disconnected (data = 0x%08x)",
(unsigned int)event.data);
statusString = "Disconnected: " + DisconnectReasonString(event.data);
@@ -487,7 +487,7 @@ namespace spades {
if(reader.GetType() != PacketTypeMapStart){
SPRaise("Unexpected packet: %d", (int)reader.GetType());
}
-
+
mapSize = reader.ReadInt();
status = NetClientStatusReceivingMap;
statusString = _Tr("NetClient", "Loading snapshot");
@@ -497,22 +497,22 @@ namespace spades {
}else if(status == NetClientStatusReceivingMap){
if(event.type == ENET_EVENT_TYPE_RECEIVE){
NetPacketReader reader(event.packet);
-
+
if(reader.GetType() == PacketTypeMapChunk){
std::vector dt = reader.GetData();
dt.erase(dt.begin());
mapData.insert(mapData.end(),
dt.begin(), dt.end());
-
+
timeToTryMapLoad = 200;
-
+
statusString = _Tr("NetClient", "Loading snapshot ({0}/{1})",
mapData.size(), mapSize);
-
+
if(mapSize == mapData.size()){
status = NetClientStatusConnected;
statusString = _Tr("NetClient", "Connected");
-
+
try{
MapLoaded();
}catch(const std::exception& ex){
@@ -528,25 +528,25 @@ namespace spades {
statusString = _Tr("NetClient", "Error");
throw;
}
-
+
}catch(...){
Disconnect();
statusString = _Tr("NetClient", "Error");
throw;
}
-
+
}
-
+
}else{
reader.DumpDebug();
-
+
if(reader.GetType() != PacketTypeWorldUpdate &&
reader.GetType() != PacketTypeExistingPlayer &&
reader.GetType() != PacketTypeCreatePlayer &&
tryMapLoadOnPacketType){
status = NetClientStatusConnected;
statusString = _Tr("NetClient", "Connected");
-
+
try{
MapLoaded();
}catch(const std::exception& ex){
@@ -574,10 +574,10 @@ namespace spades {
stillLoading:
savedPackets.push_back(reader.GetData());
}
-
+
//Handle(reader);
-
-
+
+
}
}
}else if(status == NetClientStatusConnected){
@@ -595,7 +595,7 @@ namespace spades {
}
}
}
-
+
if(status == NetClientStatusReceivingMap){
if(timeToTryMapLoad > 0){
timeToTryMapLoad--;
@@ -626,11 +626,11 @@ namespace spades {
}
}
}
-
+
World *NetClient::GetWorld(){
return client->GetWorld();
}
-
+
Player * NetClient::GetPlayerOrNull(int pId){
SPADES_MARK_FUNCTION();
if(!GetWorld())
@@ -649,7 +649,7 @@ namespace spades {
SPRaise("Invalid Player ID %d: Doesn't exist", pId);
return GetWorld()->GetPlayer(pId);
}
-
+
Player *NetClient::GetLocalPlayer() {
SPADES_MARK_FUNCTION();
if(!GetWorld())
@@ -658,7 +658,7 @@ namespace spades {
SPRaise("Failed to get local player: no local player");
return GetWorld()->GetLocalPlayer();
}
-
+
Player *NetClient::GetLocalPlayerOrNull() {
SPADES_MARK_FUNCTION();
if(!GetWorld())
@@ -677,14 +677,14 @@ namespace spades {
inp.sprint = (bits & (1 << 7)) != 0;
return inp;
}
-
+
WeaponInput ParseWeaponInput(uint8_t bits){
WeaponInput inp;
inp.primary = ((bits & (1)) != 0);
inp.secondary = ((bits & (1 << 1)) != 0);
return inp;
}
-
+
std::string NetClient::DisconnectReasonString(enet_uint32 num){
switch(num){
case 1:
@@ -703,10 +703,10 @@ namespace spades {
return _Tr("NetClient", "Unknown Reason");
}
}
-
+
void NetClient::Handle(spades::client::NetPacketReader & reader) {
SPADES_MARK_FUNCTION();
-
+
switch(reader.GetType()){
case PacketTypePositionData:
{
@@ -757,7 +757,7 @@ namespace spades {
front.x = reader.ReadFloat();
front.y = reader.ReadFloat();
front.z = reader.ReadFloat();
-
+
savedPlayerPos[idx] = pos;
savedPlayerFront[idx] = front;
if(pos.x != 0.f ||
@@ -780,7 +780,7 @@ namespace spades {
if(p != GetWorld()->GetLocalPlayer()){
p->SetPosition(pos);
p->SetOrientation(front);
-
+
PosRecord& rec = playerPosRecords[idx];
if(rec.valid) {
float timespan = GetWorld()->GetTime() - rec.time;
@@ -789,7 +789,7 @@ namespace spades {
vel *= 1.f / 32.f;
p->SetVelocity(vel);
}
-
+
rec.valid = true;
rec.pos = pos;
rec.time = GetWorld()->GetTime();
@@ -807,9 +807,9 @@ namespace spades {
{
int pId = reader.ReadByte();
Player *p = GetPlayer(pId);
-
+
PlayerInput inp = ParsePlayerInput(reader.ReadByte());
-
+
if(GetWorld()->GetLocalPlayer() == p) {
// handle "/fly" jump
if(inp.jump) {
@@ -817,27 +817,27 @@ namespace spades {
}
break;
}
-
+
p->SetInput(inp);
}
break;
-
+
case PacketTypeWeaponInput:
if(!GetWorld())
break;
{
int pId = reader.ReadByte();
Player *p = GetPlayer(pId);
-
+
WeaponInput inp = ParseWeaponInput(reader.ReadByte());
-
+
if(GetWorld()->GetLocalPlayer() == p)
break;
-
+
p->SetWeaponInput(inp);
}
break;
-
+
// Hit Packet is Client-to-Server!
case PacketTypeSetHP:
{
@@ -852,7 +852,7 @@ namespace spades {
HurtTypeFall, hurtPos);
}
break;
-
+
case PacketTypeGrenadePacket:
if(!GetWorld())
break;
@@ -873,12 +873,12 @@ namespace spades {
// emit by Player
break;
}*/
-
+
Grenade *g = new Grenade(GetWorld(), pos, vel, fuseLen);
GetWorld()->AddGrenade(g);
}
break;
-
+
case PacketTypeSetTool:
{
Player *p = GetPlayer(reader.ReadByte());
@@ -911,11 +911,11 @@ namespace spades {
int team = reader.ReadByte();
int weapon = reader.ReadByte();
int tool = reader.ReadByte();
- int kills = reader.ReadInt();
+ int kills = reader.ReadInt();
IntVector3 color = reader.ReadIntColor();
std::string name = reader.ReadRemainingString();
// TODO: decode name?
-
+
WeaponType wType;
switch(weapon){
case 0:
@@ -930,12 +930,12 @@ namespace spades {
default:
SPRaise("Received invalid weapon: %d", weapon);
}
-
+
Player *p = new Player(GetWorld(), pId, wType, team, savedPlayerPos[pId], GetWorld()->GetTeam(team).color);
p->SetHeldBlockColor(color);
//p->SetOrientation(savedPlayerFront[pId]);
GetWorld()->SetPlayer(pId, p);
-
+
switch(tool){
case 0: p->SetTool(Player::ToolSpade); break;
case 1: p->SetTool(Player::ToolBlock); break;
@@ -944,11 +944,11 @@ namespace spades {
default:
SPRaise("Received invalid tool type: %d", tool);
}
-
+
World::PlayerPersistent& pers = GetWorld()->GetPlayerPersistent(pId);
pers.name = name;
pers.kills = kills;
-
+
savedPlayerTeam[pId] = team;
}
break;
@@ -963,7 +963,7 @@ namespace spades {
pos.x = reader.ReadFloat();
pos.y = reader.ReadFloat();
pos.z = reader.ReadFloat();
-
+
IGameMode* mode = GetWorld()->GetMode();
if( mode && IGameMode::m_CTF == mode->ModeType() ){
CTFGameMode *ctf = static_cast(mode);
@@ -986,11 +986,11 @@ namespace spades {
if(type >= tc->GetNumTerritories()){
SPRaise("Invalid territory id specified: %d (max = %d)", (int)type, tc->GetNumTerritories() - 1);
}
-
+
if(state > 2){
SPRaise("Invalid state %d specified for territory owner.", (int)state);
}
-
+
TCGameMode::Territory *t = tc->GetTerritory(type);
t->pos = pos;
t->ownerTeamId = state;/*
@@ -1014,7 +1014,7 @@ namespace spades {
pos.z = reader.ReadFloat() - 2.f;
std::string name = reader.ReadRemainingString();
// TODO: decode name?
-
+
if( pId < 0 || pId >= 32 ) {
SPLog( "Ignoring player 32 (bug in pyspades?: %s)", name.c_str() );
break;
@@ -1033,43 +1033,43 @@ namespace spades {
default:
SPRaise("Received invalid weapon: %d", weapon);
}
-
+
Player *p = new Player(GetWorld(), pId,
wType, team,
savedPlayerPos[pId],
-
+
GetWorld()->GetTeam(team).color);
p->SetPosition(pos);
GetWorld()->SetPlayer(pId, p);
-
+
World::PlayerPersistent& pers = GetWorld()->GetPlayerPersistent(pId);
-
+
if(!name.empty()) // sometimes becomes empty
pers.name = name;
-
+
playerPosRecords[pId].valid = false;
-
+
if(pId == GetWorld()->GetLocalPlayerIndex()){
client->LocalPlayerCreated();
lastPlayerInput = 0xffffffff;
lastWeaponInput = 0xffffffff;
- SendHeldBlockColor(); // ensure block color synchronized
+ SendHeldBlockColor(); // ensure block color synchronized
}else{
- if(team < 2 && pId < (int)playerPosRecords.size()) {
- PosRecord& rec = playerPosRecords[pId];
-
- rec.valid = true;
- rec.pos = pos;
- rec.time = GetWorld()->GetTime();
- }
+ if(team < 2 && pId < (int)playerPosRecords.size()) {
+ PosRecord& rec = playerPosRecords[pId];
+
+ rec.valid = true;
+ rec.pos = pos;
+ rec.time = GetWorld()->GetTime();
+ }
if(savedPlayerTeam[pId] != team && team < 2){
-
+
client->PlayerJoinedTeam(p);
-
+
savedPlayerTeam[pId] = team;
}
}
-
+
}
break;
case PacketTypeBlockAction:
@@ -1080,7 +1080,7 @@ namespace spades {
pos.x = reader.ReadInt();
pos.y = reader.ReadInt();
pos.z = reader.ReadInt();
-
+
std::vector cells;
if(action == 0){
bool replace = GetWorld()->GetMap()->IsSolidWrapped(pos.x, pos.y, pos.z);
@@ -1097,7 +1097,7 @@ namespace spades {
cells.push_back(pos);
client->PlayerDestroyedBlockWithWeaponOrTool(pos);
GetWorld()->DestroyBlock(cells);
-
+
if(p && p->GetTool() == Player::ToolSpade){
p->GotBlock();
}
@@ -1128,20 +1128,20 @@ namespace spades {
pos2.x = reader.ReadInt();
pos2.y = reader.ReadInt();
pos2.z = reader.ReadInt();
-
+
IntVector3 col = p ? p->GetBlockColor():
temporaryPlayerBlockColor;
std::vector cells;
cells = GetWorld()->CubeLine(pos1, pos2, 50);
-
+
for(size_t i = 0; i < cells.size(); i++){
if(!GetWorld()->GetMap()->IsSolid(cells[i].x, cells[i].y, cells[i].z)){
GetWorld()->CreateBlock(cells[i], col);
-
+
}
}
-
-
+
+
if(p){
p->UsedBlocks(static_cast (cells.size()));
client->PlayerCreatedBlock(p);
@@ -1158,21 +1158,21 @@ namespace spades {
IntVector3 teamColors[2];
teamColors[0] = reader.ReadIntColor();
teamColors[1] = reader.ReadIntColor();
-
+
std::string teamNames[2];
teamNames[0] = reader.ReadString(10);
teamNames[1] = reader.ReadString(10);
-
+
World::Team& t1 = GetWorld()->GetTeam(0);
World::Team& t2 = GetWorld()->GetTeam(1);
t1.color = teamColors[0];
t2.color = teamColors[1];
t1.name = teamNames[0];
t2.name = teamNames[1];
-
+
GetWorld()->SetFogColor(fogColor);
GetWorld()->SetLocalPlayerIndex(pId);
-
+
int mode = reader.ReadByte();
if(mode == 0){
// CTF
@@ -1180,15 +1180,15 @@ namespace spades {
try{
CTFGameMode::Team& mt1 = mode->GetTeam(0);
CTFGameMode::Team& mt2 = mode->GetTeam(1);
-
+
mt1.score = reader.ReadByte();
mt2.score = reader.ReadByte();
mode->SetCaptureLimit(reader.ReadByte());
-
+
int intelFlags = reader.ReadByte();
mt1.hasIntel = (intelFlags & 1) != 0;
mt2.hasIntel = (intelFlags & 2) != 0;
-
+
if(mt2.hasIntel){
mt1.carrier = reader.ReadByte();
reader.ReadData(11);
@@ -1197,7 +1197,7 @@ namespace spades {
mt1.flagPos.y = reader.ReadFloat();
mt1.flagPos.z = reader.ReadFloat();
}
-
+
if(mt1.hasIntel){
mt2.carrier = reader.ReadByte();
reader.ReadData(11);
@@ -1206,15 +1206,15 @@ namespace spades {
mt2.flagPos.y = reader.ReadFloat();
mt2.flagPos.z = reader.ReadFloat();
}
-
+
mt1.basePos.x = reader.ReadFloat();
mt1.basePos.y = reader.ReadFloat();
mt1.basePos.z = reader.ReadFloat();
-
+
mt2.basePos.x = reader.ReadFloat();
mt2.basePos.y = reader.ReadFloat();
mt2.basePos.z = reader.ReadFloat();
-
+
GetWorld()->SetMode(mode);
}catch(...){
delete mode;
@@ -1225,13 +1225,13 @@ namespace spades {
TCGameMode *mode = new TCGameMode(GetWorld());
try{
int numTer = reader.ReadByte();
-
+
for(int i = 0; i < numTer; i++){
TCGameMode::Territory ter;
ter.pos.x = reader.ReadFloat();
ter.pos.y = reader.ReadFloat();
ter.pos.z = reader.ReadFloat();
-
+
int state = reader.ReadByte();
ter.ownerTeamId = state;
ter.progressBasePos = 0.f;
@@ -1241,7 +1241,7 @@ namespace spades {
ter.mode = mode;
mode->AddTerritory(ter);
}
-
+
GetWorld()->SetMode(mode);
}catch(...){
delete mode;
@@ -1268,7 +1268,7 @@ namespace spades {
default:
SPInvalidEnum("kt", kt);
}
-
+
int respawnTime = reader.ReadByte();
switch(type){
case KillTypeFall:
@@ -1328,9 +1328,9 @@ namespace spades {
case PacketTypePlayerLeft:
{
Player *p = GetPlayer(reader.ReadByte());
-
+
client->PlayerLeaving(p);
-
+
savedPlayerTeam[p->GetId()] = -1;
playerPosRecords[p->GetId()].valid = false;
GetWorld()->SetPlayer(p->GetId(), NULL);
@@ -1342,29 +1342,29 @@ namespace spades {
int territoryId = reader.ReadByte();
bool winning = reader.ReadByte() != 0;
int state = reader.ReadByte();
-
+
IGameMode* mode = GetWorld()->GetMode();
- if(mode == NULL) break;
+ if(mode == NULL) break;
if( mode->ModeType() != IGameMode::m_TC ) {
SPRaise("Received PacketTypeTerritoryCapture in non-TC gamemode");
}
TCGameMode *tc = static_cast(mode);
-
+
if(territoryId >= tc->GetNumTerritories()){
SPRaise("Invalid territory id %d specified (max = %d)", territoryId,
tc->GetNumTerritories()-1);
}
-
+
client->TeamCapturedTerritory(state, territoryId);
-
+
TCGameMode::Territory *t = tc->GetTerritory(territoryId);
-
+
t->ownerTeamId = state;
t->progressBasePos = 0.f;
t->progressRate = 0.f;
t->progressStartTime = 0.f;
t->capturingTeamId = -1;
-
+
if(winning)
client->TeamWon(state);
}
@@ -1375,24 +1375,24 @@ namespace spades {
int capturingTeam = reader.ReadByte();
int rate = (int8_t)reader.ReadByte();
float progress = reader.ReadFloat();
-
+
IGameMode* mode = GetWorld()->GetMode();
- if(mode == NULL) break;
+ if(mode == NULL) break;
if( mode->ModeType() != IGameMode::m_TC ) {
SPRaise("Received PacketTypeProgressBar in non-TC gamemode");
}
TCGameMode *tc = static_cast(mode);
-
+
if(territoryId >= tc->GetNumTerritories()){
SPRaise("Invalid territory id %d specified (max = %d)", territoryId,
tc->GetNumTerritories()-1);
}
-
+
if(progress < -0.1f || progress > 1.1f)
SPRaise("Progress value out of range(%f)", progress);
-
+
TCGameMode::Territory *t = tc->GetTerritory(territoryId);
-
+
t->progressBasePos = progress;
t->progressRate = (float)rate * TC_CAPTURE_RATE;
t->progressStartTime = GetWorld()->GetTime();
@@ -1403,7 +1403,7 @@ namespace spades {
{
if(!GetWorld()) SPRaise("No world");
IGameMode* mode = GetWorld()->GetMode();
- if(mode == NULL) break;
+ if(mode == NULL) break;
if( mode->ModeType() != IGameMode::m_CTF ) {
SPRaise("Received PacketTypeIntelCapture in non-TC gamemode");
}
@@ -1413,7 +1413,7 @@ namespace spades {
GetWorld()->GetPlayerPersistent(p->GetId()).kills += 10;
ctf->GetTeam(p->GetTeamId()).hasIntel = false;
ctf->GetTeam(p->GetTeamId()).score++;
-
+
bool winning = reader.ReadByte() != 0;
if(winning)
client->TeamWon(p->GetTeamId());
@@ -1423,7 +1423,7 @@ namespace spades {
{
Player *p = GetPlayer(reader.ReadByte());
IGameMode* mode = GetWorld()->GetMode();
- if(mode == NULL) break;
+ if(mode == NULL) break;
if( mode->ModeType() != IGameMode::m_CTF ) {
SPRaise("Received PacketTypeIntelPickup in non-TC gamemode");
}
@@ -1438,21 +1438,21 @@ namespace spades {
{
Player *p = GetPlayer(reader.ReadByte());
IGameMode* mode = GetWorld()->GetMode();
- if(mode == NULL) break;
+ if(mode == NULL) break;
if( mode->ModeType() != IGameMode::m_CTF ) {
SPRaise("Received PacketTypeIntelPickup in non-TC gamemode");
}
CTFGameMode *ctf = static_cast(mode);
CTFGameMode::Team& team = ctf->GetTeam(p->GetTeamId());
team.hasIntel = false;
-
+
Vector3 pos;
pos.x = reader.ReadFloat();
pos.y = reader.ReadFloat();
pos.z = reader.ReadFloat();
-
+
ctf->GetTeam(1 - p->GetTeamId()).flagPos = pos;
-
+
client->PlayerDropIntel(p);
}
break;
@@ -1527,7 +1527,7 @@ namespace spades {
reader.DumpDebug();
}
}
-
+
void NetClient::SendJoin(int team, WeaponType weapType, std::string name, int kills){
SPADES_MARK_FUNCTION();
int weapId;
@@ -1537,7 +1537,7 @@ namespace spades {
case SHOTGUN_WEAPON: weapId = 2; break;
default: SPInvalidEnum("weapType", weapType);
}
-
+
NetPacketWriter wri(PacketTypeExistingPlayer);
wri.Write((uint8_t)GetWorld()->GetLocalPlayerIndex());
wri.Write((uint8_t)team);
@@ -1548,7 +1548,7 @@ namespace spades {
wri.Write(name, 16);
enet_peer_send(peer, 0, wri.CreatePacket());
}
-
+
void NetClient::SendPosition(){
SPADES_MARK_FUNCTION();
NetPacketWriter wri(PacketTypePositionData);
@@ -1561,7 +1561,7 @@ namespace spades {
enet_peer_send(peer, 0, wri.CreatePacket());
//printf("> (%f %f %f)\n", v.x, v.y, v.z);
}
-
+
void NetClient::SendOrientation(spades::Vector3 v){
SPADES_MARK_FUNCTION();
NetPacketWriter wri(PacketTypeOrientationData);
@@ -1572,7 +1572,7 @@ namespace spades {
enet_peer_send(peer, 0, wri.CreatePacket());
//printf("> (%f %f %f)\n", v.x, v.y, v.z);
}
-
+
void NetClient::SendPlayerInput(PlayerInput inp) {
SPADES_MARK_FUNCTION();
@@ -1596,7 +1596,7 @@ namespace spades {
enet_peer_send(peer, 0, wri.CreatePacket());
}
-
+
void NetClient::SendWeaponInput( WeaponInput inp) {
SPADES_MARK_FUNCTION();
uint8_t bits = 0;
@@ -1613,13 +1613,13 @@ namespace spades {
enet_peer_send(peer, 0, wri.CreatePacket());
}
-
+
void NetClient::SendBlockAction(spades::IntVector3 v,
BlockActionType type){
SPADES_MARK_FUNCTION();
NetPacketWriter wri(PacketTypeBlockAction);
wri.Write((uint8_t)GetLocalPlayer()->GetId());
-
+
switch(type){
case BlockActionCreate: wri.Write((uint8_t)0); break;
case BlockActionTool: wri.Write((uint8_t)1); break;
@@ -1627,44 +1627,44 @@ namespace spades {
case BlockActionGrenade: wri.Write((uint8_t)3); break;
default: SPInvalidEnum("type", type);
}
-
+
wri.Write((uint32_t)v.x);
wri.Write((uint32_t)v.y);
wri.Write((uint32_t)v.z);
-
+
enet_peer_send(peer, 0, wri.CreatePacket());
}
-
+
void NetClient::SendBlockLine(spades::IntVector3 v1,
spades::IntVector3 v2) {
SPADES_MARK_FUNCTION();
NetPacketWriter wri(PacketTypeBlockLine);
wri.Write((uint8_t)GetLocalPlayer()->GetId());
-
+
wri.Write((uint32_t)v1.x);
wri.Write((uint32_t)v1.y);
wri.Write((uint32_t)v1.z);
wri.Write((uint32_t)v2.x);
wri.Write((uint32_t)v2.y);
wri.Write((uint32_t)v2.z);
-
+
enet_peer_send(peer, 0, wri.CreatePacket());
}
-
+
void NetClient::SendReload() {
SPADES_MARK_FUNCTION();
NetPacketWriter wri(PacketTypeWeaponReload);
wri.Write((uint8_t)GetLocalPlayer()->GetId());
-
+
// these value should be 255, or
// NetClient will think reload was done when
// it receives echoed WeaponReload packet
wri.Write((uint8_t)255); // clip_ammo; not used?
wri.Write((uint8_t)255); // reserve_ammo; not used?
-
+
enet_peer_send(peer, 0, wri.CreatePacket());
}
-
+
void NetClient::SendHeldBlockColor() {
SPADES_MARK_FUNCTION();
NetPacketWriter wri(PacketTypeSetColour);
@@ -1672,9 +1672,9 @@ namespace spades {
IntVector3 v = GetLocalPlayer()->GetBlockColor();
wri.WriteColor(v);
enet_peer_send(peer, 0, wri.CreatePacket());
-
+
}
-
+
void NetClient::SendTool(){
SPADES_MARK_FUNCTION();
NetPacketWriter wri(PacketTypeSetTool);
@@ -1691,34 +1691,34 @@ namespace spades {
default:
SPInvalidEnum("tool", GetLocalPlayer()->GetTool());
}
-
+
enet_peer_send(peer, 0, wri.CreatePacket());
}
-
+
void NetClient::SendGrenade(spades::client::Grenade *g){
SPADES_MARK_FUNCTION();
NetPacketWriter wri(PacketTypeGrenadePacket);
wri.Write((uint8_t)GetLocalPlayer()->GetId());
-
+
wri.Write(g->GetFuse());
-
+
Vector3 v = g->GetPosition();
wri.Write(v.x);
wri.Write(v.y);
wri.Write(v.z);
-
+
v = g->GetVelocity();
wri.Write(v.x);
wri.Write(v.y);
wri.Write(v.z);
enet_peer_send(peer, 0, wri.CreatePacket());
}
-
+
void NetClient::SendHit(int targetPlayerId, HitType type){
SPADES_MARK_FUNCTION();
NetPacketWriter wri(PacketTypeHitPacket);
wri.Write((uint8_t)targetPlayerId);
-
+
switch(type){
case HitTypeTorso:
wri.Write((uint8_t)0);
@@ -1740,7 +1740,7 @@ namespace spades {
}
enet_peer_send(peer, 0, wri.CreatePacket());
}
-
+
void NetClient::SendChat(std::string text,
bool global) {
SPADES_MARK_FUNCTION();
@@ -1751,7 +1751,7 @@ namespace spades {
wri.Write((uint8_t)0);
enet_peer_send(peer, 0, wri.CreatePacket());
}
-
+
void NetClient::SendWeaponChange(WeaponType wt){
SPADES_MARK_FUNCTION();
NetPacketWriter wri(PacketTypeChangeWeapon);
@@ -1768,9 +1768,9 @@ namespace spades {
break;
}
enet_peer_send(peer, 0, wri.CreatePacket());
-
+
}
-
+
void NetClient::SendTeamChange(int team) {
SPADES_MARK_FUNCTION();
NetPacketWriter wri(PacketTypeChangeTeam);
@@ -1799,7 +1799,7 @@ namespace spades {
SPLog("Sending version back.");
enet_peer_send(peer, 0, wri.CreatePacket());
}
-
+
void NetClient::MapLoaded() {
SPADES_MARK_FUNCTION();
MemoryStream compressed(mapData.data(),
@@ -1807,30 +1807,30 @@ namespace spades {
DeflateStream inflate(&compressed, CompressModeDecompress, false);
GameMap *map;
map = GameMap::Load(&inflate);
-
+
SPLog("Map decoding succeeded.");
-
+
// now initialize world
World *w = new World();
w->SetMap(map);
map->Release();
SPLog("World initialized.");
-
+
client->SetWorld(w);
-
+
mapData.clear();
-
+
SPAssert(GetWorld());
-
+
SPLog("World loaded. Processing saved packets (%d)...",
(int)savedPackets.size());
-
+
for(size_t i = 0; i < playerPosRecords.size(); i++)
playerPosRecords[i].valid = false;
std::fill(savedPlayerTeam.begin(),
savedPlayerTeam.end(),
-1);
-
+
// do saved packets
try{
for(size_t i =0;i 0.5) {
lastUp = host->totalSentData / sw.GetTime();
@@ -1861,7 +1861,7 @@ namespace spades {
sw.Reset();
}
}
-
-
+
+
}
}
diff --git a/Sources/Client/Player.cpp b/Sources/Client/Player.cpp
index 35af6370..b0ee0270 100644
--- a/Sources/Client/Player.cpp
+++ b/Sources/Client/Player.cpp
@@ -1,22 +1,22 @@
/*
- Copyright (c) 2013 yvt,
+ Copyright (c) 2013 yvt,
based on code of pysnip (c) Mathias Kaerlev 2011-2012.
-
+
This file is part of OpenSpades.
-
+
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see .
-
+
*/
#include "Player.h"
@@ -34,14 +34,14 @@
namespace spades {
namespace client {
-
+
Player::Player(World *w, int playerId,
WeaponType wType, int teamId,
Vector3 position,
IntVector3 color):
world(w){
SPADES_MARK_FUNCTION();
-
+
lastClimbTime = -100;
lastJumpTime = -100;
lastJump = false;
@@ -56,53 +56,53 @@ namespace spades {
eye = MakeVector3(0,0,0);
moveDistance = 0.f;
moveSteps = 0;
-
+
this->playerId = playerId;
this->weapon = Weapon::CreateWeapon(wType, this);
this->weaponType = wType;
this->teamId = teamId;
this->weapon->Reset();
this->color = color;
-
+
health = 100;
grenades = 3;
blockStocks = 50;
blockColor = IntVector3::Make(111, 111, 111);
-
+
nextSpadeTime = 0.f;
nextDigTime = 0.f;
nextGrenadeTime = 0.f;
nextBlockTime = 0.f;
firstDig = false;
lastReloadingTime = 0.f;
-
+
pendingPlaceBlock = false;
-
+
blockCursorActive = false;
blockCursorDragging = false;
-
+
holdingGrenade = false;
reloadingServerSide = false;
canPending = false;
}
-
+
Player::~Player() {
SPADES_MARK_FUNCTION();
delete weapon;
}
-
+
bool Player::IsLocalPlayer(){
if(!world)
return false;
return world->GetLocalPlayer() == this;
}
-
+
void Player::SetInput(PlayerInput newInput) {
SPADES_MARK_FUNCTION();
-
+
if(!IsAlive())
return;
-
+
if(newInput.crouch != input.crouch && !airborne) {
if(newInput.crouch)
position.z += 0.9f;
@@ -111,14 +111,14 @@ namespace spades {
}
input = newInput;
}
-
+
void Player::SetWeaponInput(WeaponInput newInput){
SPADES_MARK_FUNCTION();
auto *listener = GetWorld()->GetListener();
-
+
if(!IsAlive())
return;
-
+
if(input.sprint && !input.crouch && (input.moveBackward || input.moveForward || input.moveLeft || input.moveRight)){
newInput.primary = false;
newInput.secondary = false;
@@ -166,11 +166,11 @@ namespace spades {
if(nextBlockTime > world->GetTime() +
std::max(GetToolPrimaryDelay(),
GetToolSecondaryDelay())) {
- nextBlockTime = world->GetTime() +
- std::max(GetToolPrimaryDelay(),
+ nextBlockTime = world->GetTime() +
+ std::max(GetToolPrimaryDelay(),
GetToolSecondaryDelay());
- }
-
+ }
+
if(world->GetTime() < nextBlockTime){
newInput.primary = false;
newInput.secondary = false;
@@ -218,7 +218,7 @@ namespace spades {
}
}
}
-
+
blockCursorDragging = false;
blockCursorActive = false;
}
@@ -226,17 +226,17 @@ namespace spades {
if(newInput.primary != weapInput.primary ||
newInput.primary){
if(newInput.primary){
-
+
if(!weapInput.primary)
lastSingleBlockBuildSeqDone = false;
if(IsBlockCursorActive() && blockStocks > 0){
if(listener &&
this == world->GetLocalPlayer())
listener->LocalPlayerBlockAction(blockCursorPos, BlockActionCreate);
-
+
lastSingleBlockBuildSeqDone = true;
// blockStocks--; decrease when created
-
+
nextBlockTime = world->GetTime() + GetToolPrimaryDelay();
}else if(blockStocks > 0 && airborne && canPending &&
this == world->GetLocalPlayer()) {
@@ -245,7 +245,7 @@ namespace spades {
}else if(!IsBlockCursorActive()) {
// wait for building becoming possible
}
-
+
blockCursorDragging = false;
blockCursorActive = false;
}else{
@@ -264,12 +264,12 @@ namespace spades {
}else{
SPAssert(false);
}
-
+
weapInput = newInput;
-
-
+
+
}
-
+
void Player::Reload() {
SPADES_MARK_FUNCTION();
if(health == 0){
@@ -281,99 +281,99 @@ namespace spades {
weapon->IsReloading())
reloadingServerSide = true;
}
-
+
void Player::ReloadDone(int clip, int stock) {
reloadingServerSide = false;
weapon->ReloadDone(clip, stock);
}
-
+
void Player::Restock() {
SPADES_MARK_FUNCTION();
if(health == 0){
// dead man cannot restock
return;
}
-
+
weapon->Restock();
grenades = 3;
blockStocks = 50;
health = 100;
-
+
if(world->GetListener())
world->GetListener()->PlayerRestocked(this);
}
-
+
void Player::GotBlock() {
if(blockStocks < 50)
blockStocks++;
}
-
+
void Player::SetTool(spades::client::Player::ToolType t) {
SPADES_MARK_FUNCTION();
-
+
if(t == tool)
return;
tool = t;
holdingGrenade = false;
blockCursorActive = false;
blockCursorDragging = false;
-
+
reloadingServerSide = false;
-
+
WeaponInput inp;
SetWeaponInput(inp);
-
+
weapon->AbortReload();
-
+
if(world->GetListener())
world->GetListener()->PlayerChangedTool(this);
}
-
+
void Player::SetHeldBlockColor(spades::IntVector3 col){
blockColor = col;
}
-
+
void Player::SetPosition(const spades::Vector3 &v){
SPADES_MARK_FUNCTION();
-
+
position = v;
eye = v;
-
+
}
-
+
void Player::SetVelocity(const spades::Vector3 &v) {
SPADES_MARK_FUNCTION();
-
+
velocity = v;
}
-
+
void Player::SetOrientation(const spades::Vector3 &v) {
SPADES_MARK_FUNCTION();
-
+
orientation = v;
}
-
+
void Player::Turn(float longitude, float latitude){
SPADES_MARK_FUNCTION();
-
+
Vector3 o = GetFront();
float lng = atan2f(o.y, o.x);
float lat = atan2f(o.z, sqrtf(o.x*o.x+o.y*o.y));
-
+
lng += longitude;
lat += latitude;
-
+
if(lat < -static_cast(M_PI) * .49f)
lat = -static_cast(M_PI) * .49f;
if(lat > static_cast(M_PI) * .49f)
lat = static_cast(M_PI) * .49f;
-
+
o.x = cosf(lng) * cosf(lat);
o.y = sinf(lng) * cosf(lat);
o.z = sinf(lat);
SetOrientation(o);
}
-
+
void Player::SetHP(int hp,
HurtType type,
spades::Vector3 p) {
@@ -387,18 +387,18 @@ namespace spades {
p);
}
}
-
+
void Player::Update(float dt) {
SPADES_MARK_FUNCTION();
auto* listener = world->GetListener();
-
+
MovePlayer(dt);
-
+
if(!IsAlive()) {
// do death cleanup
blockCursorDragging = false;
}
-
+
if(tool == ToolSpade){
if(weapInput.primary){
if(world->GetTime() > nextSpadeTime){
@@ -417,7 +417,7 @@ namespace spades {
auto *map = GetWorld()->GetMap();
result = map->CastRay2(GetEye(), GetFront(), 12);
canPending = false;
-
+
if(blockCursorDragging) {
// check the starting point is not floating
auto start = blockCursorDragPos;
@@ -438,19 +438,19 @@ namespace spades {
blockCursorDragging = false;
}
}
-
+
if(result.hit &&
(result.hitBlock + result.normal).z < 62 &&
(!OverlapsWithOneBlock(result.hitBlock + result.normal)) &&
BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f &&
!pendingPlaceBlock){
-
+
// Building is possible, and there's no delayed block placement.
blockCursorActive = true;
blockCursorPos = result.hitBlock + result.normal;
-
+
}else if(pendingPlaceBlock){
-
+
// Delayed Block Placement: When player attempts to place a block while jumping and
// placing block is currently impossible, building will be delayed until it becomes
// possible, as long as player is airborne.
@@ -465,24 +465,24 @@ namespace spades {
BoxDistanceToBlock(pendingPlaceBlockPos) < 3.f){
// now building became possible.
SPAssert(this == world->GetLocalPlayer());
-
+
if(GetWorld()->GetListener())
GetWorld()->GetListener()->LocalPlayerBlockAction(pendingPlaceBlockPos, BlockActionCreate);
-
+
pendingPlaceBlock = false;
lastSingleBlockBuildSeqDone = true;
// blockStocks--; decrease when created
-
+
nextBlockTime = world->GetTime() + GetToolPrimaryDelay();
}
-
+
}else{
// Delayed Block Placement can be activated only when the only reason making placement
// impossible is that block to be placed overlaps with the player's hitbox.
canPending = result.hit &&
(result.hitBlock + result.normal).z < 62 &&
BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f;
-
+
blockCursorActive = false;
int dist = 11;
for(; dist >= 1 &&
@@ -497,10 +497,10 @@ namespace spades {
GetFront(),
dist);
}
-
+
blockCursorPos = result.hitBlock + result.normal;
}
-
+
}else if(tool == ToolWeapon){
}else if(tool == ToolGrenade){
if(holdingGrenade){
@@ -509,13 +509,13 @@ namespace spades {
}
}
}
-
+
if(tool != ToolWeapon)
weapon->SetShooting(false);
if(weapon->FrameNext(dt)){
FireWeapon();
}
-
+
if(weapon->IsReloading()) {
lastReloadingTime = world->GetTime();
}else if(reloadingServerSide) {
@@ -527,27 +527,27 @@ namespace spades {
}
}
}
-
+
bool Player::RayCastApprox(spades::Vector3 start, spades::Vector3 dir){
Vector3 diff = position - start;
-
+
// |P-A| * cos(theta)
float c = Vector3::Dot(diff, dir);
-
+
// |P-A|^2
float sq = diff.GetPoweredLength();
-
+
// |P-A| * sin(theta)
float dist = sqrtf(sq - c * c);
-
+
return dist < 8.f;
}
-
- static float GetHorizontalLength(const Vector3 &v)
- {
- return std::sqrt(v.x * v.x + v.y * v.y);
- }
-
+
+ static float GetHorizontalLength(const Vector3 &v)
+ {
+ return std::sqrt(v.x * v.x + v.y * v.y);
+ }
+
enum class HitBodyPart {
None,
Head,
@@ -555,49 +555,49 @@ namespace spades {
Limb1, Limb2,
Arms
};
-
+
void Player::FireWeapon() {
SPADES_MARK_FUNCTION();
-
+
Vector3 muzzle = GetEye();
muzzle += GetFront() * 0.01f;
-
+
// for hit-test debugging
std::map playerHits;
std::vector bulletVectors;
-
+
//Vector3 right = GetRight();
//Vector3 up = GetUp();
-
+
int pellets = weapon->GetPelletSize();
float spread = weapon->GetSpread();
GameMap *map = world->GetMap();
-
+
// pyspades takes destroying more than one block as a
// speed hack (shotgun does this)
bool blockDestroyed = false;
-
+
Vector3 dir2 = GetFront();
for(int i =0 ; i < pellets; i++){
-
+
// AoS 0.75's way (dir2 shouldn't be normalized!)
dir2.x += (GetRandom() - GetRandom()) * spread;
dir2.y += (GetRandom() - GetRandom()) * spread;
dir2.z += (GetRandom() - GetRandom()) * spread;
Vector3 dir = dir2.Normalize();
-
+
bulletVectors.push_back(dir);
-
+
// first do map raycast
GameMap::RayCastResult mapResult;
mapResult = map->CastRay2(muzzle,
dir,
500);
-
+
Player *hitPlayer = NULL;
float hitPlayerDistance = 0.f;
HitBodyPart hitPart = HitBodyPart::None;
-
+
for(int i = 0; i < world->GetNumPlayerSlots(); i++){
Player *other = world->GetPlayer(i);
if(other == this || other == NULL)
@@ -608,10 +608,10 @@ namespace spades {
// quickly reject players unlikely to be hit
if(!other->RayCastApprox(muzzle, dir))
continue;
-
+
HitBoxes hb = other->GetHitBoxes();
Vector3 hitPos;
-
+
if(hb.head.RayCast(muzzle, dir, &hitPos)) {
float dist = GetHorizontalLength(hitPos - muzzle);
if(hitPlayer == NULL ||
@@ -622,7 +622,7 @@ namespace spades {
}
}
if(hb.torso.RayCast(muzzle, dir, &hitPos)) {
- float dist = GetHorizontalLength(hitPos - muzzle);
+ float dist = GetHorizontalLength(hitPos - muzzle);
if(hitPlayer == NULL ||
dist < hitPlayerDistance){
hitPlayer = other;
@@ -646,23 +646,23 @@ namespace spades {
}
}
}
-
+
Vector3 finalHitPos;
finalHitPos = muzzle + dir * 128.f;
-
+
if(hitPlayer == nullptr && !mapResult.hit) {
// might hit water surface.
-
+
}
-
+
if(mapResult.hit && GetHorizontalLength(mapResult.hitPos - muzzle) < 128.f &&
(hitPlayer == NULL || GetHorizontalLength(mapResult.hitPos - muzzle) < hitPlayerDistance)){
IntVector3 outBlockCoord = mapResult.hitBlock;
// TODO: set correct ray distance
// FIXME: why ray casting twice?
-
+
finalHitPos = mapResult.hitPos;
-
+
if(outBlockCoord.x >= 0 && outBlockCoord.y >= 0 && outBlockCoord.z >= 0 &&
outBlockCoord.x < map->Width() && outBlockCoord.y < map->Height() &&
outBlockCoord.z < map->Depth()){
@@ -682,10 +682,10 @@ namespace spades {
int y = outBlockCoord.y;
int z = outBlockCoord.z;
SPAssert(map->IsSolid(x, y, z));
-
+
Vector3 blockF = {x + .5f, y + .5f, z + .5f};
float distance = GetHorizontalLength(blockF - muzzle);
-
+
uint32_t color = map->GetColor(x, y, z);
int health = color >> 24;
health -= weapon->GetDamage(HitTypeBlock, distance);
@@ -697,23 +697,23 @@ namespace spades {
world->GetLocalPlayer() == this)
world->GetListener()->LocalPlayerBlockAction
(outBlockCoord, BlockActionTool);
-
+
}
color = (color & 0xffffff) | ((uint32_t)health << 24);
if(map->IsSolid(x, y, z))
map->Set(x, y, z, true, color);
-
+
if(world->GetListener())
world->GetListener()->BulletHitBlock(mapResult.hitPos,
mapResult.hitBlock,
mapResult.normal);
}
}
- }else if(hitPlayer != NULL){
+ }else if(hitPlayer != NULL){
if(hitPlayerDistance < 128.f){
-
+
finalHitPos = muzzle + dir * hitPlayerDistance;
-
+
switch(hitPart) {
case HitBodyPart::Head:
playerHits[hitPlayer->GetId()].numHeadHits++;
@@ -734,7 +734,7 @@ namespace spades {
SPAssert(false);
break;
}
-
+
if(world->GetListener()){
switch(hitPart) {
case HitBodyPart::Head:
@@ -769,20 +769,20 @@ namespace spades {
}
}
}
-
+
if(world->GetListener() && this != world->GetLocalPlayer())
world->GetListener()->AddBulletTracer(this,
muzzle, finalHitPos);
-
+
// one pellet done
}
-
+
// do hit test debugging
auto *debugger = world->GetHitTestDebugger();
if(debugger && IsLocalPlayer()) {
debugger->SaveImage(playerHits, bulletVectors);
}
-
+
// in AoS 0.75's way
Vector3 o = orientation;
Vector3 rec = weapon->GetRecoil();
@@ -792,29 +792,29 @@ namespace spades {
o += GetRight() * rec.x * sinf(world->GetTime() * 10.f);
o = o.Normalize();
SetOrientation(o);
-
+
reloadingServerSide = false;
}
-
+
void Player::ThrowGrenade(){
SPADES_MARK_FUNCTION();
-
+
if(!holdingGrenade)
return;
grenades--;
-
+
Vector3 muzzle = GetEye() + GetFront() * 0.1f;
Vector3 vel = GetFront() * 1.f;
float fuse = world->GetTime() - grenadeTime;
fuse = 3.f - fuse;
-
+
if(health <= 0){
// drop, don't throw
vel = MakeVector3(0,0,0);
}
-
+
vel += GetVelocty();
-
+
if(this == world->GetLocalPlayer()){
Grenade *gren = new Grenade(world, muzzle, vel, fuse);
world->AddGrenade(gren);
@@ -825,26 +825,26 @@ namespace spades {
if(world->GetListener())
world->GetListener()->PlayerThrownGrenade(this, NULL);
}
-
+
holdingGrenade = false;
}
-
+
void Player::DigWithSpade(){
SPADES_MARK_FUNCTION();
-
+
IntVector3 outBlockCoord;
GameMap *map = world->GetMap();
Vector3 muzzle = GetEye(), dir = GetFront();
-
+
// TODO: set correct ray distance
// first do map raycast
GameMap::RayCastResult mapResult;
mapResult = map->CastRay2(muzzle,
dir,
256);
-
+
outBlockCoord = mapResult.hitBlock;
-
+
// TODO: set correct ray distance
if(mapResult.hit && BoxDistanceToBlock(mapResult.hitBlock + mapResult.normal) < 3.f &&
outBlockCoord.x >= 0 && outBlockCoord.y >= 0 && outBlockCoord.z >= 0 &&
@@ -852,17 +852,17 @@ namespace spades {
outBlockCoord.z < map->Depth()){
if(outBlockCoord.z < 62){
SPAssert(map->IsSolid(outBlockCoord.x, outBlockCoord.y, outBlockCoord.z));
-
+
// send destroy command only for local cmd
if(this == world->GetLocalPlayer()) {
-
+
if(world->GetListener())
world->GetListener()->LocalPlayerBlockAction
(outBlockCoord, BlockActionDig);
-
-
+
+
}
-
+
if(world->GetListener())
world->GetListener()->PlayerHitBlockWithSpade(this,
mapResult.hitPos,
@@ -874,14 +874,14 @@ namespace spades {
world->GetListener()->PlayerMissedSpade(this);
}
}
-
+
void Player::UseSpade() {
SPADES_MARK_FUNCTION();
-
+
bool missed = true;
-
+
Vector3 muzzle = GetEye(), dir = GetFront();
-
+
IntVector3 outBlockCoord;
GameMap *map = world->GetMap();
// TODO: set correct ray distance
@@ -890,10 +890,10 @@ namespace spades {
mapResult = map->CastRay2(muzzle,
dir,
256);
-
+
Player *hitPlayer = NULL;
int hitFlag = 0;
-
+
for(int i = 0; i < world->GetNumPlayerSlots(); i++){
Player *other = world->GetPlayer(i);
if(other == this || other == NULL)
@@ -906,27 +906,27 @@ namespace spades {
if((eye - other->GetEye()).GetChebyshevLength() >=
MELEE_DISTANCE_F)
continue;
-
+
Vector3 diff = other->GetEye() - eye;
Vector3 view;
view.x = Vector3::Dot(diff, GetRight());
view.y = Vector3::Dot(diff, GetUp());
view.z = Vector3::Dot(diff, GetFront());
-
+
if(view.z < 0.f)
continue;
-
+
view.x /= view.z;
view.y /= view.z;
view.z = 0.f;
-
+
if(view.GetChebyshevLength() < 5.f) {
hitPlayer = other;
hitFlag = 1;
break;
}
}
-
+
outBlockCoord = mapResult.hitBlock;
if(mapResult.hit && BoxDistanceToBlock(mapResult.hitBlock + mapResult.normal) < 3.f &&
(hitPlayer == NULL) &&
@@ -941,7 +941,7 @@ namespace spades {
int z = outBlockCoord.z;
SPAssert(map->IsSolid(x, y, z));
missed = false;
-
+
uint32_t color = map->GetColor(x, y, z);
int health = color >> 24;
health -= 55;
@@ -957,7 +957,7 @@ namespace spades {
color = (color & 0xffffff) | ((uint32_t)health << 24);
if(map->IsSolid(x, y, z))
map->Set(x, y, z, true, color);
-
+
if(world->GetListener())
world->GetListener()->PlayerHitBlockWithSpade(this,
mapResult.hitPos,
@@ -965,8 +965,8 @@ namespace spades {
mapResult.normal);
}
}else if(hitPlayer != NULL){
-
-
+
+
if(world->GetListener()){
if(hitFlag)
world->GetListener()->BulletHitPlayer(hitPlayer,
@@ -974,50 +974,50 @@ namespace spades {
hitPlayer->GetEye(),
this);
}
-
-
+
+
}
-
+
if(missed){
if(world->GetListener())
world->GetListener()->PlayerMissedSpade(this);
}
}
-
+
Vector3 Player::GetFront() {
SPADES_MARK_FUNCTION_DEBUG();
return orientation;
}
-
+
Vector3 Player::GetFront2D() {
SPADES_MARK_FUNCTION_DEBUG();
return MakeVector3(orientation.x,
orientation.y,
0.f).Normalize();
}
-
+
Vector3 Player::GetRight() {
SPADES_MARK_FUNCTION_DEBUG();
return -Vector3::Cross(MakeVector3(0,0,-1),
GetFront2D()).Normalize();
}
-
+
Vector3 Player::GetLeft(){
SPADES_MARK_FUNCTION_DEBUG();
return -GetRight();
}
-
+
Vector3 Player::GetUp() {
SPADES_MARK_FUNCTION_DEBUG();
return Vector3::Cross(GetRight(), GetFront())
.Normalize();
}
-
+
bool Player::GetWade() {
SPADES_MARK_FUNCTION_DEBUG();
return GetOrigin().z > 62.f;
}
-
+
Vector3 Player::GetOrigin() {
SPADES_MARK_FUNCTION_DEBUG();
Vector3 v = eye;
@@ -1025,10 +1025,10 @@ namespace spades {
v.z += .3f;
return v;
}
-
+
void Player::BoxClipMove(float fsynctics) {
SPADES_MARK_FUNCTION();
-
+
float f = fsynctics * 32.f;
float nx = f * velocity.x + position.x;
float ny = f * velocity.y + position.y;
@@ -1041,20 +1041,20 @@ namespace spades {
offset = .9f;
m = 1.35f;
}
-
+
float nz = position.z + offset;
-
+
float z;
GameMap *map = world->GetMap();
-
-
+
+
if(velocity.x < 0.f)
f = -0.45f;
else
f = 0.45f;
-
+
z = m;
-
+
while(z >= -1.36f &&
!map->ClipBox(nx + f, position.y - .45f, nz + z) &&
!map->ClipBox(nx + f, position.y + .45f, nz + z))
@@ -1076,14 +1076,14 @@ namespace spades {
}else{
velocity.x = 0.f;
}
-
+
if(velocity.y < 0.f)
f = -0.45f;
else
f = 0.45f;
-
+
z = m;
-
+
while(z >= -1.36f &&
!map->ClipBox(position.x - .45f, ny + f, nz + z) &&
!map->ClipBox(position.x + .45f, ny + f, nz + z))
@@ -1106,7 +1106,7 @@ namespace spades {
}else if(!climb){
velocity.y = 0.f;
}
-
+
if(climb){
velocity.x *= .5f;
velocity.y *= .5f;
@@ -1118,7 +1118,7 @@ namespace spades {
m = -m;
nz += velocity.z * fsynctics * 32.f;
}
-
+
airborne = true;
if(map->ClipBox(position.x - .45f, position.y - .45f, nz + m) ||
map->ClipBox(position.x - .45f, position.y + .45f, nz + m) ||
@@ -1132,14 +1132,14 @@ namespace spades {
}else{
position.z = nz - offset;
}
-
+
RepositionPlayer(position);
}
-
+
bool Player::IsOnGroundOrWade() {
return ((velocity.z >= 0.f && velocity.z < .017f) && !airborne);
}
-
+
void Player::ForceJump() {
velocity.z = -0.36f;
lastJump = true;
@@ -1148,7 +1148,7 @@ namespace spades {
lastJumpTime = world->GetTime();
}
}
-
+
void Player::MovePlayer(float fsynctics) {
if(input.jump && (!lastJump) &&
IsOnGroundOrWade()) {
@@ -1161,7 +1161,7 @@ namespace spades {
}else if(!input.jump){
lastJump = false;
}
-
+
float f = fsynctics;
if(airborne)
f *= 0.1f;
@@ -1175,7 +1175,7 @@ namespace spades {
if((input.moveForward || input.moveBackward) &&
(input.moveRight || input.moveLeft))
f /= sqrtf(2.f);
-
+
// looking up or down should alter speed
const float maxVertLookSlowdown = 0.9f;
const float vertLookSlowdownStart = 0.65f; // about 40 degrees
@@ -1200,30 +1200,30 @@ namespace spades {
velocity.x -= left.x * f;
velocity.y -= left.y * f;
}
-
+
// this is a linear approximation that's
// done in pysnip
// accurate computation is not difficult
f = fsynctics + 1.f;
velocity.z += fsynctics;
velocity.z /= f; // air friction
-
+
if(wade)
f = fsynctics * 6.f + 1.f;
else if(!airborne)
f = fsynctics * 4.f + 1.f;
-
+
velocity.x /= f;
velocity.y /= f;
-
+
float f2 = velocity.z;
BoxClipMove(fsynctics);
-
+
// hit ground
if(velocity.z == 0.f && (f2 > FALL_SLOW_DOWN)) {
velocity.x *= .5f;
velocity.y *= .5f;
-
+
if(f2 > FALL_DAMAGE_VELOCITY){
f2 -= FALL_DAMAGE_VELOCITY;
if(world->GetListener()){
@@ -1235,7 +1235,7 @@ namespace spades {
}
}
}
-
+
if(velocity.z >= 0.f && velocity.z < .017f &&
!input.sneak && !input.crouch &&
!(weapInput.secondary && IsToolWeapon())){
@@ -1245,12 +1245,12 @@ namespace spades {
float dy = f * velocity.y;
float dist = sqrtf(dx*dx+dy*dy);
moveDistance += dist * .3f;
-
+
bool madeFootstep = false;
while(moveDistance > 1.f){
moveSteps++;
moveDistance -= 1.f;
-
+
if(world->GetListener() && !madeFootstep){
world->GetListener()->PlayerMadeFootstep(this);
madeFootstep = true;
@@ -1258,19 +1258,19 @@ namespace spades {
}
}
}
-
+
bool Player::TryUncrouch(bool move) {
SPADES_MARK_FUNCTION();
-
+
float x1 = position.x + 0.45f;
float x2 = position.x - 0.45f;
float y1 = position.y + 0.45f;
float y2 = position.y - 0.45f;
float z1 = position.z + 2.25f;
float z2 = position.z - 1.35f;
-
+
GameMap *map = world->GetMap();
-
+
// lower feet
if(airborne &&
!(map->ClipBox(x1, y1, z1) ||
@@ -1290,19 +1290,19 @@ namespace spades {
}
return false;
}
-
+
void Player::RepositionPlayer(const spades::Vector3 & pos2){
SPADES_MARK_FUNCTION();
-
+
eye = position = pos2;
float f = lastClimbTime - world->GetTime();
if(f > -.25f)
eye.z += (f + .25f) / .25f;
}
-
+
float Player::GetToolPrimaryDelay() {
SPADES_MARK_FUNCTION_DEBUG();
-
+
switch(tool){
case ToolWeapon:
return weapon->GetDelay();
@@ -1316,10 +1316,10 @@ namespace spades {
SPInvalidEnum("tool", tool);
}
}
-
+
float Player::GetToolSecondaryDelay() {
SPADES_MARK_FUNCTION_DEBUG();
-
+
switch(tool){
case ToolBlock:
return GetToolPrimaryDelay();
@@ -1329,36 +1329,36 @@ namespace spades {
SPInvalidEnum("tool", tool);
}
}
-
+
float Player::GetSpadeAnimationProgress() {
SPADES_MARK_FUNCTION_DEBUG();
-
+
SPAssert(tool == ToolSpade);
SPAssert(weapInput.primary);
return 1.f - (nextSpadeTime - world->GetTime())
/ GetToolPrimaryDelay();
}
-
+
float Player::GetDigAnimationProgress() {
SPADES_MARK_FUNCTION_DEBUG();
-
+
SPAssert(tool == ToolSpade);
SPAssert(weapInput.secondary);
return 1.f - (nextDigTime - world->GetTime())
/ GetToolSecondaryDelay();
}
-
+
float Player::GetTimeToNextGrenade() {
return nextGrenadeTime - world->GetTime();
}
-
+
void Player::KilledBy(KillType type,
Player *killer,
int respawnTime) {
SPADES_MARK_FUNCTION();
health = 0;
weapon->SetShooting(false);
-
+
// if local player is killed while cooking grenade,
// drop the live grenade.
if(this == world->GetLocalPlayer() &&
@@ -1368,59 +1368,59 @@ namespace spades {
}
if(world->GetListener())
world->GetListener()->PlayerKilledPlayer(killer, this, type);
-
+
input = PlayerInput();
weapInput = WeaponInput();
this->respawnTime = world->GetTime() + respawnTime;
}
-
+
bool Player::IsAlive() {
return health > 0;
}
-
+
std::string Player::GetName() {
return world->GetPlayerPersistent(GetId()).name;
}
-
+
float Player::GetWalkAnimationProgress() {
return moveDistance * .5f +
(float)(moveSteps & 1) * .5f;
}
-
+
Player::HitBoxes Player::GetHitBoxes()
{
SPADES_MARK_FUNCTION_DEBUG();
Player::HitBoxes hb;
-
+
Vector3 front = GetFront();
-
+
float yaw = atan2(front.y, front.x) + static_cast(M_PI) * .5f;
float pitch = -atan2(front.z, sqrt(front.x * front.x + front.y * front.y));
-
+
// lower axis
Matrix4 lower = Matrix4::Translate(GetOrigin());
lower = lower * Matrix4::Rotate(MakeVector3(0,0,1), yaw);
-
+
Matrix4 torso;
-
+
if(input.crouch){
lower = lower * Matrix4::Translate(0, 0, -0.4f);
// lower
hb.limbs[0] = AABB3(-.4f, -.15f, 0.5f, 0.3f, .3f, 0.5f);
hb.limbs[0] = lower * hb.limbs[0];
-
+
hb.limbs[1] = AABB3(.1f, -.15f, 0.5f, 0.3f, .3f, 0.5f);
hb.limbs[1] = lower * hb.limbs[1];
-
+
torso = lower * Matrix4::Translate(0, 0, -0.3f);
-
+
// torso
hb.torso = AABB3(-.4f, -.15f, 0.1f, .8f, .8f, .6f);
hb.torso = torso * hb.torso;
-
+
hb.limbs[2] = AABB3(-.6f, -.15f, 0.1f, 1.2f, .3f, .6f);
hb.limbs[2] = torso * hb.limbs[2];
-
+
// head
hb.head = AABB3(-.3f, -.3f, -0.45f, .6f, .6f, 0.6f);
hb.head = Matrix4::Translate(0, 0, -0.15f) * hb.head;
@@ -1431,19 +1431,19 @@ namespace spades {
// lower
hb.limbs[0] = AABB3(-.4f, -.15f, 0.f, 0.3f, .3f, 1.f);
hb.limbs[0] = lower * hb.limbs[0];
-
+
hb.limbs[1] = AABB3(.1f, -.15f, 0.f, 0.3f, .3f, 1.f);
hb.limbs[1] = lower * hb.limbs[1];
-
+
torso = lower * Matrix4::Translate(0, 0, -1.1f);
-
+
// torso
hb.torso = AABB3(-.4f, -.15f, 0.1f, .8f, .3f, .9f);
hb.torso = torso * hb.torso;
-
+
hb.limbs[2] = AABB3(-.6f, -.15f, 0.1f, 1.2f, .3f, .9f);
hb.limbs[2] = torso * hb.limbs[2];
-
+
// head
hb.head = AABB3(-.3f, -.3f, -0.5f, .6f, .6f, 0.6f);
hb.head = Matrix4::Translate(0, 0, -0.1f) * hb.head;
@@ -1451,20 +1451,20 @@ namespace spades {
hb.head = Matrix4::Translate(0, 0, 0.1f) * hb.head;
hb.head = torso * hb.head;
}
-
+
return hb;
}
IntVector3 Player::GetColor() {
return world->GetTeam(teamId).color;
}
-
+
bool Player::IsCookingGrenade() {
return tool == ToolGrenade && holdingGrenade;
}
float Player::GetGrenadeCookTime() {
return world->GetTime() - grenadeTime;
}
-
+
void Player::SetWeaponType(WeaponType weap){
SPADES_MARK_FUNCTION_DEBUG();
if(this->weapon->GetWeaponType() == weap)
@@ -1473,11 +1473,11 @@ namespace spades {
this->weapon = Weapon::CreateWeapon(weap, this);
this->weaponType = weap;
}
-
+
void Player::SetTeam(int tId){
teamId = tId;
}
-
+
bool Player::IsReadyToUseTool() {
SPADES_MARK_FUNCTION_DEBUG();
switch(tool){
@@ -1493,7 +1493,7 @@ namespace spades {
return weapon->IsReadyToShoot();
}
}
-
+
bool Player::IsToolSelectable(ToolType type) {
SPADES_MARK_FUNCTION_DEBUG();
switch(type){
@@ -1510,7 +1510,7 @@ namespace spades {
SPAssert(false);
}
}
-
+
bool Player::OverlapsWith(const spades::AABB3 &aabb) {
SPADES_MARK_FUNCTION_DEBUG();
float offset, m;
@@ -1528,13 +1528,13 @@ namespace spades {
.9f, .9f, offset + m);
return aabb && playerBox;
}
-
+
bool Player::OverlapsWithOneBlock(spades::IntVector3 vec) {
SPADES_MARK_FUNCTION_DEBUG();
return OverlapsWith(AABB3(vec.x, vec.y, vec.z,
1, 1, 1));
}
-
+
#pragma mark - Block Construction
bool Player::IsBlockCursorActive(){
return tool == ToolBlock && blockCursorActive;
@@ -1545,7 +1545,7 @@ namespace spades {
float Player::BoxDistanceToBlock(spades::IntVector3 v){
Vector3 e = {(float)v.x, (float)v.y, (float)v.z};
e += .5f;
-
+
return (e-eye).GetChebyshevLength();
}
}
diff --git a/Sources/Core/ConcurrentDispatch.cpp b/Sources/Core/ConcurrentDispatch.cpp
index cfe7b108..99900b7b 100644
--- a/Sources/Core/ConcurrentDispatch.cpp
+++ b/Sources/Core/ConcurrentDispatch.cpp
@@ -1,21 +1,21 @@
/*
Copyright (c) 2013 yvt
-
+
This file is part of OpenSpades.
-
+
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see .
-
+
*/
#include
@@ -50,39 +50,39 @@ DEFINE_SPADES_SETTING(core_numDispatchQueueThreads, "auto");
static int GetNumCores() {
#ifdef WIN32
- SYSTEM_INFO sysinfo;
- GetSystemInfo(&sysinfo);
- return sysinfo.dwNumberOfProcessors;
+ SYSTEM_INFO sysinfo;
+ GetSystemInfo(&sysinfo);
+ return sysinfo.dwNumberOfProcessors;
#elif defined(__APPLE__)
- int nm[2];
- size_t len = 4;
- uint32_t count;
-
- nm[0] = CTL_HW; nm[1] = HW_AVAILCPU;
- sysctl(nm, 2, &count, &len, NULL, 0);
-
- if(count < 1) {
- nm[1] = HW_NCPU;
- sysctl(nm, 2, &count, &len, NULL, 0);
- if(count < 1) { count = 1; }
- }
- return count;
+ int nm[2];
+ size_t len = 4;
+ uint32_t count;
+
+ nm[0] = CTL_HW; nm[1] = HW_AVAILCPU;
+ sysctl(nm, 2, &count, &len, NULL, 0);
+
+ if(count < 1) {
+ nm[1] = HW_NCPU;
+ sysctl(nm, 2, &count, &len, NULL, 0);
+ if(count < 1) { count = 1; }
+ }
+ return count;
#elif defined(__linux__)
- return get_nprocs();
+ return get_nprocs();
#else
- return sysconf(_SC_NPROCESSORS_ONLN);
+ return sysconf(_SC_NPROCESSORS_ONLN);
#endif
}
namespace spades {
-
+
struct SyncQueueEntry{
SDL_cond *doneCond;
SDL_mutex *doneMutex;
ConcurrentDispatch *dispatch;
volatile bool done;
volatile bool released;
-
+
SyncQueueEntry(ConcurrentDispatch *disp):
doneCond(SDL_CreateCond()),
doneMutex(SDL_CreateMutex()),
@@ -98,7 +98,7 @@ namespace spades {
delete dispatch;
}
}
-
+
void Done() {
SDL_LockMutex(doneMutex);
done = true;
@@ -109,7 +109,7 @@ namespace spades {
}
SDL_UnlockMutex(doneMutex);
}
-
+
void Release() {
SDL_LockMutex(doneMutex);
released = true;
@@ -119,7 +119,7 @@ namespace spades {
}
SDL_UnlockMutex(doneMutex);
}
-
+
void Join(){
SDL_LockMutex(doneMutex);
while(!done){
@@ -128,10 +128,10 @@ namespace spades {
SDL_UnlockMutex(doneMutex);
}
};
-
+
class SynchronizedQueue {
std::list entries;
-
+
SDL_cond *pushCond;
SDL_mutex *pushMutex;
public:
@@ -143,7 +143,7 @@ namespace spades {
SDL_DestroyMutex(pushMutex);
SDL_DestroyCond(pushCond);
}
-
+
void Push(SyncQueueEntry * entry) {
SDL_LockMutex(pushMutex);
try{
@@ -155,20 +155,20 @@ namespace spades {
SDL_CondSignal(pushCond);
SDL_UnlockMutex(pushMutex);
}
-
+
SyncQueueEntry *Wait() {
SDL_LockMutex(pushMutex);
while(entries.empty()){
SDL_CondWait(pushCond, pushMutex);
}
-
+
SyncQueueEntry *ent = entries.front();
entries.pop_front();
SDL_UnlockMutex(pushMutex);
-
+
return ent;
}
-
+
SyncQueueEntry *Poll(){
SDL_LockMutex(pushMutex);
if(!entries.empty()){
@@ -181,11 +181,11 @@ namespace spades {
return NULL;
}
};
-
+
static SynchronizedQueue globalQueue;
static AutoDeletedThreadLocalStorage threadQueue("threadDispatchQueue");
static DispatchQueue *sdlQueue = NULL;
-
+
DispatchQueue::DispatchQueue(){
SPADES_MARK_FUNCTION();
internal = new SynchronizedQueue();
@@ -194,7 +194,7 @@ namespace spades {
SPADES_MARK_FUNCTION();
delete internal;
}
-
+
DispatchQueue *DispatchQueue::GetThreadQueue() {
SPADES_MARK_FUNCTION();
DispatchQueue *q = threadQueue;
@@ -204,7 +204,7 @@ namespace spades {
}
return q;
}
-
+
void DispatchQueue::ProcessQueue() {
SPADES_MARK_FUNCTION();
SyncQueueEntry *ent;
@@ -213,19 +213,19 @@ namespace spades {
}
Thread::CleanupExitedThreads();
}
-
+
void DispatchQueue::EnterEventLoop() throw() {
while(true){
SyncQueueEntry *ent = internal->Wait();
ent->dispatch->ExecuteProtected();
-
+
}
}
-
+
void DispatchQueue::MarkSDLVideoThread() {
sdlQueue = this;
}
-
+
class DispatchThread: public Thread{
public:
virtual void Run() throw() {
@@ -236,9 +236,9 @@ namespace spades {
}
}
};
-
+
static std::vector threads;
-
+
ConcurrentDispatch::ConcurrentDispatch():
entry(NULL), runnable(NULL){
SPADES_MARK_FUNCTION();
@@ -247,12 +247,12 @@ namespace spades {
entry(NULL),name(name), runnable(NULL){
SPADES_MARK_FUNCTION();
}
-
+
ConcurrentDispatch::~ConcurrentDispatch(){
SPADES_MARK_FUNCTION();
Join();
}
-
+
void ConcurrentDispatch::Execute() {
SPADES_MARK_FUNCTION();
SyncQueueEntry *ent = entry;
@@ -267,7 +267,7 @@ namespace spades {
}
ent->Done();
}
-
+
void ConcurrentDispatch::ExecuteProtected() throw() {
try{
Execute();
@@ -279,7 +279,7 @@ namespace spades {
fprintf(stderr, "(no information provided)\n");
}
}
-
+
void ConcurrentDispatch::Start() {
SPADES_MARK_FUNCTION();
if(entry){
@@ -302,7 +302,7 @@ namespace spades {
globalQueue.Push(entry);
}
}
-
+
void ConcurrentDispatch::StartOn(DispatchQueue *queue) {
SPADES_MARK_FUNCTION();
if(entry){
@@ -310,7 +310,7 @@ namespace spades {
}else{
entry = new SyncQueueEntry(this);
queue->internal->Push(entry);
-
+
if(queue == sdlQueue) {
SDL_Event evt;
memset(&evt, 0, sizeof(evt));
@@ -319,7 +319,7 @@ namespace spades {
}
}
}
-
+
void ConcurrentDispatch::Join() {
SPADES_MARK_FUNCTION();
if(!entry){
@@ -329,7 +329,7 @@ namespace spades {
entry = NULL;
}
}
-
+
void ConcurrentDispatch::Release(){
SPADES_MARK_FUNCTION();
if(entry){
@@ -337,7 +337,7 @@ namespace spades {
ent->Release();
}
}
-
+
void ConcurrentDispatch::Run(){
if(runnable)
runnable->Run();
diff --git a/Sources/Core/FileManager.cpp b/Sources/Core/FileManager.cpp
index 0940c0bb..84002ba7 100644
--- a/Sources/Core/FileManager.cpp
+++ b/Sources/Core/FileManager.cpp
@@ -1,21 +1,21 @@
/*
Copyright (c) 2013 yvt
-
+
This file is part of OpenSpades.
-
+
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see .
-
+
*/
#include "FileManager.h"
@@ -32,20 +32,20 @@ namespace spades {
SPADES_MARK_FUNCTION();
if(!fn) SPInvalidArgument("fn");
if(fn[0] == 0) SPFileNotFound(fn);
-
- // check each file systems
+
+ // check each file systems
for(auto *fs: g_fileSystems){
if(fs->FileExists(fn))
return fs->OpenForReading(fn);
}
-
- // check weak files, too
- auto weak_fn = std::string(fn) + ".weak";
- for(auto *fs: g_fileSystems){
- if(fs->FileExists(weak_fn.c_str()))
- return fs->OpenForReading(weak_fn.c_str());
- }
-
+
+ // check weak files, too
+ auto weak_fn = std::string(fn) + ".weak";
+ for(auto *fs: g_fileSystems){
+ if(fs->FileExists(weak_fn.c_str()))
+ return fs->OpenForReading(weak_fn.c_str());
+ }
+
SPFileNotFound(fn);
}
IStream *FileManager::OpenForWriting(const char *fn) {
@@ -56,9 +56,9 @@ namespace spades {
if(fs->FileExists(fn))
return fs->OpenForWriting(fn);
}
-
- // FIXME: handling of weak files
-
+
+ // FIXME: handling of weak files
+
// create file
for(auto *fs: g_fileSystems){
try{
@@ -66,50 +66,50 @@ namespace spades {
}catch(...){
}
}
-
+
SPRaise("No filesystem is writable");
}
bool FileManager::FileExists(const char *fn) {
SPADES_MARK_FUNCTION();
if(!fn) SPInvalidArgument("fn");
-
+
for(auto *fs: g_fileSystems){
if(fs->FileExists(fn))
return true;
- }
-
- // check weak files, too
- auto weak_fn = std::string(fn) + ".weak";
- for(auto *fs: g_fileSystems){
- if(fs->FileExists(weak_fn.c_str()))
- return true;
- }
-
+ }
+
+ // check weak files, too
+ auto weak_fn = std::string(fn) + ".weak";
+ for(auto *fs: g_fileSystems){
+ if(fs->FileExists(weak_fn.c_str()))
+ return true;
+ }
+
return false;
}
-
+
void FileManager::AddFileSystem(spades::IFileSystem *fs){
SPADES_MARK_FUNCTION();
AppendFileSystem(fs);
}
-
-
+
+
void FileManager::AppendFileSystem(spades::IFileSystem *fs){
SPADES_MARK_FUNCTION();
if(!fs) SPInvalidArgument("fs");
-
+
g_fileSystems.push_back(fs);
}
void FileManager::PrependFileSystem(spades::IFileSystem *fs){
SPADES_MARK_FUNCTION();
if(!fs) SPInvalidArgument("fs");
-
+
g_fileSystems.push_front(fs);
}
-
+
std::string FileManager::ReadAllBytes(const char *fn) {
SPADES_MARK_FUNCTION();
-
+
IStream *stream = OpenForReading(fn);
try{
std::string ret = stream->ReadAllBytes();
@@ -120,23 +120,23 @@ namespace spades {
throw;
}
}
-
+
std::vector FileManager::EnumFiles(const char *path) {
std::vector list;
std::set set;
if(!path) SPInvalidArgument("path");
-
+
for(auto *fs: g_fileSystems){
std::vector l = fs->EnumFiles(path);
for(size_t i = 0; i < l.size(); i++)
set.insert(l[i]);
}
-
+
for(auto& s: set)
list.push_back(s);
-
+
return list;
}
-
+
}
diff --git a/Sources/ScriptBindings/Config.cpp b/Sources/ScriptBindings/Config.cpp
index eb269135..196dc435 100644
--- a/Sources/ScriptBindings/Config.cpp
+++ b/Sources/ScriptBindings/Config.cpp
@@ -1,21 +1,21 @@
/*
Copyright (c) 2013 yvt
-
+
This file is part of OpenSpades.
-
+
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see .
-
+
*/
#include "ScriptManager.h"
@@ -25,28 +25,28 @@
#include
namespace spades {
-
- namespace
- {
- ThreadLocalStorage writeAllowed;
-
- // SettingItemDescriptor supplied to ItemHandle must have the static storage duration
- std::unordered_map
- settingItemDescriptors;
-
- const SettingItemDescriptor *MakeSettingItemDescriptor
- (const std::string &name, const std::string &defaultValue)
- {
- auto it = settingItemDescriptors.find(name);
- if (it != settingItemDescriptors.end()) {
- return it->second;
- }
- auto *descriptor = new SettingItemDescriptor(defaultValue, SettingItemFlags::None);
- settingItemDescriptors.insert(make_pair(name, descriptor));
- return descriptor;
- }
- }
-
+
+ namespace
+ {
+ ThreadLocalStorage writeAllowed;
+
+ // SettingItemDescriptor supplied to ItemHandle must have the static storage duration
+ std::unordered_map
+ settingItemDescriptors;
+
+ const SettingItemDescriptor *MakeSettingItemDescriptor
+ (const std::string &name, const std::string &defaultValue)
+ {
+ auto it = settingItemDescriptors.find(name);
+ if (it != settingItemDescriptors.end()) {
+ return it->second;
+ }
+ auto *descriptor = new SettingItemDescriptor(defaultValue, SettingItemFlags::None);
+ settingItemDescriptors.insert(make_pair(name, descriptor));
+ return descriptor;
+ }
+ }
+
void MaskConfigUpdateByScript(bool disabled)
{
if (!writeAllowed) {
@@ -54,32 +54,32 @@ namespace spades {
}
*writeAllowed = !disabled;
}
-
-
+
+
class ConfigRegistrar: public ScriptObjectRegistrar {
-
-
+
+
public:
ConfigRegistrar():
ScriptObjectRegistrar("Config") {}
-
+
class ConfigItem: public RefCountedObject {
Settings::ItemHandle handle;
- public:
- ConfigItem(const std::string& name, const std::string& defaultValue):
- handle(name, MakeSettingItemDescriptor(name, defaultValue)){
- }
- ConfigItem(const std::string& name):
- handle(name, nullptr){
- }
-
+ public:
+ ConfigItem(const std::string& name, const std::string& defaultValue):
+ handle(name, MakeSettingItemDescriptor(name, defaultValue)){
+ }
+ ConfigItem(const std::string& name):
+ handle(name, nullptr){
+ }
+
static ConfigItem *Construct(const std::string& name, const std::string& defaultValue) {
return new ConfigItem(name, defaultValue);
}
static ConfigItem *Construct(const std::string& name) {
return new ConfigItem(name);
}
-
+
ConfigItem *operator =(float fv) {
if (!writeAllowed || !*writeAllowed) {
return this;
@@ -92,7 +92,7 @@ namespace spades {
if (!writeAllowed || !*writeAllowed) {
return this;
}
-
+
handle = v;
AddRef();
return this;
@@ -101,7 +101,7 @@ namespace spades {
if (!writeAllowed || !*writeAllowed) {
return this;
}
-
+
handle = v;
AddRef();
return this;
@@ -128,12 +128,12 @@ namespace spades {
return (std::string)handle;
}
};
-
+
static CScriptArray *GetAllConfigNames() {
auto *ctx = asGetActiveContext();
auto *engine = ctx->GetEngine();
auto *arrayType = engine->GetTypeInfoByDecl("array");
- auto *array = CScriptArray::Create(arrayType);
+ auto *array = CScriptArray::Create(arrayType);
auto names = Settings::GetInstance()->GetAllItemNames();
array->Resize(static_cast(names.size()));
for(std::size_t i = 0; i < names.size(); i++) {
@@ -141,7 +141,7 @@ namespace spades {
}
return array;
}
-
+
virtual void Register(ScriptManager *manager, Phase phase) {
asIScriptEngine *eng = manager->GetEngine();
int r;
@@ -222,7 +222,7 @@ namespace spades {
asMETHOD(ConfigItem, GetStringValue),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterGlobalFunction("array@ GetAllConfigNames()",
asFUNCTION(GetAllConfigNames),
asCALL_CDECL);
@@ -233,8 +233,8 @@ namespace spades {
}
}
};
-
+
static ConfigRegistrar registrar;
-
+
}
diff --git a/Sources/ScriptBindings/PrimitiveArray.cpp b/Sources/ScriptBindings/PrimitiveArray.cpp
index 87a32d73..d4c75c43 100644
--- a/Sources/ScriptBindings/PrimitiveArray.cpp
+++ b/Sources/ScriptBindings/PrimitiveArray.cpp
@@ -1,21 +1,21 @@
/*
Copyright (c) 2013 yvt
-
+
This file is part of OpenSpades.
-
+
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see .
-
+
*/
#include "ScriptManager.h"
@@ -46,45 +46,45 @@ namespace spades {
ArrayType *obj = new ArrayType(initialSize);
asGetActiveContext()->GetEngine()->NotifyGarbageCollectorOfNewObject(obj, scrType);
return obj;
- }
- static ArrayType *Factory3(asUINT initialSize, T initialValue) {
- if(initialSize > 1024 * 1024 * 256) {
- asGetActiveContext()->SetException("Too many array elements");
- return NULL;
- }
- ArrayType *obj = new ArrayType(initialSize, initialValue);
- asGetActiveContext()->GetEngine()->NotifyGarbageCollectorOfNewObject(obj, scrType);
- return obj;
- }
- static ArrayType *Factory4(void *initList) {
- asUINT length = *reinterpret_cast(initList);
- if(length > 1024 * 1024 * 256) {
- asGetActiveContext()->SetException("Too many array elements");
- }
- ArrayType *obj = new ArrayType(initList);
- asGetActiveContext()->GetEngine()->NotifyGarbageCollectorOfNewObject(obj, scrType);
- return obj;
- }
-
+ }
+ static ArrayType *Factory3(asUINT initialSize, T initialValue) {
+ if(initialSize > 1024 * 1024 * 256) {
+ asGetActiveContext()->SetException("Too many array elements");
+ return NULL;
+ }
+ ArrayType *obj = new ArrayType(initialSize, initialValue);
+ asGetActiveContext()->GetEngine()->NotifyGarbageCollectorOfNewObject(obj, scrType);
+ return obj;
+ }
+ static ArrayType *Factory4(void *initList) {
+ asUINT length = *reinterpret_cast(initList);
+ if(length > 1024 * 1024 * 256) {
+ asGetActiveContext()->SetException("Too many array elements");
+ }
+ ArrayType *obj = new ArrayType(initList);
+ asGetActiveContext()->GetEngine()->NotifyGarbageCollectorOfNewObject(obj, scrType);
+ return obj;
+ }
+
PrimitiveArray(asUINT initialSize = 0) {
inner.resize(initialSize);
- }
- PrimitiveArray(asUINT initialSize, T initialValue) {
- inner.resize(initialSize, initialValue);
- }
- PrimitiveArray(void *initList) {
- asUINT length = *reinterpret_cast(initList);
- inner.resize(length);
- memcpy(inner.data(), reinterpret_cast(initList) + 1, inner.size() * sizeof(T));
- }
-
+ }
+ PrimitiveArray(asUINT initialSize, T initialValue) {
+ inner.resize(initialSize, initialValue);
+ }
+ PrimitiveArray(void *initList) {
+ asUINT length = *reinterpret_cast(initList);
+ inner.resize(length);
+ memcpy(inner.data(), reinterpret_cast(initList) + 1, inner.size() * sizeof(T));
+ }
+
void AddRef() {
refCount &= 0x7fffffff;
asAtomicInc(refCount);
}
void Release() {
refCount &= 0x7fffffff;
-
+
if(asAtomicDec(refCount) <= 0)
delete this;
}
@@ -99,7 +99,7 @@ namespace spades {
}
void EnumReferences(asIScriptEngine *eng) {}
void ReleaseAllReferences(asIScriptEngine *eng){}
-
+
T& At(asUINT index) {
if(index >= inner.size()){
asGetActiveContext()->SetException("Index out of bounds");
@@ -160,7 +160,7 @@ namespace spades {
inner.reserve((size_t)siz);
}
}
-
+
void SortAsc(asUINT index, asUINT count){
if(count <= 0) return;
if(index + count > inner.size()){
@@ -186,24 +186,24 @@ namespace spades {
void SortDesc() {
SortDesc(0, GetSize());
}
-
+
void Reverse() {
std::reverse(inner.begin(), inner.end());
}
-
+
int Find(const T& val) const {
typename std::vector::const_iterator it = std::find(inner.begin(), inner.end(), val);
if(it == inner.end()) return -1;
return static_cast (it - inner.begin());
}
-
+
int Find(asUINT ind, const T& val) const {
if(ind >= GetSize()) return -1;
typename std::vector::const_iterator it = std::find(inner.begin() + ind, inner.end(), val);
if(it == inner.end()) return -1;
return static_cast (it - inner.begin());
}
-
+
bool operator ==(const ArrayType& array) const {
if(this == &array)
return true;
@@ -215,13 +215,13 @@ namespace spades {
return false;
return true;
}
-
+
bool IsEmpty() const {
return inner.empty();
}
-
+
};
-
+
template
class PrimitiveArrayRegistrar: public ScriptObjectRegistrar {
std::string typeName;
@@ -304,154 +304,154 @@ namespace spades {
F("void f(int& in)"),
asMETHOD(ArrayType, ReleaseAllReferences), asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("%s& opIndex(uint)"),
asMETHODPR(ArrayType, At, (asUINT), T&),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("const %s& opIndex(uint) const"),
asMETHODPR(ArrayType, At, (asUINT) const, const T&),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("array<%s> &opAssign(const array<%s>&)"),
asMETHODPR(ArrayType, operator =, (const ArrayType&), ArrayType&),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("void insertAt(uint, const %s& in)"),
asMETHODPR(ArrayType, InsertAt, (asUINT, const T&), void),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("void removeAt(uint)"),
asMETHOD(ArrayType, RemoveAt),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("void insertLast(const %s& in)"),
asMETHOD(ArrayType, InsertLast),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("void removeLast()"),
asMETHOD(ArrayType, RemoveLast),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("uint length()"),
asMETHOD(ArrayType, GetSize),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("void resize(uint)"),
asMETHOD(ArrayType, Resize),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("void reserve(uint)"),
asMETHOD(ArrayType, Reserve),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("void sortAsc()"),
asMETHODPR(ArrayType, SortAsc, (), void),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("void sortAsc(uint, uint)"),
asMETHODPR(ArrayType, SortAsc, (asUINT, asUINT), void),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("void sortDesc()"),
asMETHODPR(ArrayType, SortDesc, (), void),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("void sortDesc(uint, uint)"),
asMETHODPR(ArrayType, SortDesc, (asUINT, asUINT), void),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("int find(const %s& in) const"),
asMETHODPR(ArrayType, Find, (const T&) const, int),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("int find(uint, const %s& in) const"),
asMETHODPR(ArrayType, Find, (asUINT, const T&) const, int),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("bool opEquals(const array<%s>&) const"),
asMETHODPR(ArrayType, operator ==, (const ArrayType&) const, bool),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("uint get_length()"),
asMETHOD(ArrayType, GetSize),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("void set_length(uint)"),
asMETHOD(ArrayType, Resize),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("bool isEmpty()"),
asMETHOD(ArrayType, IsEmpty),
asCALL_THISCALL);
manager->CheckError(r);
-
+
// STL name
-
+
r = eng->RegisterObjectMethod(ATN(),
F("uint size()"),
asMETHOD(ArrayType, GetSize),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("bool empty()"),
asMETHOD(ArrayType, IsEmpty),
asCALL_THISCALL);
manager->CheckError(r);
-
-
+
+
r = eng->RegisterObjectMethod(ATN(),
F("void push_back(const %s& in)"),
asMETHOD(ArrayType, InsertLast),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("void pop_back()"),
asMETHOD(ArrayType, RemoveLast),
asCALL_THISCALL);
manager->CheckError(r);
-
+
r = eng->RegisterObjectMethod(ATN(),
F("void erase(uint)"),
asMETHOD(ArrayType, RemoveAt),
@@ -474,5 +474,5 @@ namespace spades {
static PrimitiveArrayRegistrar uint64ArrayRegistrar("uint64");
static PrimitiveArrayRegistrar floatArrayRegistrar("float");
static PrimitiveArrayRegistrar doubleArrayRegistrar("double");
-
+
}
diff --git a/Sources/Tools/BdfToOSFont.cpp b/Sources/Tools/BdfToOSFont.cpp
index fcf896bd..37b7395e 100644
--- a/Sources/Tools/BdfToOSFont.cpp
+++ b/Sources/Tools/BdfToOSFont.cpp
@@ -55,15 +55,15 @@ typedef unsigned __int32 uint32_t;
/* Targa image and header fields -------------------------------------------*/
typedef struct
{
- /* Note that Targa is stored in little-endian order */
- uint8_t image_id_length;
-
- uint8_t color_map_type;
- /* color map = palette */
+ /* Note that Targa is stored in little-endian order */
+ uint8_t image_id_length;
+
+ uint8_t color_map_type;
+ /* color map = palette */
#define TGA_COLOR_MAP_ABSENT 0
#define TGA_COLOR_MAP_PRESENT 1
-
- uint8_t image_type;
+
+ uint8_t image_type;
#define TGA_IMAGE_TYPE_NONE 0 /* no image data */
#define TGA_IMAGE_TYPE_COLORMAP 1 /* uncompressed, color-mapped */
#define TGA_IMAGE_TYPE_BGR 2 /* uncompressed, true-color */
@@ -71,49 +71,49 @@ typedef struct
#define TGA_IMAGE_TYPE_COLORMAP_RLE 9 /* run-length, color-mapped */
#define TGA_IMAGE_TYPE_BGR_RLE 10 /* run-length, true-color */
#define TGA_IMAGE_TYPE_MONO_RLE 11 /* run-length, black and white */
-
- /* color map specification */
- uint16_t color_map_origin; /* index of first entry */
- uint16_t color_map_length; /* number of entries included */
- uint8_t color_map_depth; /* number of bits per entry */
-
- /* image specification */
- uint16_t origin_x;
- uint16_t origin_y;
- uint16_t width;
- uint16_t height;
- uint8_t pixel_depth;
-
- uint8_t image_descriptor;
- /* bits 0,1,2,3 - attribute bits per pixel
- * bit 4 - set if image is stored right-to-left
- * bit 5 - set if image is stored top-to-bottom
- * bits 6,7 - unused (must be set to zero)
- */
+
+ /* color map specification */
+ uint16_t color_map_origin; /* index of first entry */
+ uint16_t color_map_length; /* number of entries included */
+ uint8_t color_map_depth; /* number of bits per entry */
+
+ /* image specification */
+ uint16_t origin_x;
+ uint16_t origin_y;
+ uint16_t width;
+ uint16_t height;
+ uint8_t pixel_depth;
+
+ uint8_t image_descriptor;
+ /* bits 0,1,2,3 - attribute bits per pixel
+ * bit 4 - set if image is stored right-to-left
+ * bit 5 - set if image is stored top-to-bottom
+ * bits 6,7 - unused (must be set to zero)
+ */
#define TGA_ATTRIB_BITS (uint8_t)(BIT(0)|BIT(1)|BIT(2)|BIT(3))
#define TGA_R_TO_L_BIT (uint8_t)BIT(4)
#define TGA_T_TO_B_BIT (uint8_t)BIT(5)
#define TGA_UNUSED_BITS (uint8_t)(BIT(6)|BIT(7))
- /* Note: right-to-left order is not honored by some Targa readers */
-
- uint8_t *image_id;
- /* The length of this field is given in image_id_length, it's read raw
- * from the file so it's not not guaranteed to be zero-terminated. If
- * it's not NULL, it needs to be deallocated. see: tga_free_buffers()
- */
-
- uint8_t *color_map_data;
- /* See the "color map specification" fields above. If not NULL, this
- * field needs to be deallocated. see: tga_free_buffers()
- */
-
- uint8_t *image_data;
- /* Follows image specification fields (see above) */
-
- /* Extension area and developer area are silently ignored. The Targa 2.0
- * spec says we're not required to read or write them.
- */
-
+ /* Note: right-to-left order is not honored by some Targa readers */
+
+ uint8_t *image_id;
+ /* The length of this field is given in image_id_length, it's read raw
+ * from the file so it's not not guaranteed to be zero-terminated. If
+ * it's not NULL, it needs to be deallocated. see: tga_free_buffers()
+ */
+
+ uint8_t *color_map_data;
+ /* See the "color map specification" fields above. If not NULL, this
+ * field needs to be deallocated. see: tga_free_buffers()
+ */
+
+ uint8_t *image_data;
+ /* Follows image specification fields (see above) */
+
+ /* Extension area and developer area are silently ignored. The Targa 2.0
+ * spec says we're not required to read or write them.
+ */
+
} tga_image;
@@ -130,24 +130,24 @@ int tga_is_mono(const tga_image *tga);
/* Error handling ----------------------------------------------------------*/
typedef enum {
- TGA_NOERR,
- TGAERR_FOPEN,
- TGAERR_EOF,
- TGAERR_WRITE,
- TGAERR_CMAP_TYPE,
- TGAERR_IMG_TYPE,
- TGAERR_NO_IMG,
- TGAERR_CMAP_MISSING,
- TGAERR_CMAP_PRESENT,
- TGAERR_CMAP_LENGTH,
- TGAERR_CMAP_DEPTH,
- TGAERR_ZERO_SIZE,
- TGAERR_PIXEL_DEPTH,
- TGAERR_NO_MEM,
- TGAERR_NOT_CMAP,
- TGAERR_RLE,
- TGAERR_INDEX_RANGE,
- TGAERR_MONO
+ TGA_NOERR,
+ TGAERR_FOPEN,
+ TGAERR_EOF,
+ TGAERR_WRITE,
+ TGAERR_CMAP_TYPE,
+ TGAERR_IMG_TYPE,
+ TGAERR_NO_IMG,
+ TGAERR_CMAP_MISSING,
+ TGAERR_CMAP_PRESENT,
+ TGAERR_CMAP_LENGTH,
+ TGAERR_CMAP_DEPTH,
+ TGAERR_ZERO_SIZE,
+ TGAERR_PIXEL_DEPTH,
+ TGAERR_NO_MEM,
+ TGAERR_NOT_CMAP,
+ TGAERR_RLE,
+ TGAERR_INDEX_RANGE,
+ TGAERR_MONO
} tga_result;
const char *tga_error(const tga_result errcode);
@@ -242,22 +242,22 @@ static uint8_t rle_packet_len(const uint8_t *row, const uint16_t pos,
uint8_t tga_get_attribute_bits(const tga_image *tga)
{
- return tga->image_descriptor & TGA_ATTRIB_BITS;
+ return tga->image_descriptor & TGA_ATTRIB_BITS;
}
int tga_is_right_to_left(const tga_image *tga)
{
- return (tga->image_descriptor & TGA_R_TO_L_BIT) != 0;
+ return (tga->image_descriptor & TGA_R_TO_L_BIT) != 0;
}
int tga_is_top_to_bottom(const tga_image *tga)
{
- return (tga->image_descriptor & TGA_T_TO_B_BIT) != 0;
+ return (tga->image_descriptor & TGA_T_TO_B_BIT) != 0;
}
int tga_is_colormapped(const tga_image *tga)
{
- return (
+ return (
tga->image_type == TGA_IMAGE_TYPE_COLORMAP ||
tga->image_type == TGA_IMAGE_TYPE_COLORMAP_RLE
);
@@ -265,7 +265,7 @@ int tga_is_colormapped(const tga_image *tga)
int tga_is_rle(const tga_image *tga)
{
- return (
+ return (
tga->image_type == TGA_IMAGE_TYPE_COLORMAP_RLE ||
tga->image_type == TGA_IMAGE_TYPE_BGR_RLE ||
tga->image_type == TGA_IMAGE_TYPE_MONO_RLE
@@ -274,7 +274,7 @@ int tga_is_rle(const tga_image *tga)
int tga_is_mono(const tga_image *tga)
{
- return (
+ return (
tga->image_type == TGA_IMAGE_TYPE_MONO ||
tga->image_type == TGA_IMAGE_TYPE_MONO_RLE
);
@@ -289,8 +289,8 @@ int tga_is_mono(const tga_image *tga)
*/
const char *tga_error(const tga_result errcode)
{
- switch (errcode)
- {
+ switch (errcode)
+ {
case TGA_NOERR:
return "no error";
case TGAERR_FOPEN:
@@ -329,7 +329,7 @@ const char *tga_error(const tga_result errcode)
return "image is mono";
default:
return "unknown error code";
- }
+ }
}
@@ -345,111 +345,111 @@ tga_result tga_read_from_FILE(tga_image *dest, std::istream& fp)
{
#define BARF(errcode) \
{ tga_free_buffers(dest); return errcode; }
-
+
#define READ(destptr, size) \
if(fp.readsome(reinterpret_cast(destptr), size) < size) BARF(TGAERR_EOF)
//if (fread(destptr, size, 1, fp) != 1) BARF(TGAERR_EOF)
-
+
#define READ16(dest) \
{ if (fp.readsome(reinterpret_cast(&dest), 2) != 2) BARF(TGAERR_EOF); \
dest = letoh16(dest); }
//{ if (fread(&(dest), 2, 1, fp) != 1) BARF(TGAERR_EOF); \
//dest = letoh16(dest); }
-
- dest->image_id = NULL;
- dest->color_map_data = NULL;
- dest->image_data = NULL;
-
- READ(&dest->image_id_length,1);
- READ(&dest->color_map_type,1);
- if (dest->color_map_type != TGA_COLOR_MAP_ABSENT &&
- dest->color_map_type != TGA_COLOR_MAP_PRESENT)
+
+ dest->image_id = NULL;
+ dest->color_map_data = NULL;
+ dest->image_data = NULL;
+
+ READ(&dest->image_id_length,1);
+ READ(&dest->color_map_type,1);
+ if (dest->color_map_type != TGA_COLOR_MAP_ABSENT &&
+ dest->color_map_type != TGA_COLOR_MAP_PRESENT)
BARF(TGAERR_CMAP_TYPE);
-
- READ(&dest->image_type, 1);
- if (dest->image_type == TGA_IMAGE_TYPE_NONE)
+
+ READ(&dest->image_type, 1);
+ if (dest->image_type == TGA_IMAGE_TYPE_NONE)
BARF(TGAERR_NO_IMG);
-
- if (dest->image_type != TGA_IMAGE_TYPE_COLORMAP &&
- dest->image_type != TGA_IMAGE_TYPE_BGR &&
- dest->image_type != TGA_IMAGE_TYPE_MONO &&
- dest->image_type != TGA_IMAGE_TYPE_COLORMAP_RLE &&
- dest->image_type != TGA_IMAGE_TYPE_BGR_RLE &&
- dest->image_type != TGA_IMAGE_TYPE_MONO_RLE)
+
+ if (dest->image_type != TGA_IMAGE_TYPE_COLORMAP &&
+ dest->image_type != TGA_IMAGE_TYPE_BGR &&
+ dest->image_type != TGA_IMAGE_TYPE_MONO &&
+ dest->image_type != TGA_IMAGE_TYPE_COLORMAP_RLE &&
+ dest->image_type != TGA_IMAGE_TYPE_BGR_RLE &&
+ dest->image_type != TGA_IMAGE_TYPE_MONO_RLE)
BARF(TGAERR_IMG_TYPE);
-
- if (tga_is_colormapped(dest) &&
- dest->color_map_type == TGA_COLOR_MAP_ABSENT)
+
+ if (tga_is_colormapped(dest) &&
+ dest->color_map_type == TGA_COLOR_MAP_ABSENT)
BARF(TGAERR_CMAP_MISSING);
-
- if (!tga_is_colormapped(dest) &&
- dest->color_map_type == TGA_COLOR_MAP_PRESENT)
+
+ if (!tga_is_colormapped(dest) &&
+ dest->color_map_type == TGA_COLOR_MAP_PRESENT)
BARF(TGAERR_CMAP_PRESENT);
-
- READ16(dest->color_map_origin);
- READ16(dest->color_map_length);
- READ(&dest->color_map_depth, 1);
- if (dest->color_map_type == TGA_COLOR_MAP_PRESENT)
- {
- if (dest->color_map_length == 0)
- BARF(TGAERR_CMAP_LENGTH);
-
- if (!UNMAP_DEPTH(dest->color_map_depth))
- BARF(TGAERR_CMAP_DEPTH);
- }
-
- READ16(dest->origin_x);
- READ16(dest->origin_y);
- READ16(dest->width);
- READ16(dest->height);
-
- if (dest->width == 0 || dest->height == 0)
+
+ READ16(dest->color_map_origin);
+ READ16(dest->color_map_length);
+ READ(&dest->color_map_depth, 1);
+ if (dest->color_map_type == TGA_COLOR_MAP_PRESENT)
+ {
+ if (dest->color_map_length == 0)
+ BARF(TGAERR_CMAP_LENGTH);
+
+ if (!UNMAP_DEPTH(dest->color_map_depth))
+ BARF(TGAERR_CMAP_DEPTH);
+ }
+
+ READ16(dest->origin_x);
+ READ16(dest->origin_y);
+ READ16(dest->width);
+ READ16(dest->height);
+
+ if (dest->width == 0 || dest->height == 0)
BARF(TGAERR_ZERO_SIZE);
-
- READ(&dest->pixel_depth, 1);
- if (!SANE_DEPTH(dest->pixel_depth) ||
+
+ READ(&dest->pixel_depth, 1);
+ if (!SANE_DEPTH(dest->pixel_depth) ||
(dest->pixel_depth != 8 && tga_is_colormapped(dest)) )
BARF(TGAERR_PIXEL_DEPTH);
-
- READ(&dest->image_descriptor, 1);
-
- if (dest->image_id_length > 0)
- {
- dest->image_id = (uint8_t*)malloc(dest->image_id_length);
- if (dest->image_id == NULL) BARF(TGAERR_NO_MEM);
- READ(dest->image_id, dest->image_id_length);
- }
-
- if (dest->color_map_type == TGA_COLOR_MAP_PRESENT)
- {
- dest->color_map_data = (uint8_t*)malloc(
+
+ READ(&dest->image_descriptor, 1);
+
+ if (dest->image_id_length > 0)
+ {
+ dest->image_id = (uint8_t*)malloc(dest->image_id_length);
+ if (dest->image_id == NULL) BARF(TGAERR_NO_MEM);
+ READ(dest->image_id, dest->image_id_length);
+ }
+
+ if (dest->color_map_type == TGA_COLOR_MAP_PRESENT)
+ {
+ dest->color_map_data = (uint8_t*)malloc(
(dest->color_map_origin + dest->color_map_length) *
dest->color_map_depth / 8);
- if (dest->color_map_data == NULL) BARF(TGAERR_NO_MEM);
- READ(dest->color_map_data +
+ if (dest->color_map_data == NULL) BARF(TGAERR_NO_MEM);
+ READ(dest->color_map_data +
(dest->color_map_origin * dest->color_map_depth / 8),
dest->color_map_length * dest->color_map_depth / 8);
- }
-
- dest->image_data = (uint8_t*) malloc(
+ }
+
+ dest->image_data = (uint8_t*) malloc(
dest->width * dest->height * dest->pixel_depth / 8);
- if (dest->image_data == NULL)
+ if (dest->image_data == NULL)
BARF(TGAERR_NO_MEM);
-
- if (tga_is_rle(dest))
- {
- /* read RLE */
- tga_result result = tga_read_rle(dest, fp);
- if (result != TGA_NOERR) BARF(result);
- }
- else
- {
- /* uncompressed */
- READ(dest->image_data,
+
+ if (tga_is_rle(dest))
+ {
+ /* read RLE */
+ tga_result result = tga_read_rle(dest, fp);
+ if (result != TGA_NOERR) BARF(result);
+ }
+ else
+ {
+ /* uncompressed */
+ READ(dest->image_data,
dest->width * dest->height * dest->pixel_depth / 8);
- }
-
- return TGA_NOERR;
+ }
+
+ return TGA_NOERR;
#undef BARF
#undef READ
#undef READ16
@@ -466,47 +466,47 @@ static tga_result tga_read_rle(tga_image *dest, std::istream& fp)
#define RLE_BIT BIT(7)
#define READ(dest, size) \
if (fp.readsome(reinterpret_cast(dest), size) != size) return TGAERR_EOF
-
- uint8_t *pos;
- uint32_t p_loaded = 0,
+
+ uint8_t *pos;
+ uint32_t p_loaded = 0,
p_expected = dest->width * dest->height;
- uint8_t bpp = dest->pixel_depth/8; /* bytes per pixel */
-
- pos = dest->image_data;
-
- while ((p_loaded < p_expected)/* && !feof(fp)*/)
- {
- uint8_t b;
- READ(&b, 1);
- if (b & RLE_BIT)
- {
- /* is an RLE packet */
- uint8_t count, tmp[4], i;
-
- count = (b & ~RLE_BIT) + 1;
- READ(tmp, bpp);
-
- for (i=0; i p_expected) return TGAERR_RLE;
- memcpy(pos, tmp, bpp);
- pos += bpp;
- }
- }
- else /* RAW packet */
- {
- uint8_t count;
-
- count = (b & ~RLE_BIT) + 1;
- if (p_loaded + count > p_expected) return TGAERR_RLE;
-
- p_loaded += count;
- READ(pos, bpp*count);
- pos += count * bpp;
- }
- }
- return TGA_NOERR;
+ uint8_t bpp = dest->pixel_depth/8; /* bytes per pixel */
+
+ pos = dest->image_data;
+
+ while ((p_loaded < p_expected)/* && !feof(fp)*/)
+ {
+ uint8_t b;
+ READ(&b, 1);
+ if (b & RLE_BIT)
+ {
+ /* is an RLE packet */
+ uint8_t count, tmp[4], i;
+
+ count = (b & ~RLE_BIT) + 1;
+ READ(tmp, bpp);
+
+ for (i=0; i p_expected) return TGAERR_RLE;
+ memcpy(pos, tmp, bpp);
+ pos += bpp;
+ }
+ }
+ else /* RAW packet */
+ {
+ uint8_t count;
+
+ count = (b & ~RLE_BIT) + 1;
+ if (p_loaded + count > p_expected) return TGAERR_RLE;
+
+ p_loaded += count;
+ READ(pos, bpp*count);
+ pos += count * bpp;
+ }
+ }
+ return TGA_NOERR;
#undef RLE_BIT
#undef READ
}
@@ -525,35 +525,35 @@ static tga_result tga_write_row_RLE(std::ostream& fp,
{
#define WRITE(src, size) \
fp.write(reinterpret_cast(src), size)
-
+
//if (fwrite(src, size, 1, fp) != 1) return TGAERR_WRITE
-
- uint16_t pos = 0;
- uint16_t bpp = src->pixel_depth / 8;
-
- while (pos < src->width)
- {
- packet_type type = rle_packet_type(row, pos, src->width, bpp);
- uint8_t len = rle_packet_len(row, pos, src->width, bpp, type);
- uint8_t packet_header;
-
- packet_header = len - 1;
- if (type == RLE) packet_header |= BIT(7);
-
- WRITE(&packet_header, 1);
- if (type == RLE)
- {
- WRITE(PIXEL(pos), bpp);
- }
- else /* type == RAW */
- {
- WRITE(PIXEL(pos), bpp*len);
- }
-
- pos += len;
- }
-
- return TGA_NOERR;
+
+ uint16_t pos = 0;
+ uint16_t bpp = src->pixel_depth / 8;
+
+ while (pos < src->width)
+ {
+ packet_type type = rle_packet_type(row, pos, src->width, bpp);
+ uint8_t len = rle_packet_len(row, pos, src->width, bpp, type);
+ uint8_t packet_header;
+
+ packet_header = len - 1;
+ if (type == RLE) packet_header |= BIT(7);
+
+ WRITE(&packet_header, 1);
+ if (type == RLE)
+ {
+ WRITE(PIXEL(pos), bpp);
+ }
+ else /* type == RAW */
+ {
+ WRITE(PIXEL(pos), bpp*len);
+ }
+
+ pos += len;
+ }
+
+ return TGA_NOERR;
#undef WRITE
}
@@ -569,15 +569,15 @@ fp.write(reinterpret_cast(src), size)
static packet_type rle_packet_type(const uint8_t *row, const uint16_t pos,
const uint16_t width, const uint16_t bpp)
{
- if (pos == width - 1) return RAW; /* one pixel */
- if (SAME(pos,pos+1)) /* dupe pixel */
- {
- if (bpp > 1) return RLE; /* inefficient for bpp=1 */
-
- /* three repeats makes the bpp=1 case efficient enough */
- if ((pos < width - 2) && SAME(pos+1,pos+2)) return RLE;
- }
- return RAW;
+ if (pos == width - 1) return RAW; /* one pixel */
+ if (SAME(pos,pos+1)) /* dupe pixel */
+ {
+ if (bpp > 1) return RLE; /* inefficient for bpp=1 */
+
+ /* three repeats makes the bpp=1 case efficient enough */
+ if ((pos < width - 2) && SAME(pos+1,pos+2)) return RLE;
+ }
+ return RAW;
}
@@ -589,35 +589,35 @@ static packet_type rle_packet_type(const uint8_t *row, const uint16_t pos,
static uint8_t rle_packet_len(const uint8_t *row, const uint16_t pos,
const uint16_t width, const uint16_t bpp, const packet_type type)
{
- uint8_t len = 2;
-
- if (pos == width - 1) return 1;
- if (pos == width - 2) return 2;
-
- if (type == RLE)
- {
- while (pos + len < width)
- {
- if (SAME(pos, pos+len))
- len++;
- else
- return len;
-
- if (len == 128) return 128;
- }
- }
- else /* type == RAW */
- {
- while (pos + len < width)
- {
- if (rle_packet_type(row, pos+len, width, bpp) == RAW)
- len++;
- else
- return len;
- if (len == 128) return 128;
- }
- }
- return len; /* hit end of row (width) */
+ uint8_t len = 2;
+
+ if (pos == width - 1) return 1;
+ if (pos == width - 2) return 2;
+
+ if (type == RLE)
+ {
+ while (pos + len < width)
+ {
+ if (SAME(pos, pos+len))
+ len++;
+ else
+ return len;
+
+ if (len == 128) return 128;
+ }
+ }
+ else /* type == RAW */
+ {
+ while (pos + len < width)
+ {
+ if (rle_packet_type(row, pos+len, width, bpp) == RAW)
+ len++;
+ else
+ return len;
+ if (len == 128) return 128;
+ }
+ }
+ return len; /* hit end of row (width) */
}
#undef SAME
#undef PIXEL
@@ -637,92 +637,92 @@ tga_result tga_write_to_FILE(std::ostream& fp, const tga_image *src)
fp.write(reinterpret_cast(srcptr), size)
//fp->Write(srcptr, size)
//if (fwrite(srcptr, size, 1, fp) != 1) return TGAERR_WRITE
-
+
#define WRITE16(src) \
{ uint16_t _temp = htole16(src); \
fp.write(reinterpret_cast(&_temp), 2); }
-
+
//if (fwrite(&_temp, 2, 1, fp) != 1) return TGAERR_WRITE; }
-
- WRITE(&src->image_id_length, 1);
-
- if (src->color_map_type != TGA_COLOR_MAP_ABSENT &&
- src->color_map_type != TGA_COLOR_MAP_PRESENT)
+
+ WRITE(&src->image_id_length, 1);
+
+ if (src->color_map_type != TGA_COLOR_MAP_ABSENT &&
+ src->color_map_type != TGA_COLOR_MAP_PRESENT)
return TGAERR_CMAP_TYPE;
- WRITE(&src->color_map_type, 1);
-
- if (src->image_type == TGA_IMAGE_TYPE_NONE)
+ WRITE(&src->color_map_type, 1);
+
+ if (src->image_type == TGA_IMAGE_TYPE_NONE)
return TGAERR_NO_IMG;
- if (src->image_type != TGA_IMAGE_TYPE_COLORMAP &&
- src->image_type != TGA_IMAGE_TYPE_BGR &&
- src->image_type != TGA_IMAGE_TYPE_MONO &&
- src->image_type != TGA_IMAGE_TYPE_COLORMAP_RLE &&
- src->image_type != TGA_IMAGE_TYPE_BGR_RLE &&
- src->image_type != TGA_IMAGE_TYPE_MONO_RLE)
+ if (src->image_type != TGA_IMAGE_TYPE_COLORMAP &&
+ src->image_type != TGA_IMAGE_TYPE_BGR &&
+ src->image_type != TGA_IMAGE_TYPE_MONO &&
+ src->image_type != TGA_IMAGE_TYPE_COLORMAP_RLE &&
+ src->image_type != TGA_IMAGE_TYPE_BGR_RLE &&
+ src->image_type != TGA_IMAGE_TYPE_MONO_RLE)
return TGAERR_IMG_TYPE;
- WRITE(&src->image_type, 1);
-
- if (tga_is_colormapped(src) &&
- src->color_map_type == TGA_COLOR_MAP_ABSENT)
+ WRITE(&src->image_type, 1);
+
+ if (tga_is_colormapped(src) &&
+ src->color_map_type == TGA_COLOR_MAP_ABSENT)
return TGAERR_CMAP_MISSING;
- if (!tga_is_colormapped(src) &&
- src->color_map_type == TGA_COLOR_MAP_PRESENT)
+ if (!tga_is_colormapped(src) &&
+ src->color_map_type == TGA_COLOR_MAP_PRESENT)
return TGAERR_CMAP_PRESENT;
- if (src->color_map_type == TGA_COLOR_MAP_PRESENT)
- {
- if (src->color_map_length == 0)
- return TGAERR_CMAP_LENGTH;
-
- if (!UNMAP_DEPTH(src->color_map_depth))
- return TGAERR_CMAP_DEPTH;
- }
- WRITE16(src->color_map_origin);
- WRITE16(src->color_map_length);
- WRITE(&src->color_map_depth, 1);
-
- WRITE16(src->origin_x);
- WRITE16(src->origin_y);
-
- if (src->width == 0 || src->height == 0)
+ if (src->color_map_type == TGA_COLOR_MAP_PRESENT)
+ {
+ if (src->color_map_length == 0)
+ return TGAERR_CMAP_LENGTH;
+
+ if (!UNMAP_DEPTH(src->color_map_depth))
+ return TGAERR_CMAP_DEPTH;
+ }
+ WRITE16(src->color_map_origin);
+ WRITE16(src->color_map_length);
+ WRITE(&src->color_map_depth, 1);
+
+ WRITE16(src->origin_x);
+ WRITE16(src->origin_y);
+
+ if (src->width == 0 || src->height == 0)
return TGAERR_ZERO_SIZE;
- WRITE16(src->width);
- WRITE16(src->height);
-
- if (!SANE_DEPTH(src->pixel_depth) ||
+ WRITE16(src->width);
+ WRITE16(src->height);
+
+ if (!SANE_DEPTH(src->pixel_depth) ||
(src->pixel_depth != 8 && tga_is_colormapped(src)) )
return TGAERR_PIXEL_DEPTH;
- WRITE(&src->pixel_depth, 1);
-
- WRITE(&src->image_descriptor, 1);
-
- if (src->image_id_length > 0)
- WRITE(&src->image_id, src->image_id_length);
-
- if (src->color_map_type == TGA_COLOR_MAP_PRESENT)
- WRITE(src->color_map_data +
+ WRITE(&src->pixel_depth, 1);
+
+ WRITE(&src->image_descriptor, 1);
+
+ if (src->image_id_length > 0)
+ WRITE(&src->image_id, src->image_id_length);
+
+ if (src->color_map_type == TGA_COLOR_MAP_PRESENT)
+ WRITE(src->color_map_data +
(src->color_map_origin * src->color_map_depth / 8),
- src->color_map_length * src->color_map_depth / 8);
-
- if (tga_is_rle(src))
- {
- uint16_t row;
- for (row=0; rowheight; row++)
- {
- tga_result result = tga_write_row_RLE(fp, src,
+ src->color_map_length * src->color_map_depth / 8);
+
+ if (tga_is_rle(src))
+ {
+ uint16_t row;
+ for (row=0; rowheight; row++)
+ {
+ tga_result result = tga_write_row_RLE(fp, src,
src->image_data + row*src->width*src->pixel_depth/8);
- if (result != TGA_NOERR) return result;
- }
- }
- else
- {
- /* uncompressed */
- WRITE(src->image_data,
- src->width * src->height * src->pixel_depth / 8);
- }
-
- WRITE(tga_id, tga_id_length);
-
- return TGA_NOERR;
+ if (result != TGA_NOERR) return result;
+ }
+ }
+ else
+ {
+ /* uncompressed */
+ WRITE(src->image_data,
+ src->width * src->height * src->pixel_depth / 8);
+ }
+
+ WRITE(tga_id, tga_id_length);
+
+ return TGA_NOERR;
#undef WRITE
#undef WRITE16
}
@@ -738,25 +738,25 @@ fp.write(reinterpret_cast(&_temp), 2); }
static void init_tga_image(tga_image *img, uint8_t *image,
const uint16_t width, const uint16_t height, const uint8_t depth)
{
- img->image_id_length = 0;
- img->color_map_type = TGA_COLOR_MAP_ABSENT;
- img->image_type = TGA_IMAGE_TYPE_NONE; /* override this below! */
- img->color_map_origin = 0;
- img->color_map_length = 0;
- img->color_map_depth = 0;
- img->origin_x = 0;
- img->origin_y = 0;
- img->width = width;
- img->height = height;
- img->pixel_depth = depth;
- img->image_descriptor = TGA_T_TO_B_BIT;
- img->image_id = NULL;
- img->color_map_data = NULL;
- img->image_data = image;
+ img->image_id_length = 0;
+ img->color_map_type = TGA_COLOR_MAP_ABSENT;
+ img->image_type = TGA_IMAGE_TYPE_NONE; /* override this below! */
+ img->color_map_origin = 0;
+ img->color_map_length = 0;
+ img->color_map_depth = 0;
+ img->origin_x = 0;
+ img->origin_y = 0;
+ img->width = width;
+ img->height = height;
+ img->pixel_depth = depth;
+ img->image_descriptor = TGA_T_TO_B_BIT;
+ img->image_id = NULL;
+ img->color_map_data = NULL;
+ img->image_data = image;
}
/*
-
-
+
+
tga_result tga_write_mono(const char *filename, uint8_t *image,
const uint16_t width, const uint16_t height)
{
@@ -765,9 +765,9 @@ static void init_tga_image(tga_image *img, uint8_t *image,
img.image_type = TGA_IMAGE_TYPE_MONO;
return tga_write(filename, &img);
}
-
-
-
+
+
+
tga_result tga_write_mono_rle(const char *filename, uint8_t *image,
const uint16_t width, const uint16_t height)
{
@@ -776,9 +776,9 @@ static void init_tga_image(tga_image *img, uint8_t *image,
img.image_type = TGA_IMAGE_TYPE_MONO_RLE;
return tga_write(filename, &img);
}
-
-
-
+
+
+
tga_result tga_write_bgr(const char *filename, uint8_t *image,
const uint16_t width, const uint16_t height, const uint8_t depth)
{
@@ -787,9 +787,9 @@ static void init_tga_image(tga_image *img, uint8_t *image,
img.image_type = TGA_IMAGE_TYPE_BGR;
return tga_write(filename, &img);
}
-
-
-
+
+
+
tga_result tga_write_bgr_rle(const char *filename, uint8_t *image,
const uint16_t width, const uint16_t height, const uint8_t depth)
{
@@ -835,43 +835,43 @@ static void init_tga_image(tga_image *img, uint8_t *image,
*/
tga_result tga_flip_horiz(tga_image *img)
{
- uint16_t row;
- size_t bpp;
- uint8_t *left, *right;
- int r_to_l;
-
- if (!SANE_DEPTH(img->pixel_depth)) return TGAERR_PIXEL_DEPTH;
- bpp = (size_t)(img->pixel_depth / 8); /* bytes per pixel */
-
- for (row=0; rowheight; row++)
- {
- left = img->image_data + row * img->width * bpp;
- right = left + (img->width - 1) * bpp;
-
- /* reverse from left to right */
- while (left < right)
- {
- uint8_t buffer[4];
-
- /* swap */
- memcpy(buffer, left, bpp);
- memcpy(left, right, bpp);
- memcpy(right, buffer, bpp);
-
- left += bpp;
- right -= bpp;
- }
- }
-
- /* Correct image_descriptor's left-to-right-ness. */
- r_to_l = tga_is_right_to_left(img);
- img->image_descriptor &= ~TGA_R_TO_L_BIT; /* mask out r-to-l bit */
- if (!r_to_l)
+ uint16_t row;
+ size_t bpp;
+ uint8_t *left, *right;
+ int r_to_l;
+
+ if (!SANE_DEPTH(img->pixel_depth)) return TGAERR_PIXEL_DEPTH;
+ bpp = (size_t)(img->pixel_depth / 8); /* bytes per pixel */
+
+ for (row=0; rowheight; row++)
+ {
+ left = img->image_data + row * img->width * bpp;
+ right = left + (img->width - 1) * bpp;
+
+ /* reverse from left to right */
+ while (left < right)
+ {
+ uint8_t buffer[4];
+
+ /* swap */
+ memcpy(buffer, left, bpp);
+ memcpy(left, right, bpp);
+ memcpy(right, buffer, bpp);
+
+ left += bpp;
+ right -= bpp;
+ }
+ }
+
+ /* Correct image_descriptor's left-to-right-ness. */
+ r_to_l = tga_is_right_to_left(img);
+ img->image_descriptor &= ~TGA_R_TO_L_BIT; /* mask out r-to-l bit */
+ if (!r_to_l)
/* was l-to-r, need to set r_to_l */
- img->image_descriptor |= TGA_R_TO_L_BIT;
- /* else bit is already rubbed out */
-
- return TGA_NOERR;
+ img->image_descriptor |= TGA_R_TO_L_BIT;
+ /* else bit is already rubbed out */
+
+ return TGA_NOERR;
}
@@ -882,44 +882,44 @@ tga_result tga_flip_horiz(tga_image *img)
*/
tga_result tga_flip_vert(tga_image *img)
{
- uint16_t col;
- size_t bpp, line;
- uint8_t *top, *bottom;
- int t_to_b;
-
- if (!SANE_DEPTH(img->pixel_depth)) return TGAERR_PIXEL_DEPTH;
- bpp = (size_t)(img->pixel_depth / 8); /* bytes per pixel */
- line = bpp * img->width; /* bytes per line */
-
- for (col=0; colwidth; col++)
- {
- top = img->image_data + col * bpp;
- bottom = top + (img->height - 1) * line;
-
- /* reverse from top to bottom */
- while (top < bottom)
- {
- uint8_t buffer[4];
-
- /* swap */
- memcpy(buffer, top, bpp);
- memcpy(top, bottom, bpp);
- memcpy(bottom, buffer, bpp);
-
- top += line;
- bottom -= line;
- }
- }
-
- /* Correct image_descriptor's top-to-bottom-ness. */
- t_to_b = tga_is_top_to_bottom(img);
- img->image_descriptor &= ~TGA_T_TO_B_BIT; /* mask out t-to-b bit */
- if (!t_to_b)
+ uint16_t col;
+ size_t bpp, line;
+ uint8_t *top, *bottom;
+ int t_to_b;
+
+ if (!SANE_DEPTH(img->pixel_depth)) return TGAERR_PIXEL_DEPTH;
+ bpp = (size_t)(img->pixel_depth / 8); /* bytes per pixel */
+ line = bpp * img->width; /* bytes per line */
+
+ for (col=0; colwidth; col++)
+ {
+ top = img->image_data + col * bpp;
+ bottom = top + (img->height - 1) * line;
+
+ /* reverse from top to bottom */
+ while (top < bottom)
+ {
+ uint8_t buffer[4];
+
+ /* swap */
+ memcpy(buffer, top, bpp);
+ memcpy(top, bottom, bpp);
+ memcpy(bottom, buffer, bpp);
+
+ top += line;
+ bottom -= line;
+ }
+ }
+
+ /* Correct image_descriptor's top-to-bottom-ness. */
+ t_to_b = tga_is_top_to_bottom(img);
+ img->image_descriptor &= ~TGA_T_TO_B_BIT; /* mask out t-to-b bit */
+ if (!t_to_b)
/* was b-to-t, need to set t_to_b */
- img->image_descriptor |= TGA_T_TO_B_BIT;
- /* else bit is already rubbed out */
-
- return TGA_NOERR;
+ img->image_descriptor |= TGA_T_TO_B_BIT;
+ /* else bit is already rubbed out */
+
+ return TGA_NOERR;
}
@@ -931,41 +931,41 @@ tga_result tga_flip_vert(tga_image *img)
*/
tga_result tga_color_unmap(tga_image *img)
{
- uint8_t bpp = img->color_map_depth / 8; /* bytes per pixel */
- int pos;
- void *tmp;
-
- if (!tga_is_colormapped(img)) return TGAERR_NOT_CMAP;
- if (img->pixel_depth != 8) return TGAERR_PIXEL_DEPTH;
- if (!SANE_DEPTH(img->color_map_depth)) return TGAERR_CMAP_DEPTH;
-
- tmp = realloc(img->image_data, img->width * img->height * bpp);
- if (tmp == NULL) return TGAERR_NO_MEM;
- img->image_data = (uint8_t*) tmp;
-
- for (pos = img->width * img->height - 1; pos >= 0; pos--)
- {
- uint8_t c_index = img->image_data[pos];
- uint8_t *c_bgr = img->color_map_data + (c_index * bpp);
-
- if (c_index >= img->color_map_origin + img->color_map_length)
- return TGAERR_INDEX_RANGE;
-
- memcpy(img->image_data + (pos*bpp), c_bgr, (size_t)bpp);
- }
-
- /* clean up */
- img->image_type = TGA_IMAGE_TYPE_BGR;
- img->pixel_depth = img->color_map_depth;
-
- free(img->color_map_data);
- img->color_map_data = NULL;
- img->color_map_type = TGA_COLOR_MAP_ABSENT;
- img->color_map_origin = 0;
- img->color_map_length = 0;
- img->color_map_depth = 0;
-
- return TGA_NOERR;
+ uint8_t bpp = img->color_map_depth / 8; /* bytes per pixel */
+ int pos;
+ void *tmp;
+
+ if (!tga_is_colormapped(img)) return TGAERR_NOT_CMAP;
+ if (img->pixel_depth != 8) return TGAERR_PIXEL_DEPTH;
+ if (!SANE_DEPTH(img->color_map_depth)) return TGAERR_CMAP_DEPTH;
+
+ tmp = realloc(img->image_data, img->width * img->height * bpp);
+ if (tmp == NULL) return TGAERR_NO_MEM;
+ img->image_data = (uint8_t*) tmp;
+
+ for (pos = img->width * img->height - 1; pos >= 0; pos--)
+ {
+ uint8_t c_index = img->image_data[pos];
+ uint8_t *c_bgr = img->color_map_data + (c_index * bpp);
+
+ if (c_index >= img->color_map_origin + img->color_map_length)
+ return TGAERR_INDEX_RANGE;
+
+ memcpy(img->image_data + (pos*bpp), c_bgr, (size_t)bpp);
+ }
+
+ /* clean up */
+ img->image_type = TGA_IMAGE_TYPE_BGR;
+ img->pixel_depth = img->color_map_depth;
+
+ free(img->color_map_data);
+ img->color_map_data = NULL;
+ img->color_map_type = TGA_COLOR_MAP_ABSENT;
+ img->color_map_origin = 0;
+ img->color_map_length = 0;
+ img->color_map_depth = 0;
+
+ return TGA_NOERR;
}
@@ -976,12 +976,12 @@ tga_result tga_color_unmap(tga_image *img)
*/
uint8_t *tga_find_pixel(const tga_image *img, uint16_t x, uint16_t y)
{
- if (x >= img->width || y >= img->height)
- return NULL;
-
- if (!tga_is_top_to_bottom(img)) y = img->height - 1 - y;
- if (tga_is_right_to_left(img)) x = img->width - 1 - x;
- return img->image_data + (x + y * img->width) * img->pixel_depth/8;
+ if (x >= img->width || y >= img->height)
+ return NULL;
+
+ if (!tga_is_top_to_bottom(img)) y = img->height - 1 - y;
+ if (tga_is_right_to_left(img)) x = img->width - 1 - x;
+ return img->image_data + (x + y * img->width) * img->pixel_depth/8;
}
@@ -994,46 +994,46 @@ uint8_t *tga_find_pixel(const tga_image *img, uint16_t x, uint16_t y)
tga_result tga_unpack_pixel(const uint8_t *src, const uint8_t bits,
uint8_t *b, uint8_t *g, uint8_t *r, uint8_t *a)
{
- switch (bits)
- {
+ switch (bits)
+ {
case 32:
if (b) *b = src[0];
if (g) *g = src[1];
if (r) *r = src[2];
if (a) *a = src[3];
break;
-
+
case 24:
if (b) *b = src[0];
if (g) *g = src[1];
if (r) *r = src[2];
if (a) *a = 0;
break;
-
+
case 16:
- {
- uint16_t src16 = (uint16_t)(src[1] << 8) | (uint16_t)src[0];
-
+ {
+ uint16_t src16 = (uint16_t)(src[1] << 8) | (uint16_t)src[0];
+
#define FIVE_BITS (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4))
- if (b) *b = ((src16 ) & FIVE_BITS) << 3;
- if (g) *g = ((src16 >> 5) & FIVE_BITS) << 3;
- if (r) *r = ((src16 >> 10) & FIVE_BITS) << 3;
- if (a) *a = (uint8_t)( (src16 & BIT(15)) ? 255 : 0 );
+ if (b) *b = ((src16 ) & FIVE_BITS) << 3;
+ if (g) *g = ((src16 >> 5) & FIVE_BITS) << 3;
+ if (r) *r = ((src16 >> 10) & FIVE_BITS) << 3;
+ if (a) *a = (uint8_t)( (src16 & BIT(15)) ? 255 : 0 );
#undef FIVE_BITS
- break;
- }
-
+ break;
+ }
+
case 8:
if (b) *b = *src;
if (g) *g = *src;
if (r) *r = *src;
if (a) *a = 0;
break;
-
+
default:
return TGAERR_PIXEL_DEPTH;
- }
- return TGA_NOERR;
+ }
+ return TGA_NOERR;
}
@@ -1045,41 +1045,41 @@ tga_result tga_unpack_pixel(const uint8_t *src, const uint8_t bits,
tga_result tga_pack_pixel(uint8_t *dest, const uint8_t bits,
const uint8_t b, const uint8_t g, const uint8_t r, const uint8_t a)
{
- switch (bits)
- {
+ switch (bits)
+ {
case 32:
dest[0] = b;
dest[1] = g;
dest[2] = r;
dest[3] = a;
break;
-
+
case 24:
dest[0] = b;
dest[1] = g;
dest[2] = r;
break;
-
+
case 16:
- {
- uint16_t tmp;
-
+ {
+ uint16_t tmp;
+
#define FIVE_BITS (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4))
- tmp = (b >> 3) & FIVE_BITS;
- tmp |= ((g >> 3) & FIVE_BITS) << 5;
- tmp |= ((r >> 3) & FIVE_BITS) << 10;
- if (a > 127) tmp |= BIT(15);
+ tmp = (b >> 3) & FIVE_BITS;
+ tmp |= ((g >> 3) & FIVE_BITS) << 5;
+ tmp |= ((r >> 3) & FIVE_BITS) << 10;
+ if (a > 127) tmp |= BIT(15);
#undef FIVE_BITS
-
- dest[0] = (uint8_t) (tmp & 0x00FF);
- dest[1] = (uint8_t)((tmp & 0xFF00) >> 8);
- break;
- }
-
+
+ dest[0] = (uint8_t) (tmp & 0x00FF);
+ dest[1] = (uint8_t)((tmp & 0xFF00) >> 8);
+ break;
+ }
+
default:
return TGAERR_PIXEL_DEPTH;
- }
- return TGA_NOERR;
+ }
+ return TGA_NOERR;
}
@@ -1091,59 +1091,59 @@ tga_result tga_pack_pixel(uint8_t *dest, const uint8_t bits,
tga_result tga_desaturate(tga_image *img, const int cr, const int cg,
const int cb, const int dv)
{
- uint8_t bpp = img->pixel_depth / 8; /* bytes per pixel */
- uint8_t *dest, *src, *tmp;
-
- if (tga_is_mono(img)) return TGAERR_MONO;
- if (tga_is_colormapped(img))
- {
- tga_result result = tga_color_unmap(img);
- if (result != TGA_NOERR) return result;
- }
- if (!UNMAP_DEPTH(img->pixel_depth)) return TGAERR_PIXEL_DEPTH;
-
- dest = img->image_data;
- for (src = img->image_data;
- src < img->image_data + img->width*img->height*bpp;
- src += bpp)
- {
- uint8_t b, g, r;
- (void)tga_unpack_pixel(src, img->pixel_depth, &b, &g, &r, NULL);
-
- *dest = (uint8_t)( ( (int)b * cb +
+ uint8_t bpp = img->pixel_depth / 8; /* bytes per pixel */
+ uint8_t *dest, *src, *tmp;
+
+ if (tga_is_mono(img)) return TGAERR_MONO;
+ if (tga_is_colormapped(img))
+ {
+ tga_result result = tga_color_unmap(img);
+ if (result != TGA_NOERR) return result;
+ }
+ if (!UNMAP_DEPTH(img->pixel_depth)) return TGAERR_PIXEL_DEPTH;
+
+ dest = img->image_data;
+ for (src = img->image_data;
+ src < img->image_data + img->width*img->height*bpp;
+ src += bpp)
+ {
+ uint8_t b, g, r;
+ (void)tga_unpack_pixel(src, img->pixel_depth, &b, &g, &r, NULL);
+
+ *dest = (uint8_t)( ( (int)b * cb +
(int)g * cg +
(int)r * cr ) / dv );
- dest++;
- }
-
- /* shrink */
- tmp = (uint8_t *)realloc(img->image_data, img->width * img->height);
- if (tmp == NULL) return TGAERR_NO_MEM;
- img->image_data = tmp;
-
- img->pixel_depth = 8;
- img->image_type = TGA_IMAGE_TYPE_MONO;
- return TGA_NOERR;
+ dest++;
+ }
+
+ /* shrink */
+ tmp = (uint8_t *)realloc(img->image_data, img->width * img->height);
+ if (tmp == NULL) return TGAERR_NO_MEM;
+ img->image_data = tmp;
+
+ img->pixel_depth = 8;
+ img->image_type = TGA_IMAGE_TYPE_MONO;
+ return TGA_NOERR;
}
tga_result tga_desaturate_rec_601_1(tga_image *img)
{
- return tga_desaturate(img, 2989, 5866, 1145, 10000);
+ return tga_desaturate(img, 2989, 5866, 1145, 10000);
}
tga_result tga_desaturate_rec_709(tga_image *img)
{
- return tga_desaturate(img, 2126, 7152, 722, 10000);
+ return tga_desaturate(img, 2126, 7152, 722, 10000);
}
tga_result tga_desaturate_itu(tga_image *img)
{
- return tga_desaturate(img, 2220, 7067, 713, 10000);
+ return tga_desaturate(img, 2220, 7067, 713, 10000);
}
tga_result tga_desaturate_avg(tga_image *img)
{
- return tga_desaturate(img, 1,1,1, 3);
+ return tga_desaturate(img, 1,1,1, 3);
}
@@ -1154,72 +1154,72 @@ tga_result tga_desaturate_avg(tga_image *img)
*/
tga_result tga_convert_depth(tga_image *img, const uint8_t bits)
{
- size_t src_size, dest_size;
- uint8_t src_bpp, dest_bpp;
- uint8_t *src, *dest;
-
- if (!UNMAP_DEPTH(bits) ||
- !SANE_DEPTH(img->pixel_depth)
+ size_t src_size, dest_size;
+ uint8_t src_bpp, dest_bpp;
+ uint8_t *src, *dest;
+
+ if (!UNMAP_DEPTH(bits) ||
+ !SANE_DEPTH(img->pixel_depth)
) return TGAERR_PIXEL_DEPTH;
-
- if (tga_is_colormapped(img))
- {
- tga_result result = tga_color_unmap(img);
- if (result != TGA_NOERR) return result;
- }
-
- if (img->pixel_depth == bits) return TGA_NOERR; /* no op, no err */
-
- src_bpp = img->pixel_depth / 8;
- dest_bpp = bits / 8;
-
- src_size = (size_t)( img->width * img->height * src_bpp );
- dest_size = (size_t)( img->width * img->height * dest_bpp );
-
- if (src_size > dest_size)
- {
- void *tmp;
-
- /* convert forwards */
- dest = img->image_data;
- for (src = img->image_data;
- src < img->image_data + img->width * img->height * src_bpp;
- src += src_bpp)
- {
- uint8_t r,g,b,a;
- (void)tga_unpack_pixel(src, img->pixel_depth, &r, &g, &b, &a);
- (void)tga_pack_pixel(dest, bits, r, g, b, a);
- dest += dest_bpp;
- }
-
- /* shrink */
- tmp = realloc(img->image_data, img->width * img->height * dest_bpp);
- if (tmp == NULL) return TGAERR_NO_MEM;
- img->image_data = (unsigned char *)tmp;
- }
- else
- {
- /* expand */
- void *tmp = realloc(img->image_data,
+
+ if (tga_is_colormapped(img))
+ {
+ tga_result result = tga_color_unmap(img);
+ if (result != TGA_NOERR) return result;
+ }
+
+ if (img->pixel_depth == bits) return TGA_NOERR; /* no op, no err */
+
+ src_bpp = img->pixel_depth / 8;
+ dest_bpp = bits / 8;
+
+ src_size = (size_t)( img->width * img->height * src_bpp );
+ dest_size = (size_t)( img->width * img->height * dest_bpp );
+
+ if (src_size > dest_size)
+ {
+ void *tmp;
+
+ /* convert forwards */
+ dest = img->image_data;
+ for (src = img->image_data;
+ src < img->image_data + img->width * img->height * src_bpp;
+ src += src_bpp)
+ {
+ uint8_t r,g,b,a;
+ (void)tga_unpack_pixel(src, img->pixel_depth, &r, &g, &b, &a);
+ (void)tga_pack_pixel(dest, bits, r, g, b, a);
+ dest += dest_bpp;
+ }
+
+ /* shrink */
+ tmp = realloc(img->image_data, img->width * img->height * dest_bpp);
+ if (tmp == NULL) return TGAERR_NO_MEM;
+ img->image_data = (unsigned char *)tmp;
+ }
+ else
+ {
+ /* expand */
+ void *tmp = realloc(img->image_data,
img->width * img->height * dest_bpp);
- if (tmp == NULL) return TGAERR_NO_MEM;
- img->image_data = (uint8_t*) tmp;
-
- /* convert backwards */
- dest = img->image_data + (img->width*img->height - 1) * dest_bpp;
- for (src = img->image_data + (img->width*img->height - 1) * src_bpp;
- src >= img->image_data;
- src -= src_bpp)
- {
- uint8_t r,g,b,a;
- (void)tga_unpack_pixel(src, img->pixel_depth, &r, &g, &b, &a);
- (void)tga_pack_pixel(dest, bits, r, g, b, a);
- dest -= dest_bpp;
- }
- }
-
- img->pixel_depth = bits;
- return TGA_NOERR;
+ if (tmp == NULL) return TGAERR_NO_MEM;
+ img->image_data = (uint8_t*) tmp;
+
+ /* convert backwards */
+ dest = img->image_data + (img->width*img->height - 1) * dest_bpp;
+ for (src = img->image_data + (img->width*img->height - 1) * src_bpp;
+ src >= img->image_data;
+ src -= src_bpp)
+ {
+ uint8_t r,g,b,a;
+ (void)tga_unpack_pixel(src, img->pixel_depth, &r, &g, &b, &a);
+ (void)tga_pack_pixel(dest, bits, r, g, b, a);
+ dest -= dest_bpp;
+ }
+ }
+
+ img->pixel_depth = bits;
+ return TGA_NOERR;
}
@@ -1229,20 +1229,20 @@ tga_result tga_convert_depth(tga_image *img, const uint8_t bits)
*/
tga_result tga_swap_red_blue(tga_image *img)
{
- uint8_t *ptr;
- uint8_t bpp = img->pixel_depth / 8;
-
- if (!UNMAP_DEPTH(img->pixel_depth)) return TGAERR_PIXEL_DEPTH;
-
- for (ptr = img->image_data;
- ptr < img->image_data + (img->width * img->height - 1) * bpp;
- ptr += bpp)
- {
- uint8_t r,g,b,a;
- (void)tga_unpack_pixel(ptr, img->pixel_depth, &b,&g,&r,&a);
- (void)tga_pack_pixel(ptr, img->pixel_depth, r,g,b,a);
- }
- return TGA_NOERR;
+ uint8_t *ptr;
+ uint8_t bpp = img->pixel_depth / 8;
+
+ if (!UNMAP_DEPTH(img->pixel_depth)) return TGAERR_PIXEL_DEPTH;
+
+ for (ptr = img->image_data;
+ ptr < img->image_data + (img->width * img->height - 1) * bpp;
+ ptr += bpp)
+ {
+ uint8_t r,g,b,a;
+ (void)tga_unpack_pixel(ptr, img->pixel_depth, &b,&g,&r,&a);
+ (void)tga_pack_pixel(ptr, img->pixel_depth, r,g,b,a);
+ }
+ return TGA_NOERR;
}
@@ -1253,21 +1253,21 @@ tga_result tga_swap_red_blue(tga_image *img)
*/
void tga_free_buffers(tga_image *img)
{
- if (img->image_id != NULL)
- {
- free(img->image_id);
- img->image_id = NULL;
- }
- if (img->color_map_data != NULL)
- {
- free(img->color_map_data);
- img->color_map_data = NULL;
- }
- if (img->image_data != NULL)
- {
- free(img->image_data);
- img->image_data = NULL;
- }
+ if (img->image_id != NULL)
+ {
+ free(img->image_id);
+ img->image_id = NULL;
+ }
+ if (img->color_map_data != NULL)
+ {
+ free(img->color_map_data);
+ img->color_map_data = NULL;
+ }
+ if (img->image_data != NULL)
+ {
+ free(img->image_data);
+ img->image_data = NULL;
+ }
}
/*
@@ -1283,24 +1283,24 @@ namespace spades {
virtual bool CanSave(){
return true;
}
-
+
virtual bool CheckExtension(const std::string& filename){
return EndsWith(filename, ".tga");
}
-
+
virtual std::string GetName(){
static std::string name("dmr.ath.cx Targa Exporter");
return name;
}
-
+
virtual Bitmap *Load(IStream *str){
SPADES_MARK_FUNCTION();
-
+
SPNotImplemented();
}
virtual void Save(IStream *stream, Bitmap *bmp){
SPADES_MARK_FUNCTION();
-
+
tga_image img;
std::vector data;
data.resize(bmp->GetWidth() * bmp->GetHeight() * 4);
@@ -1313,18 +1313,18 @@ namespace spades {
(void)tga_swap_red_blue(&img);
//(void)tga_flip_vert(&img);
img.image_descriptor ^= TGA_T_TO_B_BIT;
-
+
tga_result result;
result = tga_write_to_FILE(stream, &img);
-
+
if(result != TGA_NOERR){
SPRaise("Targa exporter library failure: %s", tga_error(result));
}
}
};
-
+
static TargaWriter sharedCodec;
-
+
}
*/
@@ -1333,7 +1333,7 @@ class Bitmap {
std::vector pixels;
int w, h;
public:
-
+
Bitmap(int w=0, int h=0):
w(w), h(h){
pixels.resize(w * h);
@@ -1422,7 +1422,7 @@ public:
}
assert(maxY >= 0);
outBitmap.Resize(maxX - minX + 1, maxY - minY + 1);
-
+
int nw = maxX - minX + 1;
int nh = maxY - minY + 1;
for(int x = 0; x < nw; x++) {
@@ -1430,7 +1430,7 @@ public:
outBitmap(x, y) = (*this)(x + minX, y + minY);
}
}
-
+
srcX = minX;
srcY = minY;
}
@@ -1445,21 +1445,21 @@ public:
Item() = default;
Item(const IndexType& idx, int w, int h):
index(idx), w(w), h(h) {
-
+
}
};
private:
std::unordered_map items;
-
+
public:
AtlasBuilder() {
-
+
}
-
+
~AtlasBuilder() {}
AtlasBuilder(const AtlasBuilder&) = delete;
AtlasBuilder& operator =(const AtlasBuilder&) = delete;
-
+
bool TryPack(int binWidth, int binHeight) {
int shelfTop = 0, shelfHeight = 0;
int shelfRight = 0;
@@ -1486,11 +1486,11 @@ public:
}
return true;
}
-
+
void AddItem(const IndexType& index, int w, int h) {
items[index] = Item(index, w, h);
}
-
+
const Item& GetItem(const IndexType& index) const {
return items.find(index)->second;
}
@@ -1505,7 +1505,7 @@ public:
#include
class JISDecoder: public CharsetDecoder {
-
+
iconv_t cd;
public:
JISDecoder() {
@@ -1516,7 +1516,7 @@ public:
}
virtual char32_t Decode(const std::string& str) {
int index = std::stoi(str.substr(2), 0, 16);
-
+
// non-standard JIS chars (called "機種依存文字")
// iconv won't convert them...
switch(index) {
@@ -1615,7 +1615,7 @@ public:
case 0x2d7d: break;
case 0x2d7e: break;
}
-
+
char inBuf[2] = {(char)(index+0x00), (char)((index >> 8)+0x00)};
std::swap(inBuf[0], inBuf[1]);
size_t inBufLen = 2;
@@ -1628,12 +1628,12 @@ public:
std::cerr << "failed to convert " << str << " (" << index << ") to Unicode (ignored)" << std::endl;
return 0;
}
-
+
int idx = outBuf[0];
idx += static_cast(outBuf[1]) << 8;
idx += static_cast(outBuf[2]) << 16;
idx += static_cast(outBuf[3]) << 24;
-
+
return static_cast(idx);
}
};
@@ -1825,18 +1825,18 @@ static std::vector Split(const std::string& str, const std::string&
}
int main(int argc, char **argv) {
-
+
if(argc <= 1){
std::cout << "BDF (JIS Code) to OpenSpades font converter" << std::endl;
std::cout << "USAGE: BdfToOSFont OUTFILE [FILTERS...] < BDFFONT.bdf" << std::endl;
return 0;
}
-
+
AtlasBuilder builder;
std::unordered_map glyphs;
-
+
std::unique_ptr decoder(static_cast(new JISDecoder));
-
+
bool applySoftFilter = false;
bool applyThickenFilter = false;
bool applyDoubleFilter = false;
@@ -1852,23 +1852,23 @@ int main(int argc, char **argv) {
applyDilationFilter = true;
}
}
-
+
char32_t currentChar = 0;
int dwidth;
int size = 16;
int bbxX = 0, bbxY = 0, bbxW = 16, bbxH = 16;
int scaling = applyDoubleFilter ? 2 : 1;
-
+
std::string lineBuffer;
while(!std::cin.eof()) {
std::getline(std::cin, lineBuffer);
-
+
auto firstPartIndex = lineBuffer.find(' ');
if(firstPartIndex == std::string::npos)
firstPartIndex = lineBuffer.size();
-
+
auto cmd = lineBuffer.substr(0, firstPartIndex);
-
+
if(cmd == "STARTCHAR") {
auto hexCode = lineBuffer.substr(firstPartIndex + 1);
if(hexCode.find("U+") == 0){
@@ -1902,11 +1902,11 @@ int main(int argc, char **argv) {
return 1;
}
std::getline(std::cin, lineBuffer);
-
+
if(lineBuffer == "ENDCHAR") {
break;
}
-
+
int len = lineBuffer.size();
int y = bmp2.GetHeight();
bmp2.Resize(std::max(bmp2.GetWidth(), len * 4), y + 1);
@@ -1920,12 +1920,12 @@ int main(int argc, char **argv) {
x += 4;
}
}
-
+
if(currentChar == 0) {
// no char code.
continue;
}
-
+
if(applyDoubleFilter){
ApplyDoubleFilter(bmp2);
dwidth *= 2;
@@ -1936,24 +1936,24 @@ int main(int argc, char **argv) {
ApplyDilationFilter(bmp2);
if(applySoftFilter)
ApplySoftFilter(bmp2);
-
+
int origHeight = bmp2.GetHeight();
-
+
int srcX, srcY;
bmp2.Trim(*bmp, srcX, srcY);
-
+
srcX += bbxX * scaling;
srcY += size - origHeight - bbxY;
-
+
Glyph g;
g.index = currentChar;
g.bitmap = bmp;
g.advance = dwidth;
g.x = srcX;
g.y = srcY;
-
+
glyphs[currentChar] = g;
-
+
if(bmp->GetWidth() == 0){
// empty
continue;
@@ -1961,9 +1961,9 @@ int main(int argc, char **argv) {
builder.AddItem(currentChar, bmp->GetWidth() + 2, bmp->GetHeight() + 2);
}
}
-
+
std::cerr << "packing" << std::endl;
-
+
int binWidth = 1, binHeight = 1;
while(!builder.TryPack(binWidth, binHeight)) {
if(binWidth == binHeight) {
@@ -1972,36 +1972,36 @@ int main(int argc, char **argv) {
binHeight <<= 1;
}
}
-
+
std::cerr << "Bin Size = " << binWidth << " x " << binHeight << std::endl;
-
+
{
Bitmap bin(binWidth, binHeight);
-
+
for(auto& it: glyphs) {
auto& item = it.second;
if(item.bitmap->GetWidth() == 0)
continue; // empty glyph
-
+
const auto& info = builder.GetItem(item.index);
//std::cerr <GetWidth()<<"x"<GetHeight()< rgba;
rgba.resize(binWidth * binHeight);
-
+
for(int x = 0; x < binWidth; x++)
for(int y = 0; y < binHeight; y++){
int alpha = bin(x, y);
rgba[x + y * binWidth] = (alpha << 24) | 0xffffff;
}
-
+
std::cerr << "saving" << std::endl;
-
+
tga_image img;
init_tga_image(&img, reinterpret_cast(rgba.data()),
binWidth, binHeight,
@@ -2010,32 +2010,32 @@ int main(int argc, char **argv) {
(void)tga_swap_red_blue(&img);
(void)tga_flip_vert(&img);
img.image_descriptor ^= TGA_T_TO_B_BIT;
-
+
tga_result result;
std::string tifPath = argv[1];
tifPath += ".tga";
std::ofstream ofs(tifPath);
result = tga_write_to_FILE(ofs, &img);
-
+
}
-
+
{
std::cerr << "writing descriptor" << std::endl;
std::string binPath = argv[1];
binPath += ".ospfont";
std::ofstream ofs(binPath);
-
+
ofs.write("OpenSpadesFontFl", 16);
-
+
uint32_t count = static_cast(glyphs.size());
static_assert(sizeof(count) == 4, "Oh no");
-
+
// write num of glyphs
ofs.write(reinterpret_cast(&count), 4);
-
+
// write font size
ofs.write(reinterpret_cast(&size), 4);
-
+
struct GlyphInfo {
uint32_t unicode;
uint16_t x, y;
@@ -2043,31 +2043,31 @@ int main(int argc, char **argv) {
uint16_t advance;
int16_t offX, offY;
};
-
+
std::vector infos;
-
+
for(auto& it: glyphs) {
auto& item = it.second;
-
+
if(item.bitmap->GetWidth() == 0) {
// empty glyph
GlyphInfo inf;
-
+
inf.unicode = static_cast(item.index);
inf.x = static_cast(0xffff);
inf.y = static_cast(0xffff);
inf.w = 0; inf.h = 0;
inf.offX = 0; inf.offY = 0;
inf.advance = static_cast(item.advance);
-
+
infos.push_back(inf);
continue;
}
-
+
const auto& info = builder.GetItem(item.index);
-
+
GlyphInfo inf;
-
+
inf.unicode = static_cast(item.index);
inf.x = static_cast(info.x);
inf.y = static_cast(info.y);
@@ -2076,10 +2076,10 @@ int main(int argc, char **argv) {
inf.offX = static_cast(item.x);
inf.offY = static_cast(item.y);
inf.advance = static_cast(item.advance);
-
+
infos.push_back(inf);
}
-
+
ofs.write(reinterpret_cast(infos.data()), sizeof(GlyphInfo) *
infos.size());
}