<commit_before>#include "poke.h"
#include "registerOverride.h"
#include <nds/dma.h>
#include <nds/arm9/video.h>
#include <cassert>

#define VRAM_F_SIZE (16*1024)
#define VRAM_G_SIZE (16*1024)
#define VRAM_H_SIZE (32*1024)
#define VRAM_I_SIZE (16*1024)

ITCM_CODE static bool pointerInRange(volatile void *needle, volatile void *base, size_t size);

ITCM_CODE void Poke::Perform() {
	registerOverride<uint8_t> oldVRamMode;

	if(pointerInRange(addr, VRAM_F, VRAM_F_SIZE)) {
		oldVRamMode.set(&VRAM_F_CR, VRAM_F_LCD);
	} else if(pointerInRange(addr, VRAM_G, VRAM_G_SIZE)) {
		oldVRamMode.set(&VRAM_G_CR, VRAM_G_LCD);
	} else if(pointerInRange(addr, VRAM_H, VRAM_H_SIZE)) {
		oldVRamMode.set(&VRAM_H_CR, VRAM_H_LCD);
	} else if(pointerInRange(addr, VRAM_I, VRAM_I_SIZE)) {
		oldVRamMode.set(&VRAM_I_CR, VRAM_I_LCD);
	}

	switch(mode) {
	case PM_NOOP:
		break;
	case PM_INT:
		switch(size) {
		case sizeof(uint8_t) :
			*((volatile uint8_t*)addr) = value8;
			break;
		case sizeof(uint16_t) :
			*((volatile uint16_t*)addr) = value16;
			break;
		case sizeof(uint32_t) :
			*((volatile uint32_t*)addr) = value32;
			break;
		default:
			assert(0);
		}
		break;
	case PM_BITFIELD:
		switch(size) {
		case sizeof(uint8_t) :
			bitField8.Poke((volatile uint8_t*)addr);
			break;
		case sizeof(uint16_t) :
			bitField16.Poke((volatile uint16_t*)addr);
			break;
		case sizeof(uint32_t) :
			bitField32.Poke((volatile uint32_t*)addr);
			break;
		default:
			assert(0);
		}
		break;
	case PM_DMA_16:
		dmaCopyHalfWords(3, valuePtr.get(), (void*)addr, size);
		break;
	case PM_DMA_32:
		dmaCopyWords(3, valuePtr.get(), (void*)addr, size);
		break;
	case PM_MEMCPY_8: {
		volatile uint8_t *src = valuePtr.get();
		std::copy(src, src + size, (uint8_t *)addr);
	} break;
	case PM_MEMCPY_16: {
		volatile uint16_t *src = (volatile uint16_t *)valuePtr.get();
		std::copy(src, src + size/2, (uint16_t *)addr);
	} break;
	case PM_MEMCPY_32: {
		volatile uint32_t *src = (volatile uint32_t *)valuePtr.get();
		std::copy(src, src + size/4, (uint32_t *)addr);
	} break;
	}
}

static bool pointerInRange(uintptr_t needle, uintptr_t base, size_t size) {
	return needle >= base && needle < (base + size);
}
static bool pointerInRange(volatile void *needle, volatile void *base, size_t size) {
	return pointerInRange((uintptr_t)needle, (uintptr_t)base, size);
}<commit_msg>Pokes should use the dma channel with the highest priority<commit_after>#include "poke.h"
#include "registerOverride.h"
#include <nds/dma.h>
#include <nds/arm9/video.h>
#include <cassert>

#define VRAM_F_SIZE (16*1024)
#define VRAM_G_SIZE (16*1024)
#define VRAM_H_SIZE (32*1024)
#define VRAM_I_SIZE (16*1024)

ITCM_CODE static bool pointerInRange(volatile void *needle, volatile void *base, size_t size);

ITCM_CODE void Poke::Perform() {
	registerOverride<uint8_t> oldVRamMode;

	if(pointerInRange(addr, VRAM_F, VRAM_F_SIZE)) {
		oldVRamMode.set(&VRAM_F_CR, VRAM_F_LCD);
	} else if(pointerInRange(addr, VRAM_G, VRAM_G_SIZE)) {
		oldVRamMode.set(&VRAM_G_CR, VRAM_G_LCD);
	} else if(pointerInRange(addr, VRAM_H, VRAM_H_SIZE)) {
		oldVRamMode.set(&VRAM_H_CR, VRAM_H_LCD);
	} else if(pointerInRange(addr, VRAM_I, VRAM_I_SIZE)) {
		oldVRamMode.set(&VRAM_I_CR, VRAM_I_LCD);
	}

	switch(mode) {
	case PM_NOOP:
		break;
	case PM_INT:
		switch(size) {
		case sizeof(uint8_t) :
			*((volatile uint8_t*)addr) = value8;
			break;
		case sizeof(uint16_t) :
			*((volatile uint16_t*)addr) = value16;
			break;
		case sizeof(uint32_t) :
			*((volatile uint32_t*)addr) = value32;
			break;
		default:
			assert(0);
		}
		break;
	case PM_BITFIELD:
		switch(size) {
		case sizeof(uint8_t) :
			bitField8.Poke((volatile uint8_t*)addr);
			break;
		case sizeof(uint16_t) :
			bitField16.Poke((volatile uint16_t*)addr);
			break;
		case sizeof(uint32_t) :
			bitField32.Poke((volatile uint32_t*)addr);
			break;
		default:
			assert(0);
		}
		break;
	case PM_DMA_16:
		dmaCopyHalfWords(0, valuePtr.get(), (void*)addr, size);
		break;
	case PM_DMA_32:
		dmaCopyWords(0, valuePtr.get(), (void*)addr, size);
		break;
	case PM_MEMCPY_8: {
		volatile uint8_t *src = valuePtr.get();
		std::copy(src, src + size, (uint8_t *)addr);
	} break;
	case PM_MEMCPY_16: {
		volatile uint16_t *src = (volatile uint16_t *)valuePtr.get();
		std::copy(src, src + size/2, (uint16_t *)addr);
	} break;
	case PM_MEMCPY_32: {
		volatile uint32_t *src = (volatile uint32_t *)valuePtr.get();
		std::copy(src, src + size/4, (uint32_t *)addr);
	} break;
	}
}

static bool pointerInRange(uintptr_t needle, uintptr_t base, size_t size) {
	return needle >= base && needle < (base + size);
}
static bool pointerInRange(volatile void *needle, volatile void *base, size_t size) {
	return pointerInRange((uintptr_t)needle, (uintptr_t)base, size);
}<|endoftext|>


<commit_before>#include "HCUBE_Defines.h"

#include "Experiments/HCUBE_AtariExperiment.h"
#include <boost/foreach.hpp>
#include "../../../ale_v0.1/test.hpp"

using namespace NEAT;

namespace HCUBE
{
  AtariExperiment::AtariExperiment(string _experimentName,int _threadID):
    Experiment(_experimentName,_threadID), rom_file(""),
    display_active(false)
  {
    substrate_width = 16;
    substrate_height = 21;

    layerInfo = NEAT::LayeredSubstrateInfo();
    layerInfo.layerSizes.push_back(Vector2<int>(substrate_width,substrate_height));
    layerInfo.layerIsInput.push_back(true);
    layerInfo.layerLocations.push_back(Vector3<float>(0,0,0));
    layerInfo.layerNames.push_back("Input");

    layerInfo.layerSizes.push_back(Vector2<int>(substrate_width,substrate_height));
    layerInfo.layerIsInput.push_back(false);
    layerInfo.layerLocations.push_back(Vector3<float>(0,4,0));
    layerInfo.layerNames.push_back("Output");

    layerInfo.layerAdjacencyList.push_back(std::pair<string,string>("Input","Output"));

    layerInfo.normalize = true;
    layerInfo.useOldOutputNames = false;
    layerInfo.layerValidSizes = layerInfo.layerSizes;

    substrate = NEAT::LayeredSubstrate<float>();
    substrate.setLayerInfo(layerInfo);

  }

  NEAT::GeneticPopulation* AtariExperiment::createInitialPopulation(int populationSize) {
    GeneticPopulation *population = new GeneticPopulation();
    vector<GeneticNodeGene> genes;

    genes.push_back(GeneticNodeGene("Bias","NetworkSensor",0,false));
    genes.push_back(GeneticNodeGene("X1","NetworkSensor",0,false));
    genes.push_back(GeneticNodeGene("X2","NetworkSensor",0,false));
    genes.push_back(GeneticNodeGene("Y1","NetworkSensor",0,false));
    genes.push_back(GeneticNodeGene("Y2","NetworkSensor",0,false));
    genes.push_back(GeneticNodeGene("Output_Input_Output","NetworkOutputNode",1,false,ACTIVATION_FUNCTION_SIGMOID));

    for (int a=0;a<populationSize;a++) {
      shared_ptr<GeneticIndividual> individual(new GeneticIndividual(genes,true,1.0));
      for (int b=0;b<10;b++) {
        individual->testMutate();
      }
      population->addIndividual(individual);
    }

    cout << "Finished creating population\n";
    return population;
  }

  void AtariExperiment::populateSubstrate(shared_ptr<NEAT::GeneticIndividual> individual) {
    if (currentSubstrateIndividual == individual)
      return;

    currentSubstrateIndividual = individual;
    substrate.populateSubstrate(individual);
  }

  void AtariExperiment::processGroup(shared_ptr<NEAT::GeneticGeneration> generation)
  {
    static int i=0;

    shared_ptr<NEAT::GeneticIndividual> individual = group.front();
    individual->setFitness(10);

    // Print the individual
    //individual->print();

    populateSubstrate(individual);

    //individual->reward(100);
    runAtariEpisode(individual);
  }

