<commit_before>#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include <stdlib.h>
#include "packet.h"

#define BUFSIZE 121
#define FILENAME "Testfile"
#define TEST_FILENAME "Testfile2"
#define PORT 10038
#define PAKSIZE 128
#define ACK 0
#define NAK 1

using namespace std;

bool gremlin(Packet * pack, int corruptProb, int lossProb);
bool init(int argc, char** argv);
bool loadFile();
bool sendFile();
bool getFile();
char * recvPkt();
bool isvpack(unsigned char * p);
Packet createPacket(int index);
bool sendPacket();
bool isAck();
void handleAck();
void handleNak(int& x);

int seqNum;
int s;
int probCorrupt;
int probLoss;
string hs;
short int port;
char * file;
unsigned char* window[16]; //packet window
int windowBase; //used to determine position in window of arriving packets
int length;
struct sockaddr_in a;
struct sockaddr_in sa;
socklen_t salen;
string fstr;
bool dropPck;
Packet p;
int delayT;
unsigned char b[BUFSIZE];

int main(int argc, char** argv) {

  if(!init(argc, argv)) return -1;

  if(sendto(s, "GET Testfile", BUFSIZE + 7, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
    cout << "Package sending failed. (socket s, server address sa, message m)" << endl;
    return false;
  }

  getFile();

  return 0;
}

bool init(int argc, char** argv) {
  windowBase = 0; //initialize windowBase
  s = 0;

  hs = string("131.204.14.") + argv[1]; /* Needs to be updated? Might be a string like "tux175.engr.auburn.edu." */
  port = 10038; /* Can be any port within 10038-10041, inclusive. */

  char* delayTStr = argv[2];
  delayT = boost::lexical_cast<int>(delayTStr);

  /*if(!loadFile()) {
    cout << "Loading file failed. (filename FILENAME)" << endl;
    return false;
  }*/

  if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
    cout << "Socket creation failed. (socket s)" << endl;
    return false;
  }

  memset((char *)&a, 0, sizeof(a));
  a.sin_family = AF_INET;
  a.sin_addr.s_addr = htonl(INADDR_ANY); //why does this always give us 0?
  a.sin_port = htons(0);

  if (bind(s, (struct sockaddr *)&a, sizeof(a)) < 0){
    cout << "Socket binding failed. (socket s, address a)" << endl;
    return false;
  }

  memset((char *)&sa, 0, sizeof(sa));
  sa.sin_family = AF_INET;
  sa.sin_port = htons(port);
  inet_pton(AF_INET, hs.c_str(), &(sa.sin_addr));

  cout << endl;

  cout << "Server address (inet mode): " << inet_ntoa(sa.sin_addr) << endl;
  cout << "Port: " << ntohs(sa.sin_port) << endl;

  cout << endl << endl;

  /*fstr = string(file);

  cout << "File: " << endl << fstr << endl << endl;*/

  seqNum = 0;
  dropPck = false;
  return true;
}

bool loadFile() {

  ifstream is (FILENAME, ifstream::binary);

  if(is) {
    is.seekg(0, is.end);
    length = is.tellg();
    is.seekg(0, is.beg);

    file = new char[length];

    cout << "Reading " << length << " characters..." << endl;
    is.read(file, length);

    if(!is) { cout << "File reading failed. (filename " << FILENAME << "). Only " << is.gcount() << " could be read."; return false; }
    is.close();
  }
  return true;
}

bool sendFile() {

  for(int x = 0; x <= length / BUFSIZE; x++) {
    p = createPacket(x);
    if(!sendPacket()) continue;

    if(isAck()) {
      handleAck();
    } else {
      handleNak(x);
    }

    memset(b, 0, BUFSIZE);
  }
  return true;
}

Packet createPacket(int index){
    cout << endl;
    cout << "=== TRANSMISSION START" << endl;
    string mstr = fstr.substr(index * BUFSIZE, BUFSIZE);
    if(index * BUFSIZE + BUFSIZE > length) {
      mstr[length - (index * BUFSIZE)] = '\0';
    }
    return Packet (seqNum, mstr.c_str());
}

bool sendPacket(){
    int pc = probCorrupt; int pl = probLoss;
    if((dropPck = gremlin(&p, pc, pl)) == false){
      if(sendto(s, p.str(), BUFSIZE + 7, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
        cout << "Package sending failed. (socket s, server address sa, message m)" << endl;
        return false;
      }
      return true;
    } else return false;
}
bool isAck() {
    recvfrom(s, b, BUFSIZE + 7, 0, (struct sockaddr *)&sa, &salen);

    cout << endl << "=== SERVER RESPONSE TEST" << endl;
    cout << "Data: " << b << endl;
    if(b[6] == '0') return true;
    else return false;
}
void handleAck() {

}
void handleNak(int& x) {

      char * sns = new char[2];
      memcpy(sns, &b[0], 1);
      sns[1] = '\0';

      char * css = new char[5];
      memcpy(css, &b[1], 5);

      char * db = new char[BUFSIZE + 1];
      memcpy(db, &b[2], BUFSIZE);
      db[BUFSIZE] = '\0';

      cout << "Sequence number: " << sns << endl;
      cout << "Checksum: " << css << endl;

      Packet pk (0, db);
      pk.setSequenceNum(boost::lexical_cast<int>(sns));
      pk.setCheckSum(boost::lexical_cast<int>(css));

      if(!pk.chksm()) x--;
      else x = (x - 2 > 0) ? x - 2 : 0;
}

bool gremlin(Packet * pack, int corruptProb, int lossProb){
  bool dropPacket = false;
  int r = rand() % 100;

  cout << "Corruption probability: " << corruptProb << endl;
  cout << "Random number: " << r << endl;

  if(r <= (lossProb)){
    dropPacket = true;
    cout << "Dropped!" << endl;
  }
  else if(r <= (corruptProb)){
    cout << "Corrupted!" << endl;
    pack->loadDataBuffer((char*)"GREMLIN LOL");
  }
  else seqNum = (seqNum) ? false : true;
  cout << "Seq. num: " << pack->getSequenceNum() << endl;
  cout << "Checksum: " << pack->getCheckSum() << endl;
  cout << "Message: "  << pack->getDataBuffer() << endl;

  return dropPacket;
}

bool isvpack(unsigned char * p) {
  cout << endl << "=== IS VALID PACKET TESTING" << endl;

  char * sns = new char[2];
  memcpy(sns, &p[0], 1);
  sns[1] = '\0';

  char * css = new char[6];
  memcpy(css, &p[1], 6);
  css[5] = '\0';

  char * db = new char[121 + 1];
  memcpy(db, &p[7], 121);
  db[121] = '\0';

  cout << "Seq. num: " << sns << endl;
  cout << "Checksum: " << css << endl;
  cout << "Message: " << db << endl;

  int sn = boost::lexical_cast<int>(sns);
  int cs = boost::lexical_cast<int>(css);

  Packet pk (0, db);
  pk.setSequenceNum(sn);

  // change to validate based on checksum and sequence number

  if(sn == seqNum) return false;
  if(cs != pk.generateCheckSum()) return false;
  return true;
}

bool getFile(){
  /* Loop forever, waiting for messages from a client. */
  cout << "Waiting on port " << PORT << "..." << endl;

  ofstream file("Dumpfile");

  int rlen;
  int ack;

  for (;;) {
    unsigned char packet[PAKSIZE + 1];
    unsigned char dataPull[PAKSIZE - 7 + 1];
    rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&sa, &salen);

	/* Begin Window Loading */
	int tempSeqNum = boost::lexical_cast<int>(packet[0]);
	int properIndex = tempSeqNum - windowBase;

	window[properIndex] = packet;
	cout << "Packet loaded into window" << endl;
	char* tempTest = new char[6];
		memcpy(tempTest, &window[1], 0);
		tempTest[5] = '\0';

	cout << "The Checksum pulled from client window: " << tempTest[0] << endl;

	for(int x = 0; x < PAKSIZE - 7; x++) {
      dataPull[x] = packet[x + 7];
    }
    dataPull[PAKSIZE - 7] = '\0';
    packet[PAKSIZE] = '\0';
    if (rlen > 0) {
      char * css = new char[6];
      memcpy(css, &packet[1], 5);
      css[5] = '\0';
      cout << endl << endl << "=== RECEIPT" << endl;
      cout << "Seq. num: " << packet[0] << endl;
      cout << "Checksum: " << css << endl;
      cout << "Received message: " << dataPull << endl;
      if(isvpack(packet)) {
        ack = ACK;
		if(boost::lexical_cast<int>(packet[0]) == windowBase) windowBase++; //increment base of window //FIXME
        file << dataPull;
		file.flush();
      } else {
        ack = NAK;
      }
      cout << "Sent response: ";
      cout << ((ack == ACK) ? "ACK " : "NAK ") << windowBase << endl;

	  if(packet[6] == '1') usleep(delayT*1000);

      if(sendto(s, *windowBase, PAKSIZE, 0, (struct sockaddr *)&sa, salen) < 0) {
        cout << "Acknowledgement failed. (socket s, acknowledgement message ack, client address ca, client address length calen)" << endl;
        return 0;
      }
      delete css;
    }
  }
  file.close();
  return true;
}
<commit_msg>please work so close omg<commit_after>#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include <stdlib.h>
#include "packet.h"

