<commit_before>/*
    msn p2p protocol

    Copyright (c) 2003-2005 by Olivier Goffart        <ogoffart@ kde.org>

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

#include "msnp2p.h"
#include "msnp2pdisplatcher.h"
#include "msnp2pincoming.h"

// qt
#include <qregexp.h>
#include <qfile.h>
#include <qtextcodec.h>

// kde
#include <kdebug.h>
#include <kmdcodec.h>
#include <ktempfile.h>
#include <krun.h>
#include <klocale.h>
#include <kglobal.h>
#include <kdeversion.h>
#include <kstandarddirs.h>

//kopete
#include <kopetetransfermanager.h>

MSNP2PIncoming::MSNP2PIncoming( unsigned long int sessionID , MSNP2PDisplatcher *parent )
	: MSNP2P(sessionID , parent)
{
	m_file=0l;
	m_Rfile=0L;
	m_kopeteTransfer=0L;
}

MSNP2PIncoming::~MSNP2PIncoming()
{
	if(m_kopeteTransfer)
	{
		m_kopeteTransfer->slotError( KIO::ERR_INTERNAL , i18n("Connection closed")  );
	}

	if(m_file)
		delete m_file;
	else
		delete m_Rfile;
}

void MSNP2PIncoming::parseMessage(MessageStruct &msgStr)
{
	MSNP2P::parseMessage(msgStr);

	if(m_Rfile)  //we are already downloading something to this file
	{			//m_file->file()->writeBlock( (msg.data()+startBinHeader+48) , dataMessageSize );
		m_Rfile->writeBlock( (msgStr.message.data()+48) , msgStr.dataMessageSize );

		if(m_kopeteTransfer)
			m_kopeteTransfer->slotProcessed( msgStr.dataOffset+msgStr.dataMessageSize );

		if(msgStr.dataOffset+msgStr.dataMessageSize >= msgStr.totalSize) //the file is complete
		{
			if(m_file)
			{
				m_file->close();
				m_parent->fileReceived(m_file , m_obj);
				m_file=0;
				m_Rfile=0L;
			}
			else
			{
				if(m_kopeteTransfer) m_kopeteTransfer->slotComplete();
				m_Rfile->close();
				delete m_Rfile;
				m_Rfile=0L;
			}
/*
			delete m_file;*/

				//send the bye message
			makeMSNSLPMessage(BYE, QString::null);

			m_parent->finished(this);
				//deleteLater();
		}
	}
	else if(msgStr.message.data()[48] == '\0' )
	{  //This can be only the data preparaion message.   prepare to download
		m_file=new KTempFile( locateLocal( "tmp", "msnpicture-" ), ".png" );
		m_file->setAutoDelete(true);
		m_Rfile=m_file->file();

	}
	else
	{
		QString dataMessage=QCString((msgStr.message.data()+48) , msgStr.dataMessageSize);
		kdDebug(14141) << k_funcinfo <<" dataMessage: "  << dataMessage << endl;

		if (dataMessage.contains("INVITE") )
		{
			if(! m_kopeteTransfer )
			{
				return;
			}
			//Parse the message to get some info for replying
			QRegExp rx(";branch=\\{([0-9A-F\\-]*)\\}\r\n");
			rx.search( dataMessage );
			m_branch=rx.cap(1);

			rx=QRegExp("Call-ID: \\{([0-9A-F\\-]*)\\}\r\n");
			rx.search( dataMessage );
			m_CallID=rx.cap(1);

		    //dirrect connection is not yet implemented, use the connection via MSNP2P
			QString content="Bridge: TCPv1\r\n"
					"Listening: false\r\n"
					"Nonce: {00000000-0000-0000-0000-000000000000}\r\n\r\n";

			makeMSNSLPMessage(OK, content);

			m_Rfile=new QFile( m_kopeteTransfer->destinationURL().path() );
			if(!m_Rfile->open(IO_WriteOnly))
			{
				if(m_kopeteTransfer)
				{
							//TODO: handle the QFILE error
					m_kopeteTransfer->slotError( KIO::ERR_CANNOT_OPEN_FOR_WRITING , i18n("Cannot open file for writing")  );
					m_kopeteTransfer=0L;
					return;
				}
				abortCurrentTransfer();
			}
		}
		else if (dataMessage.contains("BYE"))
		{
			abortCurrentTransfer();
		}
		else if(dataMessage.contains("200 OK"))
		{
			//ignore
		}
		else
		{ //this seems to be _probably_ (just a guess) a utf-16 message.   we will download it completely.
			/*
			 * The message looks like this:
			 *
			MIME-Version: 1.0
			Content-Type: image/gif
			\0
			base64:[ENCODED-IMAGE]
			 *  Sometimes, the base64 ends with =  sometimes it does not.
			 */

			if(msgStr.dataOffset ==0)
				fullContentMessage=QString::null;

			/*
			 * The following line doesn't works, because, wihtout reason i understand, the string contains some \0
			 * (\0\0 in utf-16)  between the   Content-Type:   and the Base64:

			QTextCodec *codec = QTextCodec::codecForName("ISO-10646-UCS-2");
			if(!codec)
			return; //abort();
			fullContentMessage += codec->toUnicode(msg.data()+startBinHeader+48-1 , dataMessageSize)

			 * Quick hack to parse utf-16 and remove \0\0 :
			 * The message shouldn't contains non ASCII char  (it's base64)  so i think i could do like that.
			 * FIXME:  yes, this is not 100% correct
			 */
			for(unsigned int f= 48 ; f < 48 + msgStr.dataMessageSize ; f+=2)
			{
				if(msgStr.message[f] != 0)
				{
					fullContentMessage+=QChar( msgStr.message[f] );
				}
			}

			//the message may be splitted
			if(msgStr.dataOffset+msgStr.dataMessageSize >= msgStr.totalSize)
			{ //whe have the whole

				kdDebug(14141) << k_funcinfo <<"Analyse the image message: " << fullContentMessage <<  endl;

				QString ext;
				QRegExp rx("Content-Type: ([a-zA-Z0-9/]*)");
				if( rx.search( fullContentMessage ) != -1 )
				{
					QString contentType=rx.cap(1);
					if(contentType=="image/gif")
						ext=".gif";
					else if(contentType=="image/png")
						ext=".png";
					else
					{
						kdWarning(14140) << k_funcinfo << contentType << " is not recognized.  A MSN message is not displayed" <<  endl;
						return;
					}
				}
				else
					return;

				rx=QRegExp("base64:([a-zA-Z0-9+\\-.*/!]*)");
				if( rx.search( fullContentMessage ) != -1 )
				{
					QString base64=rx.cap(1);

					QByteArray image;
					KCodecs::base64Decode( base64.utf8() , image );

					KTempFile *imageFile=new KTempFile( locateLocal( "tmp", "msntypewrite-" ), ext );
					imageFile->setAutoDelete(true);
					imageFile->file()->writeBlock( image.data() , image.size() );
					imageFile->file()->close();

					m_parent->fileReceived( imageFile , "typewrite" );
				}
			}
		}
	}
}

void MSNP2PIncoming::abortCurrentTransfer()
{
	if(m_kopeteTransfer)
	{
		delete m_Rfile;
		m_Rfile=0L;

		//this need to be reseted before sending the BYE message.
		m_totalDataSize=0;
		m_offset=0;
		m_footer='\0';

		//FIXME: i'm not sure it's like that i should abort the transfer.
		makeMSNSLPMessage(BYE, "\r\n\r\n" );
	}
	m_parent->finished(this);
}

void MSNP2PIncoming::slotKopeteTransferDestroyed()
{
	m_kopeteTransfer=0L;
	kdDebug(14140) << k_funcinfo << endl;
}

void MSNP2PIncoming::error()
{
	MSNP2P::error();

	if(m_kopeteTransfer)
	{
		m_kopeteTransfer->slotError( KIO::ERR_INTERNAL , i18n("Malformed packet received")  );
		m_kopeteTransfer=0L;
	}
}