  void AtariExperiment::runAtariEpisode(shared_ptr<NEAT::GeneticIndividual> individual) {
    // Check that rom exists and is readable
    ifstream file(rom_file.c_str());
    if (!file.good()) {
      cerr << "Unable to find or open rom file: \"" << rom_file << "\"" << endl;
      exit(-1);
    }

    // Initialize Atari Stuff
    initializeEmulator(rom_file.c_str(),display_active);
    MediaSource &mediasrc = theOSystem->console().mediaSource();
    int pixel_screen_width = mediasrc.width();
    int pixel_screen_height = mediasrc.height();
    for (int i=0; i<pixel_screen_height; ++i) { // Initialize our screen matrix
      IntVect row;
      for (int j=0; j<pixel_screen_width; ++j)
        row.push_back(-1);
      screen_matrix.push_back(row);
    }
    // Intialize our ram array
    for (int i=0; i<RAM_LENGTH; i++)
      ram_content.push_back(0);

    System* emulator_system = &theOSystem->console().system();
    controller = (InternalController*) theOSystem->getGameController();
    self_detection_agent = (SelfDetectionAgent*) controller->getPlayerAgentLeft();
    visProc = &(self_detection_agent->visProc);
    game_settings = controller->getGameSettings();
    // Initialize Atari Stuff - fin

    // Main Loop
    int skip_frames_num = game_settings->i_skip_frames_num;
    int frame_skip_ctr = 0;

    // Reset the game mutliple times
    for (int i=0; i<5; i++)
      theOSystem->applyAction(RESET);
    int delay_after_restart = game_settings->i_delay_after_restart;
    Action action = game_settings->e_first_action;
    if (action == UNDEFINED) action = PLAYER_A_NOOP;
    for (int i=0; i<delay_after_restart; i++)
      theOSystem->applyAction(action);
    time_start = time(NULL);
    bool game_ended = false;
    int frame = 0;
    float episode_reward = 0;
    while (!game_ended) {
      frame++;

      // Should we take an action this turn?
      bool take_action = frame_skip_ctr++ >= skip_frames_num;
      if (take_action) {
        frame_skip_ctr = 0;

        // Get the latest screen
        int ind_i, ind_j;
        uInt8* pi_curr_frame_buffer = mediasrc.currentFrameBuffer();
        for (int i = 0; i < pixel_screen_width * pixel_screen_height; i++) {
          uInt8 v = pi_curr_frame_buffer[i];
          ind_i = i / pixel_screen_width;
          ind_j = i - (ind_i * pixel_screen_width);
          screen_matrix[ind_i][ind_j] = v;
        }

        // Get the latest ram content
        for(int i = 0; i<RAM_LENGTH; i++) {
          int offset = i;
          offset &= 0x7f; // there are only 128 bytes
          ram_content[i] = emulator_system->peek(offset + 0x80);
        }

        float reward = game_settings->get_reward(&screen_matrix,&ram_content);
        episode_reward += reward;

        // Check if game has ended
        game_ended = game_settings->is_end_of_game(&screen_matrix,&ram_content,frame);

        // Get the object representation
        visProc->process_image(&screen_matrix, action);

        substrate.getNetwork()->reinitialize(); // Set value of all nodes to zero
        substrate.getNetwork()->dummyActivation();

        // Set substrate value for all objects (of a certain size)
        for (int i=0; i<visProc->obj_classes.size(); i++) {
          Prototype& proto = visProc->obj_classes[i];

          if (!proto.is_valid) // not a strong enough prototype yet
            continue;
          if (proto.obj_ids.size() == 0) // no obhects on screen
            continue;

          // Map object classes to values
          //float assigned_value = proto.value;
          float assigned_value = 0;
          if (proto.size == 41) // HACK: Hardcoded mapping from object classes to values
              assigned_value = 2;
          else if (proto.size == 42)
              assigned_value = -1;

          // Assign values to each of the objects
          for (set<long>::iterator it=proto.obj_ids.begin(); it!=proto.obj_ids.end(); it++) {
            long obj_id = *it;
            assert(visProc->composite_objs.find(obj_id) != visProc->composite_objs.end());
            point obj_centroid = visProc->composite_objs[obj_id].get_centroid();
            int adj_x = obj_centroid.x * substrate_width / pixel_screen_width;
            int adj_y = obj_centroid.y * substrate_height / pixel_screen_height;
            substrate.setValue((Node(adj_x,adj_y,0)),assigned_value);
          }
        }

        // Set substrate value for self
        point self_centroid = visProc->get_self_centroid();
        int self_x = -1, self_y = -1;
        if (self_centroid.x >= 0 && self_centroid.y >= 0) {
          self_x = self_centroid.x * substrate_width / pixel_screen_width;
          self_y = self_centroid.y * substrate_height / pixel_screen_height;
          substrate.setValue(Node(self_x,self_y,0),1.0);
        }

        // for (int y=0; y<substrate_height; ++y) {
        //     for (int x=0; x<substrate_width; ++x) {
        //         float val = substrate.getValue(Node(x,y,0));
        //         printf("%1.0f ",val);
        //     }
        //     printf("\n");
        // }
        // printf("\n");
        // cin.get();

        substrate.getNetwork()->update();

        // Choose which action to take
        float noop_val = substrate.getValue((Node(self_x,self_y,1)));
        float up_val   = (self_y <= 0) ? noop_val : substrate.getValue((Node(self_x,self_y-1,1)));
        float down_val = (self_y >= substrate_height-1) ? noop_val : substrate.getValue((Node(self_x,self_y+1,1)));
        float left_val = (self_x <= 0) ? noop_val : substrate.getValue((Node(self_x-1,self_y,1)));
        float right_val= (self_x >= substrate_width-1) ? noop_val : substrate.getValue((Node(self_x+1,self_y,1)));

        ActionVect *allowed_actions = game_settings->pv_possible_actions;
        Action actionIds[] = {PLAYER_A_NOOP,PLAYER_A_UP,PLAYER_A_DOWN,PLAYER_A_LEFT,PLAYER_A_RIGHT};
        float action_vals[] = {noop_val,up_val,down_val,left_val,right_val};

        int max_id = 0; // all games should have noop
        float max_val = action_vals[0];
        int size = sizeof(actionIds) / sizeof(Action);
        for (int i=1; i < size; i++) {
            if (action_vals[i] > max_val &&
                std::find(allowed_actions->begin(), allowed_actions->end(), actionIds[i]) != allowed_actions->end()) {
                max_val = action_vals[i];
                max_id = i;
            }
        }

        action = actionIds[max_id];

        // Display the screen
        if (display_active)
          display_screen(screen_matrix);
      }

      // Apply action to simulator and update the simulator
      theOSystem->applyAction(action);

      if (frame % 1000 == 0) {
        time_end = time(NULL);
        double avg = ((double)frame)/(time_end - time_start);
        cerr << "Average main loop iterations per sec = " << avg << endl;
      }
    }

    // Give the reward to the agent
    individual->reward(episode_reward);
  }

  void AtariExperiment::preprocessIndividual(shared_ptr<NEAT::GeneticGeneration> generation,
                                             shared_ptr<NEAT::GeneticIndividual> individual) {
    if (individual->getNode("X1") == NULL) {
      printf("Got blank individual\n");
    }
  }

  void AtariExperiment::processIndividualPostHoc(shared_ptr<NEAT::GeneticIndividual> individual)
  {
    // NEAT::FastNetwork<float> network = individual->spawnFastPhenotypeStack<float>();

    // //TODO Put in userdata

    // double fitness = 10.0;
    // double maxFitness = 10.0;

    // for (int x1=0;x1<2;x1++)
    //   {
    //     for (int x2=0;x2<2;x2++)
    //       {
    //         network.reinitialize();

    //         network.setValue("X1",x1);
    //         network.setValue("X2",x2);
    //         network.setValue("Bias",0.3f);

    //         network.update();

    //         double value = network.getValue("Output");

    //         double expectedValue = (double)(x1 ^ x2);

    //         fitness += (5000*(2-fabs(value-expectedValue)));
    //         maxFitness += 5000*2;
    //       }
    //   }

    // cout << "POST HOC ANALYSIS: " << fitness << "/" << maxFitness << endl;
  }

  Experiment* AtariExperiment::clone()
  {
    AtariExperiment* experiment = new AtariExperiment(*this);

    return experiment;
  }
}
<commit_msg>Dissallow hyperneat from taking the NOOP action.<commit_after>#include "HCUBE_Defines.h"

#include "Experiments/HCUBE_AtariExperiment.h"
#include <boost/foreach.hpp>
#include "../../../ale_v0.1/test.hpp"

using namespace NEAT;

namespace HCUBE
{
  AtariExperiment::AtariExperiment(string _experimentName,int _threadID):
    Experiment(_experimentName,_threadID), rom_file(""),
    display_active(false)
  {
    substrate_width = 16;
    substrate_height = 21;

    layerInfo = NEAT::LayeredSubstrateInfo();
    layerInfo.layerSizes.push_back(Vector2<int>(substrate_width,substrate_height));
    layerInfo.layerIsInput.push_back(true);
    layerInfo.layerLocations.push_back(Vector3<float>(0,0,0));
    layerInfo.layerNames.push_back("Input");

    layerInfo.layerSizes.push_back(Vector2<int>(substrate_width,substrate_height));
    layerInfo.layerIsInput.push_back(false);
    layerInfo.layerLocations.push_back(Vector3<float>(0,4,0));
    layerInfo.layerNames.push_back("Output");

    layerInfo.layerAdjacencyList.push_back(std::pair<string,string>("Input","Output"));

    layerInfo.normalize = true;
    layerInfo.useOldOutputNames = false;
    layerInfo.layerValidSizes = layerInfo.layerSizes;

    substrate = NEAT::LayeredSubstrate<float>();
    substrate.setLayerInfo(layerInfo);

  }

  NEAT::GeneticPopulation* AtariExperiment::createInitialPopulation(int populationSize) {
    GeneticPopulation *population = new GeneticPopulation();
    vector<GeneticNodeGene> genes;

    genes.push_back(GeneticNodeGene("Bias","NetworkSensor",0,false));
    genes.push_back(GeneticNodeGene("X1","NetworkSensor",0,false));
    genes.push_back(GeneticNodeGene("X2","NetworkSensor",0,false));
    genes.push_back(GeneticNodeGene("Y1","NetworkSensor",0,false));
    genes.push_back(GeneticNodeGene("Y2","NetworkSensor",0,false));
    genes.push_back(GeneticNodeGene("Output_Input_Output","NetworkOutputNode",1,false,ACTIVATION_FUNCTION_SIGMOID));

    for (int a=0;a<populationSize;a++) {
      shared_ptr<GeneticIndividual> individual(new GeneticIndividual(genes,true,1.0));
      for (int b=0;b<10;b++) {
        individual->testMutate();
      }
      population->addIndividual(individual);
    }

    cout << "Finished creating population\n";
    return population;
  }

  void AtariExperiment::populateSubstrate(shared_ptr<NEAT::GeneticIndividual> individual) {
    if (currentSubstrateIndividual == individual)
      return;

    currentSubstrateIndividual = individual;
    substrate.populateSubstrate(individual);
  }

  void AtariExperiment::processGroup(shared_ptr<NEAT::GeneticGeneration> generation)
  {
    static int i=0;

    shared_ptr<NEAT::GeneticIndividual> individual = group.front();
    individual->setFitness(10);

    // Print the individual
    //individual->print();

    populateSubstrate(individual);

    //individual->reward(100);
    runAtariEpisode(individual);
  }

