zibbr

Random 3d and p2p stuff that was originally the beginnings of an overly ambitious p2p virtual world thingy
git clone https://code.literati.org/zibbr.git
Log | Files | Refs

commit 7ec170ec2f5764920986a859e267bba30b64c968
Author: Sean Lynch <seanl@literati.org>
Date:   Fri, 22 Jan 2010 16:07:33 -0800

Initial checkin

Diffstat:
Aastar/8puzzle.cpp | 802+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aastar/findpath.cpp | 344+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aastar/fsa.h | 250+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aastar/license.txt | 20++++++++++++++++++++
Aastar/readme.txt | 145+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aastar/stlastar.h | 754+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acmake/CMakeLists.txt | 1+
Acmake/modules/COPYING-CMAKE-SCRIPTS | 22++++++++++++++++++++++
Acmake/modules/CheckStructMember.cmake | 40++++++++++++++++++++++++++++++++++++++++
Acmake/modules/CheckType.cmake | 37+++++++++++++++++++++++++++++++++++++
Acmake/modules/FindENET.cmake | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acmake/modules/FindMyGUI.cmake | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Acmake/modules/FindOGRE.cmake | 462+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acmake/modules/FindOGREBullet.cmake | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acmake/modules/FindOIS.cmake | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acmake/modules/FindOgreMax.cmake | 37+++++++++++++++++++++++++++++++++++++
Acmake/modules/FindSQLITE.cmake | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Acmake/modules/FindTinyXML.cmake | 36++++++++++++++++++++++++++++++++++++
Acmake/scripts/FindPkgMacros.cmake | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acmake/scripts/MacroLogFeature.cmake | 134+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acmake/scripts/PreprocessorUtils.cmake | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ajs/CMakeLists.txt | 17+++++++++++++++++
Ajs/js-funcs.c | 42++++++++++++++++++++++++++++++++++++++++++
Ajs/js-funcs.h | 8++++++++
Ajs/js-test.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Azibbrtest/CMakeLists.txt | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
26 files changed, 3796 insertions(+), 0 deletions(-)