#define BUFSIZE 121
#define FILENAME "Testfile"
#define TEST_FILENAME "Testfile2"
#define PORT 10038
#define PAKSIZE 128
#define ACK 0
#define NAK 1

using namespace std;

bool gremlin(Packet * pack, int corruptProb, int lossProb);
bool init(int argc, char** argv);
bool loadFile();
bool sendFile();
bool getFile();
char * recvPkt();
bool isvpack(unsigned char * p);
Packet createPacket(int index);
bool sendPacket();
bool isAck();
void handleAck();
void handleNak(int& x);

int seqNum;
int s;
int probCorrupt;
int probLoss;
string hs;
short int port;
char * file;
unsigned char* window[16]; //packet window
int windowBase; //used to determine position in window of arriving packets
int length;
struct sockaddr_in a;
struct sockaddr_in sa;
socklen_t salen;
string fstr;
bool dropPck;
Packet p;
int delayT;
unsigned char b[BUFSIZE];

int main(int argc, char** argv) {

  if(!init(argc, argv)) return -1;

  if(sendto(s, "GET Testfile", BUFSIZE + 7, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
    cout << "Package sending failed. (socket s, server address sa, message m)" << endl;
    return false;
  }

  getFile();

  return 0;
}

bool init(int argc, char** argv) {
  windowBase = 0; //initialize windowBase
  s = 0;

  hs = string("131.204.14.") + argv[1]; /* Needs to be updated? Might be a string like "tux175.engr.auburn.edu." */
  port = 10038; /* Can be any port within 10038-10041, inclusive. */

  char* delayTStr = argv[2];
  delayT = boost::lexical_cast<int>(delayTStr);

  /*if(!loadFile()) {
    cout << "Loading file failed. (filename FILENAME)" << endl;
    return false;
  }*/

  if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
    cout << "Socket creation failed. (socket s)" << endl;
    return false;
  }

  memset((char *)&a, 0, sizeof(a));
  a.sin_family = AF_INET;
  a.sin_addr.s_addr = htonl(INADDR_ANY); //why does this always give us 0?
  a.sin_port = htons(0);

  if (bind(s, (struct sockaddr *)&a, sizeof(a)) < 0){
    cout << "Socket binding failed. (socket s, address a)" << endl;
    return false;
  }

  memset((char *)&sa, 0, sizeof(sa));
  sa.sin_family = AF_INET;
  sa.sin_port = htons(port);
  inet_pton(AF_INET, hs.c_str(), &(sa.sin_addr));

  cout << endl;

  cout << "Server address (inet mode): " << inet_ntoa(sa.sin_addr) << endl;
  cout << "Port: " << ntohs(sa.sin_port) << endl;

  cout << endl << endl;

  /*fstr = string(file);

  cout << "File: " << endl << fstr << endl << endl;*/

  seqNum = 0;
  dropPck = false;
  return true;
}

bool loadFile() {

  ifstream is (FILENAME, ifstream::binary);

  if(is) {
    is.seekg(0, is.end);
    length = is.tellg();
    is.seekg(0, is.beg);

    file = new char[length];

    cout << "Reading " << length << " characters..." << endl;
    is.read(file, length);

    if(!is) { cout << "File reading failed. (filename " << FILENAME << "). Only " << is.gcount() << " could be read."; return false; }
    is.close();
  }
  return true;
}

bool sendFile() {

  for(int x = 0; x <= length / BUFSIZE; x++) {
    p = createPacket(x);
    if(!sendPacket()) continue;

    if(isAck()) {
      handleAck();
    } else {
      handleNak(x);
    }

    memset(b, 0, BUFSIZE);
  }
  return true;
}

Packet createPacket(int index){
    cout << endl;
    cout << "=== TRANSMISSION START" << endl;
    string mstr = fstr.substr(index * BUFSIZE, BUFSIZE);
    if(index * BUFSIZE + BUFSIZE > length) {
      mstr[length - (index * BUFSIZE)] = '\0';
    }
    return Packet (seqNum, mstr.c_str());
}

bool sendPacket(){
    int pc = probCorrupt; int pl = probLoss;
    if((dropPck = gremlin(&p, pc, pl)) == false){
      if(sendto(s, p.str(), BUFSIZE + 7, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
        cout << "Package sending failed. (socket s, server address sa, message m)" << endl;
        return false;
      }
      return true;
    } else return false;
}
bool isAck() {
    recvfrom(s, b, BUFSIZE + 7, 0, (struct sockaddr *)&sa, &salen);

    cout << endl << "=== SERVER RESPONSE TEST" << endl;
    cout << "Data: " << b << endl;
    if(b[6] == '0') return true;
    else return false;
}
void handleAck() {

}
void handleNak(int& x) {

      char * sns = new char[2];
      memcpy(sns, &b[0], 1);
      sns[1] = '\0';

      char * css = new char[5];
      memcpy(css, &b[1], 5);

      char * db = new char[BUFSIZE + 1];
      memcpy(db, &b[2], BUFSIZE);
      db[BUFSIZE] = '\0';

      cout << "Sequence number: " << sns << endl;
      cout << "Checksum: " << css << endl;

      Packet pk (0, db);
      pk.setSequenceNum(boost::lexical_cast<int>(sns));
      pk.setCheckSum(boost::lexical_cast<int>(css));

      if(!pk.chksm()) x--;
      else x = (x - 2 > 0) ? x - 2 : 0;
}

bool gremlin(Packet * pack, int corruptProb, int lossProb){
  bool dropPacket = false;
  int r = rand() % 100;

  cout << "Corruption probability: " << corruptProb << endl;
  cout << "Random number: " << r << endl;

  if(r <= (lossProb)){
    dropPacket = true;
    cout << "Dropped!" << endl;
  }
  else if(r <= (corruptProb)){
    cout << "Corrupted!" << endl;
    pack->loadDataBuffer((char*)"GREMLIN LOL");
  }
  else seqNum = (seqNum) ? false : true;
  cout << "Seq. num: " << pack->getSequenceNum() << endl;
  cout << "Checksum: " << pack->getCheckSum() << endl;
  cout << "Message: "  << pack->getDataBuffer() << endl;

  return dropPacket;
}

bool isvpack(unsigned char * p) {
  cout << endl << "=== IS VALID PACKET TESTING" << endl;

  char * sns = new char[2];
  memcpy(sns, &p[0], 1);
  sns[1] = '\0';

  char * css = new char[6];
  memcpy(css, &p[1], 6);
  css[5] = '\0';

  char * db = new char[121 + 1];
  memcpy(db, &p[7], 121);
  db[121] = '\0';

  cout << "Seq. num: " << sns << endl;
  cout << "Checksum: " << css << endl;
  cout << "Message: " << db << endl;

  int sn = boost::lexical_cast<int>(sns);
  int cs = boost::lexical_cast<int>(css);

  Packet pk (0, db);
  pk.setSequenceNum(sn);

  // change to validate based on checksum and sequence number

  if(sn == seqNum) return false;
  if(cs != pk.generateCheckSum()) return false;
  return true;
}

bool getFile(){
  /* Loop forever, waiting for messages from a client. */
  cout << "Waiting on port " << PORT << "..." << endl;

  ofstream file("Dumpfile");

  int rlen;
  int ack;

  for (;;) {
    unsigned char packet[PAKSIZE + 1];
    unsigned char dataPull[PAKSIZE - 7 + 1];
    rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&sa, &salen);

	/* Begin Window Loading */
	int tempSeqNum = boost::lexical_cast<int>(packet[0]);
	int properIndex = tempSeqNum - windowBase;

	window[properIndex] = packet;
	cout << "Packet loaded into window" << endl;
	char* tempTest = new char[6];
		memcpy(tempTest, &window[1], 0);
		tempTest[5] = '\0';

	cout << "The Checksum pulled from client window: " << tempTest[0] << endl;

	for(int x = 0; x < PAKSIZE - 7; x++) {
      dataPull[x] = packet[x + 7];
    }
    dataPull[PAKSIZE - 7] = '\0';
    packet[PAKSIZE] = '\0';
    if (rlen > 0) {
      char * css = new char[6];
      memcpy(css, &packet[1], 5);
      css[5] = '\0';
      cout << endl << endl << "=== RECEIPT" << endl;
      cout << "Seq. num: " << packet[0] << endl;
      cout << "Checksum: " << css << endl;
      cout << "Received message: " << dataPull << endl;
      if(isvpack(packet)) {
        ack = ACK;
		if(boost::lexical_cast<int>(packet[0]) == windowBase) windowBase++; //increment base of window //FIXME
        file << dataPull;
		file.flush();
      } else {
        ack = NAK;
      }
      cout << "Sent response: ";
      cout << ((ack == ACK) ? "ACK " : "NAK ") << windowBase << endl;

	  if(packet[6] == '1') usleep(delayT*1000);

	  string s = tostring(windowBase);
	  const char * ackval = s.c_str();

      if(sendto(s, *windowBase, PAKSIZE, 0, (struct sockaddr *)&sa, salen) < 0) {
        cout << "Acknowledgement failed. (socket s, acknowledgement message ack, client address ca, client address length calen)" << endl;
        return 0;
      }
      delete css;
    }
  }
  file.close();
  return true;
}
<|endoftext|>