#include "msnp2pincoming.moc"
<commit_msg>make sure this is the data preparation message<commit_after>/*
    msn p2p protocol

    Copyright (c) 2003-2005 by Olivier Goffart        <ogoffart@ kde.org>

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

#include "msnp2p.h"
#include "msnp2pdisplatcher.h"
#include "msnp2pincoming.h"

// qt
#include <qregexp.h>
#include <qfile.h>
#include <qtextcodec.h>

// kde
#include <kdebug.h>
#include <kmdcodec.h>
#include <ktempfile.h>
#include <krun.h>
#include <klocale.h>
#include <kglobal.h>
#include <kdeversion.h>
#include <kstandarddirs.h>

//kopete
#include <kopetetransfermanager.h>

MSNP2PIncoming::MSNP2PIncoming( unsigned long int sessionID , MSNP2PDisplatcher *parent )
	: MSNP2P(sessionID , parent)
{
	m_file=0l;
	m_Rfile=0L;
	m_kopeteTransfer=0L;
}

MSNP2PIncoming::~MSNP2PIncoming()
{
	if(m_kopeteTransfer)
	{
		m_kopeteTransfer->slotError( KIO::ERR_INTERNAL , i18n("Connection closed")  );
	}

	if(m_file)
		delete m_file;
	else
		delete m_Rfile;
}

void MSNP2PIncoming::parseMessage(MessageStruct &msgStr)
{
	MSNP2P::parseMessage(msgStr);

	if(m_Rfile)  //we are already downloading something to this file
	{			//m_file->file()->writeBlock( (msg.data()+startBinHeader+48) , dataMessageSize );
		m_Rfile->writeBlock( (msgStr.message.data()+48) , msgStr.dataMessageSize );

		if(m_kopeteTransfer)
			m_kopeteTransfer->slotProcessed( msgStr.dataOffset+msgStr.dataMessageSize );

		if(msgStr.dataOffset+msgStr.dataMessageSize >= msgStr.totalSize) //the file is complete
		{
			if(m_file)
			{
				m_file->close();
				m_parent->fileReceived(m_file , m_obj);
				m_file=0;
				m_Rfile=0L;
			}
			else
			{
				if(m_kopeteTransfer) m_kopeteTransfer->slotComplete();
				m_Rfile->close();
				delete m_Rfile;
				m_Rfile=0L;
			}
/*
			delete m_file;*/

				//send the bye message
			makeMSNSLPMessage(BYE, QString::null);

			m_parent->finished(this);
				//deleteLater();
		}
	}
	else if(msgStr.message.data()[48] == '\0' && msgStr.dataMessageSize==4)
	{  //This can be only the data preparaion message.   prepare to download
		m_file=new KTempFile( locateLocal( "tmp", "msnpicture-" ), ".png" );
		m_file->setAutoDelete(true);
		m_Rfile=m_file->file();

	}
	else
	{
		QString dataMessage=QCString((msgStr.message.data()+48) , msgStr.dataMessageSize);
		kdDebug(14141) << k_funcinfo <<" dataMessage: "  << dataMessage << endl;

		if (dataMessage.contains("INVITE") )
		{
			if(! m_kopeteTransfer )
			{
				return;
			}
			//Parse the message to get some info for replying
			QRegExp rx(";branch=\\{([0-9A-F\\-]*)\\}\r\n");
			rx.search( dataMessage );
			m_branch=rx.cap(1);

			rx=QRegExp("Call-ID: \\{([0-9A-F\\-]*)\\}\r\n");
			rx.search( dataMessage );
			m_CallID=rx.cap(1);

		    //dirrect connection is not yet implemented, use the connection via MSNP2P
			QString content="Bridge: TCPv1\r\n"
					"Listening: false\r\n"
					"Nonce: {00000000-0000-0000-0000-000000000000}\r\n\r\n";

			makeMSNSLPMessage(OK, content);

			m_Rfile=new QFile( m_kopeteTransfer->destinationURL().path() );
			if(!m_Rfile->open(IO_WriteOnly))
			{
				if(m_kopeteTransfer)
				{
							//TODO: handle the QFILE error
					m_kopeteTransfer->slotError( KIO::ERR_CANNOT_OPEN_FOR_WRITING , i18n("Cannot open file for writing")  );
					m_kopeteTransfer=0L;
					return;
				}
				abortCurrentTransfer();
			}
		}
		else if (dataMessage.contains("BYE"))
		{
			abortCurrentTransfer();
		}
		else if(dataMessage.contains("200 OK"))
		{
			//ignore
		}
		else
		{ //this seems to be _probably_ (just a guess) a utf-16 message.   we will download it completely.
			/*
			 * The message looks like this:
			 *
			MIME-Version: 1.0
			Content-Type: image/gif
			\0
			base64:[ENCODED-IMAGE]
			 *  Sometimes, the base64 ends with =  sometimes it does not.
			 */

			if(msgStr.dataOffset ==0)
				fullContentMessage=QString::null;

			/*
			 * The following line doesn't works, because, wihtout reason i understand, the string contains some \0
			 * (\0\0 in utf-16)  between the   Content-Type:   and the Base64:

			QTextCodec *codec = QTextCodec::codecForName("ISO-10646-UCS-2");
			if(!codec)
			return; //abort();
			fullContentMessage += codec->toUnicode(msg.data()+startBinHeader+48-1 , dataMessageSize)

			 * Quick hack to parse utf-16 and remove \0\0 :
			 * The message shouldn't contains non ASCII char  (it's base64)  so i think i could do like that.
			 * FIXME:  yes, this is not 100% correct
			 */
			for(unsigned int f= 48 ; f < 48 + msgStr.dataMessageSize ; f+=2)
			{
				if(msgStr.message[f] != 0)
				{
					fullContentMessage+=QChar( msgStr.message[f] );
				}
			}

			//the message may be splitted
			if(msgStr.dataOffset+msgStr.dataMessageSize >= msgStr.totalSize)
			{ //whe have the whole

				kdDebug(14141) << k_funcinfo <<"Analyse the image message: " << fullContentMessage <<  endl;

				QString ext;
				QRegExp rx("Content-Type: ([a-zA-Z0-9/]*)");
				if( rx.search( fullContentMessage ) != -1 )
				{
					QString contentType=rx.cap(1);
					if(contentType=="image/gif")
						ext=".gif";
					else if(contentType=="image/png")
						ext=".png";
					else
					{
						kdWarning(14140) << k_funcinfo << contentType << " is not recognized.  A MSN message is not displayed" <<  endl;
						return;
					}
				}
				else
					return;

				rx=QRegExp("base64:([a-zA-Z0-9+\\-.*/!]*)");
				if( rx.search( fullContentMessage ) != -1 )
				{
					QString base64=rx.cap(1);

					QByteArray image;
					KCodecs::base64Decode( base64.utf8() , image );

					KTempFile *imageFile=new KTempFile( locateLocal( "tmp", "msntypewrite-" ), ext );
					imageFile->setAutoDelete(true);
					imageFile->file()->writeBlock( image.data() , image.size() );
					imageFile->file()->close();

					m_parent->fileReceived( imageFile , "typewrite" );
				}
			}
		}
	}
}

void MSNP2PIncoming::abortCurrentTransfer()
{
	if(m_kopeteTransfer)
	{
		delete m_Rfile;
		m_Rfile=0L;

		//this need to be reseted before sending the BYE message.
		m_totalDataSize=0;
		m_offset=0;
		m_footer='\0';

		//FIXME: i'm not sure it's like that i should abort the transfer.
		makeMSNSLPMessage(BYE, "\r\n\r\n" );
	}
	m_parent->finished(this);
}

void MSNP2PIncoming::slotKopeteTransferDestroyed()
{
	m_kopeteTransfer=0L;
	kdDebug(14140) << k_funcinfo << endl;
}

void MSNP2PIncoming::error()
{
	MSNP2P::error();

	if(m_kopeteTransfer)
	{
		m_kopeteTransfer->slotError( KIO::ERR_INTERNAL , i18n("Malformed packet received")  );
		m_kopeteTransfer=0L;
	}
}

#include "msnp2pincoming.moc"
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
//#include "LessParser.h"
#include "Parser.h"
int	main()
{
	std::ifstream fs;
	fs.open("test1.less", std::ios::in);
	//Tokenizer(fs);
	Parser lesparser = Parser(Tokenizer(fs));
	lesparser.printTree(lesparser.getRootNode());
	//lesparser.showTokens();
	return 0;
}<commit_msg>make Parser initialize right<commit_after>#include <iostream>
#include <fstream>
//#include "LessParser.h"
#include "Parser.h"
int	main(int argc, char **argv)
{
	std::ifstream fs;
	fs.open(argv[1], std::ios::in);
	Tokenizer tokenizer = Tokenizer(fs);
	Parser lesparser = Parser(tokenizer);
	lesparser.printTree(lesparser.getRootNode());
	//lesparser.showTokens();
	return 0;
}
<|endoftext|>


<commit_before>#include <gflags/gflags.h>
#include <sstream>

#include "codesearch.h"
#include "metrics.h"
#include "git_indexer.h"
#include "smart_git.h"
#include "debug.h"

namespace {
    metric git_walk("timer.git.walk");
    metric git_contents("timer.git.contents");
};

using namespace std;

DEFINE_string(order_root, "", "Walk top-level directories in this order.");
DEFINE_bool(revparse, false, "Display parsed revisions, rather than as-provided");

git_indexer::git_indexer(code_searcher *cs,
                         const string& repopath,
                         const string& name,
                         json_object *metadata)
    : cs_(cs), repo_(0), name_(name), metadata_(metadata) {
    git_repository_open(&repo_, repopath.c_str());
    if (repo_ == NULL) {
        fprintf(stderr, "Unable to open repo: %s\n", repopath.c_str());
        exit(1);
    }
    idx_repo_ = cs_->open_repo(name, metadata);

    int err;
    if ((err = git_threads_init()) != 0)
        die("git_threads_init: %s", giterr_last()->message);
    git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, GIT_OBJ_BLOB, 10*1024);
    git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, GIT_OBJ_OFS_DELTA, 10*1024);
    git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, GIT_OBJ_REF_DELTA, 10*1024);
}

git_indexer::~git_indexer() {
    git_repository_free(repo_);
}

void git_indexer::walk(const string& ref) {
    smart_object<git_commit> commit;
    smart_object<git_tree> tree;
    git_revparse_single(commit, repo_, (ref + "^0").c_str());
    git_commit_tree(tree, commit);

    char oidstr[GIT_OID_HEXSZ+1];
    string name = FLAGS_revparse ?
        strdup(git_oid_tostr(oidstr, sizeof(oidstr), git_commit_id(commit))) : ref;
    if (name_.size())
        name = name_ + ":" + name;

    idx_tree_ = cs_->open_revision(idx_repo_, ref);
    walk_root(name, tree);
}

void git_indexer::walk_root(const string& ref, git_tree *tree) {
    metric::timer tm_walk(git_walk);
    map<string, const git_tree_entry *> root;
    vector<const git_tree_entry *> ordered;
    int entries = git_tree_entrycount(tree);
    for (int i = 0; i < entries; ++i) {
        const git_tree_entry *ent = git_tree_entry_byindex(tree, i);
        root[git_tree_entry_name(ent)] = ent;
    }

    istringstream stream(FLAGS_order_root);
    string dir;
    while(stream >> dir) {
        map<string, const git_tree_entry *>::iterator it = root.find(dir);
        if (it == root.end())
            continue;
        ordered.push_back(it->second);
        root.erase(it);
    }
    for (map<string, const git_tree_entry *>::iterator it = root.begin();
         it != root.end(); ++it)
        ordered.push_back(it->second);
    for (vector<const git_tree_entry *>::iterator it = ordered.begin();
         it != ordered.end(); ++it) {
        smart_object<git_object> obj;
        git_tree_entry_to_object(obj, repo_, *it);
        string path = string(git_tree_entry_name(*it));
        tm_walk.pause();

        if (git_tree_entry_type(*it) == GIT_OBJ_TREE) {
            walk_tree(ref, path + "/", obj);
        } else if (git_tree_entry_type(*it) == GIT_OBJ_BLOB) {
            metric::timer tm_content(git_contents);
            const char *data = static_cast<const char*>(git_blob_rawcontent(obj));
            cs_->index_file(idx_tree_, path, StringPiece(data, git_blob_rawsize(obj)));
        }
        tm_walk.start();
    }
}