  void AtariExperiment::runAtariEpisode(shared_ptr<NEAT::GeneticIndividual> individual) {
    // Check that rom exists and is readable
    ifstream file(rom_file.c_str());
    if (!file.good()) {
      cerr << "Unable to find or open rom file: \"" << rom_file << "\"" << endl;
      exit(-1);
    }

    // Initialize Atari Stuff
    initializeEmulator(rom_file.c_str(),display_active);
    MediaSource &mediasrc = theOSystem->console().mediaSource();
    int pixel_screen_width = mediasrc.width();
    int pixel_screen_height = mediasrc.height();
    for (int i=0; i<pixel_screen_height; ++i) { // Initialize our screen matrix
      IntVect row;
      for (int j=0; j<pixel_screen_width; ++j)
        row.push_back(-1);
      screen_matrix.push_back(row);
    }
    // Intialize our ram array
    for (int i=0; i<RAM_LENGTH; i++)
      ram_content.push_back(0);

    System* emulator_system = &theOSystem->console().system();
    controller = (InternalController*) theOSystem->getGameController();
    self_detection_agent = (SelfDetectionAgent*) controller->getPlayerAgentLeft();
    visProc = &(self_detection_agent->visProc);
    game_settings = controller->getGameSettings();
    // Initialize Atari Stuff - fin

    // Main Loop
    int skip_frames_num = game_settings->i_skip_frames_num;
    int frame_skip_ctr = 0;

    // Reset the game mutliple times
    for (int i=0; i<5; i++)
      theOSystem->applyAction(RESET);
    int delay_after_restart = game_settings->i_delay_after_restart;
    Action action = game_settings->e_first_action;
    if (action == UNDEFINED) action = PLAYER_A_NOOP;
    for (int i=0; i<delay_after_restart; i++)
      theOSystem->applyAction(action);
    time_start = time(NULL);
    bool game_ended = false;
    int frame = 0;
    float episode_reward = 0;
    while (!game_ended) {
      frame++;

      // Should we take an action this turn?
      bool take_action = frame_skip_ctr++ >= skip_frames_num;
      if (take_action) {
        frame_skip_ctr = 0;

        // Get the latest screen
        int ind_i, ind_j;
        uInt8* pi_curr_frame_buffer = mediasrc.currentFrameBuffer();
        for (int i = 0; i < pixel_screen_width * pixel_screen_height; i++) {
          uInt8 v = pi_curr_frame_buffer[i];
          ind_i = i / pixel_screen_width;
          ind_j = i - (ind_i * pixel_screen_width);
          screen_matrix[ind_i][ind_j] = v;
        }

        // Get the latest ram content
        for(int i = 0; i<RAM_LENGTH; i++) {
          int offset = i;
          offset &= 0x7f; // there are only 128 bytes
          ram_content[i] = emulator_system->peek(offset + 0x80);
        }

        float reward = game_settings->get_reward(&screen_matrix,&ram_content);
        episode_reward += reward;

        // Check if game has ended
        game_ended = game_settings->is_end_of_game(&screen_matrix,&ram_content,frame);

        // Get the object representation
        visProc->process_image(&screen_matrix, action);

        substrate.getNetwork()->reinitialize(); // Set value of all nodes to zero
        substrate.getNetwork()->dummyActivation();

        // Set substrate value for all objects (of a certain size)
        for (int i=0; i<visProc->obj_classes.size(); i++) {
          Prototype& proto = visProc->obj_classes[i];

          if (!proto.is_valid) // not a strong enough prototype yet
            continue;
          if (proto.obj_ids.size() == 0) // no obhects on screen
            continue;

          // Map object classes to values
          //float assigned_value = proto.value;
          float assigned_value = 0;
          if (proto.size == 41) // HACK: Hardcoded mapping from object classes to values
              assigned_value = 2;
          else if (proto.size == 42)
              assigned_value = -1;

          // Assign values to each of the objects
          for (set<long>::iterator it=proto.obj_ids.begin(); it!=proto.obj_ids.end(); it++) {
            long obj_id = *it;
            assert(visProc->composite_objs.find(obj_id) != visProc->composite_objs.end());
            point obj_centroid = visProc->composite_objs[obj_id].get_centroid();
            int adj_x = obj_centroid.x * substrate_width / pixel_screen_width;
            int adj_y = obj_centroid.y * substrate_height / pixel_screen_height;
            substrate.setValue((Node(adj_x,adj_y,0)),assigned_value);
          }
        }

        // Set substrate value for self
        point self_centroid = visProc->get_self_centroid();
        int self_x = -1, self_y = -1;
        if (self_centroid.x >= 0 && self_centroid.y >= 0) {
          self_x = self_centroid.x * substrate_width / pixel_screen_width;
          self_y = self_centroid.y * substrate_height / pixel_screen_height;
          substrate.setValue(Node(self_x,self_y,0),1.0);
        }

        // for (int y=0; y<substrate_height; ++y) {
        //     for (int x=0; x<substrate_width; ++x) {
        //         float val = substrate.getValue(Node(x,y,0));
        //         printf("%1.0f ",val);
        //     }
        //     printf("\n");
        // }
        // printf("\n");
        // cin.get();

        substrate.getNetwork()->update();

        // Get possible actions
        ActionVect *allowed_actions = game_settings->pv_possible_actions;
        Action actionIds[] = {PLAYER_A_NOOP,PLAYER_A_UP,PLAYER_A_DOWN,PLAYER_A_LEFT,PLAYER_A_RIGHT};

        // If no self detected, take a random action.
        if (self_x < 0 || self_y < 0) {
            printf("Unable to detect the self. Taking random action.\n");
            action = (*allowed_actions)[rand() % allowed_actions->size()];
        } else {
            // Choose which action to take
            float noop_val = -1e37;//substrate.getValue((Node(self_x,self_y,1)));
            float up_val   = (self_y <= 0) ? noop_val : substrate.getValue((Node(self_x,self_y-1,1)));
            float down_val = (self_y >= substrate_height-1) ? noop_val : substrate.getValue((Node(self_x,self_y+1,1)));
            float left_val = (self_x <= 0) ? noop_val : substrate.getValue((Node(self_x-1,self_y,1)));
            float right_val= (self_x >= substrate_width-1) ? noop_val : substrate.getValue((Node(self_x+1,self_y,1)));

            float action_vals[] = {noop_val,up_val,down_val,left_val,right_val};

            int max_id = 0; // all games should have noop
            float max_val = action_vals[0];
            int size = sizeof(actionIds) / sizeof(Action);
            for (int i=1; i < size; i++) {
                if (action_vals[i] > max_val &&
                    std::find(allowed_actions->begin(), allowed_actions->end(), actionIds[i]) != allowed_actions->end()) {
                    max_val = action_vals[i];
                    max_id = i;
                }
            }
            action = actionIds[max_id];
        }

        // Display the screen
        if (display_active)
          display_screen(screen_matrix);
      }

      // Apply action to simulator and update the simulator
      theOSystem->applyAction(action);

      if (frame % 1000 == 0) {
        time_end = time(NULL);
        double avg = ((double)frame)/(time_end - time_start);
        cerr << "Average main loop iterations per sec = " << avg << endl;
      }
    }

    // Give the reward to the agent
    individual->reward(episode_reward);
  }

  void AtariExperiment::preprocessIndividual(shared_ptr<NEAT::GeneticGeneration> generation,
                                             shared_ptr<NEAT::GeneticIndividual> individual) {
    if (individual->getNode("X1") == NULL) {
      printf("Got blank individual\n");
    }
  }

  void AtariExperiment::processIndividualPostHoc(shared_ptr<NEAT::GeneticIndividual> individual)
  {
    // NEAT::FastNetwork<float> network = individual->spawnFastPhenotypeStack<float>();

    // //TODO Put in userdata

    // double fitness = 10.0;
    // double maxFitness = 10.0;

    // for (int x1=0;x1<2;x1++)
    //   {
    //     for (int x2=0;x2<2;x2++)
    //       {
    //         network.reinitialize();

    //         network.setValue("X1",x1);
    //         network.setValue("X2",x2);
    //         network.setValue("Bias",0.3f);

    //         network.update();

    //         double value = network.getValue("Output");

    //         double expectedValue = (double)(x1 ^ x2);

    //         fitness += (5000*(2-fabs(value-expectedValue)));
    //         maxFitness += 5000*2;
    //       }
    //   }

    // cout << "POST HOC ANALYSIS: " << fitness << "/" << maxFitness << endl;
  }

  Experiment* AtariExperiment::clone()
  {
    AtariExperiment* experiment = new AtariExperiment(*this);

    return experiment;
  }
}
<|endoftext|>


<commit_before>// -------------------------------------------------------------------------
//    @FileName			:		NFCWS.cpp
//    @Author			:		Stone.xin
//    @Date				:		2016-12-22
//    @Module			:		NFCWS
// -------------------------------------------------------------------------

#include "NFCWS.h"
#include <string.h>
#include <atomic>

bool NFCWS::Execute()
{
	m_EndPoint.poll_one();
	return false;
}

int NFCWS::Initialization(const unsigned int nMaxClient, const unsigned short nPort, const int nCpuCount)
{
	mnPort = nPort;
	mnMaxConnect = nMaxClient;
	mnCpuCount = nCpuCount;

	m_EndPoint.init_asio();

	m_EndPoint.set_message_handler(std::bind(
		&NFCWS::OnMessageHandler, this,
		std::placeholders::_1, std::placeholders::_2
		));

	m_EndPoint.set_open_handler(std::bind(
		&NFCWS::OnOpenHandler, this,
		std::placeholders::_1));

	m_EndPoint.set_close_handler(std::bind(
		&NFCWS::OnCloseHandler, this,
		std::placeholders::_1));

	m_EndPoint.set_fail_handler(std::bind(
		&NFCWS::OnFailHandler, this,
		std::placeholders::_1));

	m_EndPoint.set_pong_handler(std::bind(
		&NFCWS::OnPongHandler, this,
		std::placeholders::_1, std::placeholders::_2));

	m_EndPoint.set_interrupt_handler(std::bind(
		&NFCWS::OnInterruptHandler, this,
		std::placeholders::_1));

	m_EndPoint.set_pong_timeout_handler(std::bind(
		&NFCWS::OnPongTimeOutHandler, this,
		std::placeholders::_1, std::placeholders::_2));

	m_EndPoint.listen(nPort);
	m_EndPoint.start_accept();

	return 0;
}