<commit_before>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp

#include <NDK/Systems/VelocitySystem.hpp>
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/Components/PhysicsComponent.hpp>
#include <NDK/Components/VelocityComponent.hpp>

namespace Ndk
{
	VelocitySystem::VelocitySystem()
	{
		Requires<NodeComponent, VelocityComponent>();
		Excludes<PhysicsComponent>();
	}

	void VelocitySystem::OnUpdate(float elapsedTime)
	{
		for (const Ndk::EntityHandle& entity : GetEntities())
		{
			NodeComponent& node = entity->GetComponent<NodeComponent>();
			const VelocityComponent& velocity = entity->GetComponent<VelocityComponent>();

			node.Move(velocity.linearVelocity * elapsedTime);
		}
	}

	SystemIndex VelocitySystem::systemIndex;
}
<commit_msg>SDK/VelocitySystem: Make VelocitySystem move the node in the global space<commit_after>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp

#include <NDK/Systems/VelocitySystem.hpp>
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/Components/PhysicsComponent.hpp>
#include <NDK/Components/VelocityComponent.hpp>

namespace Ndk
{
	VelocitySystem::VelocitySystem()
	{
		Requires<NodeComponent, VelocityComponent>();
		Excludes<PhysicsComponent>();
	}

	void VelocitySystem::OnUpdate(float elapsedTime)
	{
		for (const Ndk::EntityHandle& entity : GetEntities())
		{
			NodeComponent& node = entity->GetComponent<NodeComponent>();
			const VelocityComponent& velocity = entity->GetComponent<VelocityComponent>();

			node.Move(velocity.linearVelocity * elapsedTime, Nz::CoordSys_Global);
		}
	}

	SystemIndex VelocitySystem::systemIndex;
}
<|endoftext|>


<commit_before>#include "DebugPanel.h"
#include <ui\IMGUI.h>

DebugPanel::DebugPanel() : _count(0) , _pos(10,710), _state(1) {
}

DebugPanel::~DebugPanel() {
}

void DebugPanel::reset() {
	_count = 0;
}

void DebugPanel::show(const char* name, float value) {
	if (_count + 1 < 32) {
		DebugEntry& entry = _entries[_count++];
		entry.name = name;
		entry.type = DebugEntry::DT_FLOAT;
		entry.values[0] = value;
	}
}

void DebugPanel::show(const char* name, int value) {
	if (_count + 1 < 32) {
		DebugEntry& entry = _entries[_count++];
		entry.name = name;
		entry.type = DebugEntry::DT_INT;
		entry.values[0] = value;
	}
}

void DebugPanel::show(const char* name, const v2& value) {
	if (_count + 1 < 32) {
		DebugEntry& entry = _entries[_count++];
		entry.name = name;
		entry.type = DebugEntry::DT_VEC2;
		entry.values[0] = value.x;
		entry.values[1] = value.y;
	}
}

void DebugPanel::render() {
	gui::start(1, &_pos);
	char buffer[128];
	if (gui::begin("Debug values", &_state)) {
		for (int i = 0; i < _count; ++i) {
			const DebugEntry& entry = _entries[i];
			switch (entry.type) {
				case DebugEntry::DT_FLOAT : sprintf_s(buffer, 128, "%s : %3.2f", entry.name, entry.values[0]); break;
				case DebugEntry::DT_VEC2: sprintf_s(buffer, 128, "%s : %3.2f , %3.2f", entry.name, entry.values[0], entry.values[1]); break;
				case DebugEntry::DT_INT: sprintf_s(buffer, 128, "%s : %d", entry.name, static_cast<int>(entry.values[0])); break;
			}
			gui::Label(2 + i, buffer);
		}
	}
	gui::end();
}<commit_msg>no more id used by IMGUI<commit_after>#include "DebugPanel.h"
#include <ui\IMGUI.h>

DebugPanel::DebugPanel() : _count(0) , _pos(10,710), _state(1) {
}

DebugPanel::~DebugPanel() {
}

void DebugPanel::reset() {
	_count = 0;
}

void DebugPanel::show(const char* name, float value) {
	if (_count + 1 < 32) {
		DebugEntry& entry = _entries[_count++];
		entry.name = name;
		entry.type = DebugEntry::DT_FLOAT;
		entry.values[0] = value;
	}
}

void DebugPanel::show(const char* name, int value) {
	if (_count + 1 < 32) {
		DebugEntry& entry = _entries[_count++];
		entry.name = name;
		entry.type = DebugEntry::DT_INT;
		entry.values[0] = value;
	}
}

void DebugPanel::show(const char* name, const v2& value) {
	if (_count + 1 < 32) {
		DebugEntry& entry = _entries[_count++];
		entry.name = name;
		entry.type = DebugEntry::DT_VEC2;
		entry.values[0] = value.x;
		entry.values[1] = value.y;
	}
}

void DebugPanel::render() {
	gui::start(1, &_pos);
	char buffer[128];
	if (gui::begin("Debug values", &_state)) {
		for (int i = 0; i < _count; ++i) {
			const DebugEntry& entry = _entries[i];
			switch (entry.type) {
				case DebugEntry::DT_FLOAT : sprintf_s(buffer, 128, "%s : %3.2f", entry.name, entry.values[0]); break;
				case DebugEntry::DT_VEC2: sprintf_s(buffer, 128, "%s : %3.2f , %3.2f", entry.name, entry.values[0], entry.values[1]); break;
				case DebugEntry::DT_INT: sprintf_s(buffer, 128, "%s : %d", entry.name, static_cast<int>(entry.values[0])); break;
			}
			gui::Label(buffer);
		}
	}
	gui::end();
}<|endoftext|>


<commit_before>#include "Flesh.h"

Flesh::Flesh(string skin, float x, float y, int cid, Fighter *cpartner) : Fighter(cid, x, cpartner){
	path = "flesh/" + skin + "/";

	sprite[IDLE] = Sprite(path + "idle.png", 8, 10);
	sprite[RUNNING] = Sprite(path + "running.png", 8, 10);
	sprite[JUMPING] = Sprite(path + "jumping.png", 6, 10);
	sprite[FALLING] = Sprite(path + "falling.png", 7, 10);
	sprite[CROUCH] = Sprite(path + "crouch.png", 6, 20);
	sprite[IDLE_ATK_NEUTRAL_1] = Sprite(path + "idle_atk_neutral.png", 12, 10);
	sprite[IDLE_ATK_NEUTRAL_2] = Sprite(path + "idle_atk_neutral.png", 12, 10);
	sprite[IDLE_ATK_NEUTRAL_3] = Sprite(path + "idle_atk_neutral.png", 12, 10);
	sprite[IDLE_ATK_FRONT] = Sprite(path + "idle_atk_front.png", 4, 10);
	sprite[JUMP_ATK_DOWN_FALLLOOP] = Sprite(path + "jump_atk_down_fallloop.png", 3, 10);
	sprite[JUMP_ATK_DOWN_DMG] = Sprite(path + "jump_atk_down_dmg.png", 3, 10);
	sprite[IDLE_ATK_DOWN] = Sprite(path + "idle_atk_down.png", 4, 10);

	crouching_size = Vector(84, 59);
	not_crouching_size = Vector(84, 84);

	tags["flesh"] = true;
	tags[skin] = true;
	box = Rectangle(x, y, 84, 84);
}