void git_indexer::walk_tree(const string& ref,
                            const string& pfx,
                            git_tree *tree) {
    metric::timer tm_walk(git_walk);
    string path;
    int entries = git_tree_entrycount(tree);
    int i;
    for (i = 0; i < entries; i++) {
        const git_tree_entry *ent = git_tree_entry_byindex(tree, i);
        path = pfx + git_tree_entry_name(ent);
        smart_object<git_object> obj;
        git_tree_entry_to_object(obj, repo_, ent);
        tm_walk.pause();
        if (git_tree_entry_type(ent) == GIT_OBJ_TREE) {
            walk_tree(ref, path + "/", obj);
        } else if (git_tree_entry_type(ent) == GIT_OBJ_BLOB) {
            metric::timer tm_contents(git_contents);
            const char *data = static_cast<const char*>(git_blob_rawcontent(obj));
            cs_->index_file(idx_tree_, path, StringPiece(data, git_blob_rawsize(obj)));
        }
        tm_walk.start();
    }
}
<commit_msg>libgit2: init threads before using libgit2<commit_after>#include <gflags/gflags.h>
#include <sstream>

#include "codesearch.h"
#include "metrics.h"
#include "git_indexer.h"
#include "smart_git.h"
#include "debug.h"

namespace {
    metric git_walk("timer.git.walk");
    metric git_contents("timer.git.contents");
};

using namespace std;

DEFINE_string(order_root, "", "Walk top-level directories in this order.");
DEFINE_bool(revparse, false, "Display parsed revisions, rather than as-provided");

git_indexer::git_indexer(code_searcher *cs,
                         const string& repopath,
                         const string& name,
                         json_object *metadata)
    : cs_(cs), repo_(0), name_(name), metadata_(metadata) {
    int err;
    if ((err = git_threads_init()) != 0)
        die("git_threads_init: %s", giterr_last()->message);

    git_repository_open(&repo_, repopath.c_str());
    if (repo_ == NULL) {
        fprintf(stderr, "Unable to open repo: %s\n", repopath.c_str());
        exit(1);
    }
    idx_repo_ = cs_->open_repo(name, metadata);

    git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, GIT_OBJ_BLOB, 10*1024);
    git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, GIT_OBJ_OFS_DELTA, 10*1024);
    git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, GIT_OBJ_REF_DELTA, 10*1024);
}

git_indexer::~git_indexer() {
    git_repository_free(repo_);
}

void git_indexer::walk(const string& ref) {
    smart_object<git_commit> commit;
    smart_object<git_tree> tree;
    git_revparse_single(commit, repo_, (ref + "^0").c_str());
    git_commit_tree(tree, commit);

    char oidstr[GIT_OID_HEXSZ+1];
    string name = FLAGS_revparse ?
        strdup(git_oid_tostr(oidstr, sizeof(oidstr), git_commit_id(commit))) : ref;
    if (name_.size())
        name = name_ + ":" + name;

    idx_tree_ = cs_->open_revision(idx_repo_, ref);
    walk_root(name, tree);
}

void git_indexer::walk_root(const string& ref, git_tree *tree) {
    metric::timer tm_walk(git_walk);
    map<string, const git_tree_entry *> root;
    vector<const git_tree_entry *> ordered;
    int entries = git_tree_entrycount(tree);
    for (int i = 0; i < entries; ++i) {
        const git_tree_entry *ent = git_tree_entry_byindex(tree, i);
        root[git_tree_entry_name(ent)] = ent;
    }

    istringstream stream(FLAGS_order_root);
    string dir;
    while(stream >> dir) {
        map<string, const git_tree_entry *>::iterator it = root.find(dir);
        if (it == root.end())
            continue;
        ordered.push_back(it->second);
        root.erase(it);
    }
    for (map<string, const git_tree_entry *>::iterator it = root.begin();
         it != root.end(); ++it)
        ordered.push_back(it->second);
    for (vector<const git_tree_entry *>::iterator it = ordered.begin();
         it != ordered.end(); ++it) {
        smart_object<git_object> obj;
        git_tree_entry_to_object(obj, repo_, *it);
        string path = string(git_tree_entry_name(*it));
        tm_walk.pause();

        if (git_tree_entry_type(*it) == GIT_OBJ_TREE) {
            walk_tree(ref, path + "/", obj);
        } else if (git_tree_entry_type(*it) == GIT_OBJ_BLOB) {
            metric::timer tm_content(git_contents);
            const char *data = static_cast<const char*>(git_blob_rawcontent(obj));
            cs_->index_file(idx_tree_, path, StringPiece(data, git_blob_rawsize(obj)));
        }
        tm_walk.start();
    }
}

void git_indexer::walk_tree(const string& ref,
                            const string& pfx,
                            git_tree *tree) {
    metric::timer tm_walk(git_walk);
    string path;
    int entries = git_tree_entrycount(tree);
    int i;
    for (i = 0; i < entries; i++) {
        const git_tree_entry *ent = git_tree_entry_byindex(tree, i);
        path = pfx + git_tree_entry_name(ent);
        smart_object<git_object> obj;
        git_tree_entry_to_object(obj, repo_, ent);
        tm_walk.pause();
        if (git_tree_entry_type(ent) == GIT_OBJ_TREE) {
            walk_tree(ref, path + "/", obj);
        } else if (git_tree_entry_type(ent) == GIT_OBJ_BLOB) {
            metric::timer tm_contents(git_contents);
            const char *data = static_cast<const char*>(git_blob_rawcontent(obj));
            cs_->index_file(idx_tree_, path, StringPiece(data, git_blob_rawsize(obj)));
        }
        tm_walk.start();
    }
}
<|endoftext|>


<commit_before>/**************************************************************************
 *
 * Copyright 2013-2014 RAD Game Tools and Valve Software
 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
 * All Rights Reserved.
 *
 * 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.
 *
 **************************************************************************/

// File: vogl_port_posix.cpp

#if !defined(PLATFORM_POSIX)
    #error "vogl_port_posix should not be compiled on non-POSIX platforms."
#endif

#include "vogl_port.h"
#include <dlfcn.h>
#include <fcntl.h>
#include <paths.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/time.h>

int plat_chdir(const char* path)
{
    return chdir(path);
}

char* plat_getcwd(char *buffer, int maxlen)
{
    return getcwd(buffer, maxlen);
}

const char* plat_gettmpdir()
{
    static char s_tmpdir[PATH_MAX];

    if (!s_tmpdir[0])
    {
        const char *tmpdir = getenv("TMPDIR");

        if (!tmpdir)
        {
            tmpdir = P_tmpdir;
            if (!tmpdir)
                tmpdir = _PATH_TMP;
        }

        strncpy(s_tmpdir, tmpdir, sizeof(s_tmpdir));
        s_tmpdir[sizeof(s_tmpdir) - 1] = 0;

        // Remove trailing slash.
        size_t slen = strlen(s_tmpdir);
        if ((slen > 0) && (s_tmpdir[slen - 1] == '/'))
            s_tmpdir[--slen] = 0;
    }

    return s_tmpdir;
}

char* plat_gettmpfname(char *buffer, int maxlen, const char *prefix)
{
    struct timeval cur_time;
    vogl::uint32 rnd32 = plat_rand();
    const char *tmpdir = plat_gettmpdir();

    gettimeofday(&cur_time, NULL);

    uint64_t time64 = cur_time.tv_sec * 1000000ULL + cur_time.tv_usec;

    // Create a fileiname with THREADID & RAND32 & TIME64.
    snprintf(buffer, maxlen, "%s/_%s_%x_%x_%" PRIx64 ".tmp", tmpdir, prefix, plat_gettid(), rnd32, time64);
    buffer[maxlen - 1] = 0;
    return buffer;
}

// Tests for the existence of the specified path, returns true if it exists and false otherwise.
bool plat_fexist(const char* path)
{
    return access(path, F_OK) == 0;
}

pid_t plat_gettid()
{
    return static_cast<pid_t>(syscall(SYS_gettid));
}

uint64_t plat_posix_gettid()
{
    return static_cast<uint64_t>(pthread_self());
}

pid_t plat_getpid()
{
    return getpid();
}

pid_t plat_getppid()
{
    return getppid();
}

size_t plat_rand_s(vogl::uint32* out_array, size_t out_array_length)
{
    static __thread unsigned int s_seed = 0;

    if (s_seed == 0)
    {
        // Try to seed rand_r() with /dev/urandom.
        ssize_t nbytes = 0;
        int fd = open("/dev/urandom", O_RDONLY);
        if (fd != -1)
        {
            nbytes = read(fd, &s_seed, sizeof(s_seed));
            close(fd);
        }

        // If that didn't work, fallback to time and thread id.
        if (nbytes != sizeof(s_seed))
        {
            struct timeval time;
            gettimeofday(&time, NULL);
            s_seed = plat_gettid() ^ ((time.tv_sec * 1000) + (time.tv_usec / 1000));
        }
    }

    for (size_t i = 0; i < out_array_length; ++i)
        out_array[i] = rand_r(&s_seed);

    return out_array_length;
}

vogl::uint32 plat_rand()
{
    vogl::uint32 num;
    plat_rand_s(&num, 1);
    return num;
}