bool NFCWS::Final()
{
	CloseSocketAll();
	m_EndPoint.stop_listening();

	return true;
}

bool NFCWS::SendMsgToAllClient(const char * msg, const uint32_t nLen)
{
	if (nLen <= 0)
	{
		return false;
	}

	session_list::iterator it = mmObject.begin();
	while (it!=mmObject.end())
	{
		WSObjectPtr pWSObject = it->second;
		if (pWSObject && !pWSObject->NeedRemove())
		{
			try
			{
				m_EndPoint.send(it->first, msg, nLen, websocketpp::frame::opcode::TEXT);
			}
			catch (websocketpp::exception& e)
			{
				std::cout<<"websocket exception: "<<e.what()<<std::endl;
			}
		}
		it++;
	}

	return true;
}

bool NFCWS::SendMsgToClient(const char * msg, const uint32_t nLen, std::vector<websocketpp::connection_hdl> vList)
{
	for (auto vIt:vList)
	{
		auto pWSObject = GetNetObject(vIt);
		if (pWSObject && !pWSObject->NeedRemove())
		{
			try
			{
				m_EndPoint.send(vIt, msg, nLen, websocketpp::frame::opcode::TEXT);
				return true;
			}
			catch (websocketpp::exception& e)
			{
				std::cout << "websocket exception: " << e.what() << std::endl;
			}
		}
	}
	return false;
}

bool NFCWS::SendMsgToClient(const char * msg, const uint32_t nLen, websocketpp::connection_hdl hd)
{
	auto pWSObject = GetNetObject(hd);
	if (pWSObject && !pWSObject->NeedRemove())
	{
		try
		{
			m_EndPoint.send(hd, msg, nLen, websocketpp::frame::opcode::TEXT);
			return true;
		}
		catch (websocketpp::exception& e)
		{
			std::cout << "websocket exception: " << e.what() << std::endl;
		}
	}
	return false;
}

bool NFCWS::AddNetObject(websocketpp::connection_hdl hd,WSObjectPtr pWSObject)
{
	auto pObject = GetNetObject(hd);
	if (pObject)
	{
		return false;
	}
	mmObject.emplace(session_list::value_type(hd,pWSObject));
	return true;
}

WSObjectPtr NFCWS::GetNetObject(websocketpp::connection_hdl hd)
{
	session_list::iterator it = mmObject.find(hd);
	if (it == mmObject.end())
	{
		return nullptr;
	}
	return it->second;
}

void NFCWS::ExecuteClose()
{
	for each (auto vIt in mvRemoveObject)
	{
		CloseObject(vIt);
	}
	mvRemoveObject.clear();
}

bool NFCWS::CloseSocketAll()
{
	session_list::iterator it = mmObject.begin();
	for (it; it != mmObject.end(); ++it)
	{
		mvRemoveObject.push_back(it->first);
	}

	ExecuteClose();

	mmObject.clear();

	return true;
}

void NFCWS::CloseObject(websocketpp::connection_hdl hd, int nCloseCode/* =1000 */, const std::string& strCloseReason/* ="" */)
{
	m_EndPoint.close(hd, nCloseCode, strCloseReason);
}

void NFCWS::OnMessageHandler(websocketpp::connection_hdl hd, NFWebSockConf::message_ptr msg)
{
	auto pObject = GetNetObject(hd);
	if (!pObject)
	{
		return;
	}

	if (mRecvCB)
	{
		mRecvCB(hd,msg->get_payload());
	}
}

void NFCWS::OnOpenHandler(websocketpp::connection_hdl hd)
{
	WSObjectPtr pWSObject(NF_NEW(WSObject));
	if (AddNetObject(hd,pWSObject))
	{
		if (mEventCB)
		{
			mEventCB(hd, NF_WS_EVENT_OPEN);
		}
	}
}

bool NFCWS::RemoveConnection(websocketpp::connection_hdl hd, NF_WS_EVENT evt, int nCloseCode /* = 1000 */, const std::string& strCloseReason /* = "" */)
{
	session_list::iterator it = mmObject.find(hd);
	if (it != mmObject.end())
	{
		mvRemoveObject.push_back(hd);
		return true;
	}
	return false;
}

void NFCWS::OnCloseHandler(websocketpp::connection_hdl hd)
{
	RemoveConnection(hd, NF_WS_EVENT_CLOSE);
}

void NFCWS::OnFailHandler(websocketpp::connection_hdl hd)
{
	RemoveConnection(hd, NF_WS_EVENT_FAIL);
}

void NFCWS::OnInterruptHandler(websocketpp::connection_hdl hd)
{
	RemoveConnection(hd, NF_WS_EVENT_INTERRUPT);
}

bool NFCWS::OnPongHandler(websocketpp::connection_hdl hd, std::string str)
{
	return true;
}

void NFCWS::OnPongTimeOutHandler(websocketpp::connection_hdl hd, std::string str)
{
	RemoveConnection(hd, NF_WS_EVENT_PONG_TIMEOUT);
}
<commit_msg>change for each to for loop<commit_after>// -------------------------------------------------------------------------
//    @FileName			:		NFCWS.cpp
//    @Author			:		Stone.xin
//    @Date				:		2016-12-22
//    @Module			:		NFCWS
// -------------------------------------------------------------------------

#include "NFCWS.h"
#include <string.h>
#include <atomic>

bool NFCWS::Execute()
{
	m_EndPoint.poll_one();
	return false;
}

int NFCWS::Initialization(const unsigned int nMaxClient, const unsigned short nPort, const int nCpuCount)
{
	mnPort = nPort;
	mnMaxConnect = nMaxClient;
	mnCpuCount = nCpuCount;

	m_EndPoint.init_asio();

	m_EndPoint.set_message_handler(std::bind(
		&NFCWS::OnMessageHandler, this,
		std::placeholders::_1, std::placeholders::_2
		));

	m_EndPoint.set_open_handler(std::bind(
		&NFCWS::OnOpenHandler, this,
		std::placeholders::_1));

	m_EndPoint.set_close_handler(std::bind(
		&NFCWS::OnCloseHandler, this,
		std::placeholders::_1));

	m_EndPoint.set_fail_handler(std::bind(
		&NFCWS::OnFailHandler, this,
		std::placeholders::_1));

	m_EndPoint.set_pong_handler(std::bind(
		&NFCWS::OnPongHandler, this,
		std::placeholders::_1, std::placeholders::_2));

	m_EndPoint.set_interrupt_handler(std::bind(
		&NFCWS::OnInterruptHandler, this,
		std::placeholders::_1));

	m_EndPoint.set_pong_timeout_handler(std::bind(
		&NFCWS::OnPongTimeOutHandler, this,
		std::placeholders::_1, std::placeholders::_2));

	m_EndPoint.listen(nPort);
	m_EndPoint.start_accept();

	return 0;
}

bool NFCWS::Final()
{
	CloseSocketAll();
	m_EndPoint.stop_listening();

	return true;
}

bool NFCWS::SendMsgToAllClient(const char * msg, const uint32_t nLen)
{
	if (nLen <= 0)
	{
		return false;
	}

	session_list::iterator it = mmObject.begin();
	while (it!=mmObject.end())
	{
		WSObjectPtr pWSObject = it->second;
		if (pWSObject && !pWSObject->NeedRemove())
		{
			try
			{
				m_EndPoint.send(it->first, msg, nLen, websocketpp::frame::opcode::TEXT);
			}
			catch (websocketpp::exception& e)
			{
				std::cout<<"websocket exception: "<<e.what()<<std::endl;
			}
		}
		it++;
	}

	return true;
}

bool NFCWS::SendMsgToClient(const char * msg, const uint32_t nLen, std::vector<websocketpp::connection_hdl> vList)
{
	for (auto vIt:vList)
	{
		auto pWSObject = GetNetObject(vIt);
		if (pWSObject && !pWSObject->NeedRemove())
		{
			try
			{
				m_EndPoint.send(vIt, msg, nLen, websocketpp::frame::opcode::TEXT);
				return true;
			}
			catch (websocketpp::exception& e)
			{
				std::cout << "websocket exception: " << e.what() << std::endl;
			}
		}
	}
	return false;
}

bool NFCWS::SendMsgToClient(const char * msg, const uint32_t nLen, websocketpp::connection_hdl hd)
{
	auto pWSObject = GetNetObject(hd);
	if (pWSObject && !pWSObject->NeedRemove())
	{
		try
		{
			m_EndPoint.send(hd, msg, nLen, websocketpp::frame::opcode::TEXT);
			return true;
		}
		catch (websocketpp::exception& e)
		{
			std::cout << "websocket exception: " << e.what() << std::endl;
		}
	}
	return false;
}

bool NFCWS::AddNetObject(websocketpp::connection_hdl hd,WSObjectPtr pWSObject)
{
	auto pObject = GetNetObject(hd);
	if (pObject)
	{
		return false;
	}
	mmObject.emplace(session_list::value_type(hd,pWSObject));
	return true;
}

WSObjectPtr NFCWS::GetNetObject(websocketpp::connection_hdl hd)
{
	session_list::iterator it = mmObject.find(hd);
	if (it == mmObject.end())
	{
		return nullptr;
	}
	return it->second;
}

void NFCWS::ExecuteClose()
{
	for(auto vIt : mvRemoveObject)
	{
		CloseObject(vIt);
	}
	mvRemoveObject.clear();
}

bool NFCWS::CloseSocketAll()
{
	session_list::iterator it = mmObject.begin();
	while(it != mmObject.end())
	{
		mvRemoveObject.push_back(it->first);
		it++;
	}

	ExecuteClose();

	mmObject.clear();

	return true;
}

void NFCWS::CloseObject(websocketpp::connection_hdl hd, int nCloseCode/* =1000 */, const std::string& strCloseReason/* ="" */)
{
	m_EndPoint.close(hd, nCloseCode, strCloseReason);
}

void NFCWS::OnMessageHandler(websocketpp::connection_hdl hd, NFWebSockConf::message_ptr msg)
{
	auto pObject = GetNetObject(hd);
	if (!pObject)
	{
		return;
	}

	if (mRecvCB)
	{
		mRecvCB(hd,msg->get_payload());
	}
}

void NFCWS::OnOpenHandler(websocketpp::connection_hdl hd)
{
	WSObjectPtr pWSObject(NF_NEW(WSObject));
	if (AddNetObject(hd,pWSObject))
	{
		if (mEventCB)
		{
			mEventCB(hd, NF_WS_EVENT_OPEN);
		}
	}
}