void Flesh::update_machine_state(float delta){
	switch(state){
		case FighterState::IDLE_ATK_NEUTRAL_1:
			if(sprite[state].is_finished()){
				check_idle();
				check_crouch();
				check_idle_atk_neutral_2();
			}else if(pressed[ATTACK_BUTTON]){
				combo++;
			}
		break;

		case FighterState::IDLE_ATK_NEUTRAL_2:
			if(sprite[state].is_finished()){
				check_idle();
				check_crouch();
				check_idle_atk_neutral_3();
			}else if(pressed[ATTACK_BUTTON]){
				combo++;
			}
		break;

		case FighterState::IDLE_ATK_NEUTRAL_3:
			if(sprite[state].is_finished()){
				check_idle();
				check_crouch();
			}
		break;

		case FighterState::IDLE_ATK_FRONT:
			if(sprite[state].is_finished()){
				check_idle();
				check_crouch();
			}
		break;

		case FighterState::JUMP_ATK_DOWN_FALLLOOP:
			speed.x = 3 * (orientation == LEFT ? -1 : 1);
			speed.y = 3;

			check_jump_atk_down_dmg();
			if(on_floor){
				printf("to no chao, parsa\n");
				speed.x = 0;
				speed.y = 0;
				check_idle();
				check_left();
				check_right();
			}
		break;

		case FighterState::JUMP_ATK_DOWN_DMG:
			if(sprite[state].is_finished()){
				check_idle();
				check_crouch();
			}
		break;

		case FighterState::IDLE_ATK_DOWN:
			if(sprite[state].is_finished()){
				check_idle();
				check_crouch();
			}
		break;

		case FighterState::IDLE:
			combo = 0;
			check_jump();
			check_left();
			check_right();
			check_idle_atk_down();
			check_crouch();
			check_fall();
			check_idle_atk_neutral_1();
			check_idle_atk_front();
		break;

		case FighterState::JUMPING:
			check_left(false);
			check_right(false);
			check_fall();
			check_jump_atk_down_fallloop();
			check_idle();
		break;

		case FighterState::FALLING:
			check_idle();
			check_left(false);
			check_right(false);
			check_fall();
			check_crouch();
			check_jump_atk_down_fallloop();
		break;

		case FighterState::RUNNING:
			check_jump();
			check_left(false);
			check_right(false);
			check_idle();
			check_crouch();
			check_idle_atk_neutral_1();
			check_idle_atk_front();
			check_fall();
		break;

		case FighterState::CROUCH:
			check_idle();
			check_fall();
		break;
	}
}

void Flesh::check_jump(bool change){
	if(pressed[JUMP_BUTTON]){
		if(change) temporary_state = FighterState::JUMPING;
		speed.y = -5;
		on_floor = false;
	}
}

void Flesh::check_fall(bool change){
	if(speed.y > 0){
		if(change) temporary_state = FighterState::FALLING;
	}
}

void Flesh::check_left(bool change){
	if(is_holding[LEFT_BUTTON]){
		if(change) temporary_state = FighterState::RUNNING;
		speed.x = -2;
		orientation = Orientation::LEFT;
	}
}

void Flesh::check_right(bool change){
	if(is_holding[RIGHT_BUTTON]){
		if(change) temporary_state = FighterState::RUNNING;
		speed.x = 2;
		orientation = Orientation::RIGHT;
	}
}

void Flesh::check_idle(bool change){
	if(speed.x == 0 and on_floor and not is_holding[DOWN_BUTTON]){
		if(change) temporary_state = FighterState::IDLE;
		printf("Temporary state = %d\n", temporary_state);
	}
}

void Flesh::check_crouch(bool change){
	if(is_holding[DOWN_BUTTON] and not is_holding[ATTACK_BUTTON] and on_floor){
   		if(change) temporary_state = FighterState::CROUCH;
    }
}

void Flesh::check_idle_atk_neutral_1(bool change){
	if(pressed[ATTACK_BUTTON] and not is_holding[DOWN_BUTTON]){
		if(change) temporary_state = FighterState::IDLE_ATK_NEUTRAL_1;
	}
}

void Flesh::check_idle_atk_neutral_2(bool change){
	printf("Pressing: %d\n", is_holding[ATTACK_BUTTON]);
	if(combo){
		combo--;
		if(change) temporary_state = FighterState::IDLE_ATK_NEUTRAL_2;
	}
}

void Flesh::check_idle_atk_neutral_3(bool change){
	if(combo){
		combo--;
		if(change) temporary_state = FighterState::IDLE_ATK_NEUTRAL_3;
	}
}

void Flesh::check_idle_atk_front(bool change){
	if(pressed[ATTACK_BUTTON] and (is_holding[LEFT_BUTTON] or is_holding[RIGHT_BUTTON])){
		if(change) temporary_state = FighterState::IDLE_ATK_FRONT;
		orientation = is_holding[LEFT_BUTTON] ? Orientation::LEFT : Orientation::RIGHT;
	}
}

void Flesh::check_jump_atk_down_fallloop(bool change){
	if(pressed[ATTACK_BUTTON] and is_holding[DOWN_BUTTON]){
		if(change) temporary_state = FighterState::JUMP_ATK_DOWN_FALLLOOP;
	}
}

void Flesh::check_jump_atk_down_dmg(bool change){
	if(grab){
		if(change) temporary_state = FighterState::JUMP_ATK_DOWN_DMG;
	}
}

void Flesh::check_idle_atk_down(bool change){
	if(is_holding[ATTACK_BUTTON] and is_holding[DOWN_BUTTON]){
		if(change) temporary_state = FighterState::IDLE_ATK_DOWN;
	}
}

void Flesh::check_pass_through_platform(bool change){

}

void Flesh::check_defense(bool change){

}

void Flesh::check_stunt(bool change){

}

void Flesh::check_dead(bool change){

}
<commit_msg>Fix fallloop bug<commit_after>#include "Flesh.h"

Flesh::Flesh(string skin, float x, float y, int cid, Fighter *cpartner) : Fighter(cid, x, cpartner){
	path = "flesh/" + skin + "/";

	sprite[IDLE] = Sprite(path + "idle.png", 8, 10);
	sprite[RUNNING] = Sprite(path + "running.png", 8, 10);
	sprite[JUMPING] = Sprite(path + "jumping.png", 6, 10);
	sprite[FALLING] = Sprite(path + "falling.png", 7, 10);
	sprite[CROUCH] = Sprite(path + "crouch.png", 6, 20);
	sprite[IDLE_ATK_NEUTRAL_1] = Sprite(path + "idle_atk_neutral.png", 12, 10);
	sprite[IDLE_ATK_NEUTRAL_2] = Sprite(path + "idle_atk_neutral.png", 12, 10);
	sprite[IDLE_ATK_NEUTRAL_3] = Sprite(path + "idle_atk_neutral.png", 12, 10);
	sprite[IDLE_ATK_FRONT] = Sprite(path + "idle_atk_front.png", 4, 10);
	sprite[JUMP_ATK_DOWN_FALLLOOP] = Sprite(path + "jump_atk_down_fallloop.png", 3, 10);
	sprite[JUMP_ATK_DOWN_DMG] = Sprite(path + "jump_atk_down_dmg.png", 3, 10);
	sprite[IDLE_ATK_DOWN] = Sprite(path + "idle_atk_down.png", 4, 10);

	crouching_size = Vector(84, 59);
	not_crouching_size = Vector(84, 84);

	tags["flesh"] = true;
	tags[skin] = true;
	box = Rectangle(x, y, 84, 84);
}