// Returns the size of a virtual page of memory.
vogl::int32 plat_get_virtual_page_size()
{
    return sysconf(_SC_PAGE_SIZE);
}

static int get_prot_from_access(vogl::uint32 access_flags)
{
    int ret_flags = 0;
    if ((access_flags & PLAT_WRITE) == PLAT_WRITE)
    {
        ret_flags |= PROT_WRITE;
        access_flags &= ~PLAT_WRITE;
    }

    if ((access_flags & (PLAT_READ)) == (PLAT_READ))
    {
        ret_flags |= PROT_READ;
        access_flags &= ~(PLAT_READ);
    }

    // If this fires, it means the code above needs to be updated to support the flag being passed in.
    VOGL_VERIFY(access_flags == 0);

    return ret_flags;
}

void* plat_virtual_alloc(size_t size_requested, vogl::uint32 access_flags, size_t* out_size_provided)
{
    const int prot = get_prot_from_access(access_flags);
    const int flags = MAP_ANON | MAP_SHARED;
    void *p = mmap(NULL, size_requested, prot, flags, -1, 0);

    if ((!p) || (p == MAP_FAILED))
    {
        uint e = errno;

        // Not using strerror_r because it fails when we're completely out of memory.
        char *pError_desc = strerror(e);

        char buf[256];
        sprintf(buf, "%s: mmap() of %zu bytes failed! Reason: %s (errno 0x%x)\n", VOGL_FUNCTION_INFO_CSTR, size_requested, pError_desc, e);

        write(STDERR_FILENO, buf, strlen(buf));
        abort();
    }

    *out_size_provided = size_requested;

    return p;
}

void plat_virtual_free(void* free_addr, size_t size)
{
    int res = munmap(free_addr, size);
    if (res != 0)
    {
        uint e = errno;

        // Not using strerror_r because it fails when we're completely out of memory.
        char *pError_desc = strerror(e);

        char buf[256];
        sprintf(buf, "%s: munmap() free_addr 0x%" PRIxPTR " size 0x%" PRIxPTR " failed! Reason: %s (errno 0x%x)\n", VOGL_FUNCTION_INFO_CSTR, (uintptr_t)free_addr, size, pError_desc, e);

        write(STDERR_FILENO, buf, strlen(buf));
        abort();
    }
}

#if VOGL_USE_PTHREADS_API
    int plat_sem_post(sem_t* sem, vogl::uint32 release_count)
    {
        int status = 0;
        while (release_count > 0)
        {
            status = sem_post(sem);
            if (status)
                break;
            release_count--;
        }

        return status;
    }

    void plat_try_sem_post(sem_t* sem, vogl::uint32 release_count)
    {
        while (release_count > 0)
        {
            sem_post(sem);
            release_count--;
        }
    }
#endif

void* plat_dlsym(void* handle, const char* symbol)
{
    return dlsym(handle, symbol);
}

<commit_msg>Added plat_load_system_gl implementation for posix platforms.<commit_after>/**************************************************************************
 *
 * Copyright 2013-2014 RAD Game Tools and Valve Software
 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
 * All Rights Reserved.
 *
 * 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.
 *
 **************************************************************************/

// File: vogl_port_posix.cpp

#if !defined(PLATFORM_POSIX)
    #error "vogl_port_posix should not be compiled on non-POSIX platforms."
#endif

#include "vogl_port.h"
#include <dlfcn.h>
#include <fcntl.h>
#include <paths.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/time.h>

int plat_chdir(const char* path)
{
    return chdir(path);
}

char* plat_getcwd(char *buffer, int maxlen)
{
    return getcwd(buffer, maxlen);
}

const char* plat_gettmpdir()
{
    static char s_tmpdir[PATH_MAX];

    if (!s_tmpdir[0])
    {
        const char *tmpdir = getenv("TMPDIR");

        if (!tmpdir)
        {
            tmpdir = P_tmpdir;
            if (!tmpdir)
                tmpdir = _PATH_TMP;
        }

        strncpy(s_tmpdir, tmpdir, sizeof(s_tmpdir));
        s_tmpdir[sizeof(s_tmpdir) - 1] = 0;

        // Remove trailing slash.
        size_t slen = strlen(s_tmpdir);
        if ((slen > 0) && (s_tmpdir[slen - 1] == '/'))
            s_tmpdir[--slen] = 0;
    }

    return s_tmpdir;
}

char* plat_gettmpfname(char *buffer, int maxlen, const char *prefix)
{
    struct timeval cur_time;
    vogl::uint32 rnd32 = plat_rand();
    const char *tmpdir = plat_gettmpdir();

    gettimeofday(&cur_time, NULL);

    uint64_t time64 = cur_time.tv_sec * 1000000ULL + cur_time.tv_usec;

    // Create a fileiname with THREADID & RAND32 & TIME64.
    snprintf(buffer, maxlen, "%s/_%s_%x_%x_%" PRIx64 ".tmp", tmpdir, prefix, plat_gettid(), rnd32, time64);
    buffer[maxlen - 1] = 0;
    return buffer;
}

// Tests for the existence of the specified path, returns true if it exists and false otherwise.
bool plat_fexist(const char* path)
{
    return access(path, F_OK) == 0;
}

pid_t plat_gettid()
{
    return static_cast<pid_t>(syscall(SYS_gettid));
}

uint64_t plat_posix_gettid()
{
    return static_cast<uint64_t>(pthread_self());
}

pid_t plat_getpid()
{
    return getpid();
}

pid_t plat_getppid()
{
    return getppid();
}

size_t plat_rand_s(vogl::uint32* out_array, size_t out_array_length)
{
    static __thread unsigned int s_seed = 0;

    if (s_seed == 0)
    {
        // Try to seed rand_r() with /dev/urandom.
        ssize_t nbytes = 0;
        int fd = open("/dev/urandom", O_RDONLY);
        if (fd != -1)
        {
            nbytes = read(fd, &s_seed, sizeof(s_seed));
            close(fd);
        }

        // If that didn't work, fallback to time and thread id.
        if (nbytes != sizeof(s_seed))
        {
            struct timeval time;
            gettimeofday(&time, NULL);
            s_seed = plat_gettid() ^ ((time.tv_sec * 1000) + (time.tv_usec / 1000));
        }
    }

    for (size_t i = 0; i < out_array_length; ++i)
        out_array[i] = rand_r(&s_seed);

    return out_array_length;
}

vogl::uint32 plat_rand()
{
    vogl::uint32 num;
    plat_rand_s(&num, 1);
    return num;
}

// Returns the size of a virtual page of memory.
vogl::int32 plat_get_virtual_page_size()
{
    return sysconf(_SC_PAGE_SIZE);
}

static int get_prot_from_access(vogl::uint32 access_flags)
{
    int ret_flags = 0;
    if ((access_flags & PLAT_WRITE) == PLAT_WRITE)
    {
        ret_flags |= PROT_WRITE;
        access_flags &= ~PLAT_WRITE;
    }

    if ((access_flags & (PLAT_READ)) == (PLAT_READ))
    {
        ret_flags |= PROT_READ;
        access_flags &= ~(PLAT_READ);
    }

    // If this fires, it means the code above needs to be updated to support the flag being passed in.
    VOGL_VERIFY(access_flags == 0);

    return ret_flags;
}

void* plat_virtual_alloc(size_t size_requested, vogl::uint32 access_flags, size_t* out_size_provided)
{
    const int prot = get_prot_from_access(access_flags);
    const int flags = MAP_ANON | MAP_SHARED;
    void *p = mmap(NULL, size_requested, prot, flags, -1, 0);

    if ((!p) || (p == MAP_FAILED))
    {
        uint e = errno;

        // Not using strerror_r because it fails when we're completely out of memory.
        char *pError_desc = strerror(e);

        char buf[256];
        sprintf(buf, "%s: mmap() of %zu bytes failed! Reason: %s (errno 0x%x)\n", VOGL_FUNCTION_INFO_CSTR, size_requested, pError_desc, e);

        write(STDERR_FILENO, buf, strlen(buf));
        abort();
    }

    *out_size_provided = size_requested;

    return p;
}

void plat_virtual_free(void* free_addr, size_t size)
{
    int res = munmap(free_addr, size);
    if (res != 0)
    {
        uint e = errno;

        // Not using strerror_r because it fails when we're completely out of memory.
        char *pError_desc = strerror(e);

        char buf[256];
        sprintf(buf, "%s: munmap() free_addr 0x%" PRIxPTR " size 0x%" PRIxPTR " failed! Reason: %s (errno 0x%x)\n", VOGL_FUNCTION_INFO_CSTR, (uintptr_t)free_addr, size, pError_desc, e);

        write(STDERR_FILENO, buf, strlen(buf));
        abort();
    }
}

#if VOGL_USE_PTHREADS_API
    int plat_sem_post(sem_t* sem, vogl::uint32 release_count)
    {
        int status = 0;
        while (release_count > 0)
        {
            status = sem_post(sem);
            if (status)
                break;
            release_count--;
        }

        return status;
    }

    void plat_try_sem_post(sem_t* sem, vogl::uint32 release_count)
    {
        while (release_count > 0)
        {
            sem_post(sem);
            release_count--;
        }
    }
#endif

void* plat_dlsym(void* handle, const char* symbol)
{
    return dlsym(handle, symbol);
}