bool NFCWS::RemoveConnection(websocketpp::connection_hdl hd, NF_WS_EVENT evt, int nCloseCode /* = 1000 */, const std::string& strCloseReason /* = "" */)
{
	session_list::iterator it = mmObject.find(hd);
	if (it != mmObject.end())
	{
		mvRemoveObject.push_back(hd);
		return true;
	}
	return false;
}

void NFCWS::OnCloseHandler(websocketpp::connection_hdl hd)
{
	RemoveConnection(hd, NF_WS_EVENT_CLOSE);
}

void NFCWS::OnFailHandler(websocketpp::connection_hdl hd)
{
	RemoveConnection(hd, NF_WS_EVENT_FAIL);
}

void NFCWS::OnInterruptHandler(websocketpp::connection_hdl hd)
{
	RemoveConnection(hd, NF_WS_EVENT_INTERRUPT);
}

bool NFCWS::OnPongHandler(websocketpp::connection_hdl hd, std::string str)
{
	return true;
}

void NFCWS::OnPongTimeOutHandler(websocketpp::connection_hdl hd, std::string str)
{
	RemoveConnection(hd, NF_WS_EVENT_PONG_TIMEOUT);
}
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program 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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"

#include "OgreOverlay.h"
#include "OgreRoot.h"
#include "OgreSceneManager.h"
#include "OgreOverlayContainer.h"
#include "OgreCamera.h"
#include "OgreOverlayManager.h"
#include "OgreQuaternion.h"
#include "OgreVector3.h"

namespace Ogre {

    //---------------------------------------------------------------------
    Overlay::Overlay(const String& name) :
        mName(name),
        mRotate(0.0f),
        mScrollX(0.0f), mScrollY(0.0f),
        mScaleX(1.0f), mScaleY(1.0f),
        mTransformOutOfDate(true), mTransformUpdated(true),
        mZOrder(100), mVisible(false), mInitialised(false)

    {
        mRootNode = OGRE_NEW SceneNode(NULL);

    }
    //---------------------------------------------------------------------
    Overlay::~Overlay()
    {
        OGRE_DELETE mRootNode;
    }
    //---------------------------------------------------------------------
    const String& Overlay::getName(void) const
    {
        return mName;
    }
    //---------------------------------------------------------------------
    void Overlay::assignZOrders()
	{
		ushort zorder = mZOrder * 100;

        // Notify attached 2D elements
        OverlayContainerList::iterator i, iend;
        iend = m2DElements.end();
        for (i = m2DElements.begin(); i != iend; ++i)
        {
            zorder = (*i)->_notifyZOrder(zorder);
        }
	}
    //---------------------------------------------------------------------
    void Overlay::setZOrder(ushort zorder)
    {
        // Limit to 650 since this is multiplied by 100 to pad out for containers
        assert (zorder <= 650 && "Overlay ZOrder cannot be greater than 650!");

        mZOrder = zorder;

		assignZOrders();
    }
    //---------------------------------------------------------------------
    ushort Overlay::getZOrder(void) const
    {
        return mZOrder;
    }
    //---------------------------------------------------------------------
    bool Overlay::isVisible(void) const
    {
        return mVisible;
    }
    //---------------------------------------------------------------------
    void Overlay::show(void)
    {
        mVisible = true;
		if (!mInitialised)
		{
			initialise();
		}
    }
    //---------------------------------------------------------------------
    void Overlay::hide(void)
    {
        mVisible = false;
    }
    //---------------------------------------------------------------------
	void Overlay::initialise(void)
	{
		OverlayContainerList::iterator i, iend;
		iend = m2DElements.end();
		for (i = m2DElements.begin(); i != m2DElements.end(); ++i)
		{
			(*i)->initialise();
		}
		mInitialised = true;
	}
	//---------------------------------------------------------------------
    void Overlay::add2D(OverlayContainer* cont)
    {
        m2DElements.push_back(cont);
        // Notify parent
        cont->_notifyParent(0, this);

		assignZOrders();

        Matrix4 xform;
        _getWorldTransforms(&xform);
        cont->_notifyWorldTransforms(xform);
        cont->_notifyViewport();
    }
    //---------------------------------------------------------------------
    void Overlay::remove2D(OverlayContainer* cont)
    {
        m2DElements.remove(cont);
		assignZOrders();
    }
    //---------------------------------------------------------------------
    void Overlay::add3D(SceneNode* node)
    {
        mRootNode->addChild(node);
    }
    //---------------------------------------------------------------------
    void Overlay::remove3D(SceneNode* node)
    {
        mRootNode->removeChild(node->getName());
    }
    //---------------------------------------------------------------------
    void Overlay::clear(void)
    {
        mRootNode->removeAllChildren();
        m2DElements.clear();
        // Note no deallocation, memory handled by OverlayManager & SceneManager
    }
    //---------------------------------------------------------------------
    void Overlay::setScroll(Real x, Real y)
    {
        mScrollX = x;
        mScrollY = y;
        mTransformOutOfDate = true;
        mTransformUpdated = true;
    }
    //---------------------------------------------------------------------
    Real Overlay::getScrollX(void) const
    {
        return mScrollX;
    }
    //---------------------------------------------------------------------
    Real Overlay::getScrollY(void) const
    {
        return mScrollY;
    }
      //---------------------------------------------------------------------
    OverlayContainer* Overlay::getChild(const String& name)
    {

        OverlayContainerList::iterator i, iend;
        iend = m2DElements.end();
        for (i = m2DElements.begin(); i != iend; ++i)
        {
            if ((*i)->getName() == name)
			{
				return *i;

			}
        }
        return NULL;
    }
  //---------------------------------------------------------------------
    void Overlay::scroll(Real xoff, Real yoff)
    {
        mScrollX += xoff;
        mScrollY += yoff;
        mTransformOutOfDate = true;
        mTransformUpdated = true;
    }
    //---------------------------------------------------------------------
    void Overlay::setRotate(const Radian& angle)
    {
        mRotate = angle;
        mTransformOutOfDate = true;
        mTransformUpdated = true;
    }
    //---------------------------------------------------------------------
    void Overlay::rotate(const Radian& angle)
    {
        setRotate(mRotate + angle);
    }
    //---------------------------------------------------------------------
    void Overlay::setScale(Real x, Real y)
    {
        mScaleX = x;
        mScaleY = y;
        mTransformOutOfDate = true;
        mTransformUpdated = true;
    }
    //---------------------------------------------------------------------
    Real Overlay::getScaleX(void) const
    {
        return mScaleX;
    }
    //---------------------------------------------------------------------
    Real Overlay::getScaleY(void) const
    {
        return mScaleY;
    }
    //---------------------------------------------------------------------
    void Overlay::_getWorldTransforms(Matrix4* xform) const
    {
        if (mTransformOutOfDate)
        {
            updateTransform();
        }
        *xform = mTransform;

    }
    //---------------------------------------------------------------------
    void Overlay::_findVisibleObjects(Camera* cam, RenderQueue* queue)
    {
        OverlayContainerList::iterator i, iend;

        if (OverlayManager::getSingleton().hasViewportChanged())
        {
            iend = m2DElements.end();
            for (i = m2DElements.begin(); i != iend; ++i)
            {
                (*i)->_notifyViewport();
            }
        }

        // update elements
        if (mTransformUpdated)
        {
            OverlayContainerList::iterator i, iend;
            Matrix4 xform;

            _getWorldTransforms(&xform);
            iend = m2DElements.end();
            for (i = m2DElements.begin(); i != iend; ++i)
            {
                (*i)->_notifyWorldTransforms(xform);
            }

            mTransformUpdated = false;
        }

        if (mVisible)
        {
            // Add 3D elements
            mRootNode->setPosition(cam->getDerivedPosition());
            mRootNode->setOrientation(cam->getDerivedOrientation());
            mRootNode->_update(true, false);
            // Set up the default queue group for the objects about to be added
            uint8 oldgrp = queue->getDefaultQueueGroup();
            ushort oldPriority = queue-> getDefaultRenderablePriority();
            queue->setDefaultQueueGroup(RENDER_QUEUE_OVERLAY);
            queue->setDefaultRenderablePriority((mZOrder*100)-1);
            mRootNode->_findVisibleObjects(cam, queue, NULL, true, false);
            // Reset the group
            queue->setDefaultQueueGroup(oldgrp);
            queue->setDefaultRenderablePriority(oldPriority);
            // Add 2D elements
            iend = m2DElements.end();
            for (i = m2DElements.begin(); i != iend; ++i)
            {
                (*i)->_update();

                (*i)->_updateRenderQueue(queue);
            }
        }

    }
    //---------------------------------------------------------------------
    void Overlay::updateTransform(void) const
    {
        // Ordering:
        //    1. Scale
        //    2. Rotate
        //    3. Translate

        Matrix3 rot3x3, scale3x3;
        rot3x3.FromEulerAnglesXYZ(Radian(0),Radian(0),mRotate);
        scale3x3 = Matrix3::ZERO;
        scale3x3[0][0] = mScaleX;
        scale3x3[1][1] = mScaleY;
        scale3x3[2][2] = 1.0f;

        mTransform = Matrix4::IDENTITY;
        mTransform = rot3x3 * scale3x3;
        mTransform.setTrans(Vector3(mScrollX, mScrollY, 0));

        mTransformOutOfDate = false;
    }
    //---------------------------------------------------------------------
	OverlayElement* Overlay::findElementAt(Real x, Real y)
	{
		OverlayElement* ret = NULL;
		int currZ = -1;
        OverlayContainerList::iterator i, iend;
        iend = m2DElements.end();
        for (i = m2DElements.begin(); i != iend; ++i)
        {
			int z = (*i)->getZOrder();
			if (z > currZ)
			{
				OverlayElement* elementFound = (*i)->findElementAt(x,y);
				if(elementFound)
				{
					currZ = elementFound->getZOrder();
					ret = elementFound;
				}
			}
        }
		return ret;
	}

}

<commit_msg>Notify child overlay containers when an overlay is destroyed<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program 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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"

#include "OgreOverlay.h"
#include "OgreRoot.h"
#include "OgreSceneManager.h"
#include "OgreOverlayContainer.h"
#include "OgreCamera.h"
#include "OgreOverlayManager.h"
#include "OgreQuaternion.h"
#include "OgreVector3.h"

namespace Ogre {

    //---------------------------------------------------------------------
    Overlay::Overlay(const String& name) :
        mName(name),
        mRotate(0.0f),
        mScrollX(0.0f), mScrollY(0.0f),
        mScaleX(1.0f), mScaleY(1.0f),
        mTransformOutOfDate(true), mTransformUpdated(true),
        mZOrder(100), mVisible(false), mInitialised(false)