void Flesh::update_machine_state(float delta){
	switch(state){
		case FighterState::IDLE_ATK_NEUTRAL_1:
			if(sprite[state].is_finished()){
				check_idle();
				check_crouch();
				check_idle_atk_neutral_2();
			}else if(pressed[ATTACK_BUTTON]){
				combo++;
			}
		break;

		case FighterState::IDLE_ATK_NEUTRAL_2:
			if(sprite[state].is_finished()){
				check_idle();
				check_crouch();
				check_idle_atk_neutral_3();
			}else if(pressed[ATTACK_BUTTON]){
				combo++;
			}
		break;

		case FighterState::IDLE_ATK_NEUTRAL_3:
			if(sprite[state].is_finished()){
				check_idle();
				check_crouch();
			}
		break;

		case FighterState::IDLE_ATK_FRONT:
			if(sprite[state].is_finished()){
				check_idle();
				check_crouch();
			}
		break;

		case FighterState::JUMP_ATK_DOWN_FALLLOOP:
			speed.x = 3 * (orientation == LEFT ? -1 : 1);
			speed.y = 3;
			attack_damage = 1;
			attack_mask = (1 << 4) - 1;

			check_jump_atk_down_dmg();
			if(on_floor){
				printf("to no chao, parsa\n");
				speed.x = 0;
				speed.y = 0;
				check_idle();
				check_left();
				check_right();
				check_crouch();
			}
		break;

		case FighterState::JUMP_ATK_DOWN_DMG:
			if(sprite[state].is_finished()){
				check_idle();
				check_crouch();
			}
		break;

		case FighterState::IDLE_ATK_DOWN:
			if(sprite[state].is_finished()){
				check_idle();
				check_crouch();
			}
		break;

		case FighterState::IDLE:
			combo = 0;
			attack_mask = attack_damage = 0;
			check_jump();
			check_left();
			check_right();
			check_idle_atk_down();
			check_crouch();
			check_fall();
			check_idle_atk_neutral_1();
			check_idle_atk_front();
		break;

		case FighterState::JUMPING:
			check_left(false);
			check_right(false);
			check_fall();
			check_jump_atk_down_fallloop();
			check_idle();
		break;

		case FighterState::FALLING:
			check_idle();
			check_left(false);
			check_right(false);
			check_fall();
			check_crouch();
			check_jump_atk_down_fallloop();
		break;

		case FighterState::RUNNING:
			check_jump();
			check_left(false);
			check_right(false);
			check_idle();
			check_crouch();
			check_idle_atk_neutral_1();
			check_idle_atk_front();
			check_fall();
		break;

		case FighterState::CROUCH:
			check_idle();
			check_fall();
		break;
	}
}

void Flesh::check_jump(bool change){
	if(pressed[JUMP_BUTTON]){
		if(change) temporary_state = FighterState::JUMPING;
		speed.y = -5;
		on_floor = false;
	}
}

void Flesh::check_fall(bool change){
	if(speed.y > 0){
		if(change) temporary_state = FighterState::FALLING;
	}
}

void Flesh::check_left(bool change){
	if(is_holding[LEFT_BUTTON]){
		if(change) temporary_state = FighterState::RUNNING;
		speed.x = -2;
		orientation = Orientation::LEFT;
	}
}

void Flesh::check_right(bool change){
	if(is_holding[RIGHT_BUTTON]){
		if(change) temporary_state = FighterState::RUNNING;
		speed.x = 2;
		orientation = Orientation::RIGHT;
	}
}

void Flesh::check_idle(bool change){
	if(speed.x == 0 and on_floor and not is_holding[DOWN_BUTTON]){
		if(change) temporary_state = FighterState::IDLE;
		printf("Temporary state = %d\n", temporary_state);
	}
}

void Flesh::check_crouch(bool change){
	if(is_holding[DOWN_BUTTON] and on_floor){
   		if(change) temporary_state = FighterState::CROUCH;
    }
}

void Flesh::check_idle_atk_neutral_1(bool change){
	if(pressed[ATTACK_BUTTON] and not is_holding[DOWN_BUTTON]){
		if(change) temporary_state = FighterState::IDLE_ATK_NEUTRAL_1;
	}
}

void Flesh::check_idle_atk_neutral_2(bool change){
	printf("Pressing: %d\n", is_holding[ATTACK_BUTTON]);
	if(combo){
		combo--;
		if(change) temporary_state = FighterState::IDLE_ATK_NEUTRAL_2;
	}
}

void Flesh::check_idle_atk_neutral_3(bool change){
	if(combo){
		combo--;
		if(change) temporary_state = FighterState::IDLE_ATK_NEUTRAL_3;
	}
}

void Flesh::check_idle_atk_front(bool change){
	if(pressed[ATTACK_BUTTON] and (is_holding[LEFT_BUTTON] or is_holding[RIGHT_BUTTON])){
		if(change) temporary_state = FighterState::IDLE_ATK_FRONT;
		orientation = is_holding[LEFT_BUTTON] ? Orientation::LEFT : Orientation::RIGHT;
	}
}

void Flesh::check_jump_atk_down_fallloop(bool change){
	if(pressed[ATTACK_BUTTON] and is_holding[DOWN_BUTTON]){
		if(change) temporary_state = FighterState::JUMP_ATK_DOWN_FALLLOOP;
	}
}

void Flesh::check_jump_atk_down_dmg(bool change){
	if(grab){
		if(change) temporary_state = FighterState::JUMP_ATK_DOWN_DMG;
	}
}

void Flesh::check_idle_atk_down(bool change){
	if(is_holding[ATTACK_BUTTON] and is_holding[DOWN_BUTTON]){
		if(change) temporary_state = FighterState::IDLE_ATK_DOWN;
	}
}

void Flesh::check_pass_through_platform(bool change){

}

void Flesh::check_defense(bool change){

}

void Flesh::check_stunt(bool change){

}

void Flesh::check_dead(bool change){

}
<|endoftext|>


<commit_before>/*************************************************************************/
/*  texture_editor_plugin.cpp                                            */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "texture_editor_plugin.h"

#include "core/io/resource_loader.h"
#include "core/project_settings.h"
#include "editor/editor_settings.h"

void TextureEditor::_gui_input(Ref<InputEvent> p_event) {
}

void TextureEditor::_notification(int p_what) {

	if (p_what == NOTIFICATION_READY) {

		//get_scene()->connect("node_removed",this,"_node_removed");
	}

	if (p_what == NOTIFICATION_DRAW) {

		Ref<Texture2D> checkerboard = get_icon("Checkerboard", "EditorIcons");
		Size2 size = get_size();

		draw_texture_rect(checkerboard, Rect2(Point2(), size), true);

		int tex_width = texture->get_width() * size.height / texture->get_height();
		int tex_height = size.height;

		if (tex_width > size.width) {
			tex_width = size.width;
			tex_height = texture->get_height() * tex_width / texture->get_width();
		}

		// Prevent the texture from being unpreviewable after the rescale, so that we can still see something
		if (tex_height <= 0)
			tex_height = 1;
		if (tex_width <= 0)
			tex_width = 1;

		int ofs_x = (size.width - tex_width) / 2;
		int ofs_y = (size.height - tex_height) / 2;

		if (Object::cast_to<CurveTexture>(*texture)) {
			// In the case of CurveTextures we know they are 1 in height, so fill the preview to see the gradient
			ofs_y = 0;
			tex_height = size.height;
		} else if (Object::cast_to<GradientTexture>(*texture)) {
			ofs_y = size.height / 4.0;
			tex_height = size.height / 2.0;
		}

		draw_texture_rect(texture, Rect2(ofs_x, ofs_y, tex_width, tex_height));

		Ref<Font> font = get_font("font", "Label");

		String format;
		if (Object::cast_to<ImageTexture>(*texture)) {
			format = Image::get_format_name(Object::cast_to<ImageTexture>(*texture)->get_format());
		} else if (Object::cast_to<StreamTexture>(*texture)) {
			format = Image::get_format_name(Object::cast_to<StreamTexture>(*texture)->get_format());
		} else {
			format = texture->get_class();
		}
		String text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + " " + format;

		Size2 rect = font->get_string_size(text);

		Vector2 draw_from = size - rect + Size2(-2, font->get_ascent() - 2);
		if (draw_from.x < 0)
			draw_from.x = 0;

		draw_string(font, draw_from + Vector2(2, 2), text, Color(0, 0, 0, 0.5), size.width);
		draw_string(font, draw_from - Vector2(2, 2), text, Color(0, 0, 0, 0.5), size.width);
		draw_string(font, draw_from, text, Color(1, 1, 1, 1), size.width);
	}
}

void TextureEditor::_changed_callback(Object *p_changed, const char *p_prop) {

	if (!is_visible())
		return;
	update();
}

void TextureEditor::edit(Ref<Texture2D> p_texture) {

	if (!texture.is_null())
		texture->remove_change_receptor(this);

	texture = p_texture;

	if (!texture.is_null()) {
		texture->add_change_receptor(this);
		update();
	} else {
		hide();
	}
}