void* plat_load_system_gl(int _flags)
{
    return dlopen(plat_get_system_gl_module_name(), _flags);
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkRenderWindowInteractor.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkRenderWindowInteractor.hh"
#include "vtkActor.hh"
#include "vtkCellPicker.hh"

// Description:
// Construct object so that light follows camera motion.
vtkRenderWindowInteractor::vtkRenderWindowInteractor()
{
  this->RenderWindow    = NULL;
  this->CurrentCamera   = NULL;
  this->CurrentLight    = NULL;
  this->CurrentRenderer = NULL;

  this->LightFollowCamera = 1;
  this->Initialized = 0;
  this->DesiredUpdateRate = 15;
  this->StillUpdateRate = 0;

  this->SelfCreatedPicker = 0;
  this->Picker = this->CreateDefaultPicker();
  this->OutlineActor = NULL;
  this->OutlineMapper.SetInput(this->Outline.GetOutput());
  this->PickedRenderer = NULL;
  this->CurrentActor = NULL;

  this->StartPickMethod = NULL;
  this->StartPickMethodArgDelete = NULL;
  this->StartPickMethodArg = NULL;
  this->EndPickMethod = NULL;
  this->EndPickMethodArgDelete = NULL;
  this->EndPickMethodArg = NULL;
  this->UserMethod = NULL;
  this->UserMethodArgDelete = NULL;
  this->UserMethodArg = NULL;
}

vtkRenderWindowInteractor::~vtkRenderWindowInteractor()
{
  if ( this->OutlineActor ) this->OutlineActor->Delete();
  if ( this->SelfCreatedPicker && this->Picker) this->Picker->Delete();
}

void vtkRenderWindowInteractor::FindPokedRenderer(int x,int y)
{
  vtkRendererCollection *rc;
  vtkRenderer *aren;

  this->CurrentRenderer = NULL;

  rc = this->RenderWindow->GetRenderers();

  for (rc->InitTraversal();
       ((aren = rc->GetNextItem())&&(!this->CurrentRenderer));)
    {
    if (aren->IsInViewport(x,y))
      {
      this->CurrentRenderer = aren;
      }
    }

  // we must have a value
  if (this->CurrentRenderer == NULL)
    {
    rc->InitTraversal();
    aren = rc->GetNextItem();
    this->CurrentRenderer = aren;
    }
}

void  vtkRenderWindowInteractor::FindPokedCamera(int x,int y)
{
  float *vp;
  vtkLightCollection *lc;

  this->FindPokedRenderer(x,y);
  vp = this->CurrentRenderer->GetViewport();

  this->CurrentCamera = this->CurrentRenderer->GetActiveCamera();
  memcpy(this->Center,this->CurrentRenderer->GetCenter(),sizeof(int)*2);
  this->DeltaElevation = 20.0/((vp[3] - vp[1])*this->Size[1]);
  this->DeltaAzimuth = 20.0/((vp[2] - vp[0])*this->Size[0]);

  // as a side effect also set the light
  // in case they are using light follow camera
  lc = this->CurrentRenderer->GetLights();
  lc->InitTraversal();
  this->CurrentLight = lc->GetNextItem();
}

// Description:
// When pick action successfully selects actor, this method highlights the
// actor appropriately. Currently this is done by placing a bounding box
// around the actor.
void vtkRenderWindowInteractor::HighlightActor(vtkActor *actor)
{
  if ( ! this->OutlineActor )
    {
    // have to defer creation to get right type
    this->OutlineActor = new vtkActor;
    this->OutlineActor->PickableOff();
    this->OutlineActor->DragableOff();
    this->OutlineActor->SetMapper(this->OutlineMapper);
    this->OutlineActor->GetProperty()->SetColor(1.0,1.0,1.0);
    this->OutlineActor->GetProperty()->SetAmbient(1.0);
    this->OutlineActor->GetProperty()->SetDiffuse(0.0);
    }

  if ( this->PickedRenderer )
    this->PickedRenderer->RemoveActors(OutlineActor);

  if ( ! actor )
    {
    this->PickedRenderer = NULL;
    }
  else
    {
    this->PickedRenderer = this->CurrentRenderer;
    this->CurrentRenderer->AddActors(OutlineActor);
    this->Outline.SetBounds(actor->GetBounds());
    this->CurrentActor = actor;
    }
  this->RenderWindow->Render();
}

// Description:
// Specify a method to be executed prior to the pick operation.
void vtkRenderWindowInteractor::SetStartPickMethod(void (*f)(void *), void *arg)
{
  if ( f != this->StartPickMethod || arg != this->StartPickMethodArg )
    {
    this->StartPickMethod = f;
    this->StartPickMethodArg = arg;
    this->Modified();
    }
}

// Description:
// Specify a method to be executed after the pick operation.
void vtkRenderWindowInteractor::SetEndPickMethod(void (*f)(void *), void *arg)
{
  if ( f != this->EndPickMethod || arg != this->EndPickMethodArg )
    {
    this->EndPickMethod = f;
    this->EndPickMethodArg = arg;
    this->Modified();
    }
}

// Description:
// Set the object used to perform pick operations. You can use this to
// control what type of data is picked.
void vtkRenderWindowInteractor::SetPicker(vtkPicker *picker)
{
  if ( this->Picker != picker )
    {
    if ( this->SelfCreatedPicker ) this->Picker->Delete();
    this->SelfCreatedPicker = 0;
    this->Picker = picker;
    this->Modified();
    }
}

vtkPicker *vtkRenderWindowInteractor::CreateDefaultPicker()
{
  if ( this->SelfCreatedPicker ) this->Picker->Delete();
  this->SelfCreatedPicker = 1;
  return new vtkCellPicker;
}

// Description:
// Set the user method. This method is invoked on a <u> keypress.
void vtkRenderWindowInteractor::SetUserMethod(void (*f)(void *), void *arg)
{
  if ( f != this->UserMethod || arg != this->UserMethodArg )
    {
    // delete the current arg if there is one and a delete meth
    if ((this->UserMethodArg)&&(this->UserMethodArgDelete))
      {
      (*this->UserMethodArgDelete)(this->UserMethodArg);
      }
    this->UserMethod = f;
    this->UserMethodArg = arg;
    this->Modified();
    }
}

// Description:
// Called when a void* argument is being discarded.  Lets the user free it.
void vtkRenderWindowInteractor::SetUserMethodArgDelete(void (*f)(void *))
{
  if ( f != this->UserMethodArgDelete)
    {
    this->UserMethodArgDelete = f;
    this->Modified();
    }
}

// Description:
// Called when a void* argument is being discarded.  Lets the user free it.
void vtkRenderWindowInteractor::SetStartPickMethodArgDelete(void (*f)(void *))
{
  if ( f != this->StartPickMethodArgDelete)
    {
    this->StartPickMethodArgDelete = f;
    this->Modified();
    }
}
// Description:
// Called when a void* argument is being discarded.  Lets the user free it.
void vtkRenderWindowInteractor::SetEndPickMethodArgDelete(void (*f)(void *))
{
  if ( f != this->EndPickMethodArgDelete)
    {
    this->EndPickMethodArgDelete = f;
    this->Modified();
    }
}

void vtkRenderWindowInteractor::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkObject::PrintSelf(os,indent);

  os << indent << "RenderWindow:    " << this->RenderWindow << "\n";
  os << indent << "CurrentCamera:   " << this->CurrentCamera << "\n";
  os << indent << "CurrentLight:    " << this->CurrentLight << "\n";
  os << indent << "CurrentRenderer: " << this->CurrentRenderer << "\n";
  os << indent << "LightFollowCamera: " << (this->LightFollowCamera ? "On\n" : "Off\n");
  os << indent << "DesiredUpdateRate: " << this->DesiredUpdateRate << "\n";
  os << indent << "StillUpdateRate: " << this->StillUpdateRate << "\n";
}

<commit_msg>fixed camera azimuth and Elev<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkRenderWindowInteractor.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkRenderWindowInteractor.hh"
#include "vtkActor.hh"
#include "vtkCellPicker.hh"

// Description:
// Construct object so that light follows camera motion.
vtkRenderWindowInteractor::vtkRenderWindowInteractor()
{
  this->RenderWindow    = NULL;
  this->CurrentCamera   = NULL;
  this->CurrentLight    = NULL;
  this->CurrentRenderer = NULL;

  this->LightFollowCamera = 1;
  this->Initialized = 0;
  this->DesiredUpdateRate = 15;
  this->StillUpdateRate = 0;

  this->SelfCreatedPicker = 0;
  this->Picker = this->CreateDefaultPicker();
  this->OutlineActor = NULL;
  this->OutlineMapper.SetInput(this->Outline.GetOutput());
  this->PickedRenderer = NULL;
  this->CurrentActor = NULL;

  this->StartPickMethod = NULL;
  this->StartPickMethodArgDelete = NULL;
  this->StartPickMethodArg = NULL;
  this->EndPickMethod = NULL;
  this->EndPickMethodArgDelete = NULL;
  this->EndPickMethodArg = NULL;
  this->UserMethod = NULL;
  this->UserMethodArgDelete = NULL;
  this->UserMethodArg = NULL;
}

vtkRenderWindowInteractor::~vtkRenderWindowInteractor()
{
  if ( this->OutlineActor ) this->OutlineActor->Delete();
  if ( this->SelfCreatedPicker && this->Picker) this->Picker->Delete();
}

void vtkRenderWindowInteractor::FindPokedRenderer(int x,int y)
{
  vtkRendererCollection *rc;
  vtkRenderer *aren;

  this->CurrentRenderer = NULL;

  rc = this->RenderWindow->GetRenderers();

  for (rc->InitTraversal();
       ((aren = rc->GetNextItem())&&(!this->CurrentRenderer));)
    {
    if (aren->IsInViewport(x,y))
      {
      this->CurrentRenderer = aren;
      }
    }

  // we must have a value
  if (this->CurrentRenderer == NULL)
    {
    rc->InitTraversal();
    aren = rc->GetNextItem();
    this->CurrentRenderer = aren;
    }
}