diff --git a/astar/8puzzle.cpp b/astar/8puzzle.cpp @@ -0,0 +1,802 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// STL A* Search implementation +// (C)2001 Justin Heyes-Jones +// +// This uses my A* code to solve the 8-puzzle + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include <iostream> +#include <assert.h> +#include <new> + +#include <ctype.h> + +using namespace std; + +// Configuration + +#define NUM_TIMES_TO_RUN_SEARCH 1 +#define DISPLAY_SOLUTION_FORWARDS 1 +#define DISPLAY_SOLUTION_BACKWARDS 0 +#define DISPLAY_SOLUTION_INFO 1 +#define DEBUG_LISTS 0 + +// AStar search class +#include "stlastar.h" // See header for copyright and usage information + +// Global data + +#define BOARD_WIDTH (3) +#define BOARD_HEIGHT (3) + +#define GM_TILE (-1) +#define GM_SPACE (0) +#define GM_OFF_BOARD (1) + +// Definitions + +// To use the search class you must define the following calls... + +// Data +// Your own state space information +// Functions +// (Optional) Constructor. +// Nodes are created by the user, so whether you use a +// constructor with parameters as below, or just set the object up after the +// constructor, is up to you. +// +// (Optional) Destructor. +// The destructor will be called if you create one. You +// can rely on the default constructor unless you dynamically allocate something in +// your data +// +// float GoalDistanceEstimate( PuzzleState &nodeGoal ); +// Return the estimated cost to goal from this node (pass reference to goal node) +// +// bool IsGoal( PuzzleState &nodeGoal ); +// Return true if this node is the goal. +// +// bool GetSuccessors( AStarSearch<PuzzleState> *astarsearch ); +// For each successor to this state call the AStarSearch's AddSuccessor call to +// add each one to the current search - return false if you are out of memory and the search +// will fail +// +// float GetCost( PuzzleState *successor ); +// Return the cost moving from this state to the state of successor +// +// bool IsSameState( PuzzleState &rhs ); +// Return true if the provided state is the same as this state + +// Here the example is the 8-puzzle state ... +class PuzzleState +{ + +public: + + // defs + + typedef enum + { + TL_SPACE, + TL_1, + TL_2, + TL_3, + TL_4, + TL_5, + TL_6, + TL_7, + TL_8 + + } TILE; + + // data + + static TILE g_goal[ BOARD_WIDTH*BOARD_HEIGHT]; + static TILE g_start[ BOARD_WIDTH*BOARD_HEIGHT]; + + // the tile data for the 8-puzzle + TILE tiles[ BOARD_WIDTH*BOARD_HEIGHT ]; + + // member functions + + PuzzleState() { + memcpy( tiles, g_goal, sizeof( TILE ) * BOARD_WIDTH * BOARD_HEIGHT ); + } + + PuzzleState( TILE *param_tiles ) + { + memcpy( tiles, param_tiles, sizeof( TILE ) * BOARD_WIDTH * BOARD_HEIGHT ); + } + + float GoalDistanceEstimate( PuzzleState &nodeGoal ); + bool IsGoal( PuzzleState &nodeGoal ); + bool GetSuccessors( AStarSearch<PuzzleState> *astarsearch, PuzzleState *parent_node ); + float GetCost( PuzzleState &successor ); + bool IsSameState( PuzzleState &rhs ); + + void PrintNodeInfo(); + +private: + // User stuff - Just add what you need to help you write the above functions... + + void GetSpacePosition( PuzzleState *pn, int *rx, int *ry ); + bool LegalMove( TILE *StartTiles, TILE *TargetTiles, int spx, int spy, int tx, int ty ); + int GetMap( int x, int y, TILE *tiles ); + + + + +}; + +// Goal state +PuzzleState::TILE PuzzleState::g_goal[] = +{ + TL_1, + TL_2, + TL_3, + TL_8, + TL_SPACE, + TL_4, + TL_7, + TL_6, + TL_5, +}; + +// Some nice Start states +PuzzleState::TILE PuzzleState::g_start[] = +{ + + // Three example start states from Bratko's Prolog Programming for Artificial Intelligence + +#if 1 + // ex a - 4 steps + TL_1 , + TL_3 , + TL_4 , + TL_8 , + TL_SPACE , + TL_2 , + TL_7 , + TL_6 , + TL_5 , + +#elif 0 + + // ex b - 5 steps + TL_2 , + TL_8 , + TL_3 , + TL_1 , + TL_6 , + TL_4 , + TL_7 , + TL_SPACE , + TL_5 , + +#elif 0 + + // ex c - 18 steps + TL_2 , + TL_1 , + TL_6 , + TL_4 , + TL_SPACE , + TL_8 , + TL_7 , + TL_5 , + TL_3 , + +#elif 0 + + // nasty one - doesn't solve + TL_6 , + TL_3 , + TL_SPACE , + TL_4 , + TL_8 , + TL_5 , + TL_7 , + TL_2 , + TL_1 , + +#elif 0 + + // sent by email - does work though + + TL_1 , TL_2 , TL_3 , + TL_4 , TL_5 , TL_6 , + TL_8 , TL_7 , TL_SPACE , + + +// from http://www.cs.utexas.edu/users/novak/asg-8p.html + +//Goal: Easy: Medium: Hard: Worst: + +//1 2 3 1 3 4 2 8 1 2 8 1 5 6 7 +//8 4 8 6 2 4 3 4 6 3 4 8 +//7 6 5 7 5 7 6 5 7 5 3 2 1 + + +#elif 0 + + // easy 5 + TL_1 , + TL_3 , + TL_4 , + + TL_8 , + TL_6 , + TL_2 , + + TL_7 , + TL_SPACE , + TL_5 , + + +#elif 0 + + // medium 9 + TL_2 , + TL_8 , + TL_1 , + + TL_SPACE , + TL_4 , + TL_3 , + + TL_7 , + TL_6 , + TL_5 , + +#elif 0 + + // hard 12 + TL_2 , + TL_8 , + TL_1 , + + TL_4 , + TL_6 , + TL_3 , + + TL_SPACE , + TL_7 , + TL_5 , + +#elif 0 + + // worst 30 + TL_5 , + TL_6 , + TL_7 , + + TL_4 , + TL_SPACE , + TL_8 , + + TL_3 , + TL_2 , + TL_1 , + +#elif 0 + + // 123 + // 784 + // 65 + + // two move simple board + TL_1 , + TL_2 , + TL_3 , + + TL_7 , + TL_8 , + TL_4 , + + TL_SPACE , + TL_6 , + TL_5 , + +#elif 0 + // a1 b2 c3 d4 e5 f6 g7 h8 + //C3,Blank,H8,A1,G8,F6,E5,D4,B2 + + TL_3 , + TL_SPACE , + TL_8 , + + TL_1 , + TL_8 , + TL_6 , + + TL_5 , + TL_4 , + TL_2 , + + +#endif + +}; + +bool PuzzleState::IsSameState( PuzzleState &rhs ) +{ + + for( int i=0; i<(BOARD_HEIGHT*BOARD_WIDTH); i++ ) + { + if( tiles[i] != rhs.tiles[i] ) + { + return false; + } + } + + return true; + +} + +void PuzzleState::PrintNodeInfo() +{ + cout << + (char) (tiles[0] + '0') << + (char) (tiles[1] + '0') << + (char) (tiles[2] + '0') << endl << + (char) (tiles[3] + '0') << + (char) (tiles[4] + '0') << + (char) (tiles[5] + '0') << endl << + (char) (tiles[6] + '0') << + (char) (tiles[7] + '0') << + (char) (tiles[8] + '0') << endl; +} + +// Here's the heuristic function that estimates the distance from a PuzzleState +// to the Goal. + +float PuzzleState::GoalDistanceEstimate( PuzzleState &nodeGoal ) +{ + + // Nilsson's sequence score + + int i, cx, cy, ax, ay, h = 0, s, t; + + // given a tile this returns the tile that should be clockwise + TILE correct_follower_to[ BOARD_WIDTH * BOARD_HEIGHT ] = + { + TL_SPACE, // always wrong + TL_2, + TL_3, + TL_4, + TL_5, + TL_6, + TL_7, + TL_8, + TL_1, + }; + + // given a table index returns the index of the tile that is clockwise to it 3*3 only + int clockwise_tile_of[ BOARD_WIDTH * BOARD_HEIGHT ] = + { + 1, + 2, // 012 + 5, // 345 + 0, // 678 + -1, // never called with center square + 8, + 3, + 6, + 7 + }; + + int tile_x[ BOARD_WIDTH * BOARD_HEIGHT ] = + { + /* TL_SPACE */ 1, + /* TL_1 */ 0, + /* TL_2 */ 1, + /* TL_3 */ 2, + /* TL_4 */ 2, + /* TL_5 */ 2, + /* TL_6 */ 1, + /* TL_7 */ 0, + /* TL_8 */ 0, + }; + + int tile_y[ BOARD_WIDTH * BOARD_HEIGHT ] = + { + /* TL_SPACE */ 1, + /* TL_1 */ 0, + /* TL_2 */ 0, + /* TL_3 */ 0, + /* TL_4 */ 1, + /* TL_5 */ 2, + /* TL_6 */ 2, + /* TL_7 */ 2, + /* TL_8 */ 1, + }; + + s=0; + + // score 1 point if centre is not correct + if( tiles[(BOARD_HEIGHT*BOARD_WIDTH)/2] != nodeGoal.tiles[(BOARD_HEIGHT*BOARD_WIDTH)/2] ) + { + s = 1; + } + + for( i=0; i<(BOARD_HEIGHT*BOARD_WIDTH); i++ ) + { + // this loop adds up the totaldist element in h and + // the sequence score in s + + // the space does not count + if( tiles[i] == TL_SPACE ) + { + continue; + } + + // get correct x and y of this tile + cx = tile_x[tiles[i]]; + cy = tile_y[tiles[i]]; + + // get actual + ax = i % BOARD_WIDTH; + ay = i / BOARD_WIDTH; + + // add manhatten distance to h + h += abs( cx-ax ); + h += abs( cy-ay ); + + // no s score for center tile + if( (ax == (BOARD_WIDTH/2)) && (ay == (BOARD_HEIGHT/2)) ) + { + continue; + } + + // score 2 points if not followed by successor + if( correct_follower_to[ tiles[i] ] != tiles[ clockwise_tile_of[ i ] ] ) + { + s += 2; + } + + + } + + // mult by 3 and add to h + t = h + (3*s); + + return (float) t; + +} + +bool PuzzleState::IsGoal( PuzzleState &nodeGoal ) +{ + return IsSameState( nodeGoal ); +} + +// Helper +// Return the x and y position of the space tile +void PuzzleState::GetSpacePosition( PuzzleState *pn, int *rx, int *ry ) +{ + int x,y; + + for( y=0; y<BOARD_HEIGHT; y++ ) + { + for( x=0; x<BOARD_WIDTH; x++ ) + { + if( pn->tiles[(y*BOARD_WIDTH)+x] == TL_SPACE ) + { + *rx = x; + *ry = y; + + return; + } + } + } + + assert( false && "Something went wrong. There's no space on the board" ); + +} + +int PuzzleState::GetMap( int x, int y, TILE *tiles ) +{ + + if( x < 0 || + x >= BOARD_WIDTH || + y < 0 || + y >= BOARD_HEIGHT + ) + return GM_OFF_BOARD; + + if( tiles[(y*BOARD_WIDTH)+x] == TL_SPACE ) + { + return GM_SPACE; + } + + return GM_TILE; +} + +// Given a node set of tiles and a set of tiles to move them into, do the move as if it was on a tile board +// note : returns false if the board wasn't changed, and simply returns the tiles as they were in the target +// spx and spy is the space position while tx and ty is the target move from position + +bool PuzzleState::LegalMove( TILE *StartTiles, TILE *TargetTiles, int spx, int spy, int tx, int ty ) +{ + + int t; + + if( GetMap( spx, spy, StartTiles ) == GM_SPACE ) + { + if( GetMap( tx, ty, StartTiles ) == GM_TILE ) + { + + // copy tiles + for( t=0; t<(BOARD_HEIGHT*BOARD_WIDTH); t++ ) + { + TargetTiles[t] = StartTiles[t]; + } + + + TargetTiles[ (ty*BOARD_WIDTH)+tx ] = StartTiles[ (spy*BOARD_WIDTH)+spx ]; + TargetTiles[ (spy*BOARD_WIDTH)+spx ] = StartTiles[ (ty*BOARD_WIDTH)+tx ]; + + return true; + } + } + + + return false; + +} + +// This generates the successors to the given PuzzleState. It uses a helper function called +// AddSuccessor to give the successors to the AStar class. The A* specific initialisation +// is done for each node internally, so here you just set the state information that +// is specific to the application +bool PuzzleState::GetSuccessors( AStarSearch<PuzzleState> *astarsearch, PuzzleState *parent_node ) +{ + PuzzleState NewNode; + + int sp_x,sp_y; + + GetSpacePosition( this, &sp_x, &sp_y ); + + bool ret; + + if( LegalMove( tiles, NewNode.tiles, sp_x, sp_y, sp_x, sp_y-1 ) == true ) + { + ret = astarsearch->AddSuccessor( NewNode ); + + if( !ret ) return false; + } + + if( LegalMove( tiles, NewNode.tiles, sp_x, sp_y, sp_x, sp_y+1 ) == true ) + { + ret = astarsearch->AddSuccessor( NewNode ); + + if( !ret ) return false; + } + + if( LegalMove( tiles, NewNode.tiles, sp_x, sp_y, sp_x-1, sp_y ) == true ) + { + ret = astarsearch->AddSuccessor( NewNode ); + + if( !ret ) return false; + } + + if( LegalMove( tiles, NewNode.tiles, sp_x, sp_y, sp_x+1, sp_y ) == true ) + { + ret = astarsearch->AddSuccessor( NewNode ); + + if( !ret ) return false; + } + + return true; +} + +// given this node, what does it cost to move to successor. In the case +// of our map the answer is the map terrain value at this node since that is +// conceptually where we're moving + +float PuzzleState::GetCost( PuzzleState &successor ) +{ + return 1.0f; // I love it when life is simple + +} + + +// Main + +int main( int argc, char *argv[] ) +{ + + cout << "STL A* 8-puzzle solver implementation\n(C)2001 Justin Heyes-Jones\n"; + + bool bUserBoard = false; + + if( argc > 1 ) + { + char *userboard = argv[1]; + + int i = 0; + int c; + + while( c = argv[1][i] ) + { + if( isdigit( c ) ) + { + int num = (c - '0'); + + PuzzleState::g_start[i] = static_cast<PuzzleState::TILE>(num); + + } + + i++; + } + + + } + + // Create an instance of the search class... + + AStarSearch<PuzzleState> astarsearch; + + int NumTimesToSearch = NUM_TIMES_TO_RUN_SEARCH; + + while( NumTimesToSearch-- ) + { + + // Create a start state + PuzzleState nodeStart( PuzzleState::g_start ); + + // Define the goal state + PuzzleState nodeEnd( PuzzleState::g_goal ); + + // Set Start and goal states + astarsearch.SetStartAndGoalStates( nodeStart, nodeEnd ); + + unsigned int SearchState; + + unsigned int SearchSteps = 0; + + do + { + SearchState = astarsearch.SearchStep(); + +#if DEBUG_LISTS + + float f,g,h; + + cout << "Search step " << SearchSteps << endl; + + cout << "Open:\n"; + PuzzleState *p = astarsearch.GetOpenListStart( f,g,h ); + while( p ) + { + ((PuzzleState *)p)->PrintNodeInfo(); + cout << "f: " << f << " g: " << g << " h: " << h << "\n\n"; + + p = astarsearch.GetOpenListNext( f,g,h ); + + } + + cout << "Closed:\n"; + p = astarsearch.GetClosedListStart( f,g,h ); + while( p ) + { + p->PrintNodeInfo(); + cout << "f: " << f << " g: " << g << " h: " << h << "\n\n"; + + p = astarsearch.GetClosedListNext( f,g,h ); + } + +#endif + +// Test cancel search +#if 0 + int StepCount = astarsearch.GetStepCount(); + if( StepCount == 10 ) + { + astarsearch.CancelSearch(); + } +#endif + SearchSteps++; + } + while( SearchState == AStarSearch<PuzzleState>::SEARCH_STATE_SEARCHING ); + + if( SearchState == AStarSearch<PuzzleState>::SEARCH_STATE_SUCCEEDED ) + { +#if DISPLAY_SOLUTION_FORWARDS + cout << "Search found goal state\n"; +#endif + PuzzleState *node = astarsearch.GetSolutionStart(); + +#if DISPLAY_SOLUTION_FORWARDS + cout << "Displaying solution\n"; +#endif + int steps = 0; + +#if DISPLAY_SOLUTION_FORWARDS + node->PrintNodeInfo(); + cout << endl; +#endif + for( ;; ) + { + node = astarsearch.GetSolutionNext(); + + if( !node ) + { + break; + } + +#if DISPLAY_SOLUTION_FORWARDS + node->PrintNodeInfo(); + cout << endl; +#endif + steps ++; + + }; + +#if DISPLAY_SOLUTION_FORWARDS + // todo move step count into main algorithm + cout << "Solution steps " << steps << endl; +#endif + +//////////// + + node = astarsearch.GetSolutionEnd(); + +#if DISPLAY_SOLUTION_BACKWARDS + cout << "Displaying reverse solution\n"; +#endif + steps = 0; + + node->PrintNodeInfo(); + cout << endl; + for( ;; ) + { + node = astarsearch.GetSolutionPrev(); + + if( !node ) + { + break; + } +#if DISPLAY_SOLUTION_BACKWARDS + node->PrintNodeInfo(); + cout << endl; +#endif + steps ++; + + }; + +#if DISPLAY_SOLUTION_BACKWARDS + cout << "Solution steps " << steps << endl; +#endif + +////////////// + + // Once you're done with the solution you can free the nodes up + astarsearch.FreeSolutionNodes(); + + } + else if( SearchState == AStarSearch<PuzzleState>::SEARCH_STATE_FAILED ) + { +#if DISPLAY_SOLUTION_INFO + cout << "Search terminated. Did not find goal state\n"; +#endif + } + else if( SearchState == AStarSearch<PuzzleState>::SEARCH_STATE_OUT_OF_MEMORY ) + { +#if DISPLAY_SOLUTION_INFO + cout << "Search terminated. Out of memory\n"; +#endif + } + + + + // Display the number of loops the search went through +#if DISPLAY_SOLUTION_INFO + cout << "SearchSteps : " << astarsearch.GetStepCount() << endl; +#endif + } + + return 0; +} + + diff --git a/astar/findpath.cpp b/astar/findpath.cpp @@ -0,0 +1,344 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// STL A* Search implementation +// (C)2001 Justin Heyes-Jones +// +// Finding a path on a simple grid maze +// This shows how to do shortest path finding using A* + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "stlastar.h" // See header for copyright and usage information + +#include <iostream> +#include <math.h> + +#define DEBUG_LISTS 0 +#define DEBUG_LIST_LENGTHS_ONLY 0 + +using namespace std; + +// Global data + +// The world map + +const int MAP_WIDTH = 20; +const int MAP_HEIGHT = 20; + +int map[ MAP_WIDTH * MAP_HEIGHT ] = +{ + +// 0001020304050607080910111213141516171819 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 00 + 1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,1, // 01 + 1,9,9,1,1,9,9,9,1,9,1,9,1,9,1,9,9,9,1,1, // 02 + 1,9,9,1,1,9,9,9,1,9,1,9,1,9,1,9,9,9,1,1, // 03 + 1,9,1,1,1,1,9,9,1,9,1,9,1,1,1,1,9,9,1,1, // 04 + 1,9,1,1,9,1,1,1,1,9,1,1,1,1,9,1,1,1,1,1, // 05 + 1,9,9,9,9,1,1,1,1,1,1,9,9,9,9,1,1,1,1,1, // 06 + 1,9,9,9,9,9,9,9,9,1,1,1,9,9,9,9,9,9,9,1, // 07 + 1,9,1,1,1,1,1,1,1,1,1,9,1,1,1,1,1,1,1,1, // 08 + 1,9,1,9,9,9,9,9,9,9,1,1,9,9,9,9,9,9,9,1, // 09 + 1,9,1,1,1,1,9,1,1,9,1,1,1,1,1,1,1,1,1,1, // 10 + 1,9,9,9,9,9,1,9,1,9,1,9,9,9,9,9,1,1,1,1, // 11 + 1,9,1,9,1,9,9,9,1,9,1,9,1,9,1,9,9,9,1,1, // 12 + 1,9,1,9,1,9,9,9,1,9,1,9,1,9,1,9,9,9,1,1, // 13 + 1,9,1,1,1,1,9,9,1,9,1,9,1,1,1,1,9,9,1,1, // 14 + 1,9,1,1,9,1,1,1,1,9,1,1,1,1,9,1,1,1,1,1, // 15 + 1,9,9,9,9,1,1,1,1,1,1,9,9,9,9,1,1,1,1,1, // 16 + 1,1,9,9,9,9,9,9,9,1,1,1,9,9,9,1,9,9,9,9, // 17 + 1,9,1,1,1,1,1,1,1,1,1,9,1,1,1,1,1,1,1,1, // 18 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 19 + +}; + +// map helper functions + +int GetMap( int x, int y ) +{ + + if( x < 0 || + x >= MAP_WIDTH || + y < 0 || + y >= MAP_HEIGHT + ) + { + return 9; + } + + return map[(y*MAP_WIDTH)+x]; +} + + + +// Definitions + +class MapSearchNode +{ +public: + unsigned int x; // the (x,y) positions of the node + unsigned int y; + + MapSearchNode() { x = y = 0; } + MapSearchNode( unsigned int px, unsigned int py ) { x=px; y=py; } + + float GoalDistanceEstimate( MapSearchNode &nodeGoal ); + bool IsGoal( MapSearchNode &nodeGoal ); + bool GetSuccessors( AStarSearch<MapSearchNode> *astarsearch, MapSearchNode *parent_node ); + float GetCost( MapSearchNode &successor ); + bool IsSameState( MapSearchNode &rhs ); + + void PrintNodeInfo(); + + +}; + +bool MapSearchNode::IsSameState( MapSearchNode &rhs ) +{ + + // same state in a maze search is simply when (x,y) are the same + if( (x == rhs.x) && + (y == rhs.y) ) + { + return true; + } + else + { + return false; + } + +} + +void MapSearchNode::PrintNodeInfo() +{ + cout << "Node position : (" << x << ", " << y << ")" << endl; +} + +// Here's the heuristic function that estimates the distance from a Node +// to the Goal. + +float MapSearchNode::GoalDistanceEstimate( MapSearchNode &nodeGoal ) +{ + float xd = fabs(float(((float)x - (float)nodeGoal.x))); + float yd = fabs(float(((float)y - (float)nodeGoal.y))); + + return xd + yd; +} + +bool MapSearchNode::IsGoal( MapSearchNode &nodeGoal ) +{ + + if( (x == nodeGoal.x) && + (y == nodeGoal.y) ) + { + return true; + } + + return false; +} + +// This generates the successors to the given Node. It uses a helper function called +// AddSuccessor to give the successors to the AStar class. The A* specific initialisation +// is done for each node internally, so here you just set the state information that +// is specific to the application +bool MapSearchNode::GetSuccessors( AStarSearch<MapSearchNode> *astarsearch, MapSearchNode *parent_node ) +{ + + int parent_x = -1; + int parent_y = -1; + + if( parent_node ) + { + parent_x = parent_node->x; + parent_y = parent_node->y; + } + + + MapSearchNode NewNode; + + // push each possible move except allowing the search to go backwards + + if( (GetMap( x-1, y ) < 9) + && !((parent_x == x-1) && (parent_y == y)) + ) + { + NewNode = MapSearchNode( x-1, y ); + astarsearch->AddSuccessor( NewNode ); + } + + if( (GetMap( x, y-1 ) < 9) + && !((parent_x == x) && (parent_y == y-1)) + ) + { + NewNode = MapSearchNode( x, y-1 ); + astarsearch->AddSuccessor( NewNode ); + } + + if( (GetMap( x+1, y ) < 9) + && !((parent_x == x+1) && (parent_y == y)) + ) + { + NewNode = MapSearchNode( x+1, y ); + astarsearch->AddSuccessor( NewNode ); + } + + + if( (GetMap( x, y+1 ) < 9) + && !((parent_x == x) && (parent_y == y+1)) + ) + { + NewNode = MapSearchNode( x, y+1 ); + astarsearch->AddSuccessor( NewNode ); + } + + return true; +} + +// given this node, what does it cost to move to successor. In the case +// of our map the answer is the map terrain value at this node since that is +// conceptually where we're moving + +float MapSearchNode::GetCost( MapSearchNode &successor ) +{ + return (float) GetMap( x, y ); + +} + + +// Main + +int main( int argc, char *argv[] ) +{ + + cout << "STL A* Search implementation\n(C)2001 Justin Heyes-Jones\n"; + + // Our sample problem defines the world as a 2d array representing a terrain + // Each element contains an integer from 0 to 5 which indicates the cost + // of travel across the terrain. Zero means the least possible difficulty + // in travelling (think ice rink if you can skate) whilst 5 represents the + // most difficult. 9 indicates that we cannot pass. + + // Create an instance of the search class... + + AStarSearch<MapSearchNode> astarsearch; + + unsigned int SearchCount = 0; + + const unsigned int NumSearches = 1; + + while(SearchCount < NumSearches) + { + + // Create a start state + MapSearchNode nodeStart; + nodeStart.x = rand()%MAP_WIDTH; + nodeStart.y = rand()%MAP_HEIGHT; + + // Define the goal state + MapSearchNode nodeEnd; + nodeEnd.x = rand()%MAP_WIDTH; + nodeEnd.y = rand()%MAP_HEIGHT; + + // Set Start and goal states + + astarsearch.SetStartAndGoalStates( nodeStart, nodeEnd ); + + unsigned int SearchState; + unsigned int SearchSteps = 0; + + do + { + SearchState = astarsearch.SearchStep(); + + SearchSteps++; + + #if DEBUG_LISTS + + cout << "Steps:" << SearchSteps << "\n"; + + int len = 0; + + cout << "Open:\n"; + MapSearchNode *p = astarsearch.GetOpenListStart(); + while( p ) + { + len++; + #if !DEBUG_LIST_LENGTHS_ONLY + ((MapSearchNode *)p)->PrintNodeInfo(); + #endif + p = astarsearch.GetOpenListNext(); + + } + + cout << "Open list has " << len << " nodes\n"; + + len = 0; + + cout << "Closed:\n"; + p = astarsearch.GetClosedListStart(); + while( p ) + { + len++; + #if !DEBUG_LIST_LENGTHS_ONLY + p->PrintNodeInfo(); + #endif + p = astarsearch.GetClosedListNext(); + } + + cout << "Closed list has " << len << " nodes\n"; + #endif + + } + while( SearchState == AStarSearch<MapSearchNode>::SEARCH_STATE_SEARCHING ); + + if( SearchState == AStarSearch<MapSearchNode>::SEARCH_STATE_SUCCEEDED ) + { + cout << "Search found goal state\n"; + + MapSearchNode *node = astarsearch.GetSolutionStart(); + + #if DISPLAY_SOLUTION + cout << "Displaying solution\n"; + #endif + int steps = 0; + + node->PrintNodeInfo(); + for( ;; ) + { + node = astarsearch.GetSolutionNext(); + + if( !node ) + { + break; + } + + node->PrintNodeInfo(); + steps ++; + + }; + + cout << "Solution steps " << steps << endl; + + // Once you're done with the solution you can free the nodes up + astarsearch.FreeSolutionNodes(); + + + } + else if( SearchState == AStarSearch<MapSearchNode>::SEARCH_STATE_FAILED ) + { + cout << "Search terminated. Did not find goal state\n"; + + } + + // Display the number of loops the search went through + cout << "SearchSteps : " << SearchSteps << "\n"; + + SearchCount ++; + + astarsearch.EnsureMemoryFreed(); + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/astar/fsa.h b/astar/fsa.h @@ -0,0 +1,250 @@ +/* + +A* Algorithm Implementation using STL is +Copyright (C)2001-2005 Justin Heyes-Jones + +Permission is given by the author to freely redistribute and +include this code in any program as long as this credit is +given where due. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, + INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE + IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE + OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND + PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED + CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL + DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY + NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF + WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE + OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER + THIS DISCLAIMER. + + Use at your own risk! + + + + FixedSizeAllocator class + Copyright 2001 Justin Heyes-Jones + + This class is a constant time O(1) memory manager for objects of + a specified type. The type is specified using a template class. + + Memory is allocated from a fixed size buffer which you can specify in the + class constructor or use the default. + + Using GetFirst and GetNext it is possible to iterate through the elements + one by one, and this would be the most common use for the class. + + I would suggest using this class when you want O(1) add and delete + and you don't do much searching, which would be O(n). Structures such as binary + trees can be used instead to get O(logn) access time. + +*/ + +#ifndef FSA_H +#define FSA_H + +#include <string.h> +#include <stdio.h> + +template <class USER_TYPE> class FixedSizeAllocator +{ + +public: + // Constants + enum + { + FSA_DEFAULT_SIZE = 100 + }; + + // This class enables us to transparently manage the extra data + // needed to enable the user class to form part of the double-linked + // list class + struct FSA_ELEMENT + { + USER_TYPE UserType; + + FSA_ELEMENT *pPrev; + FSA_ELEMENT *pNext; + }; + +public: // methods + FixedSizeAllocator( unsigned int MaxElements = FSA_DEFAULT_SIZE ) : + m_MaxElements( MaxElements ), + m_pFirstUsed( NULL ) + { + // Allocate enough memory for the maximum number of elements + + m_pMemory = (FSA_ELEMENT *) (new char[ m_MaxElements * sizeof(FSA_ELEMENT) ]); + + // Set the free list first pointer + m_pFirstFree = m_pMemory; + + // Clear the memory + memset( m_pMemory, 0, sizeof( FSA_ELEMENT ) * m_MaxElements ); + + // Point at first element + FSA_ELEMENT *pElement = m_pFirstFree; + + // Set the double linked free list + for( unsigned int i=0; i<m_MaxElements; i++ ) + { + pElement->pPrev = pElement-1; + pElement->pNext = pElement+1; + + pElement++; + } + + // first element should have a null prev + m_pFirstFree->pPrev = NULL; + // last element should have a null next + (pElement-1)->pNext = NULL; + + } + + + ~FixedSizeAllocator() + { + // Free up the memory + delete [] (char *) m_pMemory; + } + + // Allocate a new USER_TYPE and return a pointer to it + USER_TYPE *alloc() + { + + FSA_ELEMENT *pNewNode = NULL; + + if( !m_pFirstFree ) + { + return NULL; + } + else + { + pNewNode = m_pFirstFree; + m_pFirstFree = pNewNode->pNext; + + // if the new node points to another free node then + // change that nodes prev free pointer... + if( pNewNode->pNext ) + { + pNewNode->pNext->pPrev = NULL; + } + + // node is now on the used list + + pNewNode->pPrev = NULL; // the allocated node is always first in the list + + if( m_pFirstUsed == NULL ) + { + pNewNode->pNext = NULL; // no other nodes + } + else + { + m_pFirstUsed->pPrev = pNewNode; // insert this at the head of the used list + pNewNode->pNext = m_pFirstUsed; + } + + m_pFirstUsed = pNewNode; + } + + return reinterpret_cast<USER_TYPE*>(pNewNode); + } + + // Free the given user type + // For efficiency I don't check whether the user_data is a valid + // pointer that was allocated. I may add some debug only checking + // (To add the debug check you'd need to make sure the pointer is in + // the m_pMemory area and is pointing at the start of a node) + void free( USER_TYPE *user_data ) + { + FSA_ELEMENT *pNode = reinterpret_cast<FSA_ELEMENT*>(user_data); + + // manage used list, remove this node from it + if( pNode->pPrev ) + { + pNode->pPrev->pNext = pNode->pNext; + } + else + { + // this handles the case that we delete the first node in the used list + m_pFirstUsed = pNode->pNext; + } + + if( pNode->pNext ) + { + pNode->pNext->pPrev = pNode->pPrev; + } + + // add to free list + if( m_pFirstFree == NULL ) + { + // free list was empty + m_pFirstFree = pNode; + pNode->pPrev = NULL; + pNode->pNext = NULL; + } + else + { + // Add this node at the start of the free list + m_pFirstFree->pPrev = pNode; + pNode->pNext = m_pFirstFree; + m_pFirstFree = pNode; + } + + } + + // For debugging this displays both lists (using the prev/next list pointers) + void Debug() + { + printf( "free list " ); + + FSA_ELEMENT *p = m_pFirstFree; + while( p ) + { + printf( "%x!%x ", p->pPrev, p->pNext ); + p = p->pNext; + } + printf( "\n" ); + + printf( "used list " ); + + p = m_pFirstUsed; + while( p ) + { + printf( "%x!%x ", p->pPrev, p->pNext ); + p = p->pNext; + } + printf( "\n" ); + } + + // Iterators + + USER_TYPE *GetFirst() + { + return reinterpret_cast<USER_TYPE *>(m_pFirstUsed); + } + + USER_TYPE *GetNext( USER_TYPE *node ) + { + return reinterpret_cast<USER_TYPE *> + ( + (reinterpret_cast<FSA_ELEMENT *>(node))->pNext + ); + } + +public: // data + +private: // methods + +private: // data + + FSA_ELEMENT *m_pFirstFree; + FSA_ELEMENT *m_pFirstUsed; + unsigned int m_MaxElements; + FSA_ELEMENT *m_pMemory; + +}; + +#endif // defined FSA_H diff --git a/astar/license.txt b/astar/license.txt @@ -0,0 +1,20 @@ +Copyright (c) 2006 Justin Heyes-Jones + +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. + diff --git a/astar/readme.txt b/astar/readme.txt @@ -0,0 +1,145 @@ +********************************** +A* Algorithm by Justin Heyes-Jones +********************************** + +*********** +Description +*********** + +This implementation is intended to be simple to read yet fairly +efficient. To build it you can compile, with any recent C++ compiler, +the following files : + +For 8-puzzle solver + + 8puzzle.cpp + stlastar.h + optionally fsa.h + +Command line + + 8puzzle with no arguments runs with one of the boards in the cpp file, you can + select the one you want changing the conditional compiliation instructions. Or if you + prefer pass in a board on the command line using digits for the tile positions, where + zero is the space. The board runs from left to right, each row at a time: + + 8puzzle 013824765 + +For path finder + + findpath.cpp + stlastar.h + optionally fsa.h + + pathfind has no arguments. You can edit the simple map in pathfind.cpp and the start + and goal co-ordinates to experiement with the pathfinder. + +Fixed size allocator notes: As mentioned briefly in the tutorial you can enable and disable the +faster memory allocation. This allocates a fixed size block of memory, so you have to specify this size +with the astar constructor. You need to enlarge it if you hit an out of memory assert during the +search. + +Compilation notes: + +Microsoft Visual C++ : Confirmed working with version 8.0.50727 with some deprecation warnings +I'm going to leave the deprecation warnings in so that it still works cleanly with GCC. +TODO Make a non-deprecated compliant version using compiler checking + +GCC notes : Compiled using version 3.4.5 (MingW) + +Please let me know if it doesn't work for you and I will try to help. I cannot help if you are using +an old compiler such as Turbo C++, since I update the code to meet Ansi Standard C++ as required. + +At least in as far as the Microsoft and GCC compilers adhere to Ansi and add breaking changes. + +History: + +Updated 1th February 2009 +********************************** + +Fixed Manhattan distance bug. Should use absolute values. + +Got rid of sprintfs, use cout instead. + +Updated 3rd August 2006 +********************************** + +Fixed memory leak +Fixed special case handling for finding better path to a closed node +Fixed bug with comparing the start node with a new node by pointer instead of value +Changed code to use Manhattan distance heuristic with pathfind.cpp as it is more correct + + +Updated 27th September 2005 +********************************** + +Thanks to Gyan singh for pointing out the code no longer compiles under GCC. + +Well, that was the case. I've removed a Gnu offending conio.h include, and added lots more typename +keywords, which seem to be required now when making an iterator using a template type. + +If anyone knows what the breaking change to the compiler was for, let me know. + +Updated 6th September 2005 +********************************** + + Finally set the path to fsa.h correctly, sorry about that. + 8puzzle.cpp now defaults to using a demo puzzle that solves in a short time. + Added typename keyword to comply with latest ISO standards. + +Updated November 26th 2001 +********************************** + + Fixed a bug. When a node is deleted from the Open list I did sort_heap when make_heap + is needed to keep the heap structure valid. This causes the search to go awry under some + conditions. Thanks to Mike Ryynanen for tracking this down. + +justinhj@hotmail.com + +http://www.geocities.com/jheyesjones/astar.html + +or + +http://www.heyes-jones.com/astar.html + +A* Algorithm Implementation using STL is +Copyright (C)2001-2005 Justin Heyes-Jones + +Permission is given by the author to freely redistribute and +include this code in any program as long as this credit is +given where due. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, + INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE + IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE + OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND + PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED + CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL + DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY + NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF + WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE + OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER + THIS DISCLAIMER. + + Use at your own risk! + + + + + + + + + + + + + + + + + + + + diff --git a/astar/stlastar.h b/astar/stlastar.h @@ -0,0 +1,754 @@ +/* +A* Algorithm Implementation using STL is +Copyright (C)2001-2005 Justin Heyes-Jones + +Permission is given by the author to freely redistribute and +include this code in any program as long as this credit is +given where due. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, + INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE + IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE + OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND + PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED + CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL + DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY + NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF + WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE + OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER + THIS DISCLAIMER. + + Use at your own risk! + +*/ + +// used for text debugging +#include <iostream> +#include <stdio.h> +//#include <conio.h> +#include <assert.h> + +// stl includes +#include <algorithm> +#include <set> +#include <vector> + +using namespace std; + +// fast fixed size memory allocator, used for fast node memory management +#include "fsa.h" + +// Fixed size memory allocator can be disabled to compare performance +// Uses std new and delete instead if you turn it off +#define USE_FSA_MEMORY 1 + +// disable warning that debugging information has lines that are truncated +// occurs in stl headers +#pragma warning( disable : 4786 ) + +// The AStar search class. UserState is the users state space type +template <class UserState> class AStarSearch +{ + +public: // data + + enum + { + SEARCH_STATE_NOT_INITIALISED, + SEARCH_STATE_SEARCHING, + SEARCH_STATE_SUCCEEDED, + SEARCH_STATE_FAILED, + SEARCH_STATE_OUT_OF_MEMORY, + SEARCH_STATE_INVALID + }; + + + // A node represents a possible state in the search + // The user provided state type is included inside this type + + public: + + class Node + { + public: + + Node *parent; // used during the search to record the parent of successor nodes + Node *child; // used after the search for the application to view the search in reverse + + float g; // cost of this node + it's predecessors + float h; // heuristic estimate of distance to goal + float f; // sum of cumulative cost of predecessors and self and heuristic + + Node() : + parent( 0 ), + child( 0 ), + g( 0.0f ), + h( 0.0f ), + f( 0.0f ) + { + } + + UserState m_UserState; + }; + + + // For sorting the heap the STL needs compare function that lets us compare + // the f value of two nodes + + class HeapCompare_f + { + public: + + bool operator() ( const Node *x, const Node *y ) const + { + return x->f > y->f; + } + }; + + +public: // methods + + + // constructor just initialises private data + AStarSearch( int MaxNodes = 1000 ) : + m_AllocateNodeCount(0), +#if USE_FSA_MEMORY + m_FixedSizeAllocator( MaxNodes ), +#endif + m_State( SEARCH_STATE_NOT_INITIALISED ), + m_CurrentSolutionNode( NULL ), + m_CancelRequest( false ) + { + } + + // call at any time to cancel the search and free up all the memory + void CancelSearch() + { + m_CancelRequest = true; + } + + // Set Start and goal states + void SetStartAndGoalStates( UserState &Start, UserState &Goal ) + { + m_CancelRequest = false; + + m_Start = AllocateNode(); + m_Goal = AllocateNode(); + + assert((m_Start != NULL && m_Goal != NULL)); + + m_Start->m_UserState = Start; + m_Goal->m_UserState = Goal; + + m_State = SEARCH_STATE_SEARCHING; + + // Initialise the AStar specific parts of the Start Node + // The user only needs fill out the state information + + m_Start->g = 0; + m_Start->h = m_Start->m_UserState.GoalDistanceEstimate( m_Goal->m_UserState ); + m_Start->f = m_Start->g + m_Start->h; + m_Start->parent = 0; + + // Push the start node on the Open list + + m_OpenList.push_back( m_Start ); // heap now unsorted + + // Sort back element into heap + push_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() ); + + // Initialise counter for search steps + m_Steps = 0; + } + + // Advances search one step + unsigned int SearchStep() + { + // Firstly break if the user has not initialised the search + assert( (m_State > SEARCH_STATE_NOT_INITIALISED) && + (m_State < SEARCH_STATE_INVALID) ); + + // Next I want it to be safe to do a searchstep once the search has succeeded... + if( (m_State == SEARCH_STATE_SUCCEEDED) || + (m_State == SEARCH_STATE_FAILED) + ) + { + return m_State; + } + + // Failure is defined as emptying the open list as there is nothing left to + // search... + // New: Allow user abort + if( m_OpenList.empty() || m_CancelRequest ) + { + FreeAllNodes(); + m_State = SEARCH_STATE_FAILED; + return m_State; + } + + // Incremement step count + m_Steps ++; + + // Pop the best node (the one with the lowest f) + Node *n = m_OpenList.front(); // get pointer to the node + pop_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() ); + m_OpenList.pop_back(); + + // Check for the goal, once we pop that we're done + if( n->m_UserState.IsGoal( m_Goal->m_UserState ) ) + { + // The user is going to use the Goal Node he passed in + // so copy the parent pointer of n + m_Goal->parent = n->parent; + + // A special case is that the goal was passed in as the start state + // so handle that here + if( false == n->m_UserState.IsSameState( m_Start->m_UserState ) ) + { + FreeNode( n ); + + // set the child pointers in each node (except Goal which has no child) + Node *nodeChild = m_Goal; + Node *nodeParent = m_Goal->parent; + + do + { + nodeParent->child = nodeChild; + + nodeChild = nodeParent; + nodeParent = nodeParent->parent; + + } + while( nodeChild != m_Start ); // Start is always the first node by definition + + } + + // delete nodes that aren't needed for the solution + FreeUnusedNodes(); + + m_State = SEARCH_STATE_SUCCEEDED; + + return m_State; + } + else // not goal + { + + // We now need to generate the successors of this node + // The user helps us to do this, and we keep the new nodes in + // m_Successors ... + + m_Successors.clear(); // empty vector of successor nodes to n + + // User provides this functions and uses AddSuccessor to add each successor of + // node 'n' to m_Successors + bool ret = n->m_UserState.GetSuccessors( this, n->parent ? &n->parent->m_UserState : NULL ); + + if( !ret ) + { + + typename vector< Node * >::iterator successor; + + // free the nodes that may previously have been added + for( successor = m_Successors.begin(); successor != m_Successors.end(); successor ++ ) + { + FreeNode( (*successor) ); + } + + m_Successors.clear(); // empty vector of successor nodes to n + + // free up everything else we allocated + FreeAllNodes(); + + m_State = SEARCH_STATE_OUT_OF_MEMORY; + return m_State; + } + + // Now handle each successor to the current node ... + for( typename vector< Node * >::iterator successor = m_Successors.begin(); successor != m_Successors.end(); successor ++ ) + { + + // The g value for this successor ... + float newg = n->g + n->m_UserState.GetCost( (*successor)->m_UserState ); + + // Now we need to find whether the node is on the open or closed lists + // If it is but the node that is already on them is better (lower g) + // then we can forget about this successor + + // First linear search of open list to find node + + typename vector< Node * >::iterator openlist_result; + + for( openlist_result = m_OpenList.begin(); openlist_result != m_OpenList.end(); openlist_result ++ ) + { + if( (*openlist_result)->m_UserState.IsSameState( (*successor)->m_UserState ) ) + { + break; + } + } + + if( openlist_result != m_OpenList.end() ) + { + + // we found this state on open + + if( (*openlist_result)->g <= newg ) + { + FreeNode( (*successor) ); + + // the one on Open is cheaper than this one + continue; + } + } + + typename vector< Node * >::iterator closedlist_result; + + for( closedlist_result = m_ClosedList.begin(); closedlist_result != m_ClosedList.end(); closedlist_result ++ ) + { + if( (*closedlist_result)->m_UserState.IsSameState( (*successor)->m_UserState ) ) + { + break; + } + } + + if( closedlist_result != m_ClosedList.end() ) + { + + // we found this state on closed + + if( (*closedlist_result)->g <= newg ) + { + // the one on Closed is cheaper than this one + FreeNode( (*successor) ); + + continue; + } + } + + // This node is the best node so far with this particular state + // so lets keep it and set up its AStar specific data ... + + (*successor)->parent = n; + (*successor)->g = newg; + (*successor)->h = (*successor)->m_UserState.GoalDistanceEstimate( m_Goal->m_UserState ); + (*successor)->f = (*successor)->g + (*successor)->h; + + // Remove successor from closed if it was on it + + if( closedlist_result != m_ClosedList.end() ) + { + // remove it from Closed + FreeNode( (*closedlist_result) ); + m_ClosedList.erase( closedlist_result ); + + // Fix thanks to ... + // Greg Douglas <gregdouglasmail@gmail.com> + // who noticed that this code path was incorrect + // Here we have found a new state which is already CLOSED + // anus + + } + + // Update old version of this node + if( openlist_result != m_OpenList.end() ) + { + + FreeNode( (*openlist_result) ); + m_OpenList.erase( openlist_result ); + + // re-make the heap + // make_heap rather than sort_heap is an essential bug fix + // thanks to Mike Ryynanen for pointing this out and then explaining + // it in detail. sort_heap called on an invalid heap does not work + make_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() ); + + } + + // heap now unsorted + m_OpenList.push_back( (*successor) ); + + // sort back element into heap + push_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() ); + + } + + // push n onto Closed, as we have expanded it now + + m_ClosedList.push_back( n ); + + } // end else (not goal so expand) + + return m_State; // Succeeded bool is false at this point. + + } + + // User calls this to add a successor to a list of successors + // when expanding the search frontier + bool AddSuccessor( UserState &State ) + { + Node *node = AllocateNode(); + + if( node ) + { + node->m_UserState = State; + + m_Successors.push_back( node ); + + return true; + } + + return false; + } + + // Free the solution nodes + // This is done to clean up all used Node memory when you are done with the + // search + void FreeSolutionNodes() + { + Node *n = m_Start; + + if( m_Start->child ) + { + do + { + Node *del = n; + n = n->child; + FreeNode( del ); + + del = NULL; + + } while( n != m_Goal ); + + FreeNode( n ); // Delete the goal + + } + else + { + // if the start node is the solution we need to just delete the start and goal + // nodes + FreeNode( m_Start ); + FreeNode( m_Goal ); + } + + } + + // Functions for traversing the solution + + // Get start node + UserState *GetSolutionStart() + { + m_CurrentSolutionNode = m_Start; + if( m_Start ) + { + return &m_Start->m_UserState; + } + else + { + return NULL; + } + } + + // Get next node + UserState *GetSolutionNext() + { + if( m_CurrentSolutionNode ) + { + if( m_CurrentSolutionNode->child ) + { + + Node *child = m_CurrentSolutionNode->child; + + m_CurrentSolutionNode = m_CurrentSolutionNode->child; + + return &child->m_UserState; + } + } + + return NULL; + } + + // Get end node + UserState *GetSolutionEnd() + { + m_CurrentSolutionNode = m_Goal; + if( m_Goal ) + { + return &m_Goal->m_UserState; + } + else + { + return NULL; + } + } + + // Step solution iterator backwards + UserState *GetSolutionPrev() + { + if( m_CurrentSolutionNode ) + { + if( m_CurrentSolutionNode->parent ) + { + + Node *parent = m_CurrentSolutionNode->parent; + + m_CurrentSolutionNode = m_CurrentSolutionNode->parent; + + return &parent->m_UserState; + } + } + + return NULL; + } + + // For educational use and debugging it is useful to be able to view + // the open and closed list at each step, here are two functions to allow that. + + UserState *GetOpenListStart() + { + float f,g,h; + return GetOpenListStart( f,g,h ); + } + + UserState *GetOpenListStart( float &f, float &g, float &h ) + { + iterDbgOpen = m_OpenList.begin(); + if( iterDbgOpen != m_OpenList.end() ) + { + f = (*iterDbgOpen)->f; + g = (*iterDbgOpen)->g; + h = (*iterDbgOpen)->h; + return &(*iterDbgOpen)->m_UserState; + } + + return NULL; + } + + UserState *GetOpenListNext() + { + float f,g,h; + return GetOpenListNext( f,g,h ); + } + + UserState *GetOpenListNext( float &f, float &g, float &h ) + { + iterDbgOpen++; + if( iterDbgOpen != m_OpenList.end() ) + { + f = (*iterDbgOpen)->f; + g = (*iterDbgOpen)->g; + h = (*iterDbgOpen)->h; + return &(*iterDbgOpen)->m_UserState; + } + + return NULL; + } + + UserState *GetClosedListStart() + { + float f,g,h; + return GetClosedListStart( f,g,h ); + } + + UserState *GetClosedListStart( float &f, float &g, float &h ) + { + iterDbgClosed = m_ClosedList.begin(); + if( iterDbgClosed != m_ClosedList.end() ) + { + f = (*iterDbgClosed)->f; + g = (*iterDbgClosed)->g; + h = (*iterDbgClosed)->h; + + return &(*iterDbgClosed)->m_UserState; + } + + return NULL; + } + + UserState *GetClosedListNext() + { + float f,g,h; + return GetClosedListNext( f,g,h ); + } + + UserState *GetClosedListNext( float &f, float &g, float &h ) + { + iterDbgClosed++; + if( iterDbgClosed != m_ClosedList.end() ) + { + f = (*iterDbgClosed)->f; + g = (*iterDbgClosed)->g; + h = (*iterDbgClosed)->h; + + return &(*iterDbgClosed)->m_UserState; + } + + return NULL; + } + + // Get the number of steps + + int GetStepCount() { return m_Steps; } + + void EnsureMemoryFreed() + { +#if USE_FSA_MEMORY + assert(m_AllocateNodeCount == 0); +#endif + + } + +private: // methods + + // This is called when a search fails or is cancelled to free all used + // memory + void FreeAllNodes() + { + // iterate open list and delete all nodes + typename vector< Node * >::iterator iterOpen = m_OpenList.begin(); + + while( iterOpen != m_OpenList.end() ) + { + Node *n = (*iterOpen); + FreeNode( n ); + + iterOpen ++; + } + + m_OpenList.clear(); + + // iterate closed list and delete unused nodes + typename vector< Node * >::iterator iterClosed; + + for( iterClosed = m_ClosedList.begin(); iterClosed != m_ClosedList.end(); iterClosed ++ ) + { + Node *n = (*iterClosed); + FreeNode( n ); + } + + m_ClosedList.clear(); + + // delete the goal + + FreeNode(m_Goal); + } + + + // This call is made by the search class when the search ends. A lot of nodes may be + // created that are still present when the search ends. They will be deleted by this + // routine once the search ends + void FreeUnusedNodes() + { + // iterate open list and delete unused nodes + typename vector< Node * >::iterator iterOpen = m_OpenList.begin(); + + while( iterOpen != m_OpenList.end() ) + { + Node *n = (*iterOpen); + + if( !n->child ) + { + FreeNode( n ); + + n = NULL; + } + + iterOpen ++; + } + + m_OpenList.clear(); + + // iterate closed list and delete unused nodes + typename vector< Node * >::iterator iterClosed; + + for( iterClosed = m_ClosedList.begin(); iterClosed != m_ClosedList.end(); iterClosed ++ ) + { + Node *n = (*iterClosed); + + if( !n->child ) + { + FreeNode( n ); + n = NULL; + + } + } + + m_ClosedList.clear(); + + } + + // Node memory management + Node *AllocateNode() + { + +#if !USE_FSA_MEMORY + Node *p = new Node; + return p; +#else + Node *address = m_FixedSizeAllocator.alloc(); + + if( !address ) + { + return NULL; + } + m_AllocateNodeCount ++; + Node *p = new (address) Node; + return p; +#endif + } + + void FreeNode( Node *node ) + { + + m_AllocateNodeCount --; + +#if !USE_FSA_MEMORY + delete node; +#else + m_FixedSizeAllocator.free( node ); +#endif + } + +private: // data + + // Heap (simple vector but used as a heap, cf. Steve Rabin's game gems article) + vector< Node *> m_OpenList; + + // Closed list is a vector. + vector< Node * > m_ClosedList; + + // Successors is a vector filled out by the user each type successors to a node + // are generated + vector< Node * > m_Successors; + + // State + unsigned int m_State; + + // Counts steps + int m_Steps; + + // Start and goal state pointers + Node *m_Start; + Node *m_Goal; + + Node *m_CurrentSolutionNode; + +#if USE_FSA_MEMORY + // Memory + FixedSizeAllocator<Node> m_FixedSizeAllocator; +#endif + + //Debug : need to keep these two iterators around + // for the user Dbg functions + typename vector< Node * >::iterator iterDbgOpen; + typename vector< Node * >::iterator iterDbgClosed; + + // debugging : count memory allocation and free's + int m_AllocateNodeCount; + + bool m_CancelRequest; + +}; + + + + diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(modules) diff --git a/cmake/modules/COPYING-CMAKE-SCRIPTS b/cmake/modules/COPYING-CMAKE-SCRIPTS @@ -0,0 +1,22 @@ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/cmake/modules/CheckStructMember.cmake b/cmake/modules/CheckStructMember.cmake @@ -0,0 +1,40 @@ +# - Check if the given struct or class has the specified member variable +# CHECK_STRUCT_MEMBER (STRUCT MEMBER HEADER VARIABLE) +# +# STRUCT - the name of the struct or class you are interested in +# MEMBER - the member which existence you want to check +# HEADER - the header(s) where the prototype should be declared +# VARIABLE - variable to store the result +# +# The following variables may be set before calling this macro to +# modify the way the check is run: +# +# CMAKE_REQUIRED_FLAGS = string of compile command line flags +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) +# CMAKE_REQUIRED_INCLUDES = list of include directories + +# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org> +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +MACRO (CHECK_STRUCT_MEMBER _STRUCT _MEMBER _HEADER _RESULT) + SET(_INCLUDE_FILES) + FOREACH (it ${_HEADER}) + SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n") + ENDFOREACH (it) + + SET(_CHECK_STRUCT_MEMBER_SOURCE_CODE " +${_INCLUDE_FILES} +int main() +{ + ${_STRUCT}* tmp; + tmp->${_MEMBER}; + return 0; +} +") + + CHECK_CXX_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT}) + +ENDMACRO (CHECK_STRUCT_MEMBER) + diff --git a/cmake/modules/CheckType.cmake b/cmake/modules/CheckType.cmake @@ -0,0 +1,37 @@ +# - Check if the given struct or class has the specified member variable +# CHECK_TYPE (TYPE RESULT INCLUDES) +# +# TYPE - The variable you want to test +# HEADER - Headers included in the test +# RESULT - True if found +# +# The following variables may be set before calling this macro to +# modify the way the check is run: +# +# CMAKE_REQUIRED_FLAGS = string of compile command line flags +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) +# CMAKE_REQUIRED_INCLUDES = list of include directories + +# Copyright (c) 2008, Andrew Fenn <andrewfenn@gmail.com> +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +MACRO (CHECK_TYPE _TYPE _HEADER _RESULT) + SET(_INCLUDE_FILES) + FOREACH (it ${_HEADER}) + SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n") + ENDFOREACH (it) + + SET(_CHECK_STRUCT_MEMBER_SOURCE_CODE " +${_INCLUDE_FILES} +int main() +{ + ${_TYPE}* tmp; + return 0; +} +") + +CHECK_CXX_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT}) +ENDMACRO (CHECK_TYPE) + diff --git a/cmake/modules/FindENET.cmake b/cmake/modules/FindENET.cmake @@ -0,0 +1,74 @@ +SET( ENET_DEFINITIONS "") + +## +# You're going to have to edit this file if you intend to use it for your own project +## +SET( ENET_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/dependencies/enet ) + +IF( EXISTS ${ENET_INCLUDE_DIR} ) + SET( ENET_FOUND TRUE ) + FILE(GLOB ENET_source ${ENET_INCLUDE_DIR}/*.c) + ADD_LIBRARY(Enet_${PROJECT_NAME} ${ENET_source}) + SET(ENET_LIBRARIES Enet_${PROJECT_NAME}) + SET(ENET_INCLUDE_DIR ${ENET_INCLUDE_DIR}/include) + IF (WINDOWS) + IF (WIN32) + TARGET_LINK_LIBRARIES(Enet_${PROJECT_NAME} "ws2_32.lib") + ELSE (WIN32) + TARGET_LINK_LIBRARIES(Enet_${PROJECT_NAME} "ws2_64.lib") + ENDIF (WIN32) + ELSE (WINDOWS) # unix + INCLUDE(CheckCSourceCompiles) + INCLUDE(CheckCXXSourceCompiles) + INCLUDE(CheckStructMember) + INCLUDE(CheckType) + INCLUDE(CheckFunctionExists) + INCLUDE(CheckIncludeFiles) + + + CHECK_FUNCTION_EXISTS("gethostbyaddr_r" _HAS_GETHOSTBYADDR_R) + CHECK_FUNCTION_EXISTS("gethostbyname_r" _HAS_GETHOSTBYNAME_R) + CHECK_FUNCTION_EXISTS("poll" _HAS_POLL) + CHECK_FUNCTION_EXISTS("fcntl" _HAS_FCNTL) + CHECK_FUNCTION_EXISTS("inet_pton" _HAS_INET_PTON) + CHECK_FUNCTION_EXISTS("inet_ntop" _HAS_INET_NTOP) + + CHECK_INCLUDE_FILES ("sys/socket.h" _HAS_SOCKET_INCLUDE) + CHECK_INCLUDE_FILES ("sys/types.h" _HAS_TYPES_INCLUDE) + + CHECK_STRUCT_MEMBER("msghdr" "msg_flags" "sys/socket.h" _HAS_MSGHDR_FLAGS) + CHECK_TYPE(socklen_t "sys/types.h;sys/socket.h" _HAS_SOCKLEN_T) + + # list all from above here and add them to the definitions + SET(_CHECKS HAS_GETHOSTBYADDR_R; HAS_GETHOSTBYNAME_R; HAS_POLL; HAS_FCNTL; HAS_INET_PTON; HAS_INET_NTOP; HAS_SOCKET_INCLUDE; HAS_TYPES_INCLUDE; HAS_MSGHDR_FLAGS; HAS_SOCKLEN_T;) + FOREACH (it ${_CHECKS}) + IF (${_${it}}) + SET(ENET_DEFINITIONS "${ENET_DEFINITIONS}-D${it}=1 ") + ENDIF (${_${it}}) + ENDFOREACH (it) + + SET_SOURCE_FILES_PROPERTIES(${ENET_source} PROPERTIES COMPILE_FLAGS ${ENET_DEFINITIONS}) + ENDIF (WINDOWS) +ENDIF( EXISTS ${ENET_INCLUDE_DIR} ) + +IF( NOT ENET_FOUND) + IF( NOT ENET_INCLUDE_DIR ) + IF (ENET_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find Enet") + ENDIF (ENET_FIND_REQUIRED) + ENDIF( NOT ENET_INCLUDE_DIR ) +ENDIF( NOT ENET_FOUND) + + +# Finally, display informations if not in quiet mode +IF( NOT ENET_FIND_QUIETLY ) + MESSAGE( STATUS "Enet found " ) + MESSAGE( STATUS " libraries : ${ENET_LIBRARIES}" ) + MESSAGE( STATUS " includes : ${ENET_INCLUDE_DIR}" ) +ENDIF( NOT ENET_FIND_QUIETLY ) + +MARK_AS_ADVANCED( + ENET_INCLUDE_DIR + ENET_LIBRARIES +) + diff --git a/cmake/modules/FindMyGUI.cmake b/cmake/modules/FindMyGUI.cmake @@ -0,0 +1,53 @@ +# Find MyGUI includes and library +# +# This module defines +# MyGUI_INCLUDE_DIR +# MyGUI_LIBRARIES, the libraries to link against to use MyGUI. +# MyGUI_LIB_DIR, the location of the libraries +# MyGUI_FOUND, If false, do not try to use MyGUI +# +# Copyright © 2009, Andrew Fenn +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +IF (MyGUI_LIBRARIES AND MyGUI_INCLUDE_DIR) + SET(MyGUI_FIND_QUIETLY TRUE) # Already in cache, be silent +ENDIF (MyGUI_LIBRARIES AND MyGUI_INCLUDE_DIR) + +IF (WIN32) #Windows + MESSAGE(STATUS "Using MyGUI in dependencies") + SET(MyGUI_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/dependencies/mygui/MyGUIEngine/include) + SET(MyGUI_LIB_DIR ${CMAKE_SOURCE_DIR}/dependencies/mygui/MyGUIEngine/lib/Debug) + SET(MyGUI_LIBRARIES MyGUI) +ELSE (WIN32) #Unix + CMAKE_MINIMUM_REQUIRED(VERSION 2.4.7 FATAL_ERROR) + FIND_PACKAGE(PkgConfig) + PKG_SEARCH_MODULE(MyGUI MyGUI) + SET(MyGUI_INCLUDE_DIR ${MyGUI_INCLUDE_DIRS}) + SET(MyGUI_LIB_DIR ${MyGUI_LIBDIR}) + SET(MyGUI_LIBRARIES ${MyGUI_LIBRARIES} CACHE STRING "") +ENDIF (WIN32) + +#Do some preparation +SEPARATE_ARGUMENTS(MyGUI_INCLUDE_DIR) +SEPARATE_ARGUMENTS(MyGUI_LIBRARIES) + +SET(MyGUI_INCLUDE_DIR ${MyGUI_INCLUDE_DIR} CACHE PATH "") +SET(MyGUI_LIBRARIES ${MyGUI_LIBRARIES} CACHE STRING "") +SET(MyGUI_LIB_DIR ${MyGUI_LIB_DIR} CACHE PATH "") + +IF (MyGUI_INCLUDE_DIR AND MyGUI_LIBRARIES) + SET(MyGUI_FOUND TRUE) +ENDIF (MyGUI_INCLUDE_DIR AND MyGUI_LIBRARIES) + +IF (MyGUI_FOUND) + IF (NOT MyGUI_FIND_QUIETLY) + MESSAGE(STATUS " libraries : ${MyGUI_LIBRARIES} from ${MyGUI_LIB_DIR}") + MESSAGE(STATUS " includes : ${MyGUI_INCLUDE_DIR}") + ENDIF (NOT MyGUI_FIND_QUIETLY) +ELSE (MyGUI_FOUND) + IF (MyGUI_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find MyGUI") + ENDIF (MyGUI_FIND_REQUIRED) +ENDIF (MyGUI_FOUND) diff --git a/cmake/modules/FindOGRE.cmake b/cmake/modules/FindOGRE.cmake @@ -0,0 +1,462 @@ +#------------------------------------------------------------------- +# This file is part of the CMake build system for OGRE +# (Object-oriented Graphics Rendering Engine) +# For the latest info, see http://www.ogre3d.org/ +# +# The contents of this file are placed in the public domain. Feel +# free to make use of it in any way you like. +#------------------------------------------------------------------- + +# - Try to find OGRE +# If you have multiple versions of Ogre installed, use the CMake or +# the environment variable OGRE_HOME to point to the path where the +# desired Ogre version can be found. +# By default this script will look for a dynamic Ogre build. If you +# need to link against static Ogre libraries, set the CMake variable +# OGRE_STATIC to TRUE. +# +# Once done, this will define +# +# OGRE_FOUND - system has OGRE +# OGRE_INCLUDE_DIRS - the OGRE include directories +# OGRE_LIBRARIES - link these to use the OGRE core +# +# Additionally this script searches for the following optional +# parts of the Ogre package: +# Plugin_BSPSceneManager, Plugin_CgProgramManager, +# Plugin_OctreeSceneManager, Plugin_OctreeZone, +# Plugin_ParticleFX, Plugin_PCZSceneManager, +# RenderSystem_GL, RenderSystem_Direct3D9, RenderSystem_Direct3D10, +# CEGUIRenderer, Paging, Terrain +# +# For each of these components, the following variables are defined: +# +# OGRE_${COMPONENT}_FOUND - ${COMPONENT} is available +# OGRE_${COMPONENT}_INCLUDE_DIRS - additional include directories for ${COMPONENT} +# OGRE_${COMPONENT}_LIBRARIES - link these to use ${COMPONENT} +# +# Finally, the following variables are defined: +# +# OGRE_PLUGIN_DIR_REL - The directory where the release versions of +# the OGRE plugins are located +# OGRE_PLUGIN_DIR_DBG - The directory where the debug versions of +# the OGRE plugins are located +# OGRE_MEDIA_DIR - The directory where the OGRE sample media is +# located, if available + +include(FindPkgMacros) +include(PreprocessorUtils) +findpkg_begin(OGRE) + + +# Get path, convert backslashes as ${ENV_${var}} +getenv_path(OGRE_HOME) +getenv_path(OGRE_SDK) +getenv_path(OGRE_SOURCE) +getenv_path(OGRE_BUILD) +getenv_path(PROGRAMFILES) + + +# Determine whether to search for a dynamic or static build +if (OGRE_STATIC) + set(OGRE_LIB_SUFFIX "Static") +else () + set(OGRE_LIB_SUFFIX "") +endif () + + +set(OGRE_LIBRARY_NAMES "OgreMain${OGRE_LIB_SUFFIX}") +get_debug_names(OGRE_LIBRARY_NAMES) + +# construct search paths from environmental hints and +# OS specific guesses +if (WIN32) + set(OGRE_PREFIX_GUESSES + ${ENV_PROGRAMFILES}/OGRE + C:/OgreSDK + ) +elseif (UNIX) + set(OGRE_PREFIX_GUESSES + /opt/ogre + /opt/OGRE + /usr/lib/ogre + /usr/lib/OGRE + /usr/local/lib/ogre + /usr/local/lib/OGRE + $ENV{HOME}/ogre + $ENV{HOME}/OGRE + ) +endif () +set(OGRE_PREFIX_PATH + ${OGRE_HOME} ${ENV_OGRE_HOME} ${ENV_OGRE_SDK} + ${OGRE_PREFIX_GUESSES} +) +create_search_paths(OGRE) +# If both OGRE_BUILD and OGRE_SOURCE are set, prepare to find Ogre in a build dir +set(OGRE_PREFIX_SOURCE ${OGRE_SOURCE} ${ENV_OGRE_SOURCE}) +set(OGRE_PREFIX_BUILD ${OGRE_BUILD} ${ENV_OGRE_BUILD}) +if (OGRE_PREFIX_SOURCE AND OGRE_PREFIX_BUILD) + foreach(dir ${OGRE_PREFIX_SOURCE}) + set(OGRE_INC_SEARCH_PATH ${dir}/OgreMain/include ${dir}/Dependencies/include ${dir}/iPhoneDependencies/include ${OGRE_INC_SEARCH_PATH}) + set(OGRE_LIB_SEARCH_PATH ${dir}/lib ${dir}/Dependencies/lib ${dir}/iPhoneDependencies/lib ${OGRE_LIB_SEARCH_PATH}) + endforeach(dir) + foreach(dir ${OGRE_PREFIX_BUILD}) + set(OGRE_INC_SEARCH_PATH ${dir}/include ${OGRE_INC_SEARCH_PATH}) + set(OGRE_LIB_SEARCH_PATH ${dir}/lib ${OGRE_LIB_SEARCH_PATH}) + endforeach(dir) +else() + set(OGRE_PREFIX_SOURCE "NOTFOUND") + set(OGRE_PREFIX_BUILD "NOTFOUND") +endif () + +# redo search if any of the environmental hints changed +set(OGRE_COMPONENTS Paging Terrain CEGUIRenderer + Plugin_BSPSceneManager Plugin_CgProgramManager Plugin_OctreeSceneManager + Plugin_OctreeZone Plugin_PCZSceneManager Plugin_ParticleFX + RenderSystem_Direct3D10 RenderSystem_Direct3D9 RenderSystem_GL RenderSystem_GLES) +set(OGRE_RESET_VARS + OGRE_CONFIG_INCLUDE_DIR OGRE_INCLUDE_DIR + OGRE_LIBRARY_FWK OGRE_LIBRARY_REL OGRE_LIBRARY_DBG + OGRE_PLUGIN_DIR_DBG OGRE_PLUGIN_DIR_REL OGRE_MEDIA_DIR) +foreach (comp ${OGRE_COMPONENTS}) + set(OGRE_RESET_VARS ${OGRE_RESET_VARS} + OGRE_${comp}_INCLUDE_DIR OGRE_${comp}_LIBRARY_FWK + OGRE_${comp}_LIBRARY_DBG OGRE_${comp}_LIBRARY_REL + ) +endforeach (comp) +set(OGRE_PREFIX_WATCH ${OGRE_PREFIX_PATH} ${OGRE_PREFIX_SOURCE} ${OGRE_PREFIX_BUILD}) +clear_if_changed(OGRE_PREFIX_WATCH ${OGRE_RESET_VARS}) + +# try to locate Ogre via pkg-config +use_pkgconfig(OGRE_PKGC "OGRE${OGRE_LIB_SUFFIX}") +# try to find framework on OSX +findpkg_framework(OGRE) + +# locate Ogre include files +find_path(OGRE_CONFIG_INCLUDE_DIR NAMES OgreConfig.h HINTS ${OGRE_INC_SEARCH_PATH} ${OGRE_FRAMEWORK_INCLUDES} ${OGRE_PKGC_INCLUDE_DIRS} PATH_SUFFIXES "OGRE") +find_path(OGRE_INCLUDE_DIR NAMES OgreRoot.h HINTS ${OGRE_CONFIG_INCLUDE_DIR} ${OGRE_INC_SEARCH_PATH} ${OGRE_FRAMEWORK_INCLUDES} ${OGRE_PKGC_INCLUDE_DIRS} PATH_SUFFIXES "OGRE") +set(OGRE_INCOMPATIBLE FALSE) + +if (OGRE_INCLUDE_DIR AND OGRE_CONFIG_INCLUDE_DIR) + # determine Ogre version + file(READ ${OGRE_INCLUDE_DIR}/OgrePrerequisites.h OGRE_TEMP_VERSION_CONTENT) + get_preprocessor_entry(OGRE_TEMP_VERSION_CONTENT OGRE_VERSION_MAJOR OGRE_VERSION_MAJOR) + get_preprocessor_entry(OGRE_TEMP_VERSION_CONTENT OGRE_VERSION_MINOR OGRE_VERSION_MINOR) + get_preprocessor_entry(OGRE_TEMP_VERSION_CONTENT OGRE_VERSION_PATCH OGRE_VERSION_PATCH) + get_preprocessor_entry(OGRE_TEMP_VERSION_CONTENT OGRE_VERSION_NAME OGRE_VERSION_NAME) + set(OGRE_VERSION "${OGRE_VERSION_MAJOR}.${OGRE_VERSION_MINOR}.${OGRE_VERSION_PATCH}") + pkg_message(OGRE "Found Ogre ${OGRE_VERSION_NAME} (${OGRE_VERSION})") + + # determine configuration settings + set(OGRE_CONFIG_HEADERS + ${OGRE_CONFIG_INCLUDE_DIR}/buildsettings.h + ${OGRE_CONFIG_INCLUDE_DIR}/config.h + ${OGRE_CONFIG_INCLUDE_DIR}/OgreConfig.h + ) + foreach(CFG_FILE ${OGRE_CONFIG_HEADERS}) + if (EXISTS ${CFG_FILE}) + set(OGRE_CONFIG_HEADER ${CFG_FILE}) + break() + endif() + endforeach() + if (OGRE_CONFIG_HEADER) + file(READ ${OGRE_CONFIG_HEADER} OGRE_TEMP_CONFIG_CONTENT) + has_preprocessor_entry(OGRE_TEMP_CONFIG_CONTENT OGRE_STATIC_LIB OGRE_CONFIG_STATIC) + get_preprocessor_entry(OGRE_TEMP_CONFIG_CONTENT OGRE_THREAD_SUPPORT OGRE_CONFIG_THREADS) + get_preprocessor_entry(OGRE_TEMP_CONFIG_CONTENT OGRE_NO_FREEIMAGE OGRE_CONFIG_FREEIMAGE) + if (OGRE_CONFIG_STATIC AND OGRE_STATIC) + elseif (OGRE_CONFIG_STATIC OR OGRE_STATIC) + pkg_message(OGRE "Build type (static, dynamic) does not match the requested one.") + set(OGRE_INCOMPATIBLE TRUE) + endif () + else () + pkg_message(OGRE "Could not determine Ogre build configuration.") + set(OGRE_INCOMPATIBLE TRUE) + endif () +else () + set(OGRE_INCOMPATIBLE FALSE) +endif () + +find_library(OGRE_LIBRARY_REL NAMES ${OGRE_LIBRARY_NAMES} HINTS ${OGRE_LIB_SEARCH_PATH} ${OGRE_PKGC_LIBRARY_DIRS} ${OGRE_FRAMEWORK_SEARCH_PATH} PATH_SUFFIXES "" "release" "relwithdebinfo" "minsizerel") +find_library(OGRE_LIBRARY_DBG NAMES ${OGRE_LIBRARY_NAMES_DBG} HINTS ${OGRE_LIB_SEARCH_PATH} ${OGRE_PKGC_LIBRARY_DIRS} ${OGRE_FRAMEWORK_SEARCH_PATH} PATH_SUFFIXES "" "debug") +make_library_set(OGRE_LIBRARY) + +if(APPLE) +set(OGRE_LIBRARY_DBG ${OGRE_LIB_SEARCH_PATH}) +endif() +if (OGRE_INCOMPATIBLE) + set(OGRE_LIBRARY "NOTFOUND") +endif () + +set(OGRE_INCLUDE_DIR ${OGRE_CONFIG_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}) +list(REMOVE_DUPLICATES OGRE_INCLUDE_DIR) +findpkg_finish(OGRE) +add_parent_dir(OGRE_INCLUDE_DIRS OGRE_INCLUDE_DIR) + +mark_as_advanced(OGRE_CONFIG_INCLUDE_DIR OGRE_MEDIA_DIR OGRE_PLUGIN_DIR_REL OGRE_PLUGIN_DIR_DBG) + +if (NOT OGRE_FOUND) + return() +endif () + + +# look for required Ogre dependencies in case of static build and/or threading +if (OGRE_STATIC) + set(OGRE_DEPS_FOUND TRUE) + find_package(Cg QUIET) + find_package(DirectX QUIET) + find_package(FreeImage QUIET) + find_package(Freetype QUIET) + find_package(OpenGL QUIET) + find_package(OpenGLES QUIET) + find_package(ZLIB QUIET) + find_package(ZZip QUIET) + if (UNIX AND NOT APPLE) + find_package(X11 QUIET) + find_library(XAW_LIBRARY NAMES Xaw Xaw7 PATHS ${DEP_LIB_SEARCH_DIR} ${X11_LIB_SEARCH_PATH}) + if (NOT XAW_LIBRARY OR NOT X11_Xt_FOUND) + set(X11_FOUND FALSE) + endif () + endif () + if (APPLE) + find_package(Cocoa QUIET) + find_package(Carbon QUIET) + if (NOT Cocoa_FOUND OR NOT Carbon_FOUND) + set(OGRE_DEPS_FOUND FALSE) + endif () + endif () + + set(OGRE_LIBRARIES ${OGRE_LIBRARIES} ${OGRE_LIBRARY_FWK} ${ZZip_LIBRARIES} ${ZLIB_LIBRARIES} + ${FreeImage_LIBRARIES} ${FREETYPE_LIBRARIES} + ${X11_LIBRARIES} ${X11_Xt_LIBRARIES} ${XAW_LIBRARY} ${X11_Xrandr_LIB} + ${Cocoa_LIBRARIES} ${Carbon_LIBRARIES}) + + if (NOT ZLIB_FOUND OR NOT ZZip_FOUND) + set(OGRE_DEPS_FOUND FALSE) + endif () + if (NOT FreeImage_FOUND AND NOT OGRE_CONFIG_FREEIMAGE) + set(OGRE_DEPS_FOUND FALSE) + endif () + if (NOT FREETYPE_FOUND) + set(OGRE_DEPS_FOUND FALSE) + endif () + if (UNIX AND NOT APPLE) + if (NOT X11_FOUND) + set(OGRE_DEPS_FOUND FALSE) + endif () + endif () + + if (OGRE_CONFIG_THREADS) + find_package(Boost COMPONENTS thread QUIET) + if (NOT Boost_THREAD_FOUND) + set(OGRE_DEPS_FOUND FALSE) + endif () + endif () + + if (NOT OGRE_DEPS_FOUND) + pkg_message(OGRE "Could not find all required dependencies for the Ogre package.") + set(OGRE_FOUND FALSE) + endif () +endif () + +if (NOT OGRE_FOUND) + return() +endif () + + +get_filename_component(OGRE_LIBRARY_DIR_REL "${OGRE_LIBRARY_REL}" PATH) +get_filename_component(OGRE_LIBRARY_DIR_DBG "${OGRE_LIBRARY_DBG}" PATH) +set(OGRE_LIBRARY_DIRS ${OGRE_LIBRARY_DIR_REL} ${OGRE_LIBRARY_DIR_DBG}) + + +# look for Paging component +find_path(OGRE_Paging_INCLUDE_DIR NAMES OgrePage.h HINTS ${OGRE_INCLUDE_DIRS} ${OGRE_PREFIX_SOURCE} PATH_SUFFIXES Paging OGRE/Paging Components/Paging/include) +set(OGRE_Paging_LIBRARY_NAMES "OgrePaging${OGRE_LIB_SUFFIX}") +get_debug_names(OGRE_Paging_LIBRARY_NAMES) +find_library(OGRE_Paging_LIBRARY_REL NAMES ${OGRE_Paging_LIBRARY_NAMES} HINTS ${OGRE_LIBRARY_DIR_REL} PATH_SUFFIXES "" "release" "relwithdebinfo" "minsizerel") +find_library(OGRE_Paging_LIBRARY_DBG NAMES ${OGRE_Paging_LIBRARY_NAMES_DBG} HINTS ${OGRE_LIBRARY_DIR_DBG} PATH_SUFFIXES "" "debug") +set(OGRE_Paging_LIBRARY_FWK ${OGRE_LIBRARY_FWK}) +make_library_set(OGRE_Paging_LIBRARY) +if (OGRE_Paging_INCLUDE_DIR AND OGRE_Paging_LIBRARY) + set(OGRE_Paging_FOUND TRUE) + set(OGRE_Paging_INCLUDE_DIRS ${OGRE_Paging_INCLUDE_DIRS}) + set(OGRE_Paging_LIBRARIES ${OGRE_Paging_LIBRARIES}) +endif () +mark_as_advanced(OGRE_Paging_INCLUDE_DIR OGRE_Paging_LIBRARY_REL OGRE_Paging_LIBRARY_DBG OGRE_Paging_LIBRARY_FWK) + +# look for Terrain component +find_path(OGRE_Terrain_INCLUDE_DIR NAMES OgreTerrain.h HINTS ${OGRE_INCLUDE_DIRS} ${OGRE_PREFIX_SOURCE} PATH_SUFFIXES Terrain OGRE/Terrain Components/Terrain/include) +set(OGRE_Terrain_LIBRARY_NAMES "OgreTerrain${OGRE_LIB_SUFFIX}") +get_debug_names(OGRE_Terrain_LIBRARY_NAMES) +find_library(OGRE_Terrain_LIBRARY_REL NAMES ${OGRE_Terrain_LIBRARY_NAMES} HINTS ${OGRE_LIBRARY_DIR_REL} PATH_SUFFIXES "" "release" "relwithdebinfo" "minsizerel") +find_library(OGRE_Terrain_LIBRARY_DBG NAMES ${OGRE_Terrain_LIBRARY_NAMES_DBG} HINTS ${OGRE_LIBRARY_DIR_DBG} PATH_SUFFIXES "" "debug") +make_library_set(OGRE_Terrain_LIBRARY) +if (OGRE_Terrain_INCLUDE_DIR AND OGRE_Terrain_LIBRARY) + set(OGRE_Terrain_FOUND TRUE) + set(OGRE_Terrain_INCLUDE_DIRS ${OGRE_Terrain_INCLUDE_DIRS}) + set(OGRE_Terrain_LIBRARIES ${OGRE_Terrain_LIBRARIES} ${OGRE_Terrain_LIBRARY}) +endif () +mark_as_advanced(OGRE_Terrain_INCLUDE_DIR OGRE_Terrain_LIBRARY_REL OGRE_Terrain_LIBRARY_DBG OGRE_Terrain_LIBRARY_FWK) + +# look for CEGUI Ogre Renderer +find_package(CEGUI QUIET) +if (CEGUI_FOUND) + get_filename_component(CEGUI_LIBRARY_DIR_REL ${CEGUI_LIBRARY_REL} PATH) + get_filename_component(CEGUI_LIBRARY_DIR_DBG ${CEGUI_LIBRARY_DBG} PATH) + set(CEGUI_LIBRARY_DIRS ${CEGUI_LIBRARY_DIR_REL} ${CEGUI_LIBRARY_DIR_DBG}) + find_path(OGRE_CEGUIRenderer_INCLUDE_DIR NAMES OgreCEGUIRenderer.h + HINTS ${OGRE_INCLUDE_DIRS} ${OGRE_PREFIX_SOURCE} ${CEGUI_INCLUDE_DIRS} PATH_SUFFIXES CEGUIRenderer OGRE OGRE/CEGUIRenderer CEGUI Samples/Common/CEGUIRenderer/include) + set(OGRE_CEGUIRenderer_LIBRARY_NAMES "CEGUIOgreRenderer${OGRE_LIB_SUFFIX}" "OgreCEGUIRenderer${OGRE_LIB_SUFFIX}" "OgreGUIRenderer${OGRE_LIB_SUFFIX}") + get_debug_names(OGRE_CEGUIRenderer_LIBRARY_NAMES) + find_library(OGRE_CEGUIRenderer_LIBRARY_REL NAMES ${OGRE_CEGUIRenderer_LIBRARY_NAMES} HINTS ${OGRE_LIBRARY_DIRS} ${CEGUI_LIBRARY_DIRS} + ${OGRE_FRAMEWORK_SEARCH_PATH} PATH_SUFFIXES "" "release" "relwithdebinfo" "minsizerel") + find_library(OGRE_CEGUIRenderer_LIBRARY_DBG NAMES ${OGRE_CEGUIRenderer_LIBRARY_NAMES_DBG} HINTS ${OGRE_LIBRARY_DIRS} ${CEGUI_LIBRARY_DIRS} + ${OGRE_FRAMEWORK_SEARCH_PATH} PATH_SUFFIXES "" "debug") + make_library_set(OGRE_CEGUIRenderer_LIBRARY) + + if (OGRE_CEGUIRenderer_INCLUDE_DIR AND OGRE_CEGUIRenderer_LIBRARY) + set(OGRE_CEGUIRenderer_FOUND TRUE) + set(OGRE_CEGUIRenderer_INCLUDE_DIRS ${OGRE_CEGUIRenderer_INCLUDE_DIR} ${CEGUI_INCLUDE_DIRS}) + set(OGRE_CEGUIRenderer_LIBRARIES ${OGRE_CEGUIRenderer_LIBRARY} ${CEGUI_LIBRARIES}) + endif() + + mark_as_advanced(OGRE_CEGUIRenderer_INCLUDE_DIR OGRE_CEGUIRenderer_LIBRARY_REL OGRE_CEGUIRenderer_LIBRARY_DBG OGRE_CEGUIRenderer_LIBRARY_FWK) +endif () + + +######################################################### +# Find Ogre plugins +######################################################### + +macro(ogre_find_plugin PLUGIN HEADER) + # On Unix, the plugins might have no prefix + if (CMAKE_FIND_LIBRARY_PREFIXES) + set(TMP_CMAKE_LIB_PREFIX ${CMAKE_FIND_LIBRARY_PREFIXES}) + set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES} "") + endif() + + # strip RenderSystem_ or Plugin_ prefix from plugin name + string(REPLACE "RenderSystem_" "" PLUGIN_TEMP ${PLUGIN}) + string(REPLACE "Plugin_" "" PLUGIN_NAME ${PLUGIN_TEMP}) + + # header files for plugins are not usually needed, but find them anyway if they are present + set(OGRE_PLUGIN_PATH_SUFFIXES + PlugIns PlugIns/${PLUGIN_NAME} Plugins Plugins/${PLUGIN_NAME} ${PLUGIN} + RenderSystems RenderSystems/${PLUGIN_NAME} ${ARGN}) + find_path(OGRE_${PLUGIN}_INCLUDE_DIR NAMES ${HEADER} + HINTS ${OGRE_INCLUDE_DIRS} ${OGRE_PREFIX_SOURCE} + PATH_SUFFIXES ${OGRE_PLUGIN_PATH_SUFFIXES}) + # find link libraries for plugins + set(OGRE_${PLUGIN}_LIBRARY_NAMES "${PLUGIN}${OGRE_LIB_SUFFIX}") + get_debug_names(OGRE_${PLUGIN}_LIBRARY_NAMES) + set(OGRE_${PLUGIN}_LIBRARY_FWK ${OGRE_LIBRARY_FWK}) + find_library(OGRE_${PLUGIN}_LIBRARY_REL NAMES ${OGRE_${PLUGIN}_LIBRARY_NAMES} + HINTS ${OGRE_LIBRARY_DIRS} PATH_SUFFIXES "" OGRE opt release release/opt relwithdebinfo relwithdebinfo/opt minsizerel minsizerel/opt) + find_library(OGRE_${PLUGIN}_LIBRARY_DBG NAMES ${OGRE_${PLUGIN}_LIBRARY_NAMES_DBG} + HINTS ${OGRE_LIBRARY_DIRS} PATH_SUFFIXES "" OGRE opt debug debug/opt) + make_library_set(OGRE_${PLUGIN}_LIBRARY) + + if (OGRE_${PLUGIN}_LIBRARY OR OGRE_${PLUGIN}_INCLUDE_DIR) + set(OGRE_${PLUGIN}_FOUND TRUE) + if (OGRE_${PLUGIN}_INCLUDE_DIR) + set(OGRE_${PLUGIN}_INCLUDE_DIRS ${OGRE_${PLUGIN}_INCLUDE_DIR}) + endif() + set(OGRE_${PLUGIN}_LIBRARIES ${OGRE_${PLUGIN}_LIBRARY}) + endif () + + mark_as_advanced(OGRE_${PLUGIN}_INCLUDE_DIR OGRE_${PLUGIN}_LIBRARY_REL OGRE_${PLUGIN}_LIBRARY_DBG OGRE_${PLUGIN}_LIBRARY_FWK) + + # look for plugin dirs + if (OGRE_${PLUGIN}_FOUND) + if (NOT OGRE_PLUGIN_DIR_REL OR NOT OGRE_PLUGIN_DIR_DBG) + if (WIN32) + set(OGRE_PLUGIN_SEARCH_PATH_REL + ${OGRE_LIBRARY_DIR_REL}/.. + ${OGRE_LIBRARY_DIR_REL}/../.. + ) + set(OGRE_PLUGIN_SEARCH_PATH_DBG + ${OGRE_LIBRARY_DIR_DBG}/.. + ${OGRE_LIBRARY_DIR_DBG}/../.. + ) + find_path(OGRE_PLUGIN_DIR_REL NAMES "${PLUGIN}.dll" HINTS ${OGRE_PLUGIN_SEARCH_PATH_REL} + PATH_SUFFIXES "" bin bin/release bin/relwithdebinfo bin/minsizerel) + find_path(OGRE_PLUGIN_DIR_DBG NAMES "${PLUGIN}_d.dll" HINTS ${OGRE_PLUGIN_SEARCH_PATH_DBG} + PATH_SUFFIXES "" bin bin/debug) + elseif (UNIX) + get_filename_component(OGRE_PLUGIN_DIR_TMP ${OGRE_${PLUGIN}_LIBRARY_REL} PATH) + set(OGRE_PLUGIN_DIR_REL ${OGRE_PLUGIN_DIR_TMP} CACHE STRING "Ogre plugin dir (release)") + get_filename_component(OGRE_PLUGIN_DIR_TMP ${OGRE_${PLUGIN}_LIBRARY_DBG} PATH) + set(OGRE_PLUGIN_DIR_DBG ${OGRE_PLUGIN_DIR_TMP} CACHE STRING "Ogre plugin dir (debug)") + endif () + endif () + endif () + + if (TMP_CMAKE_LIB_PREFIX) + set(CMAKE_FIND_LIBRARY_PREFIXES ${TMP_CMAKE_LIB_PREFIX}) + endif () +endmacro(ogre_find_plugin) + +ogre_find_plugin(Plugin_PCZSceneManager OgrePCZSceneManager.h PCZ PlugIns/PCZSceneManager/include) +ogre_find_plugin(Plugin_OctreeZone OgreOctreeZone.h PCZ PlugIns/OctreeZone/include) +ogre_find_plugin(Plugin_BSPSceneManager OgreBspSceneManager.h PlugIns/BSPSceneManager/include) +ogre_find_plugin(Plugin_CgProgramManager OgreCgProgram.h PlugIns/CgProgramManager/include) +ogre_find_plugin(Plugin_OctreeSceneManager OgreOctreeSceneManager.h PlugIns/OctreeSceneManager/include) +ogre_find_plugin(Plugin_ParticleFX OgreParticleFXPrerequisites.h PlugIns/ParticleFX/include) +ogre_find_plugin(RenderSystem_GL OgreGLRenderSystem.h RenderSystems/GL/include) +ogre_find_plugin(RenderSystem_GLES OgreGLESRenderSystem.h RenderSystems/GLES/include) +ogre_find_plugin(RenderSystem_Direct3D9 OgreD3D9RenderSystem.h RenderSystems/Direct3D9/include) +ogre_find_plugin(RenderSystem_Direct3D10 OgreD3D10RenderSystem.h RenderSystems/Direct3D10/include) + +if (OGRE_STATIC) + # check if dependencies for plugins are met + if (NOT DirectX_FOUND) + set(OGRE_RenderSystem_Direct3D9_FOUND FALSE) + endif () + if (NOT DirectX_D3D10_FOUND) + set(OGRE_RenderSystem_Direct3D10_FOUND FALSE) + endif () + if (NOT OPENGL_FOUND) + set(OGRE_RenderSystem_GL_FOUND FALSE) + endif () + if (NOT OPENGLES_FOUND AND NOT OPENGLES2_FOUND) + set(OGRE_RenderSystem_GLES_FOUND FALSE) + endif () + if (NOT Cg_FOUND) + set(OGRE_Plugin_CgProgramManager_FOUND FALSE) + endif () + + set(OGRE_RenderSystem_Direct3D9_LIBRARIES ${OGRE_RenderSystem_Direct3D9_LIBRARIES} + ${DirectX_LIBRARIES} + ) + set(OGRE_RenderSystem_Direct3D10_LIBRARIES ${OGRE_RenderSystem_Direct3D10_LIBRARIES} + ${DirectX_D3D10_LIBRARIES} + ) + set(OGRE_RenderSystem_GL_LIBRARIES ${OGRE_RenderSystem_GL_LIBRARIES} + ${OPENGL_LIBRARIES} + ) + set(OGRE_RenderSystem_GLES_LIBRARIES ${OGRE_RenderSystem_GLES_LIBRARIES} + ${OPENGLES_LIBRARIES} + ) + set(OGRE_Plugin_CgProgramManager_LIBRARIES ${OGRE_Plugin_CgProgramManager_LIBRARIES} + ${Cg_LIBRARIES} + ) +endif () + +# look for the media directory +set(OGRE_MEDIA_SEARCH_PATH + ${OGRE_LIBRARY_DIR_REL}/.. + ${OGRE_LIBRARY_DIR_DBG}/.. + ${OGRE_LIBRARY_DIR_REL}/../.. + ${OGRE_LIBRARY_DIR_DBG}/../.. + ${OGRE_PREFIX_SOURCE} +) +set(OGRE_MEDIA_SEARCH_SUFFIX + Media + media + share/OGRE/media + Samples/Media +) +clear_if_changed(OGRE_PREFIX_WATCH OGRE_MEDIA_DIR) +find_path(OGRE_MEDIA_DIR NAMES packs/OgreCore.zip HINTS ${OGRE_MEDIA_SEARCH_PATH} + PATHS ${OGRE_PREFIX_PATH} PATH_SUFFIXES ${OGRE_MEDIA_SEARCH_SUFFIX}) + diff --git a/cmake/modules/FindOGREBullet.cmake b/cmake/modules/FindOGREBullet.cmake @@ -0,0 +1,65 @@ +# Find OGREBullet includes and library +# +# This module defines +# OGREBULLET_INCLUDE_DIR +# OGREBULLET_LIBRARIES, the libraries to link against to use Bullet. +# OGREBULLET_LIB_DIR, the location of the libraries +# OGREBULLET_FOUND, If false, do not try to use Bullet +# +# Copyright 2007, Matt Williams +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +IF (OGREBULLET_LIBRARIES AND OGREBULLET_INCLUDE_DIR) + SET(OGREBULLET_FIND_QUIETLY TRUE) # Already in cache, be silent +ENDIF (OGREBULLET_LIBRARIES AND OGREBULLET_INCLUDE_DIR) + +IF (WIN32) #Windows + MESSAGE(STATUS "Looking for OGREBullet") + ##SET(OGRESDK $ENV{OGRE_HOME}) + SET(OGREBULLETSOURCE $ENV{OGREBULLET_HOME}) + #IF (OGRESDK) + # MESSAGE(STATUS "Using OGRE SDK") + # STRING(REGEX REPLACE "[\\]" "/" OGRESDK "${OGRESDK}") + # SET(OGRE_INCLUDE_DIR ${OGRESDK}/include) + # SET(OGRE_LIB_DIR ${OGRESDK}/lib) + # SET(OGRE_LIBRARIES debug OgreMain_d optimized OgreMain) + #ENDIF (OGRESDK) + IF (OGREBULLETSOURCE) + MESSAGE(STATUS "Using OGREBullet built from source") + SET(OGREBULLET_INCLUDE_DIR $ENV{OGREBULLET_HOME}/Collisions/include $ENV{OGREBULLET_HOME}/Dynamics/include) + SET(OGREBULLET_LIB_DIR $ENV{OGREBULLET_HOME}/lib/Debug $ENV{OGREBULLET_HOME}/lib/Release) + SET(OGREBULLET_LIBRARIES debug OgreBulletCollisions_d debug OgreBulletDynamics_d optimized OgreBulletCollisions optimized OgreBulletDynamics) + ENDIF (OGREBULLETSOURCE) +#ELSE (WIN32) #Unix +# CMAKE_MINIMUM_REQUIRED(VERSION 2.4.7 FATAL_ERROR) +# FIND_PACKAGE(PkgConfig) +# PKG_SEARCH_MODULE(OGRE OGRE) +# SET(OGRE_INCLUDE_DIR ${OGRE_INCLUDE_DIRS}) +# SET(OGRE_LIB_DIR ${OGRE_LIBDIR}) +# SET(OGRE_LIBRARIES ${OGRE_LIBRARIES} CACHE STRING "") +ENDIF (WIN32) + +#Do some preparation +SEPARATE_ARGUMENTS(OGREBULLET_INCLUDE_DIR) +SEPARATE_ARGUMENTS(OGREBULLET_LIBRARIES) + +SET(OGREBULLET_INCLUDE_DIR ${OGREBULLET_INCLUDE_DIR} CACHE PATH "") +SET(OGREBULLET_LIBRARIES ${OGREBULLET_LIBRARIES} CACHE STRING "") +SET(OGREBULLET_LIB_DIR ${OGREBULLET_LIB_DIR} CACHE PATH "") + +IF (OGREBULLET_INCLUDE_DIR AND OGREBULLET_LIBRARIES) + SET(OGREBULLET_FOUND TRUE) +ENDIF (OGREBULLET_INCLUDE_DIR AND OGREBULLET_LIBRARIES) + +IF (OGREBULLET_FOUND) + IF (NOT OGREBULLET_FIND_QUIETLY) + MESSAGE(STATUS " libraries : ${OGREBULLET_LIBRARIES} from ${OGREBULLET_LIB_DIR}") + MESSAGE(STATUS " includes : ${OGREBULLET_INCLUDE_DIR}") + ENDIF (NOT OGREBULLET_FIND_QUIETLY) +ELSE (OGREBULLET_FOUND) + IF (OGREBULLET_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find OGREBullet") + ENDIF (OGREBULLET_FIND_REQUIRED) +ENDIF (OGREBULLET_FOUND) diff --git a/cmake/modules/FindOIS.cmake b/cmake/modules/FindOIS.cmake @@ -0,0 +1,67 @@ +# - Find OIS includes and library +# +# This module defines +# OIS_INCLUDE_DIR +# OIS_LIBRARIES, the libraries to link against to use OIS. +# OIS_LIB_DIR, the location of the libraries +# OIS_FOUND, If false, do not try to use OIS +# +# Copyright © 2007, Matt Williams +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +IF (OIS_LIBRARIES AND OIS_INCLUDE_DIR) + SET(OIS_FIND_QUIETLY TRUE) # Already in cache, be silent +ENDIF (OIS_LIBRARIES AND OIS_INCLUDE_DIR) + +IF (WIN32) #Windows + MESSAGE(STATUS "Looking for OIS") + + SET(OGRESDK $ENV{OGRE_HOME}) + SET(OGRESOURCE $ENV{OGRE_SRC}) + IF (OGRESDK) + MESSAGE(STATUS "Using OIS in OGRE SDK") + SET(OGRESDK $ENV{OGRE_HOME}) + STRING(REGEX REPLACE "[\\]" "/" OGRESDK "${OGRESDK}") + SET(OIS_INCLUDE_DIR ${OGRESDK}/include/OIS) + SET(OIS_LIB_DIR ${OGRESDK}/lib) + SET(OIS_LIBRARIES debug OIS_d optimized OIS) + ENDIF (OGRESDK) + IF (OGRESOURCE) + MESSAGE(STATUS "Using OIS in OGRE dependencies") + SET(OIS_INCLUDE_DIR C:/ogre/Dependencies/include C:/ogre/Dependencies/include/OIS) + SET(OIS_LIB_DIR C:/ogre/Dependencies/lib/Release C:/ogre/Dependencies/lib/Debug) + SET(OIS_LIBRARIES debug OIS_d optimized OIS) + ENDIF (OGRESOURCE) +ELSE (WIN32) #Unix + CMAKE_MINIMUM_REQUIRED(VERSION 2.4.7 FATAL_ERROR) + FIND_PACKAGE(PkgConfig REQUIRED) + PKG_SEARCH_MODULE(OIS OIS) + SET(OIS_INCLUDE_DIR ${OIS_INCLUDE_DIRS}) + SET(OIS_LIB_DIR ${OIS_LIBDIR}) + SET(OIS_LIBRARIES ${OIS_LIBRARIES} CACHE STRING "") +ENDIF (WIN32) + +#Do some preparation +SEPARATE_ARGUMENTS(OIS_INCLUDE_DIR) +SEPARATE_ARGUMENTS(OIS_LIBRARIES) + +SET(OIS_INCLUDE_DIR ${OIS_INCLUDE_DIR} CACHE PATH "") +SET(OIS_LIBRARIES ${OIS_LIBRARIES} CACHE STRING "") +SET(OIS_LIB_DIR ${OIS_LIB_DIR} CACHE PATH "") + +IF (OIS_INCLUDE_DIR AND OIS_LIBRARIES) + SET(OIS_FOUND TRUE) +ENDIF (OIS_INCLUDE_DIR AND OIS_LIBRARIES) + +IF (OIS_FOUND) + IF (NOT OIS_FIND_QUIETLY) + MESSAGE(STATUS " libraries : ${OIS_LIBRARIES} from ${OIS_LIB_DIR}") + MESSAGE(STATUS " includes : ${OIS_INCLUDE_DIR}") + ENDIF (NOT OIS_FIND_QUIETLY) +ELSE (OIS_FOUND) + IF (OIS_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find OIS") + ENDIF (OIS_FIND_REQUIRED) +ENDIF (OIS_FOUND) diff --git a/cmake/modules/FindOgreMax.cmake b/cmake/modules/FindOgreMax.cmake @@ -0,0 +1,37 @@ +SET( OgreMax_DEFINITIONS "" ) + +## +# You're going to have to edit this file if you intend to use it for your own project +## +SET( OgreMax_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/dependencies/OgreMax ) + +IF( EXISTS ${OgreMax_INCLUDE_DIR} ) + SET( OgreMax_FOUND TRUE ) + FILE(GLOB OgreMax_source ${OgreMax_INCLUDE_DIR}/*.cpp) + ADD_LIBRARY(OgreMax ${OgreMax_source}) + + SET( OgreMax_LIBRARIES OgreMax TinyXML) +ENDIF( EXISTS ${OgreMax_INCLUDE_DIR} ) + +IF( NOT OgreMax_FOUND) + IF( NOT OgreMax_INCLUDE_DIR ) + IF (OgreMax_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find OgreMax") + ENDIF (OgreMax_FIND_REQUIRED) + ENDIF( NOT OgreMax_INCLUDE_DIR ) +ELSE ( NOT OgreMax_FOUND) + INCLUDE_DIRECTORIES("${OgreMax_INCLUDE_DIR}") +ENDIF( NOT OgreMax_FOUND) + + +# Finally, display informations if not in quiet mode +IF( NOT OgreMax_FIND_QUIETLY ) + MESSAGE( STATUS "OgreMax found " ) + MESSAGE( STATUS " libraries : ${OgreMax_LIBRARIES}" ) + MESSAGE( STATUS " includes : ${OgreMax_INCLUDE_DIR}" ) +ENDIF( NOT OgreMax_FIND_QUIETLY ) + +MARK_AS_ADVANCED( + OgreMax_INCLUDE_DIR + OgreMax_LIBRARIES +) diff --git a/cmake/modules/FindSQLITE.cmake b/cmake/modules/FindSQLITE.cmake @@ -0,0 +1,51 @@ +# - Try to find the SQLITE library +# Once done this will define +# +# SQLITE_FOUND - system has sqlite +# SQLITE_INCLUDE_DIR - the sqlite include directory +# SQLITE_LIBRARIES - Link these to use sqlite +# SQLITE_DEFINITIONS - Compiler switches required for using sqlite +# + +IF (SQLITE_LIBRARIES AND SQLITE_INCLUDE_DIR) + SET(SQLITE_FIND_QUIETLY TRUE) # Already in cache, be silent +ENDIF (SQLITE_LIBRARIES AND SQLITE_INCLUDE_DIR) + +IF (WIN32) #Windows + MESSAGE(STATUS "Using SQLite3 in dependencies") + SET(SQLITE_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/dependencies/sqlite3) + ADD_LIBRARY(sqlite3_${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/dependencies/sqlite3/sqlite3.c) + SET( SQLITE_LIBRARIES sqlite3_${PROJECT_NAME}) + INCLUDE_DIRECTORIES("${SQLITE_INCLUDE_DIR}") +ELSE (WIN32) #Unix + CMAKE_MINIMUM_REQUIRED(VERSION 2.4.7 FATAL_ERROR) + FIND_PACKAGE(PkgConfig) + PKG_SEARCH_MODULE(SQLITE sqlite3) + SET(SQLITE_INCLUDE_DIR ${SQLITE_INCLUDE_DIRS}) + SET(SQLITE_LIB_DIR ${SQLITE_LIBDIR}) + SET(SQLITE_LIBRARIES ${SQLITE_LIBRARIES} CACHE STRING "") +ENDIF (WIN32) + +#Do some preparation +SEPARATE_ARGUMENTS(SQLITE_INCLUDE_DIR) +SEPARATE_ARGUMENTS(SQLITE_LIBRARIES) + +SET(SQLITE_INCLUDE_DIR ${SQLITE_INCLUDE_DIR} CACHE PATH "") +SET(SQLITE_LIBRARIES ${SQLITE_LIBRARIES} CACHE STRING "") +SET(SQLITE_LIB_DIR ${SQLITE_LIB_DIR} CACHE PATH "") + +IF (SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES) + SET(SQLITE_FOUND TRUE) +ENDIF (SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES) + +IF (SQLITE_FOUND) + IF (NOT SQLITE_FIND_QUIETLY) + MESSAGE(STATUS "SQLite Found") + MESSAGE(STATUS " libraries : ${SQLITE_LIBRARIES} from ${SQLITE_LIB_DIR}") + MESSAGE(STATUS " includes : ${SQLITE_INCLUDE_DIR}") + ENDIF (NOT SQLITE_FIND_QUIETLY) +ELSE (SQLITE_FOUND) + IF (SQLITE_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find SQLite3") + ENDIF (SQLITE_FIND_REQUIRED) +ENDIF (SQLITE_FOUND) diff --git a/cmake/modules/FindTinyXML.cmake b/cmake/modules/FindTinyXML.cmake @@ -0,0 +1,36 @@ +SET( TinyXML_DEFINITIONS "") + +## +# You're going to have to edit this file if you intend to use it for your own project +## +SET( TinyXML_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/dependencies/TinyXML ) + +IF( EXISTS ${TinyXML_INCLUDE_DIR} ) + SET( TinyXML_FOUND TRUE ) + FILE(GLOB TinyXML_source ${TinyXML_INCLUDE_DIR}/*.cpp) + ADD_LIBRARY(TinyXML ${TinyXML_source}) + SET( TinyXML_LIBRARIES TinyXML) +ENDIF( EXISTS ${TinyXML_INCLUDE_DIR} ) + +IF( NOT TinyXML_FOUND) + IF( NOT TinyXML_INCLUDE_DIR ) + IF (TinyXML_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find TinyXML") + ENDIF (TinyXML_FIND_REQUIRED) + ENDIF( NOT TinyXML_INCLUDE_DIR ) +ELSE ( NOT TinyXML_FOUND) + INCLUDE_DIRECTORIES("${TinyXML_INCLUDE_DIR}") +ENDIF( NOT TinyXML_FOUND) + + +# Finally, display informations if not in quiet mode +IF( NOT TinyXML_FIND_QUIETLY ) + MESSAGE( STATUS "TinyXML found " ) + MESSAGE( STATUS " libraries : ${TinyXML_LIBRARIES}" ) + MESSAGE( STATUS " includes : ${TinyXML_INCLUDE_DIR}" ) +ENDIF( NOT TinyXML_FIND_QUIETLY ) + +MARK_AS_ADVANCED( + TinyXML_INCLUDE_DIR + TinyXML_LIBRARIES +) diff --git a/cmake/scripts/FindPkgMacros.cmake b/cmake/scripts/FindPkgMacros.cmake @@ -0,0 +1,142 @@ +#------------------------------------------------------------------- +# This file is part of the CMake build system for OGRE +# (Object-oriented Graphics Rendering Engine) +# For the latest info, see http://www.ogre3d.org/ +# +# The contents of this file are placed in the public domain. Feel +# free to make use of it in any way you like. +#------------------------------------------------------------------- + +################################################################## +# Provides some common functionality for the FindPackage modules +################################################################## + +# Begin processing of package +macro(findpkg_begin PREFIX) + if (NOT ${PREFIX}_FIND_QUIETLY) + message(STATUS "Looking for ${PREFIX}...") + endif () +endmacro(findpkg_begin) + +# Display a status message unless FIND_QUIETLY is set +macro(pkg_message PREFIX) + if (NOT ${PREFIX}_FIND_QUIETLY) + message(STATUS ${ARGN}) + endif () +endmacro(pkg_message) + +# Get environment variable, define it as ENV_$var and make sure backslashes are converted to forward slashes +macro(getenv_path VAR) + set(ENV_${VAR} $ENV{${VAR}}) + # replace won't work if var is blank + if (ENV_${VAR}) + string( REGEX REPLACE "\\\\" "/" ENV_${VAR} ${ENV_${VAR}} ) + endif () +endmacro(getenv_path) + +# Construct search paths for includes and libraries from a PREFIX_PATH +macro(create_search_paths PREFIX) + foreach(dir ${${PREFIX}_PREFIX_PATH}) + set(${PREFIX}_INC_SEARCH_PATH ${${PREFIX}_INC_SEARCH_PATH} + ${dir}/include ${dir}/include/${PREFIX} ${dir}/Headers) + set(${PREFIX}_LIB_SEARCH_PATH ${${PREFIX}_LIB_SEARCH_PATH} + ${dir}/lib ${dir}/lib/${PREFIX} ${dir}/Libs) + endforeach(dir) + set(${PREFIX}_FRAMEWORK_SEARCH_PATH ${${PREFIX}_PREFIX_PATH}) +endmacro(create_search_paths) + +# clear cache variables if a certain variable changed +macro(clear_if_changed TESTVAR) + # test against internal check variable + if (NOT "${${TESTVAR}}" STREQUAL "${${TESTVAR}_INT_CHECK}") + message(STATUS "${TESTVAR} changed.") + foreach(var ${ARGN}) + set(${var} "NOTFOUND" CACHE STRING "x" FORCE) + endforeach(var) + endif () + set(${TESTVAR}_INT_CHECK ${${TESTVAR}} CACHE INTERNAL "x" FORCE) +endmacro(clear_if_changed) + +# Try to get some hints from pkg-config, if available +macro(use_pkgconfig PREFIX PKGNAME) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(${PREFIX} ${PKGNAME}) + endif () +endmacro (use_pkgconfig) + +# Couple a set of release AND debug libraries (or frameworks) +macro(make_library_set PREFIX) + if (${PREFIX}_FWK) + set(${PREFIX} ${${PREFIX}_FWK}) + elseif (${PREFIX}_REL AND ${PREFIX}_DBG) + set(${PREFIX} optimized ${${PREFIX}_REL} debug ${${PREFIX}_DBG}) + elseif (${PREFIX}_REL) + set(${PREFIX} ${${PREFIX}_REL}) + elseif (${PREFIX}_DBG) + set(${PREFIX} ${${PREFIX}_DBG}) + endif () +endmacro(make_library_set) + +# Generate debug names from given release names +macro(get_debug_names PREFIX) + foreach(i ${${PREFIX}}) + set(${PREFIX}_DBG ${${PREFIX}_DBG} ${i}d ${i}D ${i}_d ${i}_D ${i}_debug ${i}) + endforeach(i) +endmacro(get_debug_names) + +# Add the parent dir from DIR to VAR +macro(add_parent_dir VAR DIR) + get_filename_component(${DIR}_TEMP "${${DIR}}/.." ABSOLUTE) + set(${VAR} ${${VAR}} ${${DIR}_TEMP}) +endmacro(add_parent_dir) + +# Do the final processing for the package find. +macro(findpkg_finish PREFIX) + # skip if already processed during this run + if (NOT ${PREFIX}_FOUND) + if (${PREFIX}_INCLUDE_DIR AND ${PREFIX}_LIBRARY) + set(${PREFIX}_FOUND TRUE) + set(${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIR}) + set(${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARY}) + if (NOT ${PREFIX}_FIND_QUIETLY) + message(STATUS "Found ${PREFIX}: ${${PREFIX}_LIBRARIES}") + endif () + else () + if (NOT ${PREFIX}_FIND_QUIETLY) + message(STATUS "Could not locate ${PREFIX}") + endif () + if (${PREFIX}_FIND_REQUIRED) + message(FATAL_ERROR "Required library ${PREFIX} not found! Install the library (including dev packages) and try again. If the library is already installed, set the missing variables manually in cmake.") + endif () + endif () + + mark_as_advanced(${PREFIX}_INCLUDE_DIR ${PREFIX}_LIBRARY ${PREFIX}_LIBRARY_REL ${PREFIX}_LIBRARY_DBG ${PREFIX}_LIBRARY_FWK) + endif () +endmacro(findpkg_finish) + + +# Slightly customised framework finder +MACRO(findpkg_framework fwk) + IF(APPLE) + SET(${fwk}_FRAMEWORK_PATH + ${${fwk}_FRAMEWORK_SEARCH_PATH} + ${CMAKE_FRAMEWORK_PATH} + ~/Library/Frameworks + /Library/Frameworks + /System/Library/Frameworks + /Network/Library/Frameworks + /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/System/Library/Frameworks/ + ) + FOREACH(dir ${${fwk}_FRAMEWORK_PATH}) + SET(fwkpath ${dir}/${fwk}.framework) + IF(EXISTS ${fwkpath}) + SET(${fwk}_FRAMEWORK_INCLUDES ${${fwk}_FRAMEWORK_INCLUDES} + ${fwkpath}/Headers ${fwkpath}/PrivateHeaders) + if (NOT ${fwk}_LIBRARY_FWK) + SET(${fwk}_LIBRARY_FWK "-framework ${fwk}") + endif () + ENDIF(EXISTS ${fwkpath}) + ENDFOREACH(dir) + ENDIF(APPLE) +ENDMACRO(findpkg_framework) diff --git a/cmake/scripts/MacroLogFeature.cmake b/cmake/scripts/MacroLogFeature.cmake @@ -0,0 +1,134 @@ +#------------------------------------------------------------------- +# This file is part of the CMake build system for OGRE +# (Object-oriented Graphics Rendering Engine) +# For the latest info, see http://www.ogre3d.org/ +# +# The contents of this file are placed in the public domain. Feel +# free to make use of it in any way you like. +#------------------------------------------------------------------- + +# This file defines the Feature Logging macros. +# +# MACRO_LOG_FEATURE(VAR FEATURE DESCRIPTION URL [REQUIRED [MIN_VERSION [COMMENTS]]]) +# Logs the information so that it can be displayed at the end +# of the configure run +# VAR : TRUE or FALSE, indicating whether the feature is supported +# FEATURE: name of the feature, e.g. "libjpeg" +# DESCRIPTION: description what this feature provides +# URL: home page +# REQUIRED: TRUE or FALSE, indicating whether the featue is required +# MIN_VERSION: minimum version number. empty string if unneeded +# COMMENTS: More info you may want to provide. empty string if unnecessary +# +# MACRO_DISPLAY_FEATURE_LOG() +# Call this to display the collected results. +# Exits CMake with a FATAL error message if a required feature is missing +# +# Example: +# +# INCLUDE(MacroLogFeature) +# +# FIND_PACKAGE(JPEG) +# MACRO_LOG_FEATURE(JPEG_FOUND "libjpeg" "Support JPEG images" "http://www.ijg.org" TRUE "3.2a" "") +# ... +# MACRO_DISPLAY_FEATURE_LOG() + +# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org> +# Copyright (c) 2006, Allen Winter, <winter@kde.org> +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +IF (NOT _macroLogFeatureAlreadyIncluded) + SET(_file ${CMAKE_BINARY_DIR}/MissingRequirements.txt) + IF (EXISTS ${_file}) + FILE(REMOVE ${_file}) + ENDIF (EXISTS ${_file}) + + SET(_file ${CMAKE_BINARY_DIR}/EnabledFeatures.txt) + IF (EXISTS ${_file}) + FILE(REMOVE ${_file}) + ENDIF (EXISTS ${_file}) + + SET(_file ${CMAKE_BINARY_DIR}/DisabledFeatures.txt) + IF (EXISTS ${_file}) + FILE(REMOVE ${_file}) + ENDIF (EXISTS ${_file}) + + SET(_macroLogFeatureAlreadyIncluded TRUE) +ENDIF (NOT _macroLogFeatureAlreadyIncluded) + + +MACRO(MACRO_LOG_FEATURE _var _package _description _url ) # _required _minvers _comments) + + SET(_required "${ARGV4}") + SET(_minvers "${ARGV5}") + SET(_comments "${ARGV6}") + + IF (${_var}) + SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/EnabledFeatures.txt) + ELSE (${_var}) + IF (${_required} MATCHES "[Tt][Rr][Uu][Ee]") + SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/MissingRequirements.txt) + ELSE (${_required} MATCHES "[Tt][Rr][Uu][Ee]") + SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/DisabledFeatures.txt) + ENDIF (${_required} MATCHES "[Tt][Rr][Uu][Ee]") + ENDIF (${_var}) + + SET(_logtext "+ ${_package}") + + IF (NOT ${_var}) + IF (${_minvers} MATCHES ".*") + SET(_logtext "${_logtext}, ${_minvers}") + ENDIF (${_minvers} MATCHES ".*") + SET(_logtext "${_logtext}: ${_description} <${_url}>") + IF (${_comments} MATCHES ".*") + SET(_logtext "${_logtext}\n${_comments}") + ENDIF (${_comments} MATCHES ".*") +# SET(_logtext "${_logtext}\n") #double-space missing features? + ENDIF (NOT ${_var}) + FILE(APPEND "${_LOGFILENAME}" "${_logtext}\n") + +ENDMACRO(MACRO_LOG_FEATURE) + + +MACRO(MACRO_DISPLAY_FEATURE_LOG) + + SET(_file ${CMAKE_BINARY_DIR}/MissingRequirements.txt) + IF (EXISTS ${_file}) + FILE(READ ${_file} _requirements) + MESSAGE(FATAL_ERROR "\n-----------------------------------------------------------------------------\n-- The following REQUIRED packages could NOT be located on your system.\n-- Please install them before continuing this software installation.\n-- If you are in Windows, try passing -DOGRE_DEPENDENCIES_DIR=<path to dependencies>\n-----------------------------------------------------------------------------\n${_requirements}-----------------------------------------------------------------------------") + FILE(REMOVE ${_file}) + MESSAGE(FATAL_ERROR "Exiting: Missing Requirements") + ENDIF (EXISTS ${_file}) + + SET(_summary "\n") + + SET(_elist 0) + SET(_file ${CMAKE_BINARY_DIR}/EnabledFeatures.txt) + IF (EXISTS ${_file}) + SET(_elist 1) + FILE(READ ${_file} _enabled) + FILE(REMOVE ${_file}) + SET(_summary "${_summary}-----------------------------------------------------------------------------\n-- The following external packages were located on your system.\n-- This installation will have the extra features provided by these packages.\n${_enabled}") + ENDIF (EXISTS ${_file}) + + SET(_dlist 0) + SET(_file ${CMAKE_BINARY_DIR}/DisabledFeatures.txt) + IF (EXISTS ${_file}) + SET(_dlist 1) + FILE(READ ${_file} _disabled) + FILE(REMOVE ${_file}) + SET(_summary "${_summary}-----------------------------------------------------------------------------\n-- The following OPTIONAL packages could NOT be located on your system.\n-- Consider installing them to enable more features from this software.\n${_disabled}") + ELSE (EXISTS ${_file}) + IF (${_elist}) + SET(_summary "${_summary}Congratulations! All external packages have been found.\n") + ENDIF (${_elist}) + ENDIF (EXISTS ${_file}) + + IF (${_elist} OR ${_dlist}) + SET(_summary "${_summary}-----------------------------------------------------------------------------\n") + ENDIF (${_elist} OR ${_dlist}) + MESSAGE(STATUS "${_summary}") + +ENDMACRO(MACRO_DISPLAY_FEATURE_LOG) diff --git a/cmake/scripts/PreprocessorUtils.cmake b/cmake/scripts/PreprocessorUtils.cmake @@ -0,0 +1,60 @@ +#------------------------------------------------------------------- +# This file is part of the CMake build system for OGRE +# (Object-oriented Graphics Rendering Engine) +# For the latest info, see http://www.ogre3d.org/ +# +# The contents of this file are placed in the public domain. Feel +# free to make use of it in any way you like. +#------------------------------------------------------------------- + +macro(get_preprocessor_entry CONTENTS KEYWORD VARIABLE) + string(REGEX MATCH + "# *define +${KEYWORD} +((\"([^\n]*)\")|([^ \n]*))" + PREPROC_TEMP_VAR + ${${CONTENTS}} + ) + if (CMAKE_MATCH_3) + set(${VARIABLE} ${CMAKE_MATCH_3}) + else () + set(${VARIABLE} ${CMAKE_MATCH_4}) + endif () +endmacro() + +macro(has_preprocessor_entry CONTENTS KEYWORD VARIABLE) + string(REGEX MATCH + "\n *# *define +(${KEYWORD})" + PREPROC_TEMP_VAR + ${${CONTENTS}} + ) + if (CMAKE_MATCH_1) + set(${VARIABLE} TRUE) + else () + set(${VARIABLE} FALSE) + endif () +endmacro() + +macro(replace_preprocessor_entry VARIABLE KEYWORD NEW_VALUE) + string(REGEX REPLACE + "(// *)?# *define +${KEYWORD} +[^ \n]*" + "#define ${KEYWORD} ${NEW_VALUE}" + ${VARIABLE}_TEMP + ${${VARIABLE}} + ) + set(${VARIABLE} ${${VARIABLE}_TEMP}) +endmacro() + +macro(set_preprocessor_entry VARIABLE KEYWORD ENABLE) + if (${ENABLE}) + set(TMP_REPLACE_STR "#define ${KEYWORD}") + else () + set(TMP_REPLACE_STR "// #define ${KEYWORD}") + endif () + string(REGEX REPLACE + "(// *)?# *define +${KEYWORD} *\n" + ${TMP_REPLACE_STR} + ${VARIABLE}_TEMP + ${${VARIABLE}} + ) + set(${VARIABLE} ${${VARIABLE}_TEMP}) +endmacro() + diff --git a/js/CMakeLists.txt b/js/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required (VERSION 2.6) +project (TEST) + +find_path(READLINE_INCLUDE_DIR readline/readline.h /usr/include /opt/local/include) +find_path(JS_INCLUDE_DIR jsapi.h /usr/include/js /opt/local/include/js) +include_directories(${READLINE_INCLUDE_DIR} ${JS_INCLUDE_DIR}) + +find_library(JS_LIBRARY js /usr/lib /opt/local/lib) +find_library(READLINE_LIBRARY readline /usr/lib /opt/local/lib) + +IF(UNIX) + add_definitions(-DXP_UNIX) +ENDIF(UNIX) + +add_executable(js-test js-test.c js-funcs.c) +target_link_libraries(js-test ${JS_LIBRARY} ${READLINE_LIBRARY}) + diff --git a/js/js-funcs.c b/js/js-funcs.c @@ -0,0 +1,42 @@ +#include <stdio.h> +#include <readline/readline.h> +#include <jsapi.h> +#include "js-funcs.h" + +static JSBool myjs_readline(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { + const char *prompt; + + if (!JS_ConvertArguments(cx, argc, argv, "s", &prompt)) { + return JS_FALSE; + } + char *line = readline(prompt); + *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, line)); + if (line && *line) { + add_history(line); + } + free(line); + return JS_TRUE; +} + +static JSBool myjs_print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { + int i; + + for (i = 0; i < argc; i++) { + fputs(JS_GetStringBytes(JS_ValueToString(cx, argv[i])), stdout); + } + return JS_TRUE; +} + +static JSFunctionSpec myjs_global_functions[] = { + {"readline", myjs_readline, 1, 0, 0}, + {"print", myjs_print, 1, 0, 0}, + NULL, +}; + +int setup_js_functions(JSContext *cx, JSObject *global) { + if (!JS_DefineFunctions(cx, global, myjs_global_functions)) { + return 0; + } + return 1; +} + diff --git a/js/js-funcs.h b/js/js-funcs.h @@ -0,0 +1,8 @@ +#ifndef JS_FUNCS_H +#define JS_FUNCS_H 1 +#include <jsapi.h> + +int setup_js_functions(JSContext *cx, JSObject *global); + +#endif /* JS_FUNCS_H */ + diff --git a/js/js-test.c b/js/js-test.c @@ -0,0 +1,76 @@ +#include <string.h> +#include <jsapi.h> +#include "js-funcs.h" + +/* The class of the global object. */ +static JSClass global_class = { + "global", JSCLASS_GLOBAL_FLAGS, + JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, + JSCLASS_NO_OPTIONAL_MEMBERS +}; + +/* The error reporter callback. */ +void reportError(JSContext *cx, const char *message, JSErrorReport *report) +{ + fprintf(stderr, "%s:%u:%s\n", + report->filename ? report->filename : "<no filename>", + (unsigned int) report->lineno, + message); +} + +int main(int argc, const char *argv[]) +{ + /* JS variables. */ + JSRuntime *rt; + JSContext *cx; + JSObject *global; + + /* Create a JS runtime. */ + rt = JS_NewRuntime(8L * 1024L * 1024L); + if (rt == NULL) + return 1; + + /* Create a context. */ + cx = JS_NewContext(rt, 8192); + if (cx == NULL) + return 1; + JS_SetOptions(cx, JSOPTION_VAROBJFIX); + JS_SetVersion(cx, JSVERSION_1_7); + JS_SetErrorReporter(cx, reportError); + + /* Create the global object. */ + global = JS_NewObject(cx, &global_class, NULL, NULL); + if (global == NULL) + return 1; + + /* Populate the global object with the standard globals, + like Object and Array. */ + if (!JS_InitStandardClasses(cx, global)) + return 1; + + if (!setup_js_functions(cx, global)) { + return 1; + } + + /* Your application code here. This may include JSAPI calls + to create your own custom JS objects and run scripts. */ + jsval rval; + JSBool ok; + + /* + * Some example source in a C string. Larger, non-null-terminated buffers + * can be used, if you pass the buffer length to JS_EvaluateScript. + */ + JSScript *script = JS_CompileFile(cx, global, "main.js"); + + ok = JS_ExecuteScript(cx, global, script, &rval); + + /* Cleanup. */ + JS_DestroyContext(cx); + JS_DestroyRuntime(rt); + JS_ShutDown(); + return 0; +} + + diff --git a/zibbrtest/CMakeLists.txt b/zibbrtest/CMakeLists.txt @@ -0,0 +1,57 @@ +cmake_minimum_required(VERSION 2.6) +project(Hardwar) +cmake_policy(SET CMP0003 NEW) + +SET(Required_Packages + OGRE +) + +# project version +SET( ${PROJECT_NAME}_MAJOR_VERSION 0 ) +SET( ${PROJECT_NAME}_MINOR_VERSION 1 ) +SET( ${PROJECT_NAME}_PATCH_LEVEL 0 ) + +SET( CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" + "${Hardwar_SOURCE_DIR}/cmake/modules" + "${Hardwar_SOURCE_DIR}/cmake/scripts" + ) + +SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin) +SET(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib) + +# Set compiler specific build flags +if (CMAKE_COMPILER_IS_GNUCXX) + add_definitions(-msse -Wunused -g3 -O3 -Wall) +endif () +if (MSVC) + add_definitions(/fp:fast) +endif () + +IF (MSVC_IDE) + IF (EXISTS $ENV{OGRE_HOME}) + SET(OGRESDK $ENV{OGRE_HOME}) + STRING(REGEX REPLACE "[\\]" "/" OGRESDK "${OGRESDK}") + MESSAGE(STATUS "Adding Additional Link Directories") + LINK_DIRECTORIES(${OGRESDK}/lib) + ENDIF(EXISTS $ENV{OGRE_HOME}) + + SET(PLATFORM_C_FLAGS "/W3 /MD /Od /D \"WIN32\" /D \"_WINDOWS\" /D \"TIXML_USE_STL\" /D \"ENET_DLL\" /Gm /Gy /fp:fast /ZI /EHsc") + SET(PLATFORM_C_FLAGS_DEBUG "/W3 /MDd /Od /Gm /Gy /fp:fast /ZI") + + SET(CMAKE_CXX_FLAGS "${PLATFORM_C_FLAGS}") + SET(CMAKE_CXX_FLAGS_RELEASE "${PLATFORM_C_FLAGS}") + SET(CMAKE_CXX_FLAGS_DEBUG "${PLATFORM_C_FLAGS_DEBUG}") +ENDIF (MSVC_IDE) + +#this foreach loads all of the packages that you specified as required. +FOREACH(Package ${Required_Packages}) + FIND_PACKAGE(${Package} REQUIRED) + IF (${Package}_FOUND) + INCLUDE_DIRECTORIES(${${Package}_INCLUDE_DIR}) + ELSE (${Package}_FOUND) + MESSAGE(STATUS "${Package} not found") + ENDIF(${Package}_FOUND) +ENDFOREACH(Package) + +ADD_EXECUTABLE(zibbr-test zibbr-test.c) +