void TextureEditor::_bind_methods() {

	ClassDB::bind_method(D_METHOD("_gui_input"), &TextureEditor::_gui_input);
}

TextureEditor::TextureEditor() {

	set_custom_minimum_size(Size2(1, 150));
}

TextureEditor::~TextureEditor() {
	if (!texture.is_null()) {
		texture->remove_change_receptor(this);
	}
}
//
bool EditorInspectorPluginTexture::can_handle(Object *p_object) {

	return Object::cast_to<ImageTexture>(p_object) != NULL || Object::cast_to<AtlasTexture>(p_object) != NULL || Object::cast_to<StreamTexture>(p_object) != NULL || Object::cast_to<LargeTexture>(p_object) != NULL || Object::cast_to<AnimatedTexture>(p_object) != NULL;
}

void EditorInspectorPluginTexture::parse_begin(Object *p_object) {

	Texture2D *texture = Object::cast_to<Texture2D>(p_object);
	if (!texture) {
		return;
	}
	Ref<Texture2D> m(texture);

	TextureEditor *editor = memnew(TextureEditor);
	editor->edit(m);
	add_custom_control(editor);
}

TextureEditorPlugin::TextureEditorPlugin(EditorNode *p_node) {

	Ref<EditorInspectorPluginTexture> plugin;
	plugin.instance();
	add_inspector_plugin(plugin);
}
<commit_msg>[Vulkan] Add repeat flag to texture preview checkerboard background<commit_after>/*************************************************************************/
/*  texture_editor_plugin.cpp                                            */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "texture_editor_plugin.h"

#include "core/io/resource_loader.h"
#include "core/project_settings.h"
#include "editor/editor_settings.h"

void TextureEditor::_gui_input(Ref<InputEvent> p_event) {
}

void TextureEditor::_notification(int p_what) {

	if (p_what == NOTIFICATION_READY) {

		//get_scene()->connect("node_removed",this,"_node_removed");
	}

	if (p_what == NOTIFICATION_DRAW) {

		Ref<Texture2D> checkerboard = get_icon("Checkerboard", "EditorIcons");
		Size2 size = get_size();

		draw_texture_rect(checkerboard, Rect2(Point2(), size), true);

		int tex_width = texture->get_width() * size.height / texture->get_height();
		int tex_height = size.height;

		if (tex_width > size.width) {
			tex_width = size.width;
			tex_height = texture->get_height() * tex_width / texture->get_width();
		}

		// Prevent the texture from being unpreviewable after the rescale, so that we can still see something
		if (tex_height <= 0)
			tex_height = 1;
		if (tex_width <= 0)
			tex_width = 1;

		int ofs_x = (size.width - tex_width) / 2;
		int ofs_y = (size.height - tex_height) / 2;

		if (Object::cast_to<CurveTexture>(*texture)) {
			// In the case of CurveTextures we know they are 1 in height, so fill the preview to see the gradient
			ofs_y = 0;
			tex_height = size.height;
		} else if (Object::cast_to<GradientTexture>(*texture)) {
			ofs_y = size.height / 4.0;
			tex_height = size.height / 2.0;
		}

		draw_texture_rect(texture, Rect2(ofs_x, ofs_y, tex_width, tex_height));

		Ref<Font> font = get_font("font", "Label");

		String format;
		if (Object::cast_to<ImageTexture>(*texture)) {
			format = Image::get_format_name(Object::cast_to<ImageTexture>(*texture)->get_format());
		} else if (Object::cast_to<StreamTexture>(*texture)) {
			format = Image::get_format_name(Object::cast_to<StreamTexture>(*texture)->get_format());
		} else {
			format = texture->get_class();
		}
		String text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + " " + format;

		Size2 rect = font->get_string_size(text);

		Vector2 draw_from = size - rect + Size2(-2, font->get_ascent() - 2);
		if (draw_from.x < 0)
			draw_from.x = 0;

		draw_string(font, draw_from + Vector2(2, 2), text, Color(0, 0, 0, 0.5), size.width);
		draw_string(font, draw_from - Vector2(2, 2), text, Color(0, 0, 0, 0.5), size.width);
		draw_string(font, draw_from, text, Color(1, 1, 1, 1), size.width);
	}
}

void TextureEditor::_changed_callback(Object *p_changed, const char *p_prop) {

	if (!is_visible())
		return;
	update();
}

void TextureEditor::edit(Ref<Texture2D> p_texture) {

	if (!texture.is_null())
		texture->remove_change_receptor(this);

	texture = p_texture;

	if (!texture.is_null()) {
		texture->add_change_receptor(this);
		update();
	} else {
		hide();
	}
}

void TextureEditor::_bind_methods() {

	ClassDB::bind_method(D_METHOD("_gui_input"), &TextureEditor::_gui_input);
}

TextureEditor::TextureEditor() {

	set_texture_repeat(TextureRepeat::TEXTURE_REPEAT_ENABLED);
	set_custom_minimum_size(Size2(1, 150));
}

TextureEditor::~TextureEditor() {
	if (!texture.is_null()) {
		texture->remove_change_receptor(this);
	}
}
//
bool EditorInspectorPluginTexture::can_handle(Object *p_object) {

	return Object::cast_to<ImageTexture>(p_object) != NULL || Object::cast_to<AtlasTexture>(p_object) != NULL || Object::cast_to<StreamTexture>(p_object) != NULL || Object::cast_to<LargeTexture>(p_object) != NULL || Object::cast_to<AnimatedTexture>(p_object) != NULL;
}

void EditorInspectorPluginTexture::parse_begin(Object *p_object) {

	Texture2D *texture = Object::cast_to<Texture2D>(p_object);
	if (!texture) {
		return;
	}
	Ref<Texture2D> m(texture);

	TextureEditor *editor = memnew(TextureEditor);
	editor->edit(m);
	add_custom_control(editor);
}

TextureEditorPlugin::TextureEditorPlugin(EditorNode *p_node) {

	Ref<EditorInspectorPluginTexture> plugin;
	plugin.instance();
	add_inspector_plugin(plugin);
}
<|endoftext|>


<commit_before>// Solving a puzzle below
// https://twitter.com/CTak_S/status/1064819923195580417

#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <random>
#include <sstream>
#include <string>
#include <vector>
#include <boost/multi_array.hpp>

namespace {
    using Count = long long int;
    // Bitmap (1 to alive) of survivors 0..(N_PLAYERS-1)
    using State = unsigned int;
    using Index = int;
    using Survivors = std::vector<Index>;

    struct Action {
        Index player;
        State state;
        Index target;
    };
    using ActionChain = std::vector<Action>;

    // Rule of the game
    constexpr Index N_PLAYERS = 3;
    constexpr Index N_STATES = 1 << N_PLAYERS;  // 2^N_PLAYERS combinations
    constexpr Index N_ACTIONS = N_PLAYERS + 1;  // Shoot Player 0, ... (N_PLAYERS-1), or nobody
    constexpr Index N_WINNERS = N_PLAYERS;
    constexpr Index ALIVE = 1;
    const std::vector<double> HIT_RATE {0.3, 0.5, 1.0};

    // Hyper parameters
    constexpr double LEARNING_RATE = 0.001;
    constexpr double EXPLORATION_EPSILON = 0.1;
    constexpr bool IID_CHOICE = false;
    constexpr bool USE_SOFTMAX = false;  // I got unstable results with Softmax.
    constexpr Index MAX_DEPTH = 30;
    constexpr Count N_TRIALS = 10000000ll;
}

class OptimalAction {
public:
    OptimalAction(void) :
        rand_gen_(rand_dev_()), unit_distribution_(0.0, 1.0),
        value_(boost::extents[N_PLAYERS][N_STATES][N_ACTIONS]) {
        for (Index player = 0; player < N_PLAYERS; ++player) {
            for (Index state = 0; state < N_STATES; ++state) {
                for (Index action = 0; action < N_ACTIONS; ++action) {
                    // Do not shoot yourself!
                    auto count = checkAliveOrNobody(player, state);
                    value_[player][state][action] = count && checkAliveOrNobody(action, state) &&
                        (player != action) ? (1.0 / static_cast<double>(count)) : 0.0;
                }
            }
        }
        return;
    }

    virtual ~OptimalAction(void) = default;