void  vtkRenderWindowInteractor::FindPokedCamera(int x,int y)
{
  float *vp;
  vtkLightCollection *lc;

  this->FindPokedRenderer(x,y);
  vp = this->CurrentRenderer->GetViewport();

  this->CurrentCamera = this->CurrentRenderer->GetActiveCamera();
  memcpy(this->Center,this->CurrentRenderer->GetCenter(),sizeof(int)*2);
  this->DeltaElevation = -20.0/((vp[3] - vp[1])*this->Size[1]);
  this->DeltaAzimuth = -20.0/((vp[2] - vp[0])*this->Size[0]);

  // as a side effect also set the light
  // in case they are using light follow camera
  lc = this->CurrentRenderer->GetLights();
  lc->InitTraversal();
  this->CurrentLight = lc->GetNextItem();
}

// Description:
// When pick action successfully selects actor, this method highlights the
// actor appropriately. Currently this is done by placing a bounding box
// around the actor.
void vtkRenderWindowInteractor::HighlightActor(vtkActor *actor)
{
  if ( ! this->OutlineActor )
    {
    // have to defer creation to get right type
    this->OutlineActor = new vtkActor;
    this->OutlineActor->PickableOff();
    this->OutlineActor->DragableOff();
    this->OutlineActor->SetMapper(this->OutlineMapper);
    this->OutlineActor->GetProperty()->SetColor(1.0,1.0,1.0);
    this->OutlineActor->GetProperty()->SetAmbient(1.0);
    this->OutlineActor->GetProperty()->SetDiffuse(0.0);
    }

  if ( this->PickedRenderer )
    this->PickedRenderer->RemoveActors(OutlineActor);

  if ( ! actor )
    {
    this->PickedRenderer = NULL;
    }
  else
    {
    this->PickedRenderer = this->CurrentRenderer;
    this->CurrentRenderer->AddActors(OutlineActor);
    this->Outline.SetBounds(actor->GetBounds());
    this->CurrentActor = actor;
    }
  this->RenderWindow->Render();
}

// Description:
// Specify a method to be executed prior to the pick operation.
void vtkRenderWindowInteractor::SetStartPickMethod(void (*f)(void *), void *arg)
{
  if ( f != this->StartPickMethod || arg != this->StartPickMethodArg )
    {
    this->StartPickMethod = f;
    this->StartPickMethodArg = arg;
    this->Modified();
    }
}

// Description:
// Specify a method to be executed after the pick operation.
void vtkRenderWindowInteractor::SetEndPickMethod(void (*f)(void *), void *arg)
{
  if ( f != this->EndPickMethod || arg != this->EndPickMethodArg )
    {
    this->EndPickMethod = f;
    this->EndPickMethodArg = arg;
    this->Modified();
    }
}

// Description:
// Set the object used to perform pick operations. You can use this to
// control what type of data is picked.
void vtkRenderWindowInteractor::SetPicker(vtkPicker *picker)
{
  if ( this->Picker != picker )
    {
    if ( this->SelfCreatedPicker ) this->Picker->Delete();
    this->SelfCreatedPicker = 0;
    this->Picker = picker;
    this->Modified();
    }
}

vtkPicker *vtkRenderWindowInteractor::CreateDefaultPicker()
{
  if ( this->SelfCreatedPicker ) this->Picker->Delete();
  this->SelfCreatedPicker = 1;
  return new vtkCellPicker;
}

// Description:
// Set the user method. This method is invoked on a <u> keypress.
void vtkRenderWindowInteractor::SetUserMethod(void (*f)(void *), void *arg)
{
  if ( f != this->UserMethod || arg != this->UserMethodArg )
    {
    // delete the current arg if there is one and a delete meth
    if ((this->UserMethodArg)&&(this->UserMethodArgDelete))
      {
      (*this->UserMethodArgDelete)(this->UserMethodArg);
      }
    this->UserMethod = f;
    this->UserMethodArg = arg;
    this->Modified();
    }
}

// Description:
// Called when a void* argument is being discarded.  Lets the user free it.
void vtkRenderWindowInteractor::SetUserMethodArgDelete(void (*f)(void *))
{
  if ( f != this->UserMethodArgDelete)
    {
    this->UserMethodArgDelete = f;
    this->Modified();
    }
}

// Description:
// Called when a void* argument is being discarded.  Lets the user free it.
void vtkRenderWindowInteractor::SetStartPickMethodArgDelete(void (*f)(void *))
{
  if ( f != this->StartPickMethodArgDelete)
    {
    this->StartPickMethodArgDelete = f;
    this->Modified();
    }
}
// Description:
// Called when a void* argument is being discarded.  Lets the user free it.
void vtkRenderWindowInteractor::SetEndPickMethodArgDelete(void (*f)(void *))
{
  if ( f != this->EndPickMethodArgDelete)
    {
    this->EndPickMethodArgDelete = f;
    this->Modified();
    }
}

void vtkRenderWindowInteractor::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkObject::PrintSelf(os,indent);

  os << indent << "RenderWindow:    " << this->RenderWindow << "\n";
  os << indent << "CurrentCamera:   " << this->CurrentCamera << "\n";
  os << indent << "CurrentLight:    " << this->CurrentLight << "\n";
  os << indent << "CurrentRenderer: " << this->CurrentRenderer << "\n";
  os << indent << "LightFollowCamera: " << (this->LightFollowCamera ? "On\n" : "Off\n");
  os << indent << "DesiredUpdateRate: " << this->DesiredUpdateRate << "\n";
  os << indent << "StillUpdateRate: " << this->StillUpdateRate << "\n";
}

<|endoftext|>


<commit_before><commit_msg>Remove unnecessary WebCore includes.<commit_after><|endoftext|>


<commit_before>/*
 Copyright (C) 2012 by Ivan Safrin

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */

#include "TextureBrowser.h"

AssetEntry::AssetEntry(String assetPath, String assetName, String extension, Resource *resource) : UIElement() {

    this->resource = resource;
	this->assetPath = assetPath;

	if(assetName.length() > 20)
		assetName = assetName.substr(0,20)+"...";

	selectShape = new UIRect(120, 100);
	selectShape->visible = false;
	selectShape->setAnchorPoint(-1.0, -1.0, 0.0);
	addChild(selectShape);
	selectShape->processInputEvents = true;
	selectShape->setColor(0.0, 0.0, 0.0, 0.5);
    selectShape->loadTexture("browserIcons/large_selector.png");
    selectShape->setBlendingMode(Renderer::BLEND_MODE_NORMAL);

	imageShape = new UIRect(64,64);
	imageShape->setAnchorPoint(-1.0, -1.0, 0.0);
	addChild(imageShape);

	extension = extension.toLowerCase();

	if(extension == "png") {
		imageShape->loadTexture(assetPath);
	} else if(extension == "ogg" || extension == "wav") {
		imageShape->loadTexture("browserIcons/sound_icon.png");
	} else if(extension == "entity") {
		imageShape->loadTexture("browserIcons/entity_icon.png");
	} else if(extension == "sprite") {
		imageShape->loadTexture("browserIcons/sprite_icon.png");
	} else if(extension == "ttf" || extension == "otf") {
		imageShape->loadTexture("browserIcons/font_icon.png");
	} else if(extension == "vert" || extension == "frag") {
		imageShape->loadTexture("browserIcons/shader_icon.png");
	} else if(extension == "mesh") {
		imageShape->loadTexture("browserIcons/mesh_icon.png");
    } else if(extension == "mat") {
		imageShape->loadTexture("browserIcons/materials_icon.png");
    } else if(extension == "material_resource") {
		imageShape->loadTexture("browserIcons/material_resource_icon.png");
    }

	imageShape->setPosition(28, 10);
    imageShape->setBlendingMode(Renderer::BLEND_MODE_NORMAL);

    String name = assetName;
    if(name.length() > 15) {
        name = name.substr(0, 15)+"...";
    }
	nameLabel = new UILabel(name, 11);
	addChild(nameLabel);
    nameLabel->setPosition((120.0-nameLabel->getWidth())/2.0, 80);

}

AssetEntry::~AssetEntry() {
	delete imageShape;
	delete nameLabel;
	delete selectShape;
}

AssetList::AssetList() : UIElement() {

	reloadButton = new UIImageButton("browserIcons/reload_icon.png", 1.0, 20, 20);
	reloadButton->addEventListener(this, UIEvent::CLICK_EVENT);
	addChild(reloadButton);
	reloadButton->setPosition(10, 5);

}

AssetList::~AssetList() {

}

Resource *AssetList::getSelectedResource() {
    return selectedResource;
}

void AssetList::setExtensions(std::vector<String> extensions) {
	this->extensions = extensions;
	if(currentFolderPath != "") {
		showFolder(currentFolderPath);
	}
}

bool AssetList::hasExtension(String extension) {
	for(int i=0; i < extensions.size(); i++) {
		if(extensions[i] == extension.toLowerCase()) {
			return true;
		}
	}
	return false;
}

void AssetList::showResourcePool(ResourcePool *pool, int resourceFilter) {

    clearList();

	Number xPos = 20;
	Number yPos = 30;

    std::vector<Resource*> resources = pool->getResources(resourceFilter);

    String extension;

    if(resourceFilter == Resource::RESOURCE_MATERIAL ) {
        extension = "material_resource";
    }

	for(int i=0; i < resources.size(); i++) {
        AssetEntry *newEntry = new AssetEntry("", resources[i]->getResourceName(), extension, resources[i]);
        newEntry->selectShape->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
        assetEntries.push_back(newEntry);
        newEntry->setPosition(xPos, yPos);
        xPos += 120;
        if(xPos > 500) {
            xPos = 20;
            yPos += 100;
        }
        addChild(newEntry);
	}

	setWidth(640);

	if(xPos == 20) {
		setHeight(yPos+20);
	} else {
		setHeight(yPos + 120);
	}
}

void AssetList::clearList() {
	for(int i=0; i < assetEntries.size(); i++) {
		removeChild(assetEntries[i]);
		delete assetEntries[i];
	}
	assetEntries.clear();
	currentEntry = NULL;
    selectedResource = NULL;
}