    {
        mRootNode = OGRE_NEW SceneNode(NULL);

    }
    //---------------------------------------------------------------------
    Overlay::~Overlay()
    {
		// remove children

        OGRE_DELETE mRootNode;

		for (OverlayContainerList::iterator i = m2DElements.begin();
			 i != m2DElements.end(); ++i)
		{
			(*i)->_notifyParent(0, 0);
		}
    }
    //---------------------------------------------------------------------
    const String& Overlay::getName(void) const
    {
        return mName;
    }
    //---------------------------------------------------------------------
    void Overlay::assignZOrders()
	{
		ushort zorder = mZOrder * 100;

        // Notify attached 2D elements
        OverlayContainerList::iterator i, iend;
        iend = m2DElements.end();
        for (i = m2DElements.begin(); i != iend; ++i)
        {
            zorder = (*i)->_notifyZOrder(zorder);
        }
	}
    //---------------------------------------------------------------------
    void Overlay::setZOrder(ushort zorder)
    {
        // Limit to 650 since this is multiplied by 100 to pad out for containers
        assert (zorder <= 650 && "Overlay ZOrder cannot be greater than 650!");

        mZOrder = zorder;

		assignZOrders();
    }
    //---------------------------------------------------------------------
    ushort Overlay::getZOrder(void) const
    {
        return mZOrder;
    }
    //---------------------------------------------------------------------
    bool Overlay::isVisible(void) const
    {
        return mVisible;
    }
    //---------------------------------------------------------------------
    void Overlay::show(void)
    {
        mVisible = true;
		if (!mInitialised)
		{
			initialise();
		}
    }
    //---------------------------------------------------------------------
    void Overlay::hide(void)
    {
        mVisible = false;
    }
    //---------------------------------------------------------------------
	void Overlay::initialise(void)
	{
		OverlayContainerList::iterator i, iend;
		iend = m2DElements.end();
		for (i = m2DElements.begin(); i != m2DElements.end(); ++i)
		{
			(*i)->initialise();
		}
		mInitialised = true;
	}
	//---------------------------------------------------------------------
    void Overlay::add2D(OverlayContainer* cont)
    {
        m2DElements.push_back(cont);
        // Notify parent
        cont->_notifyParent(0, this);

		assignZOrders();

        Matrix4 xform;
        _getWorldTransforms(&xform);
        cont->_notifyWorldTransforms(xform);
        cont->_notifyViewport();
    }
    //---------------------------------------------------------------------
    void Overlay::remove2D(OverlayContainer* cont)
    {
        m2DElements.remove(cont);
		cont->_notifyParent(0, 0);
		assignZOrders();
    }
    //---------------------------------------------------------------------
    void Overlay::add3D(SceneNode* node)
    {
        mRootNode->addChild(node);
    }
    //---------------------------------------------------------------------
    void Overlay::remove3D(SceneNode* node)
    {
        mRootNode->removeChild(node->getName());
    }
    //---------------------------------------------------------------------
    void Overlay::clear(void)
    {
        mRootNode->removeAllChildren();
        m2DElements.clear();
        // Note no deallocation, memory handled by OverlayManager & SceneManager
    }
    //---------------------------------------------------------------------
    void Overlay::setScroll(Real x, Real y)
    {
        mScrollX = x;
        mScrollY = y;
        mTransformOutOfDate = true;
        mTransformUpdated = true;
    }
    //---------------------------------------------------------------------
    Real Overlay::getScrollX(void) const
    {
        return mScrollX;
    }
    //---------------------------------------------------------------------
    Real Overlay::getScrollY(void) const
    {
        return mScrollY;
    }
      //---------------------------------------------------------------------
    OverlayContainer* Overlay::getChild(const String& name)
    {

        OverlayContainerList::iterator i, iend;
        iend = m2DElements.end();
        for (i = m2DElements.begin(); i != iend; ++i)
        {
            if ((*i)->getName() == name)
			{
				return *i;

			}
        }
        return NULL;
    }
  //---------------------------------------------------------------------
    void Overlay::scroll(Real xoff, Real yoff)
    {
        mScrollX += xoff;
        mScrollY += yoff;
        mTransformOutOfDate = true;
        mTransformUpdated = true;
    }
    //---------------------------------------------------------------------
    void Overlay::setRotate(const Radian& angle)
    {
        mRotate = angle;
        mTransformOutOfDate = true;
        mTransformUpdated = true;
    }
    //---------------------------------------------------------------------
    void Overlay::rotate(const Radian& angle)
    {
        setRotate(mRotate + angle);
    }
    //---------------------------------------------------------------------
    void Overlay::setScale(Real x, Real y)
    {
        mScaleX = x;
        mScaleY = y;
        mTransformOutOfDate = true;
        mTransformUpdated = true;
    }
    //---------------------------------------------------------------------
    Real Overlay::getScaleX(void) const
    {
        return mScaleX;
    }
    //---------------------------------------------------------------------
    Real Overlay::getScaleY(void) const
    {
        return mScaleY;
    }
    //---------------------------------------------------------------------
    void Overlay::_getWorldTransforms(Matrix4* xform) const
    {
        if (mTransformOutOfDate)
        {
            updateTransform();
        }
        *xform = mTransform;

    }
    //---------------------------------------------------------------------
    void Overlay::_findVisibleObjects(Camera* cam, RenderQueue* queue)
    {
        OverlayContainerList::iterator i, iend;

        if (OverlayManager::getSingleton().hasViewportChanged())
        {
            iend = m2DElements.end();
            for (i = m2DElements.begin(); i != iend; ++i)
            {
                (*i)->_notifyViewport();
            }
        }

        // update elements
        if (mTransformUpdated)
        {
            OverlayContainerList::iterator i, iend;
            Matrix4 xform;

            _getWorldTransforms(&xform);
            iend = m2DElements.end();
            for (i = m2DElements.begin(); i != iend; ++i)
            {
                (*i)->_notifyWorldTransforms(xform);
            }

            mTransformUpdated = false;
        }

        if (mVisible)
        {
            // Add 3D elements
            mRootNode->setPosition(cam->getDerivedPosition());
            mRootNode->setOrientation(cam->getDerivedOrientation());
            mRootNode->_update(true, false);
            // Set up the default queue group for the objects about to be added
            uint8 oldgrp = queue->getDefaultQueueGroup();
            ushort oldPriority = queue-> getDefaultRenderablePriority();
            queue->setDefaultQueueGroup(RENDER_QUEUE_OVERLAY);
            queue->setDefaultRenderablePriority((mZOrder*100)-1);
            mRootNode->_findVisibleObjects(cam, queue, NULL, true, false);
            // Reset the group
            queue->setDefaultQueueGroup(oldgrp);
            queue->setDefaultRenderablePriority(oldPriority);
            // Add 2D elements
            iend = m2DElements.end();
            for (i = m2DElements.begin(); i != iend; ++i)
            {
                (*i)->_update();

                (*i)->_updateRenderQueue(queue);
            }
        }

    }
    //---------------------------------------------------------------------
    void Overlay::updateTransform(void) const
    {
        // Ordering:
        //    1. Scale
        //    2. Rotate
        //    3. Translate

        Matrix3 rot3x3, scale3x3;
        rot3x3.FromEulerAnglesXYZ(Radian(0),Radian(0),mRotate);
        scale3x3 = Matrix3::ZERO;
        scale3x3[0][0] = mScaleX;
        scale3x3[1][1] = mScaleY;
        scale3x3[2][2] = 1.0f;

        mTransform = Matrix4::IDENTITY;
        mTransform = rot3x3 * scale3x3;
        mTransform.setTrans(Vector3(mScrollX, mScrollY, 0));

        mTransformOutOfDate = false;
    }
    //---------------------------------------------------------------------
	OverlayElement* Overlay::findElementAt(Real x, Real y)
	{
		OverlayElement* ret = NULL;
		int currZ = -1;
        OverlayContainerList::iterator i, iend;
        iend = m2DElements.end();
        for (i = m2DElements.begin(); i != iend; ++i)
        {
			int z = (*i)->getZOrder();
			if (z > currZ)
			{
				OverlayElement* elementFound = (*i)->findElementAt(x,y);
				if(elementFound)
				{
					currZ = elementFound->getZOrder();
					ret = elementFound;
				}
			}
        }
		return ret;
	}

}

<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This program 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 Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this program. If not, see <http://www.gnu.org/licenses/>.        *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/

#include "../Node_test.h"
#include <SofaTest/Sofa_test.h>
#include <SceneCreator/SceneCreator.h>
#include <sofa/simulation/Visitor.h>
#include <SofaSimulationGraph/DAGNode.h>
#include <SofaSimulationGraph/DAGSimulation.h>

using sofa::simulation::graph::DAGNode;

namespace sofa {

using namespace modeling;
using namespace simulation;

/** Check the traversal of a Directed Acyclic Graph.
 * The traversal order is recorded in a string, and compared with an expected one.
 * @author Francois Faure, Matthieu Nesme @date 2014
 */
struct DAG_test : public Sofa_test<>
{
    DAG_test()
    {
        sofa::simulation::setSimulation(new simulation::graph::DAGSimulation());
    }

    /**
     * The TestVisitor struct records the name of the traversed nodes in a string.
     * The string can be analyzed as a trace of the traversal.
     */
    struct TestVisitor: public sofa::simulation::Visitor
    {

        std::string visited, topdown, bottomup;
        bool tree; // enforce tree traversal
        TreeTraversalRepetition repeat; // repeat callbacks

        TestVisitor()
            : Visitor(sofa::core::ExecParams::defaultInstance() )
            , tree( false )
            , repeat( NO_REPETITION )
        {
            clear();
        }

        void clear()
        {
            visited.clear();
            topdown.clear();
            bottomup.clear();
        }

        Result processNodeTopDown(simulation::Node* node)
        {
            visited += node->getName();
            topdown += node->getName();
            return RESULT_CONTINUE;
        }

        void processNodeBottomUp(simulation::Node* node)
        {
            visited += node->getName();
            bottomup += node->getName();
        }

        bool treeTraversal(TreeTraversalRepetition& r) { r=repeat; return tree; }

    };