    void Exec(Count n_trials) {
        for (Count i = 0; i < n_trials; ++i) {
            exec();
        }

        for (Index player = 0; player < N_PLAYERS; ++player) {
            std::cout << printValue(player);
        }
        return;
    }

    void exec(void) {
        Survivors survivors(N_PLAYERS, ALIVE);
        ActionChain actionChain;
        aimAndShoot(0, 0, survivors, actionChain);
        return;
    }

    char printIndexChar(Index player) {
        return player + 'A';
    }

    std::string printValue(Index player) {
        std::ostringstream os;

        os << std::setprecision(5) << "[States, actions and values for Player " << printIndexChar(player) << "]\n";
        for (Index state = 0; state < N_STATES; ++state) {
            // Exclude when the player is not alive or only alive
            if (checkPlayerAlive(player, state) < 2) {
                continue;
            }

            for (Index action = 0; action < N_ACTIONS; ++action) {
                if ((player != action) && checkPlayerAlive(action, state)) {
                    os << "Target " << printIndexChar(action) << ":" << value_[player][state][action] << ", ";
                }
                if (action >= N_PLAYERS) {
                    os << "Nobody:" << value_[player][state][action] << "\n" ;
                }
            }
        }

        os << "\n";
        return os.str();
    }

    // Converts an array to a bitmap
    State survivorsToState(const Survivors& survivors) {
        State state = 0;
        State index = 1;
        for(const auto value : survivors) {
            state += index * (value ? 1 : 0);
            index <<= 1;
        }
        return state;
    }

    // Notice that nobody is always not alive (population - player(1) + nobady(1))
    template<typename T>
    auto countPopulation(T state) {
        return __builtin_popcount(state);
    }

    // Return population of the state if the player is alive in the state, 0 othewise
    Index checkAliveOrNobody(Index player, State state) {
        return ((player >= N_PLAYERS) || (state & (1 << player))) ? countPopulation(state) : 0;
    }

    Index checkPlayerAlive(Index player, State state) {
        return (state & (1 << player)) ? countPopulation(state) : 0;
    }

    // Overwrites survivors
    void aimAndShoot(Index player, Index depth, Survivors& survivors, const ActionChain& actionChain) {
        if (depth >= MAX_DEPTH) {
            return;
        }

        const auto targets = getTargets(player, survivors);
        const auto state = survivorsToState(survivors);
        const auto target = getActionTarget(player, state, survivors, targets);

        ActionChain nextActionChain = actionChain;
        Action nextAction {player, state, target};
        nextActionChain.push_back(nextAction);
        shoot(player, survivors, target);

        if (std::accumulate(survivors.begin(), survivors.end(), 0) == 1) {
            const auto winner = std::distance(survivors.begin(),
                                              std::find(survivors.begin(), survivors.end(), ALIVE));

            // Pick up one sample to i.i.d.
            if (IID_CHOICE) {
                auto raw_index = unit_distribution_(rand_gen_) * static_cast<double>(nextActionChain.size()) - 0.5;
                auto index = std::min(nextActionChain.size() - 1,
                                      static_cast<decltype(nextActionChain.size())>(
                                          std::max(0, static_cast<int>(raw_index))));
                propagate(nextActionChain.at(index), winner);
            } else {
                // Reverse if you deduct rewards
                for(const auto& action : nextActionChain) {
                    propagate(action, winner);
                }
            }
        } else {
            aimAndShoot((player + 1) % N_PLAYERS, depth + 1, survivors, nextActionChain);
        }

        return;
    }

    std::vector<Index> getTargets(Index player, const Survivors& survivors) {
        std::vector<Index> targets;
        for(Index target = 0; target < N_PLAYERS; ++target) {
            if ((target != player) && survivors.at(target)) {
                targets.push_back(target);
            }
        }

        if (targets.size() > 1) {
            // Can shoot nobody
            targets.push_back(N_PLAYERS);
        }

        return targets;
    }

    std::vector<double> getProportions(Index player, State state) {
        // Number of targets = number of survivors - player(1) + nobody(1)
        std::vector<double> proportions(N_ACTIONS, 0.0);

        // Epsilon-greedy
        const auto rand_proportional = unit_distribution_(rand_gen_);
        const bool proportional = (rand_proportional < EXPLORATION_EPSILON);

        if (proportional) {
            // Number of targets = number of survivors - player(1) + nobody(1)
            const auto population = checkPlayerAlive(player, state);
            const double proportion = (population > 0) ? (1.0 / static_cast<double>(population)) : 0.0;
            for (Index action = 0; action < N_ACTIONS; ++action) {
                proportions.at(action) = (checkPlayerAlive(player, state) &&
                                          checkAliveOrNobody(action, state) &&
                                          (player != action)) ? proportion : 0.0;
            }
        } else {
            if (USE_SOFTMAX) {
                std::vector<double> exp_proportions(N_ACTIONS, 0.0);
                double sum = 0.0;
                for (Index action = 0; action < N_ACTIONS; ++action) {
                    const auto value = ::exp(value_[player][state][action]);
                    exp_proportions.at(action) = value;
                    sum += value;
                }

                for (Index action = 0; action < N_ACTIONS; ++action) {
                    proportions.at(action) = exp_proportions.at(action) / sum;
                }
            } else {
                for (Index action = 0; action < N_ACTIONS; ++action) {
                    proportions.at(action) = value_[player][state][action];
                }
            }
        }

        return proportions;
    }

    Index getActionTarget(Index player, State state, const Survivors& survivors, const std::vector<Index>& targets) {
        const auto proportions = getProportions(player, state);
        auto rand_value = unit_distribution_(rand_gen_);
        Index target = 0;

        while(rand_value >= 0.0) {
            rand_value -= proportions.at(target);
            target += 1;
            if (target >= N_ACTIONS) {
                break;
            }
        }

        return target - 1;
    }

    // Overwrites survivors
    void shoot(Index player, Survivors& survivors, Index target) {
        if (target < N_PLAYERS) {
            if (unit_distribution_(rand_gen_) < HIT_RATE.at(player)) {
                survivors.at(target) = 0;
            }
        }

        return;
    }

    void propagate(const Action& action, Index final_surviver) {
        // No deduction
        const auto target_value = value_[action.player][action.state][action.target];
        const auto delta = target_value * LEARNING_RATE * ((action.player == final_surviver) ? 1.0 : -1.0);
        value_[action.player][action.state][action.target] += delta;

        // Normalizes such that the sum of values is 1
        double sum = 0.0;
        for (Index i = 0; i < N_ACTIONS; ++i) {
            sum += value_[action.player][action.state][i];
        }
        for (Index i = 0; i < N_ACTIONS; ++i) {
            value_[action.player][action.state][i] /= sum;
        }
    }

private:
    using CountMatrix = boost::multi_array<Count, 4>;
    using StateActionValue = boost::multi_array<double, 3>;
    std::random_device rand_dev_;
    std::mt19937 rand_gen_;
    std::uniform_real_distribution<double> unit_distribution_;
    StateActionValue value_;
};

int main(int argc, char* argv[]) {
    OptimalAction optimalAction;

    Count n_trials = N_TRIALS;
    if (argc > 1) {
        n_trials = ::atoll(argv[1]);
    }
    optimalAction.Exec(n_trials);
    return 0;
}

/*
Local Variables:
mode: c++
coding: utf-8-dos
tab-width: nil
c-file-style: "stroustrup"
End:
*/
<commit_msg>Adjust the learning rate<commit_after>// Solving a puzzle below
// https://twitter.com/CTak_S/status/1064819923195580417

#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <random>
#include <sstream>
#include <string>
#include <vector>
#include <boost/multi_array.hpp>

namespace {
    using Count = long long int;
    // Bitmap (1 to alive) of survivors 0..(N_PLAYERS-1)
    using State = unsigned int;
    using Index = int;
    using Survivors = std::vector<Index>;

    struct Action {
        Index player;
        State state;
        Index target;
    };
    using ActionChain = std::vector<Action>;

    // Rule of the game
    constexpr Index N_PLAYERS = 3;
    constexpr Index N_STATES = 1 << N_PLAYERS;  // 2^N_PLAYERS combinations
    constexpr Index N_ACTIONS = N_PLAYERS + 1;  // Shoot Player 0, ... (N_PLAYERS-1), or nobody
    constexpr Index N_WINNERS = N_PLAYERS;
    constexpr Index ALIVE = 1;
    const std::vector<double> HIT_RATE {0.3, 0.5, 1.0};