void AssetList::showFolder(String folderPath) {

	currentFolderPath = folderPath;

    clearList();

	vector<OSFileEntry> assets = OSBasics::parseFolder(folderPath, false);

	Number xPos = 20;
	Number yPos = 30;

	for(int i=0; i < assets.size(); i++) {
		OSFileEntry entry = assets[i];
		if(entry.type != OSFileEntry::TYPE_FOLDER) {
			if(hasExtension(entry.extension)) {
				AssetEntry *newEntry = new AssetEntry(entry.fullPath, entry.name, entry.extension, NULL);
				newEntry->selectShape->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
				assetEntries.push_back(newEntry);
				newEntry->setPosition(xPos, yPos);
				xPos += 120;
				if(xPos > 500) {
					xPos = 20;
					yPos += 100;
				}
				addChild(newEntry);
			}
		}
	}

	setWidth(640);

	if(xPos == 20) {
		setHeight(yPos+20);
	} else {
		setHeight(yPos + 120);
	}

	rebuildTransformMatrix();
}

void AssetList::handleEvent(Event *event) {
	if(event->getDispatcher() == reloadButton && event->getEventCode() == UIEvent::CLICK_EVENT) {
		showFolder(currentFolderPath);
	} else {
		for(int i=0; i < assetEntries.size(); i++) {
			if(event->getDispatcher() == assetEntries[i]->selectShape && event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
				assetEntries[i]->selectShape->visible = true;
				selectedPath = assetEntries[i]->assetPath;
				printf("%s\n", selectedPath.c_str());
				if(currentEntry) {
					currentEntry->selectShape->visible = false;
				}
				currentEntry = assetEntries[i];
                selectedResource = assetEntries[i]->resource;
			}
		}
	}
}

AssetBrowser::AssetBrowser() : UIWindow(L"Asset Browser", 850, 500) {
	defaultTemplateTree = NULL;

    browseMode = BROWSE_MODE_FILES;

	Config *conf = CoreServices::getInstance()->getConfig();
	String fontName = conf->getStringValue("Polycode", "uiDefaultFontName");

	closeOnEscape = true;

	templateContainer = new UITreeContainer("boxIcon.png", L"Project", 200, 480-topPadding-padding-padding);

	FolderUserData *data = new FolderUserData();
	data->type = 0;
	templateContainer->getRootNode()->setUserData(data);

	addChild(templateContainer);
	templateContainer->setPosition(padding,topPadding+padding);
	templateContainer->getRootNode()->toggleCollapsed();

	templateContainer->getRootNode()->addEventListener(this, UITreeEvent::SELECTED_EVENT);

	assetList = new AssetList();

	listContainer = new UIScrollContainer(assetList, false, true, 640, 480-topPadding-padding-padding);
	listContainer->setPosition(220,topPadding+padding);
	addChild(listContainer);

	cancelButton = new UIButton(L"Cancel", 100);
	cancelButton->addEventListener(this, UIEvent::CLICK_EVENT);
	addChild(cancelButton);
	cancelButton->setPosition(850-80-padding-100-10, 485);

	okButton = new UIButton(L"OK", 100);
	okButton->addEventListener(this, UIEvent::CLICK_EVENT);
	addChild(okButton);
	okButton->setPosition(850-80-padding, 485);

	currentProject = NULL;
}

void AssetBrowser::setResourcePools(std::vector<ResourcePool*> pools, int resourceFilter) {

    this->resourceFilter = resourceFilter;

	templateContainer->getRootNode()->clearTree();
	templateContainer->getRootNode()->setLabelText("Resource pools");
	templateContainer->getRootNode()->setUserData(NULL);

    for(int i=0; i < pools.size(); i++) {
        ResourcePool *pool = pools[i];
        UITree *newChild = templateContainer->getRootNode()->addTreeChild("folder.png", pool->getName(), (void*)pool);
        newChild->setUserData(pool);
    }

}

void AssetBrowser::setBrowseMode(unsigned int newBrowseMode) {
    if(browseMode != newBrowseMode) {
        assetList->clearList();
        browseMode = newBrowseMode;
    }
}

void AssetBrowser::setProject(PolycodeProject *project) {

	templateContainer->getRootNode()->clearTree();

	vector<OSFileEntry> templates = OSBasics::parseFolder(project->getRootFolder(), false);
	templateContainer->getRootNode()->setLabelText(project->getProjectName());

	for(int i=0; i < templates.size(); i++) {
		OSFileEntry entry = templates[i];
		if(entry.type == OSFileEntry::TYPE_FOLDER) {
			UITree *newChild = templateContainer->getRootNode()->addTreeChild("folder.png", entry.name, NULL);
			FolderUserData *data = new FolderUserData();
			data->type = 0;
			data->folderPath = entry.fullPath;
			newChild->setUserData(data);
			newChild->toggleCollapsed();
			parseFolderIntoTree(newChild, entry);
		}
	}

	currentProject = project;
    templateContainer->getScrollContainer()->setScrollValue(0.0, 0.0);
}

AssetBrowser::~AssetBrowser() {

}

String AssetBrowser::getFileName() {
	return "";
}

String AssetBrowser::getTemplatePath() {
	return templatePath;
}

String AssetBrowser::getFullSelectedAssetPath() {
	return assetList->selectedPath;
}

String AssetBrowser::getSelectedAssetPath() {
	return assetList->selectedPath.replace(currentProject->getRootFolder()+"/", "");
}

void AssetBrowser::setExtensions(std::vector<String> extensions) {
	assetList->setExtensions(extensions);
}

Resource *AssetBrowser::getSelectedResource() {
	return assetList->getSelectedResource();

}

void AssetBrowser::handleEvent(Event *event) {
	if(event->getEventType() == "UIEvent") {
		if(event->getEventCode() == UIEvent::CLICK_EVENT) {
			if(event->getDispatcher() == okButton) {
				dispatchEvent(new UIEvent(), UIEvent::OK_EVENT);
			}

			if(event->getDispatcher() == cancelButton) {
				dispatchEvent(new UIEvent(), UIEvent::CLOSE_EVENT);
			}
		}
	}

	if(event->getEventType() == "UITreeEvent" && event->getEventCode() == UITreeEvent::SELECTED_EVENT) {
		if(event->getDispatcher() == templateContainer->getRootNode()) {
			UITreeEvent *treeEvent = (UITreeEvent*) event;

            if(browseMode == BROWSE_MODE_FILES) {
                FolderUserData *data = (FolderUserData *)treeEvent->selection->getUserData();
                if(data) {
                    assetList->showFolder(data->folderPath);
                }
            } else {
                ResourcePool *pool = (ResourcePool*) treeEvent->selection->getUserData();
                if(pool) {
                    assetList->showResourcePool(pool, resourceFilter);
                }
            }
			listContainer->setContentSize(assetList->getWidth(), assetList->getHeight());
			listContainer->setScrollValue(0,0);
		}
	}

	UIWindow::handleEvent(event);
}

void AssetBrowser::parseFolderIntoTree(UITree *tree, OSFileEntry folder) {
	vector<OSFileEntry> templates = OSBasics::parseFolder(folder.fullPath, false);
	for(int i=0; i < templates.size(); i++) {
		OSFileEntry entry = templates[i];
		if(entry.type == OSFileEntry::TYPE_FOLDER) {
			UITree *newChild = tree->addTreeChild("folder.png", entry.nameWithoutExtension, NULL);
			FolderUserData *data = new FolderUserData();
			data->type = 1;
			data->folderPath = entry.fullPath;
			newChild->setUserData(data);
			parseFolderIntoTree(newChild, entry);
		}
	}
}
<commit_msg>Fixed asset browser crashing in some scenarios<commit_after>/*
 Copyright (C) 2012 by Ivan Safrin

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */

#include "TextureBrowser.h"

AssetEntry::AssetEntry(String assetPath, String assetName, String extension, Resource *resource) : UIElement() {

    this->resource = resource;
	this->assetPath = assetPath;

	if(assetName.length() > 20)
		assetName = assetName.substr(0,20)+"...";

	selectShape = new UIRect(120, 100);
	selectShape->visible = false;
	selectShape->setAnchorPoint(-1.0, -1.0, 0.0);
	addChild(selectShape);
	selectShape->processInputEvents = true;
	selectShape->setColor(0.0, 0.0, 0.0, 0.5);
    selectShape->loadTexture("browserIcons/large_selector.png");
    selectShape->setBlendingMode(Renderer::BLEND_MODE_NORMAL);

	imageShape = new UIRect(64,64);
	imageShape->setAnchorPoint(-1.0, -1.0, 0.0);
	addChild(imageShape);

	extension = extension.toLowerCase();

	if(extension == "png") {
		imageShape->loadTexture(assetPath);
	} else if(extension == "ogg" || extension == "wav") {
		imageShape->loadTexture("browserIcons/sound_icon.png");
	} else if(extension == "entity") {
		imageShape->loadTexture("browserIcons/entity_icon.png");
	} else if(extension == "sprite") {
		imageShape->loadTexture("browserIcons/sprite_icon.png");
	} else if(extension == "ttf" || extension == "otf") {
		imageShape->loadTexture("browserIcons/font_icon.png");
	} else if(extension == "vert" || extension == "frag") {
		imageShape->loadTexture("browserIcons/shader_icon.png");
	} else if(extension == "mesh") {
		imageShape->loadTexture("browserIcons/mesh_icon.png");
    } else if(extension == "mat") {
		imageShape->loadTexture("browserIcons/materials_icon.png");
    } else if(extension == "material_resource") {
		imageShape->loadTexture("browserIcons/material_resource_icon.png");
    }

	imageShape->setPosition(28, 10);
    imageShape->setBlendingMode(Renderer::BLEND_MODE_NORMAL);

    String name = assetName;
    if(name.length() > 15) {
        name = name.substr(0, 15)+"...";
    }
	nameLabel = new UILabel(name, 11);
	addChild(nameLabel);
    nameLabel->setPosition((120.0-nameLabel->getWidth())/2.0, 80);

}