    /// utility function testing a scene graph traversals with given expected results
    static void traverse_test( Node::SPtr node, std::string treeTraverse, std::string treeTraverseRepeatAll, std::string treeTraverseRepeatOnce, std::string dagTopDown )
    {
        // dagBottumUp must be the exact inverse of dagTopDown
        std::string dagBottomUp(dagTopDown);
        std::reverse(dagBottomUp.begin(), dagBottomUp.end());

        TestVisitor t;

        t.tree = true; // visitor as TREE traversal w/o repetition
        t.execute( node.get() );
        //        cout<<"traverse_simple_tree: visited = " << t.visited << endl;
        if( t.visited != treeTraverse ){
            ADD_FAILURE() << "Dag_test::traverse_test treeTraverse: wrong traversal order, expected "<<treeTraverse<<", got " << t.visited;
        }
        t.clear();
        t.repeat = simulation::Visitor::REPEAT_ALL; // visitor as TREE traversal with repetitions
        t.execute( node.get() );
        //        cout<<"traverse_simple_tree: visited = " << t.visited << endl;
        if( t.visited != treeTraverseRepeatAll ){
            ADD_FAILURE() << "Dag_test::traverse_test treeTraverseRepeatAll: wrong traversal order, expected "<<treeTraverseRepeatAll<<", got " << t.visited;
        }
        t.clear();
        t.repeat = simulation::Visitor::REPEAT_ONCE; // visitor as TREE traversal with first repetition
        t.execute( node.get() );
        //        cout<<"traverse_simple_tree: visited = " << t.visited << endl;
        if( t.visited != treeTraverseRepeatOnce ){
            ADD_FAILURE() << "Dag_test::traverse_test treeTraverseRepeatOnce: wrong traversal order, expected "<<treeTraverseRepeatOnce<<", got " << t.visited;
        }

        t.clear();
        t.tree = false; // visitor as DAG traversal
        t.execute(node.get());
        //        cout<<"traverse_test: visited = " << t.visited << endl;
        if( t.topdown != dagTopDown ){
            ADD_FAILURE() << "Dag_test::traverse_test dagTopDown: wrong traversal order, expected "<<dagTopDown<<", got " << t.topdown;
        }
        if( t.bottomup != dagBottomUp ){
            ADD_FAILURE() << "Dag_test::traverse_test dagBottomUp: wrong traversal order, expected "<<dagBottomUp<<", got " << t.bottomup;
        }

//        sofa::simulation::getSimulation()->print(node.get());
    }

    /**
     * @brief The root and two children:
\f$
\begin{array}{ccc}
 & R & \\
 \diagup & & \diagdown \\
 A & & B
\end{array}
\f$
Expected output: RAABBR
     */
    void traverse_simple_tree()
    {
        Node::SPtr root = clearScene();
        root->setName("R");
        root->createChild("A");
        root->createChild("B");

        traverse_test( root, "RAABBR", "RAABBR", "RAABBR", "RAB" );
    }

    /**
     * @brief Diamond-shaped graph:
\f$
\begin{array}{ccc}
 & R & \\
 \diagup & & \diagdown \\
 A & & B \\
 \diagdown & & \diagup \\
 & C
\end{array}
\f$
Expected output: RABCCBAR
     */
    void traverse_simple_diamond()
    {
        Node::SPtr root = clearScene();
        root->setName("R");
        Node::SPtr A = root->createChild("A");
        Node::SPtr B = root->createChild("B");
        Node::SPtr C = A->createChild("C");
        B->addChild(C);

        traverse_test( root, "RACCABBR", "RACCABCCBR", "RACCABCCBR", "RABC" );
    }

/**
  * @brief More complex graph:

  R__
 / \ \
 A B |
 \ / |
  C  /
  \ /
   D
   |
   E

Expected output: RABCDEEDCBAR
     */
    void traverse_complex()
    {
        Node::SPtr root = clearScene();
        root->setName("R");
        Node::SPtr A = root->createChild("A");
        Node::SPtr B = root->createChild("B");
        Node::SPtr C = A->createChild("C");
        B->addChild(C);
        Node::SPtr D = C->createChild("D");
        root->addChild(D);
        Node::SPtr E = D->createChild("E");

        traverse_test( root, "RACDEEDCABBR", "RACDEEDCABCDEEDCBDEEDR", "RACDEEDCABCCBDDR", "RABCDE" );
    }

/**
  * @brief Even more complex graph:

  R__
 / \ \
 A B C
 \/ \|
  D  E
  |  |
  F  G

     */
    void traverse_morecomplex()
    {
        Node::SPtr root = clearScene();
        root->setName("R");
        Node::SPtr A = root->createChild("A");
        Node::SPtr B = root->createChild("B");
        Node::SPtr C = root->createChild("C");
        Node::SPtr D = A->createChild("D");
        B->addChild(D);
        Node::SPtr E = B->createChild("E");
        C->addChild(E);
        Node::SPtr F = D->createChild("F");
        Node::SPtr G = E->createChild("G");

        traverse_test( root, "RADFFDABEGGEBCCR", "RADFFDABDFFDEGGEBCEGGECR", "RADFFDABDDEGGEBCEECR", "RABDFCEG" );
    }

/**
  * @brief another complex case

  R______
 / \ \ \ \
 A B C D E
 \/__/_/_/
  F
  |\
  G |
  |/
  H

     */
    void traverse_morecomplex2()
    {
        Node::SPtr root = clearScene();
        root->setName("R");
        Node::SPtr A = root->createChild("A");
        Node::SPtr B = root->createChild("B");
        Node::SPtr C = root->createChild("C");
        Node::SPtr D = root->createChild("D");
        Node::SPtr E = root->createChild("E");
        Node::SPtr F = A->createChild("F");
        B->addChild(F);
        C->addChild(F);
        D->addChild(F);
        E->addChild(F);
        Node::SPtr G = F->createChild("G");
        Node::SPtr H = G->createChild("H");
        F->addChild(H);

        traverse_test( root, "RAFGHHGFABBCCDDEER",
                       "RAFGHHGHHFABFGHHGHHFBCFGHHGHHFCDFGHHGHHFDEFGHHGHHFER",
                       "RAFGHHGHHFABFFBCFFCDFFDEFFER",
                       "RABCDEFGH" );
    }

    static void getObjectByPath( Node::SPtr node, const std::string& searchpath, const std::string& objpath )
    {
        void *foundObj = node->getObject(classid(Dummy), searchpath);
        ASSERT_TRUE( foundObj!=nullptr );
        Dummy* dummyObj = reinterpret_cast<Dummy*>(foundObj);
        ASSERT_TRUE( dummyObj!=nullptr );
        EXPECT_STREQ( objpath.c_str(), dummyObj->getPathName().c_str() );
    }

    void getObject()
    {
        Node::SPtr A = clearScene();
        A->setName("A");

        Node::SPtr B = A->createChild("B");
        Node::SPtr C = A->createChild("C");
        Node::SPtr D = B->createChild("D");
        C->addChild(D);
        Node::SPtr E = D->createChild("E");

/**
        A
       / \
       B C
       \ /
        D
        |
        E
*//

        Dummy::SPtr dummyA = sofa::core::objectmodel::New<Dummy>("obj");
        A->addObject(dummyA);
        Dummy::SPtr dummyA2 = sofa::core::objectmodel::New<Dummy>("obj2");
        A->addObject(dummyA2);
        Dummy::SPtr dummyB = sofa::core::objectmodel::New<Dummy>("obj");
        B->addObject(dummyB);
        Dummy::SPtr dummyC = sofa::core::objectmodel::New<Dummy>("obj");
        C->addObject(dummyC);
        Dummy::SPtr dummyD = sofa::core::objectmodel::New<Dummy>("obj");
        D->addObject(dummyD);
        Dummy::SPtr dummyE = sofa::core::objectmodel::New<Dummy>("obj");
        E->addObject(dummyE);

        // by path
        {
        void* foundObj = A->getObject(classid(Dummy), "/inexisting");
        ASSERT_TRUE( foundObj==nullptr );
        }

        getObjectByPath( A, "/obj", "/obj" );
        getObjectByPath( A, "obj", "/obj" );
        getObjectByPath( A, "/B/obj", "/B/obj" );
        getObjectByPath( A, "C/obj", "/C/obj" );
        getObjectByPath( A, "/B/D/obj", "/B/D/obj" );
        getObjectByPath( A, "C/D/obj", "/B/D/obj" );
        getObjectByPath( A, "/B/D/E/obj", "/B/D/E/obj" );
        getObjectByPath( A, "C/D/E/obj", "/B/D/E/obj" );
        getObjectByPath( B, "obj", "/B/obj" );
        getObjectByPath( C, "D/E/obj", "/B/D/E/obj" );
        getObjectByPath( A, "/obj2", "/obj2" );
        getObjectByPath( A, "obj2", "/obj2" );

        // TODO test other getObject{s} functions

    }

};

TEST_F( DAG_test, traverse )
{
    traverse_simple_tree();
    traverse_simple_diamond();
    traverse_complex();
    traverse_morecomplex();
    traverse_morecomplex2();
}

TEST(DAGNodeTest, objectDestruction_singleObject)
{
    Node_test_objectDestruction_singleObject<DAGNode>();
}

TEST(DAGNodeTest, objectDestruction_multipleObjects)
{
    Node_test_objectDestruction_multipleObjects<DAGNode>();
}

TEST(DAGNodeTest, objectDestruction_childNode_singleObject)
{
    Node_test_objectDestruction_childNode_singleObject<DAGNode>();
}

TEST(DAGNodeTest, objectDestruction_childNode_complexChild)
{
    Node_test_objectDestruction_childNode_complexChild<DAGNode>();
}

TEST_F(DAG_test, getObject)
{
    getObject();
}

}// namespace sofa
<commit_msg>[SofaKernel] Fix compilation issue in DAG_test.cpp<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This program 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 Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this program. If not, see <http://www.gnu.org/licenses/>.        *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/

#include "../Node_test.h"
#include <SofaTest/Sofa_test.h>
#include <SceneCreator/SceneCreator.h>
#include <sofa/simulation/Visitor.h>
#include <SofaSimulationGraph/DAGNode.h>
#include <SofaSimulationGraph/DAGSimulation.h>

using sofa::simulation::graph::DAGNode;

namespace sofa {

using namespace modeling;
using namespace simulation;

/** Check the traversal of a Directed Acyclic Graph.
 * The traversal order is recorded in a string, and compared with an expected one.
 * @author Francois Faure, Matthieu Nesme @date 2014
 */
struct DAG_test : public Sofa_test<>
{
    DAG_test()
    {
        sofa::simulation::setSimulation(new simulation::graph::DAGSimulation());
    }

    /**
     * The TestVisitor struct records the name of the traversed nodes in a string.
     * The string can be analyzed as a trace of the traversal.
     */
    struct TestVisitor: public sofa::simulation::Visitor
    {