    // Hyper parameters
    constexpr double LEARNING_RATE = 0.00001;
    constexpr double EXPLORATION_EPSILON = 0.1;
    constexpr bool IID_CHOICE = false;
    constexpr bool USE_SOFTMAX = false;  // I got unstable results with Softmax.
    constexpr Index MAX_DEPTH = 30;
    constexpr Count N_TRIALS = 10000000ll;
}

class OptimalAction {
public:
    OptimalAction(void) :
        rand_gen_(rand_dev_()), unit_distribution_(0.0, 1.0),
        value_(boost::extents[N_PLAYERS][N_STATES][N_ACTIONS]) {
        for (Index player = 0; player < N_PLAYERS; ++player) {
            for (Index state = 0; state < N_STATES; ++state) {
                for (Index action = 0; action < N_ACTIONS; ++action) {
                    // Do not shoot yourself!
                    auto count = checkAliveOrNobody(player, state);
                    value_[player][state][action] = count && checkAliveOrNobody(action, state) &&
                        (player != action) ? (1.0 / static_cast<double>(count)) : 0.0;
                }
            }
        }
        return;
    }

    virtual ~OptimalAction(void) = default;

    void Exec(Count n_trials) {
        for (Count i = 0; i < n_trials; ++i) {
            exec();
        }

        for (Index player = 0; player < N_PLAYERS; ++player) {
            std::cout << printValue(player);
        }
        return;
    }

    void exec(void) {
        Survivors survivors(N_PLAYERS, ALIVE);
        ActionChain actionChain;
        aimAndShoot(0, 0, survivors, actionChain);
        return;
    }

    char printIndexChar(Index player) {
        return player + 'A';
    }

    std::string printValue(Index player) {
        std::ostringstream os;

        os << std::setprecision(5) << "[States, actions and values for Player " << printIndexChar(player) << "]\n";
        for (Index state = 0; state < N_STATES; ++state) {
            // Exclude when the player is not alive or only alive
            if (checkPlayerAlive(player, state) < 2) {
                continue;
            }

            for (Index action = 0; action < N_ACTIONS; ++action) {
                if ((player != action) && checkPlayerAlive(action, state)) {
                    os << "Target " << printIndexChar(action) << ":" << value_[player][state][action] << ", ";
                }
                if (action >= N_PLAYERS) {
                    os << "Nobody:" << value_[player][state][action] << "\n" ;
                }
            }
        }

        os << "\n";
        return os.str();
    }

    // Converts an array to a bitmap
    State survivorsToState(const Survivors& survivors) {
        State state = 0;
        State index = 1;
        for(const auto value : survivors) {
            state += index * (value ? 1 : 0);
            index <<= 1;
        }
        return state;
    }

    // Notice that nobody is always not alive (population - player(1) + nobady(1))
    template<typename T>
    auto countPopulation(T state) {
        return __builtin_popcount(state);
    }

    // Return population of the state if the player is alive in the state, 0 othewise
    Index checkAliveOrNobody(Index player, State state) {
        return ((player >= N_PLAYERS) || (state & (1 << player))) ? countPopulation(state) : 0;
    }

    Index checkPlayerAlive(Index player, State state) {
        return (state & (1 << player)) ? countPopulation(state) : 0;
    }

    // Overwrites survivors
    void aimAndShoot(Index player, Index depth, Survivors& survivors, const ActionChain& actionChain) {
        if (depth >= MAX_DEPTH) {
            return;
        }

        const auto targets = getTargets(player, survivors);
        const auto state = survivorsToState(survivors);
        const auto target = getActionTarget(player, state, survivors, targets);

        ActionChain nextActionChain = actionChain;
        Action nextAction {player, state, target};
        nextActionChain.push_back(nextAction);
        shoot(player, survivors, target);

        if (std::accumulate(survivors.begin(), survivors.end(), 0) == 1) {
            const auto winner = std::distance(survivors.begin(),
                                              std::find(survivors.begin(), survivors.end(), ALIVE));

            // Pick up one sample to i.i.d.
            if (IID_CHOICE) {
                auto raw_index = unit_distribution_(rand_gen_) * static_cast<double>(nextActionChain.size()) - 0.5;
                auto index = std::min(nextActionChain.size() - 1,
                                      static_cast<decltype(nextActionChain.size())>(
                                          std::max(0, static_cast<int>(raw_index))));
                propagate(nextActionChain.at(index), winner);
            } else {
                // Reverse if you deduct rewards
                for(const auto& action : nextActionChain) {
                    propagate(action, winner);
                }
            }
        } else {
            aimAndShoot((player + 1) % N_PLAYERS, depth + 1, survivors, nextActionChain);
        }

        return;
    }

    std::vector<Index> getTargets(Index player, const Survivors& survivors) {
        std::vector<Index> targets;
        for(Index target = 0; target < N_PLAYERS; ++target) {
            if ((target != player) && survivors.at(target)) {
                targets.push_back(target);
            }
        }

        if (targets.size() > 1) {
            // Can shoot nobody
            targets.push_back(N_PLAYERS);
        }

        return targets;
    }

    std::vector<double> getProportions(Index player, State state) {
        // Number of targets = number of survivors - player(1) + nobody(1)
        std::vector<double> proportions(N_ACTIONS, 0.0);

        // Epsilon-greedy
        const auto rand_proportional = unit_distribution_(rand_gen_);
        const bool proportional = (rand_proportional < EXPLORATION_EPSILON);

        if (proportional) {
            // Number of targets = number of survivors - player(1) + nobody(1)
            const auto population = checkPlayerAlive(player, state);
            const double proportion = (population > 0) ? (1.0 / static_cast<double>(population)) : 0.0;
            for (Index action = 0; action < N_ACTIONS; ++action) {
                proportions.at(action) = (checkPlayerAlive(player, state) &&
                                          checkAliveOrNobody(action, state) &&
                                          (player != action)) ? proportion : 0.0;
            }
        } else {
            if (USE_SOFTMAX) {
                std::vector<double> exp_proportions(N_ACTIONS, 0.0);
                double sum = 0.0;
                for (Index action = 0; action < N_ACTIONS; ++action) {
                    const auto value = ::exp(value_[player][state][action]);
                    exp_proportions.at(action) = value;
                    sum += value;
                }

                for (Index action = 0; action < N_ACTIONS; ++action) {
                    proportions.at(action) = exp_proportions.at(action) / sum;
                }
            } else {
                for (Index action = 0; action < N_ACTIONS; ++action) {
                    proportions.at(action) = value_[player][state][action];
                }
            }
        }

        return proportions;
    }

    Index getActionTarget(Index player, State state, const Survivors& survivors, const std::vector<Index>& targets) {
        const auto proportions = getProportions(player, state);
        auto rand_value = unit_distribution_(rand_gen_);
        Index target = 0;

        while(rand_value >= 0.0) {
            rand_value -= proportions.at(target);
            target += 1;
            if (target >= N_ACTIONS) {
                break;
            }
        }

        return target - 1;
    }

    // Overwrites survivors
    void shoot(Index player, Survivors& survivors, Index target) {
        if (target < N_PLAYERS) {
            if (unit_distribution_(rand_gen_) < HIT_RATE.at(player)) {
                survivors.at(target) = 0;
            }
        }

        return;
    }

    void propagate(const Action& action, Index final_surviver) {
        // No deduction
        const auto target_value = value_[action.player][action.state][action.target];
        const auto delta = target_value * LEARNING_RATE * ((action.player == final_surviver) ? 1.0 : -1.0);
        value_[action.player][action.state][action.target] += delta;

        // Normalizes such that the sum of values is 1
        double sum = 0.0;
        for (Index i = 0; i < N_ACTIONS; ++i) {
            sum += value_[action.player][action.state][i];
        }
        for (Index i = 0; i < N_ACTIONS; ++i) {
            value_[action.player][action.state][i] /= sum;
        }
    }

private:
    using CountMatrix = boost::multi_array<Count, 4>;
    using StateActionValue = boost::multi_array<double, 3>;
    std::random_device rand_dev_;
    std::mt19937 rand_gen_;
    std::uniform_real_distribution<double> unit_distribution_;
    StateActionValue value_;
};

int main(int argc, char* argv[]) {
    OptimalAction optimalAction;

    Count n_trials = N_TRIALS;
    if (argc > 1) {
        n_trials = ::atoll(argv[1]);
    }
    optimalAction.Exec(n_trials);
    return 0;
}

/*
Local Variables:
mode: c++
coding: utf-8-dos
tab-width: nil
c-file-style: "stroustrup"
End:
*/
<|endoftext|>