AssetEntry::~AssetEntry() {
	delete imageShape;
	delete nameLabel;
	delete selectShape;
}

AssetList::AssetList() : UIElement() {

	reloadButton = new UIImageButton("browserIcons/reload_icon.png", 1.0, 20, 20);
	reloadButton->addEventListener(this, UIEvent::CLICK_EVENT);
	addChild(reloadButton);
	reloadButton->setPosition(10, 5);

}

AssetList::~AssetList() {

}

Resource *AssetList::getSelectedResource() {
    return selectedResource;
}

void AssetList::setExtensions(std::vector<String> extensions) {
	this->extensions = extensions;
	if(currentFolderPath != "") {
		showFolder(currentFolderPath);
	}
}

bool AssetList::hasExtension(String extension) {
	for(int i=0; i < extensions.size(); i++) {
		if(extensions[i] == extension.toLowerCase()) {
			return true;
		}
	}
	return false;
}

void AssetList::showResourcePool(ResourcePool *pool, int resourceFilter) {

    clearList();

	Number xPos = 20;
	Number yPos = 30;

    std::vector<Resource*> resources = pool->getResources(resourceFilter);

    String extension;

    if(resourceFilter == Resource::RESOURCE_MATERIAL ) {
        extension = "material_resource";
    }

	for(int i=0; i < resources.size(); i++) {
        AssetEntry *newEntry = new AssetEntry("", resources[i]->getResourceName(), extension, resources[i]);
        newEntry->selectShape->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
        assetEntries.push_back(newEntry);
        newEntry->setPosition(xPos, yPos);
        xPos += 120;
        if(xPos > 500) {
            xPos = 20;
            yPos += 100;
        }
        addChild(newEntry);
	}

	setWidth(640);

	if(xPos == 20) {
		setHeight(yPos+20);
	} else {
		setHeight(yPos + 120);
	}
}

void AssetList::clearList() {
	for(int i=0; i < assetEntries.size(); i++) {
		removeChild(assetEntries[i]);
		delete assetEntries[i];
	}
	assetEntries.clear();
	currentEntry = NULL;
    selectedResource = NULL;
}

void AssetList::showFolder(String folderPath) {

	currentFolderPath = folderPath;

    clearList();

	vector<OSFileEntry> assets = OSBasics::parseFolder(folderPath, false);

	Number xPos = 20;
	Number yPos = 30;

	for(int i=0; i < assets.size(); i++) {
		OSFileEntry entry = assets[i];
		if(entry.type != OSFileEntry::TYPE_FOLDER) {
			if(hasExtension(entry.extension)) {
				AssetEntry *newEntry = new AssetEntry(entry.fullPath, entry.name, entry.extension, NULL);
				newEntry->selectShape->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
				assetEntries.push_back(newEntry);
				newEntry->setPosition(xPos, yPos);
				xPos += 120;
				if(xPos > 500) {
					xPos = 20;
					yPos += 100;
				}
				addChild(newEntry);
			}
		}
	}

	setWidth(640);

	if(xPos == 20) {
		setHeight(yPos+20);
	} else {
		setHeight(yPos + 120);
	}

	rebuildTransformMatrix();
}

void AssetList::handleEvent(Event *event) {
	if(event->getDispatcher() == reloadButton && event->getEventCode() == UIEvent::CLICK_EVENT) {
		showFolder(currentFolderPath);
	} else {
		for(int i=0; i < assetEntries.size(); i++) {
			if(event->getDispatcher() == assetEntries[i]->selectShape && event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
				assetEntries[i]->selectShape->visible = true;
				selectedPath = assetEntries[i]->assetPath;
				printf("%s\n", selectedPath.c_str());
				if(currentEntry) {
					currentEntry->selectShape->visible = false;
				}
				currentEntry = assetEntries[i];
                selectedResource = assetEntries[i]->resource;
			}
		}
	}
}

AssetBrowser::AssetBrowser() : UIWindow(L"Asset Browser", 850, 500) {
	defaultTemplateTree = NULL;

    browseMode = BROWSE_MODE_FILES;

	Config *conf = CoreServices::getInstance()->getConfig();
	String fontName = conf->getStringValue("Polycode", "uiDefaultFontName");

	closeOnEscape = true;

	templateContainer = new UITreeContainer("boxIcon.png", L"Project", 200, 480-topPadding-padding-padding);

	FolderUserData *data = new FolderUserData();
	data->type = 0;
	templateContainer->getRootNode()->setUserData(data);

	addChild(templateContainer);
	templateContainer->setPosition(padding,topPadding+padding);
	templateContainer->getRootNode()->toggleCollapsed();

	templateContainer->getRootNode()->addEventListener(this, UITreeEvent::SELECTED_EVENT);

	assetList = new AssetList();

	listContainer = new UIScrollContainer(assetList, false, true, 640, 480-topPadding-padding-padding);
	listContainer->setPosition(220,topPadding+padding);
	addChild(listContainer);

	cancelButton = new UIButton(L"Cancel", 100);
	cancelButton->addEventListener(this, UIEvent::CLICK_EVENT);
	addChild(cancelButton);
	cancelButton->setPosition(850-80-padding-100-10, 485);

	okButton = new UIButton(L"OK", 100);
	okButton->addEventListener(this, UIEvent::CLICK_EVENT);
	addChild(okButton);
	okButton->setPosition(850-80-padding, 485);

	currentProject = NULL;
}

void AssetBrowser::setResourcePools(std::vector<ResourcePool*> pools, int resourceFilter) {

    this->resourceFilter = resourceFilter;

	templateContainer->getRootNode()->clearTree();
	templateContainer->getRootNode()->setLabelText("Resource pools");
	templateContainer->getRootNode()->setUserData(NULL);

    for(int i=0; i < pools.size(); i++) {
        ResourcePool *pool = pools[i];
        UITree *newChild = templateContainer->getRootNode()->addTreeChild("folder.png", pool->getName(), (void*)pool);
        newChild->setUserData(pool);
    }

}

void AssetBrowser::setBrowseMode(unsigned int newBrowseMode) {
    if(browseMode != newBrowseMode) {
        assetList->clearList();
        browseMode = newBrowseMode;
    }
}

void AssetBrowser::setProject(PolycodeProject *project) {

	templateContainer->getRootNode()->clearTree();

	vector<OSFileEntry> templates = OSBasics::parseFolder(project->getRootFolder(), false);
	templateContainer->getRootNode()->setLabelText(project->getProjectName());

	for(int i=0; i < templates.size(); i++) {
		OSFileEntry entry = templates[i];
		if(entry.type == OSFileEntry::TYPE_FOLDER) {
			UITree *newChild = templateContainer->getRootNode()->addTreeChild("folder.png", entry.name, NULL);
			FolderUserData *data = new FolderUserData();
			data->type = 0;
			data->folderPath = entry.fullPath;
			newChild->setUserData(data);
			newChild->toggleCollapsed();
			parseFolderIntoTree(newChild, entry);
		}
	}

	currentProject = project;
    templateContainer->getScrollContainer()->setScrollValue(0.0, 0.0);
}

AssetBrowser::~AssetBrowser() {

}

String AssetBrowser::getFileName() {
	return "";
}

String AssetBrowser::getTemplatePath() {
	return templatePath;
}

String AssetBrowser::getFullSelectedAssetPath() {
	return assetList->selectedPath;
}

String AssetBrowser::getSelectedAssetPath() {
	return assetList->selectedPath.replace(currentProject->getRootFolder()+"/", "");
}

void AssetBrowser::setExtensions(std::vector<String> extensions) {
	assetList->setExtensions(extensions);
}

Resource *AssetBrowser::getSelectedResource() {
	return assetList->getSelectedResource();

}

void AssetBrowser::handleEvent(Event *event) {
	if(event->getEventType() == "UIEvent") {
		if(event->getEventCode() == UIEvent::CLICK_EVENT) {
			if(event->getDispatcher() == okButton) {
				dispatchEvent(new UIEvent(), UIEvent::OK_EVENT);
			}

			if(event->getDispatcher() == cancelButton) {
				dispatchEvent(new UIEvent(), UIEvent::CLOSE_EVENT);
                removeAllHandlers();
			}
		}
	}

	if(event->getEventType() == "UITreeEvent" && event->getEventCode() == UITreeEvent::SELECTED_EVENT) {
		if(event->getDispatcher() == templateContainer->getRootNode()) {
			UITreeEvent *treeEvent = (UITreeEvent*) event;

            if(browseMode == BROWSE_MODE_FILES) {
                FolderUserData *data = (FolderUserData *)treeEvent->selection->getUserData();
                if(data) {
                    assetList->showFolder(data->folderPath);
                }
            } else {
                ResourcePool *pool = (ResourcePool*) treeEvent->selection->getUserData();
                if(pool) {
                    assetList->showResourcePool(pool, resourceFilter);
                }
            }
			listContainer->setContentSize(assetList->getWidth(), assetList->getHeight());
			listContainer->setScrollValue(0,0);
		}
	}

	UIWindow::handleEvent(event);
}

void AssetBrowser::parseFolderIntoTree(UITree *tree, OSFileEntry folder) {
	vector<OSFileEntry> templates = OSBasics::parseFolder(folder.fullPath, false);
	for(int i=0; i < templates.size(); i++) {
		OSFileEntry entry = templates[i];
		if(entry.type == OSFileEntry::TYPE_FOLDER) {
			UITree *newChild = tree->addTreeChild("folder.png", entry.nameWithoutExtension, NULL);
			FolderUserData *data = new FolderUserData();
			data->type = 1;
			data->folderPath = entry.fullPath;
			newChild->setUserData(data);
			parseFolderIntoTree(newChild, entry);
		}
	}
}
<|endoftext|>