        std::string visited, topdown, bottomup;
        bool tree; // enforce tree traversal
        TreeTraversalRepetition repeat; // repeat callbacks

        TestVisitor()
            : Visitor(sofa::core::ExecParams::defaultInstance() )
            , tree( false )
            , repeat( NO_REPETITION )
        {
            clear();
        }

        void clear()
        {
            visited.clear();
            topdown.clear();
            bottomup.clear();
        }

        Result processNodeTopDown(simulation::Node* node)
        {
            visited += node->getName();
            topdown += node->getName();
            return RESULT_CONTINUE;
        }

        void processNodeBottomUp(simulation::Node* node)
        {
            visited += node->getName();
            bottomup += node->getName();
        }

        bool treeTraversal(TreeTraversalRepetition& r) { r=repeat; return tree; }

    };

    /// utility function testing a scene graph traversals with given expected results
    static void traverse_test( Node::SPtr node, std::string treeTraverse, std::string treeTraverseRepeatAll, std::string treeTraverseRepeatOnce, std::string dagTopDown )
    {
        // dagBottumUp must be the exact inverse of dagTopDown
        std::string dagBottomUp(dagTopDown);
        std::reverse(dagBottomUp.begin(), dagBottomUp.end());

        TestVisitor t;

        t.tree = true; // visitor as TREE traversal w/o repetition
        t.execute( node.get() );
        //        cout<<"traverse_simple_tree: visited = " << t.visited << endl;
        if( t.visited != treeTraverse ){
            ADD_FAILURE() << "Dag_test::traverse_test treeTraverse: wrong traversal order, expected "<<treeTraverse<<", got " << t.visited;
        }
        t.clear();
        t.repeat = simulation::Visitor::REPEAT_ALL; // visitor as TREE traversal with repetitions
        t.execute( node.get() );
        //        cout<<"traverse_simple_tree: visited = " << t.visited << endl;
        if( t.visited != treeTraverseRepeatAll ){
            ADD_FAILURE() << "Dag_test::traverse_test treeTraverseRepeatAll: wrong traversal order, expected "<<treeTraverseRepeatAll<<", got " << t.visited;
        }
        t.clear();
        t.repeat = simulation::Visitor::REPEAT_ONCE; // visitor as TREE traversal with first repetition
        t.execute( node.get() );
        //        cout<<"traverse_simple_tree: visited = " << t.visited << endl;
        if( t.visited != treeTraverseRepeatOnce ){
            ADD_FAILURE() << "Dag_test::traverse_test treeTraverseRepeatOnce: wrong traversal order, expected "<<treeTraverseRepeatOnce<<", got " << t.visited;
        }

        t.clear();
        t.tree = false; // visitor as DAG traversal
        t.execute(node.get());
        //        cout<<"traverse_test: visited = " << t.visited << endl;
        if( t.topdown != dagTopDown ){
            ADD_FAILURE() << "Dag_test::traverse_test dagTopDown: wrong traversal order, expected "<<dagTopDown<<", got " << t.topdown;
        }
        if( t.bottomup != dagBottomUp ){
            ADD_FAILURE() << "Dag_test::traverse_test dagBottomUp: wrong traversal order, expected "<<dagBottomUp<<", got " << t.bottomup;
        }

//        sofa::simulation::getSimulation()->print(node.get());
    }

    /**
     * @brief The root and two children:
\f$
\begin{array}{ccc}
 & R & \\
 \diagup & & \diagdown \\
 A & & B
\end{array}
\f$
Expected output: RAABBR
     */
    void traverse_simple_tree()
    {
        Node::SPtr root = clearScene();
        root->setName("R");
        root->createChild("A");
        root->createChild("B");

        traverse_test( root, "RAABBR", "RAABBR", "RAABBR", "RAB" );
    }

    /**
     * @brief Diamond-shaped graph:
\f$
\begin{array}{ccc}
 & R & \\
 \diagup & & \diagdown \\
 A & & B \\
 \diagdown & & \diagup \\
 & C
\end{array}
\f$
Expected output: RABCCBAR
     */
    void traverse_simple_diamond()
    {
        Node::SPtr root = clearScene();
        root->setName("R");
        Node::SPtr A = root->createChild("A");
        Node::SPtr B = root->createChild("B");
        Node::SPtr C = A->createChild("C");
        B->addChild(C);

        traverse_test( root, "RACCABBR", "RACCABCCBR", "RACCABCCBR", "RABC" );
    }

/**
  * @brief More complex graph:

  R__
 / \ \
 A B |
 \ / |
  C  /
  \ /
   D
   |
   E

Expected output: RABCDEEDCBAR
     */
    void traverse_complex()
    {
        Node::SPtr root = clearScene();
        root->setName("R");
        Node::SPtr A = root->createChild("A");
        Node::SPtr B = root->createChild("B");
        Node::SPtr C = A->createChild("C");
        B->addChild(C);
        Node::SPtr D = C->createChild("D");
        root->addChild(D);
        Node::SPtr E = D->createChild("E");

        traverse_test( root, "RACDEEDCABBR", "RACDEEDCABCDEEDCBDEEDR", "RACDEEDCABCCBDDR", "RABCDE" );
    }

/**
  * @brief Even more complex graph:

  R__
 / \ \
 A B C
 \/ \|
  D  E
  |  |
  F  G

     */
    void traverse_morecomplex()
    {
        Node::SPtr root = clearScene();
        root->setName("R");
        Node::SPtr A = root->createChild("A");
        Node::SPtr B = root->createChild("B");
        Node::SPtr C = root->createChild("C");
        Node::SPtr D = A->createChild("D");
        B->addChild(D);
        Node::SPtr E = B->createChild("E");
        C->addChild(E);
        Node::SPtr F = D->createChild("F");
        Node::SPtr G = E->createChild("G");

        traverse_test( root, "RADFFDABEGGEBCCR", "RADFFDABDFFDEGGEBCEGGECR", "RADFFDABDDEGGEBCEECR", "RABDFCEG" );
    }

/**
  * @brief another complex case

  R______
 / \ \ \ \
 A B C D E
 \/__/_/_/
  F
  |\
  G |
  |/
  H

     */
    void traverse_morecomplex2()
    {
        Node::SPtr root = clearScene();
        root->setName("R");
        Node::SPtr A = root->createChild("A");
        Node::SPtr B = root->createChild("B");
        Node::SPtr C = root->createChild("C");
        Node::SPtr D = root->createChild("D");
        Node::SPtr E = root->createChild("E");
        Node::SPtr F = A->createChild("F");
        B->addChild(F);
        C->addChild(F);
        D->addChild(F);
        E->addChild(F);
        Node::SPtr G = F->createChild("G");
        Node::SPtr H = G->createChild("H");
        F->addChild(H);

        traverse_test( root, "RAFGHHGFABBCCDDEER",
                       "RAFGHHGHHFABFGHHGHHFBCFGHHGHHFCDFGHHGHHFDEFGHHGHHFER",
                       "RAFGHHGHHFABFFBCFFCDFFDEFFER",
                       "RABCDEFGH" );
    }

    static void getObjectByPath( Node::SPtr node, const std::string& searchpath, const std::string& objpath )
    {
        void *foundObj = node->getObject(classid(Dummy), searchpath);
        ASSERT_TRUE( foundObj!=nullptr );
        Dummy* dummyObj = reinterpret_cast<Dummy*>(foundObj);
        ASSERT_TRUE( dummyObj!=nullptr );
        EXPECT_STREQ( objpath.c_str(), dummyObj->getPathName().c_str() );
    }

    void getObject()
    {
        Node::SPtr A = clearScene();
        A->setName("A");

        Node::SPtr B = A->createChild("B");
        Node::SPtr C = A->createChild("C");
        Node::SPtr D = B->createChild("D");
        C->addChild(D);
        Node::SPtr E = D->createChild("E");

/**
        A
       / \
       B C
       \ /
        D
        |
        E
*/

        Dummy::SPtr dummyA = sofa::core::objectmodel::New<Dummy>("obj");
        A->addObject(dummyA);
        Dummy::SPtr dummyA2 = sofa::core::objectmodel::New<Dummy>("obj2");
        A->addObject(dummyA2);
        Dummy::SPtr dummyB = sofa::core::objectmodel::New<Dummy>("obj");
        B->addObject(dummyB);
        Dummy::SPtr dummyC = sofa::core::objectmodel::New<Dummy>("obj");
        C->addObject(dummyC);
        Dummy::SPtr dummyD = sofa::core::objectmodel::New<Dummy>("obj");
        D->addObject(dummyD);
        Dummy::SPtr dummyE = sofa::core::objectmodel::New<Dummy>("obj");
        E->addObject(dummyE);

        // by path
        {
        void* foundObj = A->getObject(classid(Dummy), "/inexisting");
        ASSERT_TRUE( foundObj==nullptr );
        }

        getObjectByPath( A, "/obj", "/obj" );
        getObjectByPath( A, "obj", "/obj" );
        getObjectByPath( A, "/B/obj", "/B/obj" );
        getObjectByPath( A, "C/obj", "/C/obj" );
        getObjectByPath( A, "/B/D/obj", "/B/D/obj" );
        getObjectByPath( A, "C/D/obj", "/B/D/obj" );
        getObjectByPath( A, "/B/D/E/obj", "/B/D/E/obj" );
        getObjectByPath( A, "C/D/E/obj", "/B/D/E/obj" );
        getObjectByPath( B, "obj", "/B/obj" );
        getObjectByPath( C, "D/E/obj", "/B/D/E/obj" );
        getObjectByPath( A, "/obj2", "/obj2" );
        getObjectByPath( A, "obj2", "/obj2" );

        // TODO test other getObject{s} functions

    }

};

TEST_F( DAG_test, traverse )
{
    traverse_simple_tree();
    traverse_simple_diamond();
    traverse_complex();
    traverse_morecomplex();
    traverse_morecomplex2();
}

TEST(DAGNodeTest, objectDestruction_singleObject)
{
    Node_test_objectDestruction_singleObject<DAGNode>();
}

TEST(DAGNodeTest, objectDestruction_multipleObjects)
{
    Node_test_objectDestruction_multipleObjects<DAGNode>();
}

TEST(DAGNodeTest, objectDestruction_childNode_singleObject)
{
    Node_test_objectDestruction_childNode_singleObject<DAGNode>();
}

TEST(DAGNodeTest, objectDestruction_childNode_complexChild)
{
    Node_test_objectDestruction_childNode_complexChild<DAGNode>();
}

TEST_F(DAG_test, getObject)
{
    getObject();
}

}// namespace sofa
<|endoftext|>