<commit_before>/****************************************************************************
**
** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
**
** This file is part of the Qt Script Generator project on Trolltech Labs.
**
** This file may be used under the terms of the GNU General Public
** License version 2.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://www.trolltech.com/products/qt/opensource.html
**
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://www.trolltech.com/products/qt/licensing.html or contact the
** sales department at sales@trolltech.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/

#include "shellheadergenerator.h"
#include "fileout.h"

#include <QtCore/QDir>

#include <qdebug.h>

QString ShellHeaderGenerator::fileNameForClass(const AbstractMetaClass *meta_class) const
{
  return QString("PythonQtWrapper_%1.h").arg(meta_class->name());
}

void writeQtScriptQtBindingsLicense(QTextStream &stream);

void ShellHeaderGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
{

  setupGenerator->addClass(meta_class);

  if (FileOut::license)
    writeQtScriptQtBindingsLicense(s);

  QString include_block = "PYTHONQTWRAPPER_" + meta_class->name().toUpper() + "_H";

  s << "#ifndef " << include_block << endl
    << "#define " << include_block << endl << endl;

  Include inc = meta_class->typeEntry()->include();
  ShellGenerator::writeInclude(s, inc);

  s << "#include <QObject>" << endl << endl;
  s << "#include <PythonQt.h>" << endl << endl;

  IncludeList list = meta_class->typeEntry()->extraIncludes();
  qSort(list.begin(), list.end());
  foreach (const Include &inc, list) {
    ShellGenerator::writeInclude(s, inc);
  }
  s << endl;

  QString pro_file_name = meta_class->package().replace(".", "_") + "/" + meta_class->package().replace(".", "_") + ".pri";

  //    if (!meta_class->generateShellClass()) {
  //        s << "#endif" << endl << endl;
  //        priGenerator->addHeader(pro_file_name, fileNameForClass(meta_class));
  //        return ;
  //    }

  AbstractMetaFunctionList ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
    | AbstractMetaClass::WasVisible
    | AbstractMetaClass::NotRemovedFromTargetLang);

  // Shell-------------------------------------------------------------------
  if (meta_class->generateShellClass()) {

    AbstractMetaFunctionList virtualsForShell = getVirtualFunctionsForShell(meta_class);

    s << "class " << shellClassName(meta_class)
      << " : public " << meta_class->qualifiedCppName() << endl << "{" << endl;
    s << "public:" << endl;
    foreach(AbstractMetaFunction* fun, ctors) {
      s << "    ";
      writeFunctionSignature(s, fun, 0,"PythonQtShell_",
        Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
      s << ":" << meta_class->qualifiedCppName() << "(";
      QString scriptFunctionName = fun->originalName();
      AbstractMetaArgumentList args = fun->arguments();
      for (int i = 0; i < args.size(); ++i) {
        if (i > 0)
          s << ", ";
        s << args.at(i)->argumentName();
      }
      s << "),_wrapper(NULL) {};" << endl;
    }
    s << endl;

    foreach(AbstractMetaFunction* fun, virtualsForShell) {
      s << "virtual ";
      writeFunctionSignature(s, fun, 0, QString(),
        Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
      s << ";" << endl;
    }
    s << endl;
    s << "  PythonQtInstanceWrapper* _wrapper; " << endl;

    s << "};" << endl << endl;
  }

  // Promoter-------------------------------------------------------------------
  AbstractMetaFunctionList promoteFunctions = getProtectedFunctionsThatNeedPromotion(meta_class);
  if (!promoteFunctions.isEmpty()) {
    s << "class " << promoterClassName(meta_class)
      << " : public " << meta_class->qualifiedCppName() << endl << "{ public:" << endl;

    foreach(AbstractMetaFunction* fun, promoteFunctions) {
      s << "inline ";
      writeFunctionSignature(s, fun, 0, "promoted_",
        Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
      s << " { ";
      QString scriptFunctionName = fun->originalName();
      AbstractMetaArgumentList args = fun->arguments();
      if (fun->type())
        s << "return ";
      s << meta_class->qualifiedCppName() << "::";
      s << fun->originalName() << "(";
      for (int i = 0; i < args.size(); ++i) {
        if (i > 0)
          s << ", ";
        s << args.at(i)->argumentName();
      }
      s << "); }" << endl;
    }

    s << "};" << endl << endl;
  }

  // Wrapper-------------------------------------------------------------------

  s << "class " << wrapperClassName(meta_class)
    << " : public QObject" << endl
    << "{ Q_OBJECT" << endl;

  s << "public:" << endl;

  AbstractMetaEnumList enums1 = meta_class->enums();
  AbstractMetaEnumList enums;
  foreach(AbstractMetaEnum* enum1, enums1) {
    // catch gadgets and enums that are not exported on QObjects...
    if (enum1->wasPublic() && (!meta_class->isQObject() || !enum1->hasQEnumsDeclaration())) {
      enums << enum1;
    }
  }
  if (enums.count()) {
    s << "Q_ENUMS(";
    foreach(AbstractMetaEnum* enum1, enums) {
      s << enum1->name() << " ";
    }
    s << ")" << endl;

    foreach(AbstractMetaEnum* enum1, enums) {
      s << "enum " << enum1->name() << "{" << endl;
      bool first = true;
      foreach(AbstractMetaEnumValue* value, enum1->values()) {
        if (first) { first = false; }
        else { s << ", "; }
        s << "  " << value->name() << " = " << meta_class->qualifiedCppName() << "::" << value->name();
      }
      s << "};" << endl;
    }
  }

  s << "public slots:" << endl;
  if (meta_class->generateShellClass() || !meta_class->isAbstract()) {

    bool copyConstructorSeen = false;
    bool defaultConstructorSeen = false;
    foreach (const AbstractMetaFunction *fun, ctors) {
      if (!fun->isPublic() || fun->isAbstract()) { continue; }
      s << meta_class->qualifiedCppName() << "* ";
      writeFunctionSignature(s, fun, 0, "new_",
        Option(IncludeDefaultExpression | OriginalName | ShowStatic));
      s << ";" << endl;
      if (fun->arguments().size()==1 && meta_class->qualifiedCppName() == fun->arguments().at(0)->type()->typeEntry()->qualifiedCppName()) {
        copyConstructorSeen = true;
      }
      if (fun->arguments().size()==0) {
        defaultConstructorSeen = true;
      }
    }

    if (meta_class->typeEntry()->isValue()
        && !copyConstructorSeen && defaultConstructorSeen) {
      QString className = meta_class->generateShellClass()?shellClassName(meta_class):meta_class->qualifiedCppName();
      s << meta_class->qualifiedCppName() << "* new_" << meta_class->name() << "(const " << meta_class->qualifiedCppName() << "& other) {" << endl;
      s << className << "* a = new " << className << "();" << endl;
      s << "*((" << meta_class->qualifiedCppName() << "*)a) = other;" << endl;
      s << "return a; }" << endl;
    }
  }
  if (meta_class->hasPublicDestructor() && !meta_class->isNamespace()) {
    s << "void delete_" << meta_class->name() << "(" << meta_class->qualifiedCppName() << "* obj) { delete obj; } ";
    s << endl;
  }
  if (meta_class->name()=="QTreeWidgetItem") {
    s << "bool hasOwner(QTreeWidgetItem* theWrappedObject) { return theWrappedObject->treeWidget()!=NULL || theWrappedObject->parent()!=NULL; }" << endl;
  } else if (meta_class->name()=="QGraphicsItem") {
    s << "bool hasOwner(QGraphicsItem* theWrappedObject) { return theWrappedObject->scene()!=NULL || theWrappedObject->parentItem()!=NULL; }" << endl;
  }

  AbstractMetaFunctionList functions = getFunctionsToWrap(meta_class);

  foreach (const AbstractMetaFunction *function, functions) {
    if (!function->isSlot()) {
      s << "   ";
      writeFunctionSignature(s, function, 0, QString(),
        Option(FirstArgIsWrappedObject| IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
      s << ";" << endl;
    }
  }

  //    writeInjectedCode(s, meta_class);

  //  s  << endl << "    QScriptValue __qtscript_self;" << endl;

  s  << "};" << endl << endl
    << "#endif // " << include_block << endl;

  if (!ShellGenerator::isBuiltIn(meta_class->name())) {
    priGenerator->addHeader(pro_file_name, fileNameForClass(meta_class));
  }
}

void ShellHeaderGenerator::writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class)
{
  CodeSnipList code_snips = meta_class->typeEntry()->codeSnips();
  foreach (const CodeSnip &cs, code_snips) {
    if (cs.language == TypeSystem::ShellDeclaration) {
      s << cs.code() << endl;
    }
  }
}
<commit_msg>added support for qflags, which where previously missing<commit_after>/****************************************************************************
**
** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
**
** This file is part of the Qt Script Generator project on Trolltech Labs.
**
** This file may be used under the terms of the GNU General Public
** License version 2.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://www.trolltech.com/products/qt/opensource.html
**
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://www.trolltech.com/products/qt/licensing.html or contact the
** sales department at sales@trolltech.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/

#include "shellheadergenerator.h"
#include "fileout.h"

#include <QtCore/QDir>

#include <qdebug.h>

QString ShellHeaderGenerator::fileNameForClass(const AbstractMetaClass *meta_class) const
{
  return QString("PythonQtWrapper_%1.h").arg(meta_class->name());
}

void writeQtScriptQtBindingsLicense(QTextStream &stream);

void ShellHeaderGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
{

  setupGenerator->addClass(meta_class);

  if (FileOut::license)
    writeQtScriptQtBindingsLicense(s);

  QString include_block = "PYTHONQTWRAPPER_" + meta_class->name().toUpper() + "_H";

  s << "#ifndef " << include_block << endl
    << "#define " << include_block << endl << endl;

  Include inc = meta_class->typeEntry()->include();
  ShellGenerator::writeInclude(s, inc);

  s << "#include <QObject>" << endl << endl;
  s << "#include <PythonQt.h>" << endl << endl;

  IncludeList list = meta_class->typeEntry()->extraIncludes();
  qSort(list.begin(), list.end());
  foreach (const Include &inc, list) {
    ShellGenerator::writeInclude(s, inc);
  }
  s << endl;

  QString pro_file_name = meta_class->package().replace(".", "_") + "/" + meta_class->package().replace(".", "_") + ".pri";

  //    if (!meta_class->generateShellClass()) {
  //        s << "#endif" << endl << endl;
  //        priGenerator->addHeader(pro_file_name, fileNameForClass(meta_class));
  //        return ;
  //    }

  AbstractMetaFunctionList ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
    | AbstractMetaClass::WasVisible
    | AbstractMetaClass::NotRemovedFromTargetLang);

  // Shell-------------------------------------------------------------------
  if (meta_class->generateShellClass()) {

    AbstractMetaFunctionList virtualsForShell = getVirtualFunctionsForShell(meta_class);

    s << "class " << shellClassName(meta_class)
      << " : public " << meta_class->qualifiedCppName() << endl << "{" << endl;
    s << "public:" << endl;
    foreach(AbstractMetaFunction* fun, ctors) {
      s << "    ";
      writeFunctionSignature(s, fun, 0,"PythonQtShell_",
        Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
      s << ":" << meta_class->qualifiedCppName() << "(";
      QString scriptFunctionName = fun->originalName();
      AbstractMetaArgumentList args = fun->arguments();
      for (int i = 0; i < args.size(); ++i) {
        if (i > 0)
          s << ", ";
        s << args.at(i)->argumentName();
      }
      s << "),_wrapper(NULL) {};" << endl;
    }
    s << endl;

    foreach(AbstractMetaFunction* fun, virtualsForShell) {
      s << "virtual ";
      writeFunctionSignature(s, fun, 0, QString(),
        Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
      s << ";" << endl;
    }
    s << endl;
    s << "  PythonQtInstanceWrapper* _wrapper; " << endl;

    s << "};" << endl << endl;
  }

  // Promoter-------------------------------------------------------------------
  AbstractMetaFunctionList promoteFunctions = getProtectedFunctionsThatNeedPromotion(meta_class);
  if (!promoteFunctions.isEmpty()) {
    s << "class " << promoterClassName(meta_class)
      << " : public " << meta_class->qualifiedCppName() << endl << "{ public:" << endl;

    foreach(AbstractMetaFunction* fun, promoteFunctions) {
      s << "inline ";
      writeFunctionSignature(s, fun, 0, "promoted_",
        Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
      s << " { ";
      QString scriptFunctionName = fun->originalName();
      AbstractMetaArgumentList args = fun->arguments();
      if (fun->type())
        s << "return ";
      s << meta_class->qualifiedCppName() << "::";
      s << fun->originalName() << "(";
      for (int i = 0; i < args.size(); ++i) {
        if (i > 0)
          s << ", ";
        s << args.at(i)->argumentName();
      }
      s << "); }" << endl;
    }

    s << "};" << endl << endl;
  }

  // Wrapper-------------------------------------------------------------------

  s << "class " << wrapperClassName(meta_class)
    << " : public QObject" << endl
    << "{ Q_OBJECT" << endl;

  s << "public:" << endl;

  AbstractMetaEnumList enums1 = meta_class->enums();
  AbstractMetaEnumList enums;
  QList<FlagsTypeEntry*> flags;
  foreach(AbstractMetaEnum* enum1, enums1) {
    // catch gadgets and enums that are not exported on QObjects...
    if (enum1->wasPublic() && (!meta_class->isQObject() || !enum1->hasQEnumsDeclaration())) {
      enums << enum1;
      if (enum1->typeEntry()->flags()) {
        flags << enum1->typeEntry()->flags();
      }
    }
  }
  if (enums.count()) {
    s << "Q_ENUMS(";
    foreach(AbstractMetaEnum* enum1, enums) {
      s << enum1->name() << " ";
    }
    s << ")" << endl;

    if (flags.count()) {
      s << "Q_FLAGS(";
      foreach(FlagsTypeEntry* flag1, flags) {
        QString origName = flag1->originalName();
        int idx = origName.lastIndexOf("::");
        if (idx!= -1) {
          origName = origName.mid(idx+2);
        }
        s << origName << " ";
      }
      s << ")" << endl;
    }

    foreach(AbstractMetaEnum* enum1, enums) {
      s << "enum " << enum1->name() << "{" << endl;
      bool first = true;
      foreach(AbstractMetaEnumValue* value, enum1->values()) {
        if (first) { first = false; }
        else { s << ", "; }
        s << "  " << value->name() << " = " << meta_class->qualifiedCppName() << "::" << value->name();
      }
      s << "};" << endl;
    }
    if (flags.count()) {
      foreach(AbstractMetaEnum* enum1, enums) {
        if (enum1->typeEntry()->flags()) {
          QString origName = enum1->typeEntry()->flags()->originalName();
          int idx = origName.lastIndexOf("::");
          if (idx!= -1) {
            origName = origName.mid(idx+2);
          }
          s << "Q_DECLARE_FLAGS("<< origName << ", " << enum1->name() <<")"<<endl;
        }
      }
    }
  }
  s << "public slots:" << endl;
  if (meta_class->generateShellClass() || !meta_class->isAbstract()) {

    bool copyConstructorSeen = false;
    bool defaultConstructorSeen = false;
    foreach (const AbstractMetaFunction *fun, ctors) {
      if (!fun->isPublic() || fun->isAbstract()) { continue; }
      s << meta_class->qualifiedCppName() << "* ";
      writeFunctionSignature(s, fun, 0, "new_",
        Option(IncludeDefaultExpression | OriginalName | ShowStatic));
      s << ";" << endl;
      if (fun->arguments().size()==1 && meta_class->qualifiedCppName() == fun->arguments().at(0)->type()->typeEntry()->qualifiedCppName()) {
        copyConstructorSeen = true;
      }
      if (fun->arguments().size()==0) {
        defaultConstructorSeen = true;
      }
    }

    if (meta_class->typeEntry()->isValue()
        && !copyConstructorSeen && defaultConstructorSeen) {
      QString className = meta_class->generateShellClass()?shellClassName(meta_class):meta_class->qualifiedCppName();
      s << meta_class->qualifiedCppName() << "* new_" << meta_class->name() << "(const " << meta_class->qualifiedCppName() << "& other) {" << endl;
      s << className << "* a = new " << className << "();" << endl;
      s << "*((" << meta_class->qualifiedCppName() << "*)a) = other;" << endl;
      s << "return a; }" << endl;
    }
  }
  if (meta_class->hasPublicDestructor() && !meta_class->isNamespace()) {
    s << "void delete_" << meta_class->name() << "(" << meta_class->qualifiedCppName() << "* obj) { delete obj; } ";
    s << endl;
  }
  if (meta_class->name()=="QTreeWidgetItem") {
    s << "bool hasOwner(QTreeWidgetItem* theWrappedObject) { return theWrappedObject->treeWidget()!=NULL || theWrappedObject->parent()!=NULL; }" << endl;
  } else if (meta_class->name()=="QGraphicsItem") {
    s << "bool hasOwner(QGraphicsItem* theWrappedObject) { return theWrappedObject->scene()!=NULL || theWrappedObject->parentItem()!=NULL; }" << endl;
  }

  AbstractMetaFunctionList functions = getFunctionsToWrap(meta_class);

  foreach (const AbstractMetaFunction *function, functions) {
    if (!function->isSlot()) {
      s << "   ";
      writeFunctionSignature(s, function, 0, QString(),
        Option(FirstArgIsWrappedObject| IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
      s << ";" << endl;
    }
  }

  //    writeInjectedCode(s, meta_class);

  //  s  << endl << "    QScriptValue __qtscript_self;" << endl;

  s  << "};" << endl << endl
    << "#endif // " << include_block << endl;

  if (!ShellGenerator::isBuiltIn(meta_class->name())) {
    priGenerator->addHeader(pro_file_name, fileNameForClass(meta_class));
  }
}

void ShellHeaderGenerator::writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class)
{
  CodeSnipList code_snips = meta_class->typeEntry()->codeSnips();
  foreach (const CodeSnip &cs, code_snips) {
    if (cs.language == TypeSystem::ShellDeclaration) {
      s << cs.code() << endl;
    }
  }
}
<|endoftext|>


<commit_before>// ChiCheFrame.cpp

#include "ChiChe.h"

using namespace ChiChe;

//=====================================================================================
Frame::Frame( void ) : wxFrame( 0, wxID_ANY, "Chinese Checkers", wxDefaultPosition, wxSize( 900, 600 ) ), timer( this, ID_Timer )
{
	wxMenu* gameMenu = new wxMenu();
	wxMenuItem* joinGameMenuItem = new wxMenuItem( gameMenu, ID_JoinGame, wxT( "Join Game" ), wxT( "Join a hosted game on the network." ) );
	wxMenuItem* hostGameMenuItem = new wxMenuItem( gameMenu, ID_HostGame, wxT( "Host Game" ), wxT( "Host a game on the network." ) );
	wxMenuItem* leaveGameMenuItem = new wxMenuItem( gameMenu, ID_LeaveGame, wxT( "Leave Game" ), wxT( "Disconnect from a joined game." ) );
	wxMenuItem* killGameMenuItem = new wxMenuItem( gameMenu, ID_KillGame, wxT( "Kill Game" ), wxT( "Discontinue a hosted game." ) );
	wxMenuItem* exitMenuItem = new wxMenuItem( gameMenu, ID_Exit, wxT( "Exit" ), wxT( "Exit the program." ) );
	gameMenu->Append( joinGameMenuItem );
	gameMenu->Append( hostGameMenuItem );
	gameMenu->AppendSeparator();
	gameMenu->Append( leaveGameMenuItem );
	gameMenu->Append( killGameMenuItem );
	gameMenu->AppendSeparator();
	gameMenu->Append( exitMenuItem );

	wxMenu* helpMenu = new wxMenu();
	wxMenuItem* aboutMenuItem = new wxMenuItem( helpMenu, ID_About, wxT( "About" ), wxT( "Popup a dialog giving information about this program." ) );
	helpMenu->Append( aboutMenuItem );

	menuBar = new wxMenuBar();
	menuBar->Append( gameMenu, wxT( "Game" ) );
	menuBar->Append( helpMenu, wxT( "Help" ) );
	SetMenuBar( menuBar );

	statusBar = new wxStatusBar( this );
	statusBar->PushStatusText( wxT( "Welcome!  Remember to use the right mouse button to select marbles and board locations." ) );
	SetStatusBar( statusBar );

	Bind( wxEVT_MENU, &Frame::OnJoinGame, this, ID_JoinGame );
	Bind( wxEVT_MENU, &Frame::OnHostGame, this, ID_HostGame );
	Bind( wxEVT_MENU, &Frame::OnLeaveGame, this, ID_LeaveGame );
	Bind( wxEVT_MENU, &Frame::OnKillGame, this, ID_KillGame );
	Bind( wxEVT_MENU, &Frame::OnExit, this, ID_Exit );
	Bind( wxEVT_MENU, &Frame::OnAbout, this, ID_About );
	Bind( wxEVT_UPDATE_UI, &Frame::OnUpdateMenuItemUI, this, ID_JoinGame );
	Bind( wxEVT_UPDATE_UI, &Frame::OnUpdateMenuItemUI, this, ID_HostGame );
	Bind( wxEVT_UPDATE_UI, &Frame::OnUpdateMenuItemUI, this, ID_LeaveGame );
	Bind( wxEVT_UPDATE_UI, &Frame::OnUpdateMenuItemUI, this, ID_KillGame );
	Bind( wxEVT_TIMER, &Frame::OnTimer, this, ID_Timer );
	Bind( wxEVT_CLOSE_WINDOW, &Frame::OnClose, this );
	Bind( wxEVT_ACTIVATE, &Frame::OnActivate, this );

	canvas = new Canvas( this );

	wxBoxSizer* boxSizer = new wxBoxSizer( wxHORIZONTAL );
	boxSizer->Add( canvas, 1, wxALL | wxGROW, 0 );
	SetSizer( boxSizer );

	timer.Start( 50 );
	continuousRefresh = true;
}

//=====================================================================================
/*virtual*/ Frame::~Frame( void )
{
}

//=====================================================================================
void Frame::OnHostGame( wxCommandEvent& event )
{
	Server* server = wxGetApp().GetServer();
	if( server )
		return;

	// The order of this array matches the enum in the Board class.
	wxArrayString colorChoices;
	colorChoices.Add( "Red" );
	colorChoices.Add( "Green" );
	colorChoices.Add( "Blue" );
	colorChoices.Add( "Yellow" );
	colorChoices.Add( "Magenta" );
	colorChoices.Add( "Cyan" );

	wxMultiChoiceDialog multiChoiceDialog( this, wxT( "Who will particpate in this game?" ), wxT( "Choose Participants" ), colorChoices );
	if( wxID_OK != multiChoiceDialog.ShowModal() )
		return;

	wxArrayInt selections = multiChoiceDialog.GetSelections();
	if( selections.Count() < 2 )
		return;

	int participants = 0;
	for( wxArrayInt::iterator iter = selections.begin(); iter != selections.end(); iter++ )
	{
		int color = *iter + 1;
		participants |= 1 << color;
	}

	wxScopedPtr< Server > serverPtr;
	serverPtr.reset( new Server( participants ) );

	unsigned short port = ( unsigned short )wxGetNumberFromUser( wxT( "On what port should the server listen?" ), wxT( "Port:" ), wxT( "Choose Port" ), 3000, 3000, 5000, this );
	if( !serverPtr->Initialize( port ) )
		return;

	server = serverPtr.release();
	wxGetApp().SetServer( server );

	wxMessageBox( wxT( "Your game server is online and running!" ), wxT( "Server Initialization Success" ), wxOK | wxCENTRE, this );
}

//=====================================================================================
void Frame::OnJoinGame( wxCommandEvent& event )
{
	Client* client = wxGetApp().GetClient();
	if( client )
		return;

	wxString addressString = wxT( "127.0.0.1:3000" );
	wxTextEntryDialog textEntryDialog( this, wxT( "Please enter the address of the host with port number." ), wxT( "Enter Address Of Host" ), addressString );
	if( wxID_OK != textEntryDialog.ShowModal() )
		return;

	wxStringTokenizer stringTokenizer( addressString, ":" );
	wxString ipAddressString, portString;
	if( !stringTokenizer.HasMoreTokens() )
		return;
	ipAddressString = stringTokenizer.GetNextToken();
	if( !stringTokenizer.HasMoreTokens() )
		return;
	portString = stringTokenizer.GetNextToken();

	unsigned long port;
	if( !portString.ToULong( &port ) )
		return;

	wxIPV4address address;
	if( !address.Hostname( ipAddressString ) )
		return;
	address.Service( ( unsigned short )port );

	wxArrayString typeChoices;
	typeChoices.Add( "Human" );
	typeChoices.Add( "Computer (Level 1)" );
	typeChoices.Add( "Computer (Level 2)" );
	typeChoices.Add( "Computer (Level 3)" );
	wxSingleChoiceDialog singleChoiceDialog( this, wxT( "Will this be a human or computer client?" ), wxT( "Choose Client Type" ), typeChoices );
	if( wxID_OK != singleChoiceDialog.ShowModal() )
		return;

	Client::Type clientType = Client::HUMAN;
	wxString selection = singleChoiceDialog.GetStringSelection();
	if( selection == wxT( "Computer (Level 1)" ) )
		clientType = Client::COMPUTER_LEVEL_1;
	else if( selection == wxT( "Computer (Level 2)" ) )
		clientType = Client::COMPUTER_LEVEL_2;
	else if( selection == wxT( "Computer (Level 3)" ) )
		clientType = Client::COMPUTER_LEVEL_3;

	wxScopedPtr< Client > clientPtr;
	clientPtr.reset( new Client( clientType ) );

	if( !clientPtr->Connect( address ) )
		return;

	client = clientPtr.release();
	wxGetApp().SetClient( client );
}

//=====================================================================================
void Frame::OnLeaveGame( wxCommandEvent& event )
{
	KillClient();
}

//=====================================================================================
void Frame::OnKillGame( wxCommandEvent& event )
{
	KillServer();
}

//=====================================================================================
void Frame::OnExit( wxCommandEvent& event )
{
	Close( true );
}

//=====================================================================================
void Frame::KillServer( void )
{
	Server* server = wxGetApp().GetServer();
	if( server )
	{
		server->Finalize();
		delete server;
		wxGetApp().SetServer(0);
	}
}

//=====================================================================================
void Frame::KillClient( void )
{
	Client* client = wxGetApp().GetClient();
	if( client )
	{
		delete client;
		wxGetApp().SetClient(0);
	}
}

//=====================================================================================
void Frame::OnClose( wxCloseEvent& event )
{
	KillServer();
	KillClient();

	event.Skip();
}

//=====================================================================================
void Frame::OnAbout( wxCommandEvent& event )
{
	wxAboutDialogInfo aboutDialogInfo;

	aboutDialogInfo.SetName( wxT( "Chinese Checkers" ) );
	aboutDialogInfo.SetVersion( wxT( "1.0" ) );
	aboutDialogInfo.SetDescription( wxT( "This program is free software and distributed under the MIT license." ) );
	aboutDialogInfo.SetCopyright( wxT( "Copyright (C) 2013 Spencer T. Parkin <spencer.parkin@disney.com>" ) );

	wxAboutBox( aboutDialogInfo );
}

//=====================================================================================
void Frame::OnUpdateMenuItemUI( wxUpdateUIEvent& event )
{
	switch( event.GetId() )
	{
		case ID_JoinGame:
		{
			event.Enable( wxGetApp().GetClient() ? false : true );
			break;
		}
		case ID_HostGame:
		{
			event.Enable( wxGetApp().GetServer() ? false : true );
			break;
		}
		case ID_LeaveGame:
		{
			event.Enable( wxGetApp().GetClient() ? true : false );
			break;
		}
		case ID_KillGame:
		{
			event.Enable( wxGetApp().GetServer() ? true : false );
			break;
		}
	}
}

//=====================================================================================
void Frame::OnTimer( wxTimerEvent& event )
{
	// This routine was never meant to be re-entrant.
	// Re-entrancy could cause a crash due to client or server death.
	// If a dialog is put up in this routine, wxWidgets still calls the timer,
	// which can cause re-entrancy.
	static bool inOnTimer = false;
	if( inOnTimer )
		return;
	inOnTimer = true;

	Server* server = wxGetApp().GetServer();
	if( server && !server->Run() )
		KillServer();

	Client* client = wxGetApp().GetClient();
	if( client )
	{
		if( !client->Run() )
		{
			KillClient();
			wxMessageBox( wxT( "We have lost our connection with the server, possibly because the game server has gone down." ), wxT( "Connection Lost" ), wxOK | wxCENTRE, wxGetApp().GetFrame() );
		}
		else
		{
			client->Animate( canvas->FrameRate() );
			if( continuousRefresh )
				canvas->Refresh();
		}
	}

	inOnTimer = false;
}

//=====================================================================================
void Frame::OnActivate( wxActivateEvent& event )
{
	continuousRefresh = event.GetActive();
}

//=====================================================================================
wxStatusBar* Frame::GetStatusBar( void )
{
	return statusBar;
}

// ChiCheFrame.cpp
<commit_msg>add url in about box<commit_after>// ChiCheFrame.cpp

#include "ChiChe.h"

using namespace ChiChe;

//=====================================================================================
Frame::Frame( void ) : wxFrame( 0, wxID_ANY, "Chinese Checkers", wxDefaultPosition, wxSize( 900, 600 ) ), timer( this, ID_Timer )
{
	wxMenu* gameMenu = new wxMenu();
	wxMenuItem* joinGameMenuItem = new wxMenuItem( gameMenu, ID_JoinGame, wxT( "Join Game" ), wxT( "Join a hosted game on the network." ) );
	wxMenuItem* hostGameMenuItem = new wxMenuItem( gameMenu, ID_HostGame, wxT( "Host Game" ), wxT( "Host a game on the network." ) );
	wxMenuItem* leaveGameMenuItem = new wxMenuItem( gameMenu, ID_LeaveGame, wxT( "Leave Game" ), wxT( "Disconnect from a joined game." ) );
	wxMenuItem* killGameMenuItem = new wxMenuItem( gameMenu, ID_KillGame, wxT( "Kill Game" ), wxT( "Discontinue a hosted game." ) );
	wxMenuItem* exitMenuItem = new wxMenuItem( gameMenu, ID_Exit, wxT( "Exit" ), wxT( "Exit the program." ) );
	gameMenu->Append( joinGameMenuItem );
	gameMenu->Append( hostGameMenuItem );
	gameMenu->AppendSeparator();
	gameMenu->Append( leaveGameMenuItem );
	gameMenu->Append( killGameMenuItem );
	gameMenu->AppendSeparator();
	gameMenu->Append( exitMenuItem );

	wxMenu* helpMenu = new wxMenu();
	wxMenuItem* aboutMenuItem = new wxMenuItem( helpMenu, ID_About, wxT( "About" ), wxT( "Popup a dialog giving information about this program." ) );
	helpMenu->Append( aboutMenuItem );

	menuBar = new wxMenuBar();
	menuBar->Append( gameMenu, wxT( "Game" ) );
	menuBar->Append( helpMenu, wxT( "Help" ) );
	SetMenuBar( menuBar );

	statusBar = new wxStatusBar( this );
	statusBar->PushStatusText( wxT( "Welcome!  Remember to use the right mouse button to select marbles and board locations." ) );
	SetStatusBar( statusBar );

	Bind( wxEVT_MENU, &Frame::OnJoinGame, this, ID_JoinGame );
	Bind( wxEVT_MENU, &Frame::OnHostGame, this, ID_HostGame );
	Bind( wxEVT_MENU, &Frame::OnLeaveGame, this, ID_LeaveGame );
	Bind( wxEVT_MENU, &Frame::OnKillGame, this, ID_KillGame );
	Bind( wxEVT_MENU, &Frame::OnExit, this, ID_Exit );
	Bind( wxEVT_MENU, &Frame::OnAbout, this, ID_About );
	Bind( wxEVT_UPDATE_UI, &Frame::OnUpdateMenuItemUI, this, ID_JoinGame );
	Bind( wxEVT_UPDATE_UI, &Frame::OnUpdateMenuItemUI, this, ID_HostGame );
	Bind( wxEVT_UPDATE_UI, &Frame::OnUpdateMenuItemUI, this, ID_LeaveGame );
	Bind( wxEVT_UPDATE_UI, &Frame::OnUpdateMenuItemUI, this, ID_KillGame );
	Bind( wxEVT_TIMER, &Frame::OnTimer, this, ID_Timer );
	Bind( wxEVT_CLOSE_WINDOW, &Frame::OnClose, this );
	Bind( wxEVT_ACTIVATE, &Frame::OnActivate, this );

	canvas = new Canvas( this );

	wxBoxSizer* boxSizer = new wxBoxSizer( wxHORIZONTAL );
	boxSizer->Add( canvas, 1, wxALL | wxGROW, 0 );
	SetSizer( boxSizer );

	timer.Start( 50 );
	continuousRefresh = true;
}

//=====================================================================================
/*virtual*/ Frame::~Frame( void )
{
}

//=====================================================================================
void Frame::OnHostGame( wxCommandEvent& event )
{
	Server* server = wxGetApp().GetServer();
	if( server )
		return;

	// The order of this array matches the enum in the Board class.
	wxArrayString colorChoices;
	colorChoices.Add( "Red" );
	colorChoices.Add( "Green" );
	colorChoices.Add( "Blue" );
	colorChoices.Add( "Yellow" );
	colorChoices.Add( "Magenta" );
	colorChoices.Add( "Cyan" );

	wxMultiChoiceDialog multiChoiceDialog( this, wxT( "Who will particpate in this game?" ), wxT( "Choose Participants" ), colorChoices );
	if( wxID_OK != multiChoiceDialog.ShowModal() )
		return;

	wxArrayInt selections = multiChoiceDialog.GetSelections();
	if( selections.Count() < 2 )
		return;

	int participants = 0;
	for( wxArrayInt::iterator iter = selections.begin(); iter != selections.end(); iter++ )
	{
		int color = *iter + 1;
		participants |= 1 << color;
	}

	wxScopedPtr< Server > serverPtr;
	serverPtr.reset( new Server( participants ) );

	unsigned short port = ( unsigned short )wxGetNumberFromUser( wxT( "On what port should the server listen?" ), wxT( "Port:" ), wxT( "Choose Port" ), 3000, 3000, 5000, this );
	if( !serverPtr->Initialize( port ) )
		return;

	server = serverPtr.release();
	wxGetApp().SetServer( server );

	wxMessageBox( wxT( "Your game server is online and running!" ), wxT( "Server Initialization Success" ), wxOK | wxCENTRE, this );
}

//=====================================================================================
void Frame::OnJoinGame( wxCommandEvent& event )
{
	Client* client = wxGetApp().GetClient();
	if( client )
		return;

	wxString addressString = wxT( "127.0.0.1:3000" );
	wxTextEntryDialog textEntryDialog( this, wxT( "Please enter the address of the host with port number." ), wxT( "Enter Address Of Host" ), addressString );
	if( wxID_OK != textEntryDialog.ShowModal() )
		return;

	wxStringTokenizer stringTokenizer( addressString, ":" );
	wxString ipAddressString, portString;
	if( !stringTokenizer.HasMoreTokens() )
		return;
	ipAddressString = stringTokenizer.GetNextToken();
	if( !stringTokenizer.HasMoreTokens() )
		return;
	portString = stringTokenizer.GetNextToken();

	unsigned long port;
	if( !portString.ToULong( &port ) )
		return;

	wxIPV4address address;
	if( !address.Hostname( ipAddressString ) )
		return;
	address.Service( ( unsigned short )port );

	wxArrayString typeChoices;
	typeChoices.Add( "Human" );
	typeChoices.Add( "Computer (Level 1)" );
	typeChoices.Add( "Computer (Level 2)" );
	typeChoices.Add( "Computer (Level 3)" );
	wxSingleChoiceDialog singleChoiceDialog( this, wxT( "Will this be a human or computer client?" ), wxT( "Choose Client Type" ), typeChoices );
	if( wxID_OK != singleChoiceDialog.ShowModal() )
		return;

	Client::Type clientType = Client::HUMAN;
	wxString selection = singleChoiceDialog.GetStringSelection();
	if( selection == wxT( "Computer (Level 1)" ) )
		clientType = Client::COMPUTER_LEVEL_1;
	else if( selection == wxT( "Computer (Level 2)" ) )
		clientType = Client::COMPUTER_LEVEL_2;
	else if( selection == wxT( "Computer (Level 3)" ) )
		clientType = Client::COMPUTER_LEVEL_3;

	wxScopedPtr< Client > clientPtr;
	clientPtr.reset( new Client( clientType ) );

	if( !clientPtr->Connect( address ) )
		return;

	client = clientPtr.release();
	wxGetApp().SetClient( client );
}

//=====================================================================================
void Frame::OnLeaveGame( wxCommandEvent& event )
{
	KillClient();
}

//=====================================================================================
void Frame::OnKillGame( wxCommandEvent& event )
{
	KillServer();
}

//=====================================================================================
void Frame::OnExit( wxCommandEvent& event )
{
	Close( true );
}

//=====================================================================================
void Frame::KillServer( void )
{
	Server* server = wxGetApp().GetServer();
	if( server )
	{
		server->Finalize();
		delete server;
		wxGetApp().SetServer(0);
	}
}

//=====================================================================================
void Frame::KillClient( void )
{
	Client* client = wxGetApp().GetClient();
	if( client )
	{
		delete client;
		wxGetApp().SetClient(0);
	}
}

//=====================================================================================
void Frame::OnClose( wxCloseEvent& event )
{
	KillServer();
	KillClient();

	event.Skip();
}

//=====================================================================================
void Frame::OnAbout( wxCommandEvent& event )
{
	wxAboutDialogInfo aboutDialogInfo;

	aboutDialogInfo.SetName( wxT( "Chinese Checkers" ) );
	aboutDialogInfo.SetVersion( wxT( "1.0" ) );
	aboutDialogInfo.SetDescription( wxT( "This program is free software and distributed under the MIT license." ) );
	aboutDialogInfo.SetCopyright( wxT( "Copyright (C) 2013 Spencer T. Parkin <spencer.parkin@disney.com>" ) );
	aboutDialogInfo.SetWebSite( wxT( "http://spencerparkin.github.io/ChineseCheckers/" ) );

	wxAboutBox( aboutDialogInfo );
}

//=====================================================================================
void Frame::OnUpdateMenuItemUI( wxUpdateUIEvent& event )
{
	switch( event.GetId() )
	{
		case ID_JoinGame:
		{
			event.Enable( wxGetApp().GetClient() ? false : true );
			break;
		}
		case ID_HostGame:
		{
			event.Enable( wxGetApp().GetServer() ? false : true );
			break;
		}
		case ID_LeaveGame:
		{
			event.Enable( wxGetApp().GetClient() ? true : false );
			break;
		}
		case ID_KillGame:
		{
			event.Enable( wxGetApp().GetServer() ? true : false );
			break;
		}
	}
}

//=====================================================================================
void Frame::OnTimer( wxTimerEvent& event )
{
	// This routine was never meant to be re-entrant.
	// Re-entrancy could cause a crash due to client or server death.
	// If a dialog is put up in this routine, wxWidgets still calls the timer,
	// which can cause re-entrancy.
	static bool inOnTimer = false;
	if( inOnTimer )
		return;
	inOnTimer = true;

	Server* server = wxGetApp().GetServer();
	if( server && !server->Run() )
		KillServer();

	Client* client = wxGetApp().GetClient();
	if( client )
	{
		if( !client->Run() )
		{
			KillClient();
			wxMessageBox( wxT( "We have lost our connection with the server, possibly because the game server has gone down." ), wxT( "Connection Lost" ), wxOK | wxCENTRE, wxGetApp().GetFrame() );
		}
		else
		{
			client->Animate( canvas->FrameRate() );
			if( continuousRefresh )
				canvas->Refresh();
		}
	}

	inOnTimer = false;
}

//=====================================================================================
void Frame::OnActivate( wxActivateEvent& event )
{
	continuousRefresh = event.GetActive();
}

//=====================================================================================
wxStatusBar* Frame::GetStatusBar( void )
{
	return statusBar;
}

// ChiCheFrame.cpp
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: SlsPageDescriptor.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 06:20:49 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SD_SLIDESORTER_PAGE_DESCRIPTOR_HXX
#define SD_SLIDESORTER_PAGE_DESCRIPTOR_HXX

#ifndef _SV_GEN_HXX
#include <tools/gen.hxx>
#endif
#include <tools/link.hxx>
#include <vcl/bitmap.hxx>
#include <sfx2/viewfrm.hxx>

class SdPage;

#include <memory>

namespace sdr { namespace contact {
class ObjectContact;
} }

namespace sd { namespace slidesorter { namespace view {
class PageObject;
class PageObjectViewObjectContact;
} } }

namespace sd { namespace slidesorter { namespace controller {
class PageObjectFactory;
} } }

namespace sd { namespace slidesorter { namespace model {

class SlideSorterView;
class SlideRenderer;

/** Each PageDescriptor object represents the preview of one draw page,
    slide, or master page of a Draw or Impress document as they are displayed
    in the slide sorter.  This class gives access to some associated
    information like prerendered preview or position on the screen.

Bounding boxes of page objects come in four varieties:
    Model and screen/pixel coordinates and the bounding boxes of the actual
    page objects and the larger bounding boxes that include page names and
    fade symbol.

*/
class PageDescriptor
{
public:
    PageDescriptor (
        SdPage& rPage,
        const controller::PageObjectFactory& rPageObjectFactory);
    ~PageDescriptor (void);

    /** Return the page that is represented by the descriptor.
    */
    SdPage* GetPage (void) const;

    /** Return the page shape that is used for visualizing the page.
    */
    view::PageObject* GetPageObject (void);
    void ReleasePageObject (void);

    /** Return <TRUE/> when the page object is fully or parially visible. */
    bool IsVisible (void) const;

    /** Set the visible state that is returned by the IsVisible() method.
        This method is typically called by the view who renders the object
        onto the screen.
    */
    void SetVisible (bool bVisible);

    /** Make sure that the page is selected and return whether the
        selection state changed.
    */
    bool Select (void);
    /** Make sure that the page is not selected and return whether the
        selection state changed.
    */
    bool Deselect (void);

    /** Return whether the page is selected (and thus bypasses the internal
        mbIsSelected flag.
    */
    bool IsSelected (void) const;

    /** Set the internal mbIsSelected flag to the selection state of the
        page.  Use this method to synchornize a page descriptor with the
        page it describes and determine whether a redraw to update the
        selection indicator is necessary.
        @return
            When the two selection states were different <TRUE/> is
            returned.  When they were the same this method returns
            <FALSE/>.
    */
    bool UpdateSelection (void);

    bool IsFocused (void) const;
    void SetFocus (void);
    void RemoveFocus (void);

    view::PageObjectViewObjectContact* GetViewObjectContact (void) const;

    void SetViewObjectContact (
        view::PageObjectViewObjectContact* pViewObjectContact);

    /** Return the currently used page object factory.
    */
    const controller::PageObjectFactory& GetPageObjectFactory (void) const;

    /** Replace the current page object factory by the given one.
    */
    void SetPageObjectFactory (const controller::PageObjectFactory& rFactory);

    void SetModelBorder (const SvBorder& rBorder);
    SvBorder GetModelBorder (void) const;

    /** The size of the area in which the page number is displayed is
        calculated by the SlideSorterView and then stored in the page
        descriptors so that the contact objects can access them.  The
        contact objects can not calculate them on demand because the total
        number of slides is needed to do that and this number is not known
        to the contact objects.
    */
    void SetPageNumberAreaModelSize (const Size& rSize);
    Size GetPageNumberAreaModelSize (void) const;

private:
    SdPage& mrPage;

    /// The factory that is used to create PageObject objects.
    const controller::PageObjectFactory* mpPageObjectFactory;

    /** The page object will be destroyed by the page into which it has
        been inserted.
    */
    view::PageObject* mpPageObject;

    bool mbIsSelected;
    bool mbVisible;
    bool mbFocused;

    view::PageObjectViewObjectContact* mpViewObjectContact;

    /// The borders in model coordinates arround the page object.
    SvBorder maModelBorder;

    /// The size of the page number area in model coordinates.
    Size maPageNumberAreaModelSize;

    // Do not use the copy constructor operator.  It is not implemented.
    PageDescriptor (const PageDescriptor& rDescriptor);

    // Do not use the assignment operator.  It is not implemented
    // (mrPage can not be assigned).
    PageDescriptor& operator= (const PageDescriptor& rDescriptor);
};

} } } // end of namespace ::sd::slidesorter::model

#endif
<commit_msg>INTEGRATION: CWS presenterview (1.6.388); FILE MERGED 2008/03/19 10:42:52 af 1.6.388.2: #i87200# Had to add SdPage pointer for cases where it can not be determined via rxPage. 2007/04/26 14:30:40 af 1.6.388.1: #i75317# Added access to page index and XDrawPage object.  Added current page state.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: SlsPageDescriptor.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2008-04-03 14:37:18 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SD_SLIDESORTER_PAGE_DESCRIPTOR_HXX
#define SD_SLIDESORTER_PAGE_DESCRIPTOR_HXX

#include <com/sun/star/drawing/XDrawPage.hpp>
#include <tools/gen.hxx>
#include <tools/link.hxx>
#include <vcl/bitmap.hxx>
#include <sfx2/viewfrm.hxx>

#include <memory>
#include <boost/enable_shared_from_this.hpp>

class SdPage;

namespace sdr { namespace contact {
class ObjectContact;
} }

namespace sd { namespace slidesorter { namespace view {
class PageObject;
class PageObjectViewObjectContact;
} } }

namespace sd { namespace slidesorter { namespace controller {
class PageObjectFactory;
} } }

namespace sd { namespace slidesorter { namespace model {

class SlideRenderer;

namespace css = ::com::sun::star;

/** Each PageDescriptor object represents the preview of one draw page,
    slide, or master page of a Draw or Impress document as they are displayed
    in the slide sorter.  This class gives access to some associated
    information like prerendered preview or position on the screen.

Bounding boxes of page objects come in four varieties:
    Model and screen/pixel coordinates and the bounding boxes of the actual
    page objects and the larger bounding boxes that include page names and
    fade symbol.

*/
class PageDescriptor
    : public ::boost::enable_shared_from_this<PageDescriptor>
{
public:
    /** Create a PageDescriptor for the given SdPage object.
        @param rxPage
            The page that is represented by the new PageDescriptor object.
        @param pPage
            The page pointer can in some situations not be detected from
            rxPage, e.g. after undo of page deletion.  Therefore supply it
            seperately.
        @param nIndex
            This index is displayed in the view as page number.  It is not
            necessaryily the page index (not even when you add or subtract 1
            or use (x-1)/2 magic).
    */
    PageDescriptor (
        const css::uno::Reference<css::drawing::XDrawPage>& rxPage,
        SdPage* pPage,
        const sal_Int32 nIndex,
        const controller::PageObjectFactory& rPageObjectFactory);

    ~PageDescriptor (void);

    /** Return the page that is represented by the descriptor as SdPage pointer .
    */
    SdPage* GetPage (void) const;

    /** Return the page that is represented by the descriptor as XDrawPage reference.
    */
    css::uno::Reference<css::drawing::XDrawPage> GetXDrawPage (void) const;

    /** Returns the index of the page as it is displayed in the view as page
        number.  The value may differ from the index returned by the
        XDrawPage when there are hidden slides and the XIndexAccess used to
        access the model filters them out.
    */
    sal_Int32 GetPageIndex (void) const;

    /** Return the page shape that is used for visualizing the page.
    */
    view::PageObject* GetPageObject (void);
    void ReleasePageObject (void);

    /** Return <TRUE/> when the page object is fully or parially visible. */
    bool IsVisible (void) const;

    /** Set the visible state that is returned by the IsVisible() method.
        This method is typically called by the view who renders the object
        onto the screen.
    */
    void SetVisible (bool bVisible);

    /** Make sure that the page is selected and return whether the
        selection state changed.
    */
    bool Select (void);
    /** Make sure that the page is not selected and return whether the
        selection state changed.
    */
    bool Deselect (void);

    /** Return whether the page is selected (and thus bypasses the internal
        mbIsSelected flag.
    */
    bool IsSelected (void) const;

    /** Set the internal mbIsSelected flag to the selection state of the
        page.  Use this method to synchronize a page descriptor with the
        page it describes and determine whether a redraw to update the
        selection indicator is necessary.
        @return
            When the two selection states were different <TRUE/> is
            returned.  When they were the same this method returns
            <FALSE/>.
    */
    bool UpdateSelection (void);

    bool IsFocused (void) const;
    void SetFocus (void);
    void RemoveFocus (void);

    view::PageObjectViewObjectContact* GetViewObjectContact (void) const;

    void SetViewObjectContact (
        view::PageObjectViewObjectContact* pViewObjectContact);

    /** Return the currently used page object factory.
    */
    const controller::PageObjectFactory& GetPageObjectFactory (void) const;

    /** Replace the current page object factory by the given one.
    */
    void SetPageObjectFactory (const controller::PageObjectFactory& rFactory);

    void SetModelBorder (const SvBorder& rBorder);
    SvBorder GetModelBorder (void) const;

    /** The size of the area in which the page number is displayed is
        calculated by the SlideSorterView and then stored in the page
        descriptors so that the contact objects can access them.  The
        contact objects can not calculate them on demand because the total
        number of slides is needed to do that and this number is not known
        to the contact objects.
    */
    void SetPageNumberAreaModelSize (const Size& rSize);
    Size GetPageNumberAreaModelSize (void) const;

    /** Returns <TRUE/> when the slide is the current slide.
    */
    bool IsCurrentPage (void) const;

    /** Set or revoke the state of this slide being the current slide.
    */
    void SetIsCurrentPage (const bool bIsCurrent);

private:
    SdPage* mpPage;
    css::uno::Reference<css::drawing::XDrawPage> mxPage;
    /** This index is displayed as page number in the view.  It may or may
        not be actual page index.
    */
    const sal_Int32 mnIndex;

    /// The factory that is used to create PageObject objects.
    const controller::PageObjectFactory* mpPageObjectFactory;

    /** The page object will be destroyed by the page into which it has
        been inserted.
    */
    view::PageObject* mpPageObject;

    bool mbIsSelected;
    bool mbIsVisible;
    bool mbIsFocused;
    bool mbIsCurrent;

    view::PageObjectViewObjectContact* mpViewObjectContact;

    /// The borders in model coordinates arround the page object.
    SvBorder maModelBorder;

    /// The size of the page number area in model coordinates.
    Size maPageNumberAreaModelSize;

    // Do not use the copy constructor operator.  It is not implemented.
    PageDescriptor (const PageDescriptor& rDescriptor);

    // Do not use the assignment operator.  It is not implemented
    // (mrPage can not be assigned).
    PageDescriptor& operator= (const PageDescriptor& rDescriptor);
};

} } } // end of namespace ::sd::slidesorter::model

#endif
<|endoftext|>


<commit_before>#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"
#include "cinder/Rand.h"
#include "cinder/Json.h"
#include "cinder/ip/Premultiply.h"

#include "entityx/Event.h"
#include "entityx/Entity.h"
#include "entityx/System.h"

#include "puptent/BatchRenderSystem2d.h"
#include "puptent/PhysicsSystem2d.h"
#include "puptent/TextureAtlas.h"
#include "puptent/SpriteAnimation.h"

/**
 Sample app used to develop features of PupTent.
 Learning about component systems and building my own components.
 While everything is dependent on the underlying component machinery,
 it is wonderfully decoupled from other systems and components.
*/

using namespace ci;
using namespace ci::app;
using namespace std;
using namespace puptent;

using namespace entityx;
using pockets::Vertex2d;

struct MovementSystem : public System<MovementSystem>
{
  void update( shared_ptr<EntityManager> es, shared_ptr<EventManager> events, double dt ) override
  {
    if( mElements.empty() )
    {
      for( auto entity : es->entities_with_components<Locus>() )
      {
        mElements.push_back( entity.component<Locus>() );
      }
    }
    time += dt;
    for( auto& loc : mElements )
    {
      loc->rotation = fmodf( loc->rotation - M_PI * 0.01f, M_PI * 2 );
      loc->scale = math<float>::sin( 0.5f * time + M_PI * loc->position.x / 640.0f + M_PI * loc->position.y / 480.0f );
    }
  }
  double time = 0.0;
  vector<shared_ptr<Locus>> mElements;
};

class PupTentApp : public AppNative
{
public:
  void prepareSettings( Settings *settings );
	void setup();
	void update();
	void draw();
private:
  shared_ptr<EventManager>  mEvents;
  shared_ptr<EntityManager> mEntities;
  shared_ptr<SystemManager> mSystemManager;
  double                    mAverageUpdateTime = 1.0;
  double                    mAverageRenderTime = 1.0;
  Timer                     mTimer;
  TextureAtlas              mTextureAtlas;
};

void PupTentApp::prepareSettings( Settings *settings )
{
  settings->disableFrameRate();
  settings->setWindowSize( 1024, 768 );
//  settings->setFullScreen();
}

void PupTentApp::setup()
{
  gl::enableVerticalSync();
  Surface sprite_surf{ loadImage( loadAsset( "spritesheet.png" ) ) };
  if( !sprite_surf.isPremultiplied() )
  {
    ip::premultiply( &sprite_surf );
  }
  TextureAtlasRef atlas = TextureAtlas::create( sprite_surf, JsonTree( loadAsset( "spritesheet.json" ) ) );
  JsonTree animations{ loadAsset( "animations.json" ) };

  mEvents = EventManager::make();
  mEntities = EntityManager::make(mEvents);
  mSystemManager = SystemManager::make( mEntities, mEvents );
  mSystemManager->add<MovementSystem>();
  auto physics = mSystemManager->add<PhysicsSystem2d>();
  physics->createBoundaryRect( getWindowBounds() );
  auto renderer = mSystemManager->add<BatchRenderSystem2d>();
  renderer->setTexture( atlas->getTexture() );
  shared_ptr<SpriteAnimationSystem> sprite_system{ new SpriteAnimationSystem{ atlas, animations } };
  mSystemManager->add( sprite_system );
  mSystemManager->configure();

  Rand r;
  Vec2f center = getWindowCenter();
  Entity entity;
  for( int i = 0; i < 2000; ++i )
  {
    entity = mEntities->create();
    auto loc = shared_ptr<Locus>{ new Locus };
    // get an animation out of the sprite system
    auto anim = sprite_system->createSpriteAnimation( "dot" );
    auto mesh = anim->mesh;
    loc->position = { r.nextFloat( getWindowWidth() ), r.nextFloat( getWindowHeight() ) };
    loc->rotation = r.nextFloat( M_PI * 2 );
    loc->registration_point = { 0, 0 };
    float dist = loc->position.distance( center );
    ColorA color{ CM_HSV, 0.0f, 0.0f, lmap( dist, 0.0f, 0.75f * getWindowWidth(), 0.0f, 1.0f ), 1.0f };
    for( auto &v : mesh->vertices )
    {
      v.color = color;
    }
    mesh->render_layer = dist;
//    entity.assign( physics->createBox( loc->position, atlas->get( "d-0001" ).size / 12.0f, loc->rotation ) );
    entity.assign( anim );
    entity.assign( loc );
    entity.assign( mesh );
  }

  getWindow()->getSignalMouseDown().connect( [=]( MouseEvent &event ) mutable
  {
    if( entity.valid() )
    {
      if( entity.component<SpriteAnimation>() )
      {
        cout << "Removing Sprite Animation component: " << entity << endl;
        entity.remove<SpriteAnimation>();
      }
      else
      {
        cout << "Adding Mesh component: " << entity << endl;
        auto mesh = RenderMesh2dRef{ new RenderMesh2d{ 4 } };
        // perhaps have a component to hang on to texturing data
        mesh->setAsTexture( atlas->get( "dl-0001" ) );
        mesh->render_layer = 1000;
        ColorA color{ 1.0f, 1.0f, 1.0f, 1.0f };
        for( auto &v : mesh->vertices )
        {
          v.color = color;
        }
        entity.assign<RenderMesh2d>( mesh );
      }
    }
  });

  mTimer.start();
}

void PupTentApp::update()
{
  double dt = mTimer.getSeconds();
  mTimer.start();
  Timer up;
  up.start();
  mSystemManager->system<PhysicsSystem2d>()->stepPhysics(); // could parallelize this with sprite animation and some other things...
  mSystemManager->update<PhysicsSystem2d>( dt );
  mSystemManager->update<MovementSystem>( dt );
  mSystemManager->update<SpriteAnimationSystem>( dt );
  mSystemManager->update<BatchRenderSystem2d>( dt );
  double ms = up.getSeconds() * 1000;
  mAverageUpdateTime = (mAverageUpdateTime * 59.0 + ms) / 60.0;
  if( getElapsedFrames() % 90 == 0 )
  {
    cout << "Update: " << mAverageUpdateTime << ", " << ms << endl;
  }
}

void PupTentApp::draw()
{
	gl::clear( Color::black() );
  gl::disableDepthRead();
  gl::disableDepthWrite();
  gl::color( Color::white() );
  Timer dr;
  dr.start();
  mSystemManager->system<BatchRenderSystem2d>()->draw();
//  mSystemManager->system<PhysicsSystem2d>()->debugDraw();
  double ms = dr.getSeconds() * 1000;
  mAverageRenderTime = (mAverageRenderTime * 59.0 + ms) / 60.0;
  if( getElapsedFrames() % 90 == 0 )
  {
    cout << "Render ms: " << mAverageRenderTime << ", " << ms << endl;
  }
}

CINDER_APP_NATIVE( PupTentApp, RendererGl( RendererGl::AA_MSAA_8 ) )

<commit_msg>More entities.<commit_after>#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"
#include "cinder/Rand.h"
#include "cinder/Json.h"
#include "cinder/ip/Premultiply.h"

#include "entityx/Event.h"
#include "entityx/Entity.h"
#include "entityx/System.h"

#include "puptent/BatchRenderSystem2d.h"
#include "puptent/PhysicsSystem2d.h"
#include "puptent/TextureAtlas.h"
#include "puptent/SpriteAnimation.h"

/**
 Sample app used to develop features of PupTent.
 Learning about component systems and building my own components.
 While everything is dependent on the underlying component machinery,
 it is wonderfully decoupled from other systems and components.
*/

using namespace ci;
using namespace ci::app;
using namespace std;
using namespace puptent;

using namespace entityx;
using pockets::Vertex2d;

struct MovementSystem : public System<MovementSystem>
{
  void update( shared_ptr<EntityManager> es, shared_ptr<EventManager> events, double dt ) override
  {
    if( mElements.empty() )
    {
      for( auto entity : es->entities_with_components<Locus>() )
      {
        mElements.push_back( entity.component<Locus>() );
      }
    }
    time += dt;
    for( auto& loc : mElements )
    {
      loc->rotation = fmodf( loc->rotation - M_PI * 0.01f, M_PI * 2 );
      loc->scale = math<float>::sin( 0.5f * time + M_PI * loc->position.x / 640.0f + M_PI * loc->position.y / 480.0f );
    }
  }
  double time = 0.0;
  vector<shared_ptr<Locus>> mElements;
};

class PupTentApp : public AppNative
{
public:
  void prepareSettings( Settings *settings );
	void setup();
	void update();
	void draw();
private:
  shared_ptr<EventManager>  mEvents;
  shared_ptr<EntityManager> mEntities;
  shared_ptr<SystemManager> mSystemManager;
  double                    mAverageUpdateTime = 1.0;
  double                    mAverageRenderTime = 1.0;
  Timer                     mTimer;
  TextureAtlas              mTextureAtlas;
};

void PupTentApp::prepareSettings( Settings *settings )
{
  settings->disableFrameRate();
  settings->setWindowSize( 1024, 768 );
//  settings->setFullScreen();
}

void PupTentApp::setup()
{
  gl::enableVerticalSync();
  Surface sprite_surf{ loadImage( loadAsset( "spritesheet.png" ) ) };
  if( !sprite_surf.isPremultiplied() )
  {
    ip::premultiply( &sprite_surf );
  }
  TextureAtlasRef atlas = TextureAtlas::create( sprite_surf, JsonTree( loadAsset( "spritesheet.json" ) ) );
  JsonTree animations{ loadAsset( "animations.json" ) };

  mEvents = EventManager::make();
  mEntities = EntityManager::make(mEvents);
  mSystemManager = SystemManager::make( mEntities, mEvents );
  mSystemManager->add<MovementSystem>();
  auto physics = mSystemManager->add<PhysicsSystem2d>();
  physics->createBoundaryRect( getWindowBounds() );
  auto renderer = mSystemManager->add<BatchRenderSystem2d>();
  renderer->setTexture( atlas->getTexture() );
  shared_ptr<SpriteAnimationSystem> sprite_system{ new SpriteAnimationSystem{ atlas, animations } };
  mSystemManager->add( sprite_system );
  mSystemManager->configure();

  Rand r;
  Vec2f center = getWindowCenter();
  Entity entity;
  for( int i = 0; i < 8000; ++i )
  {
    entity = mEntities->create();
    auto loc = shared_ptr<Locus>{ new Locus };
    // get an animation out of the sprite system
    auto anim = sprite_system->createSpriteAnimation( "dot" );
    auto mesh = anim->mesh;
    loc->position = { r.nextFloat( getWindowWidth() ), r.nextFloat( getWindowHeight() ) };
    loc->rotation = r.nextFloat( M_PI * 2 );
    loc->registration_point = { 0, 0 };
    float dist = loc->position.distance( center );
    ColorA color{ CM_HSV, 0.0f, 0.0f, lmap( dist, 0.0f, 0.75f * getWindowWidth(), 0.0f, 1.0f ), 1.0f };
    for( auto &v : mesh->vertices )
    {
      v.color = color;
    }
    mesh->render_layer = dist;
//    entity.assign( physics->createBox( loc->position, atlas->get( "d-0001" ).size / 12.0f, loc->rotation ) );
    entity.assign( anim );
    entity.assign( loc );
    entity.assign( mesh );
  }

  getWindow()->getSignalMouseDown().connect( [=]( MouseEvent &event ) mutable
  {
    if( entity.valid() )
    {
      if( entity.component<SpriteAnimation>() )
      {
        cout << "Removing Sprite Animation component: " << entity << endl;
        entity.remove<SpriteAnimation>();
      }
      else
      {
        cout << "Adding Mesh component: " << entity << endl;
        auto mesh = RenderMesh2dRef{ new RenderMesh2d{ 4 } };
        // perhaps have a component to hang on to texturing data
        mesh->setAsTexture( atlas->get( "dl-0001" ) );
        mesh->render_layer = 1000;
        ColorA color{ 1.0f, 1.0f, 1.0f, 1.0f };
        for( auto &v : mesh->vertices )
        {
          v.color = color;
        }
        entity.assign<RenderMesh2d>( mesh );
      }
    }
  });

  mTimer.start();
}

void PupTentApp::update()
{
  double dt = mTimer.getSeconds();
  mTimer.start();
  Timer up;
  up.start();
  mSystemManager->system<PhysicsSystem2d>()->stepPhysics(); // could parallelize this with sprite animation and some other things...
  mSystemManager->update<PhysicsSystem2d>( dt );
  mSystemManager->update<MovementSystem>( dt );
  mSystemManager->update<SpriteAnimationSystem>( dt );
  mSystemManager->update<BatchRenderSystem2d>( dt );
  double ms = up.getSeconds() * 1000;
  mAverageUpdateTime = (mAverageUpdateTime * 59.0 + ms) / 60.0;
  if( getElapsedFrames() % 90 == 0 )
  {
    cout << "Update: " << mAverageUpdateTime << ", " << ms << endl;
  }
}

void PupTentApp::draw()
{
	gl::clear( Color::black() );
  gl::disableDepthRead();
  gl::disableDepthWrite();
  gl::color( Color::white() );
  Timer dr;
  dr.start();
  mSystemManager->system<BatchRenderSystem2d>()->draw();
//  mSystemManager->system<PhysicsSystem2d>()->debugDraw();
  double ms = dr.getSeconds() * 1000;
  mAverageRenderTime = (mAverageRenderTime * 59.0 + ms) / 60.0;
  if( getElapsedFrames() % 90 == 0 )
  {
    cout << "Render ms: " << mAverageRenderTime << ", " << ms << endl;
  }
}

CINDER_APP_NATIVE( PupTentApp, RendererGl( RendererGl::AA_MSAA_8 ) )

<|endoftext|>


<commit_before>#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"
#include "cinder/Rand.h"
#include "cinder/Json.h"
#include "cinder/ip/Premultiply.h"
#include "cinder/Easing.h"

#include "entityx/Event.h"
#include "entityx/Entity.h"
#include "entityx/System.h"

#include "puptent/RenderSystem.h"
#include "puptent/PhysicsSystem.h"
#include "puptent/TextureAtlas.h"
#include "puptent/SpriteSystem.h"
#include "puptent/ParticleSystem.h"
#include "puptent/ExpiresSystem.h"

/**
 Sample app used to develop features of PupTent.
 Learning about component systems and building my own components.
 While everything is dependent on the underlying component machinery,
 it is wonderfully decoupled from other systems and components.
*/

using namespace ci;
using namespace ci::app;
using namespace std;
using namespace puptent;

using namespace entityx;

struct MovementSystem : public System<MovementSystem>
{
  void update( shared_ptr<EntityManager> es, shared_ptr<EventManager> events, double dt ) override
  {
    if( mElements.empty() )
    {
      for( auto entity : es->entities_with_components<Locus>() )
      {
        mElements.push_back( entity.component<Locus>() );
      }
    }
    time += dt;
    Vec2f center = getWindowCenter();
    float max_dist = center.length();
    for( auto& loc : mElements )
    {
      loc->rotation = fmodf( loc->rotation - M_PI * 0.01f, M_PI * 2 );
      float theta = loc->position.distance( center );
      loc->scale = cos( -time * 0.66f + M_PI * theta / max_dist );
    }
  }
  double time = 0.0;
  vector<shared_ptr<Locus>> mElements;
};

class PupTentApp : public AppNative
{
public:
  void prepareSettings( Settings *settings );
	void setup();
	void update();
	void draw();
private:
  shared_ptr<EventManager>  mEvents;
  shared_ptr<EntityManager> mEntities;
  shared_ptr<SystemManager> mSystemManager;
  double                    mAverageUpdateTime = 1.0;
  double                    mAverageRenderTime = 1.0;
  Timer                     mTimer;
  TextureAtlas              mTextureAtlas;
};

void PupTentApp::prepareSettings( Settings *settings )
{
  settings->disableFrameRate();
  settings->setWindowSize( 1024, 768 );
//  settings->setFullScreen();
}

void PupTentApp::setup()
{
  gl::enableVerticalSync();
  Surface sprite_surf{ loadImage( loadAsset( "spritesheet.png" ) ) };
  if( !sprite_surf.isPremultiplied() )
  {
    ip::premultiply( &sprite_surf );
  }
  TextureAtlasRef atlas = TextureAtlas::create( sprite_surf, JsonTree( loadAsset( "spritesheet.json" ) ) );
  JsonTree animations{ loadAsset( "animations.json" ) };

  mEvents = EventManager::make();
  mEntities = EntityManager::make(mEvents);
  mSystemManager = SystemManager::make( mEntities, mEvents );
  mSystemManager->add<ExpiresSystem>();
  mSystemManager->add<MovementSystem>();
  mSystemManager->add<ParticleSystem>();
  auto physics = mSystemManager->add<PhysicsSystem>();
  physics->createBoundaryRect( getWindowBounds() );
  auto renderer = mSystemManager->add<RenderSystem>();
  renderer->setTexture( atlas->getTexture() );
  shared_ptr<SpriteAnimationSystem> sprite_system{ new SpriteAnimationSystem{ atlas, animations } };
  mSystemManager->add( sprite_system );
  mSystemManager->configure();

  Rand r;
  Vec2f center = getWindowCenter();
  float max_dist = center.length();
  Entity entity;
  vector<Entity> entity_vector;
  for( int i = 0; i < 20000; ++i )
  {
    entity = mEntities->create();
    auto loc = shared_ptr<Locus>{ new Locus };
    // get an animation out of the sprite system
    auto anim = sprite_system->createSpriteAnimation( "dot" );
    anim->current_index = r.nextInt( 0, 10 );
    loc->position = { r.nextFloat( getWindowWidth() ), r.nextFloat( getWindowHeight() ) };
    loc->rotation = r.nextFloat( M_PI * 2 );
    loc->registration_point = { 20.0f, 10.0f }; // center of the mesh created below
    float dist = loc->position.distance( center );
    loc->render_layer = dist;
//    auto color = ColorA::gray( math<float>::clamp( lmap( dist, 0.0f, max_dist - 10.0f, 0.0f, 1.0f ) ) );
    auto color = Color( CM_HSV, r.nextFloat( 0.4f, 1.0f ), 0.8f, 0.8f );
//    entity.assign( physics->createCircle( loc->position, atlas->get( "d-0001" ).size.x / 16.0f ) );
    auto mesh = entity.assign<RenderMesh>( 4 );
    mesh->setAsBox( { 0.0f, 0.0f, 40.0f, 20.0f } );
    for( auto &v : mesh->vertices )
    {
      v.color = color;
    }
//    entity.assign( anim );
    entity.assign( loc );
    RenderPass pass = eNormalPass;
    if( r.nextFloat() < 0.5f )
    {
      pass = r.nextFloat() < 0.5f ? eMultiplyPass : eAdditivePass;
    }
    entity.assign<RenderData>( mesh, loc, pass );
    // randomized expire time, weighted toward end
    entity.assign<Expires>( easeOutQuad( r.nextFloat() ) * 9.0f + 1.0f );
    entity_vector.push_back( entity );
  }

  vector<Entity> empty_vec;
  Timer performance_timer;
  double vector_avg = 0.0;
  double empty_avg = 0.0;
  double clear_avg = 0.0;
  double query_avg = 0.0;
  double mquery_avg = 0.0;
  const int iterations = 100;
  for( int i = 0; i < iterations; ++i )
  {
    performance_timer.start();
    for( auto entity : entity_vector )
    {
      auto loc = entity.component<Locus>();
      loc->position.x += 0.1f;
    }
    performance_timer.stop();
    vector_avg += performance_timer.getSeconds();

    performance_timer.start();
    vector_erase_if( &entity_vector, [](Entity entity){ return !entity.valid(); } );
    performance_timer.stop();
    clear_avg += performance_timer.getSeconds();

    performance_timer.start();
    for( auto entity : empty_vec )
    {
      auto loc = entity.component<Locus>();
      loc->position.x += 0.1f;
    }
    performance_timer.stop();
    empty_avg += performance_timer.getSeconds();

    performance_timer.start();
    for( auto entity : mEntities->entities_with_components<Locus>() )
    {
      auto loc = entity.component<Locus>();
      loc->position.x += 0.1f;
    }
    performance_timer.stop();
    query_avg += performance_timer.getSeconds();

    performance_timer.start();
    for( auto entity : mEntities->entities_with_components<Locus, Expires, RenderData, SpriteAnimation>() )
    {
      auto loc = entity.component<Locus>();
      loc->position.x += 0.1f;
    }
    performance_timer.stop();
    mquery_avg += performance_timer.getSeconds();
  }
  vector_avg /= iterations;
  empty_avg /= iterations;
  query_avg /= iterations;
  mquery_avg /= iterations;
  cout << "Vector AVG: " << vector_avg * 1000 << endl;
  cout << "Empty  AVG: " << empty_avg * 1000 << endl;
  cout << "Clear  AVG: " << clear_avg * 1000 << endl;
  cout << "Vector Tot: " << ( clear_avg + vector_avg ) * 1000 << endl;
  cout << "Query  AVG: " << query_avg * 1000 << endl;
  cout << "MQuery AVG: " << mquery_avg * 1000 << endl;

  renderer->checkOrdering();

  getWindow()->getSignalMouseDown().connect( [=]( MouseEvent &event ) mutable
  {
    if( entity.valid() )
    {
      if( entity.component<SpriteAnimation>() )
      {
        cout << "Removing Sprite Animation component: " << entity << endl;
        entity.remove<SpriteAnimation>();
      }
      else
      {
        cout << "Adding Mesh component: " << entity << endl;
        auto loc = entity.component<Locus>();
        if( loc )
        {
          loc->render_layer = 1000;
        }
        auto mesh = RenderMeshRef{ new RenderMesh{ 4 } };
        // perhaps have a component to hang on to texturing data
        mesh->matchTexture( atlas->get( "dl-0001" ) );
        ColorA color{ 1.0f, 1.0f, 1.0f, 1.0f };
        for( auto &v : mesh->vertices )
        {
          v.color = color;
        }
        entity.assign<RenderMesh>( mesh );
        entity.component<RenderData>()->mesh = mesh;
      }
    }
  });

  mTimer.start();
}

void PupTentApp::update()
{
  double dt = mTimer.getSeconds();
  mTimer.start();
  Timer up;
  up.start();
//  mSystemManager->system<PhysicsSystem>()->stepPhysics(); // could parallelize this with sprite animation and some other things...
//  mSystemManager->update<PhysicsSystem>( dt );
  mSystemManager->update<ExpiresSystem>( dt );
  mSystemManager->update<MovementSystem>( dt );
  mSystemManager->update<SpriteAnimationSystem>( dt );
  mSystemManager->update<ParticleSystem>( dt );
  mSystemManager->update<RenderSystem>( dt );
  double ms = up.getSeconds() * 1000;
  mAverageUpdateTime = (mAverageUpdateTime * 59.0 + ms) / 60.0;
  if( getElapsedFrames() % 90 == 0 )
  {
    cout << "Update: " << mAverageUpdateTime << ", " << ms << endl;
  }
}

void PupTentApp::draw()
{
	gl::clear( Color::black() );
  gl::color( Color::white() );
  Timer dr;
  dr.start();
//  mSystemManager->system<PhysicsSystem>()->debugDraw();
  mSystemManager->system<RenderSystem>()->draw();
  double ms = dr.getSeconds() * 1000;
  mAverageRenderTime = (mAverageRenderTime * 59.0 + ms) / 60.0;
  if( getElapsedFrames() % 90 == 0 )
  {
    cout << "Render: " << mAverageRenderTime << ", " << ms << endl;
  }
}

CINDER_APP_NATIVE( PupTentApp, RendererGl( RendererGl::AA_MSAA_4 ) )
<commit_msg>Removed unused variable.<commit_after>#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"
#include "cinder/Rand.h"
#include "cinder/Json.h"
#include "cinder/ip/Premultiply.h"
#include "cinder/Easing.h"

#include "entityx/Event.h"
#include "entityx/Entity.h"
#include "entityx/System.h"

#include "puptent/RenderSystem.h"
#include "puptent/PhysicsSystem.h"
#include "puptent/TextureAtlas.h"
#include "puptent/SpriteSystem.h"
#include "puptent/ParticleSystem.h"
#include "puptent/ExpiresSystem.h"

/**
 Sample app used to develop features of PupTent.
 Learning about component systems and building my own components.
 While everything is dependent on the underlying component machinery,
 it is wonderfully decoupled from other systems and components.
*/

using namespace ci;
using namespace ci::app;
using namespace std;
using namespace puptent;

using namespace entityx;

struct MovementSystem : public System<MovementSystem>
{
  void update( shared_ptr<EntityManager> es, shared_ptr<EventManager> events, double dt ) override
  {
    if( mElements.empty() )
    {
      for( auto entity : es->entities_with_components<Locus>() )
      {
        mElements.push_back( entity.component<Locus>() );
      }
    }
    time += dt;
    Vec2f center = getWindowCenter();
    float max_dist = center.length();
    for( auto& loc : mElements )
    {
      loc->rotation = fmodf( loc->rotation - M_PI * 0.01f, M_PI * 2 );
      float theta = loc->position.distance( center );
      loc->scale = cos( -time * 0.66f + M_PI * theta / max_dist );
    }
  }
  double time = 0.0;
  vector<shared_ptr<Locus>> mElements;
};

class PupTentApp : public AppNative
{
public:
  void prepareSettings( Settings *settings );
	void setup();
	void update();
	void draw();
private:
  shared_ptr<EventManager>  mEvents;
  shared_ptr<EntityManager> mEntities;
  shared_ptr<SystemManager> mSystemManager;
  double                    mAverageUpdateTime = 1.0;
  double                    mAverageRenderTime = 1.0;
  Timer                     mTimer;
  TextureAtlas              mTextureAtlas;
};

void PupTentApp::prepareSettings( Settings *settings )
{
  settings->disableFrameRate();
  settings->setWindowSize( 1024, 768 );
//  settings->setFullScreen();
}

void PupTentApp::setup()
{
  gl::enableVerticalSync();
  Surface sprite_surf{ loadImage( loadAsset( "spritesheet.png" ) ) };
  if( !sprite_surf.isPremultiplied() )
  {
    ip::premultiply( &sprite_surf );
  }
  TextureAtlasRef atlas = TextureAtlas::create( sprite_surf, JsonTree( loadAsset( "spritesheet.json" ) ) );
  JsonTree animations{ loadAsset( "animations.json" ) };

  mEvents = EventManager::make();
  mEntities = EntityManager::make(mEvents);
  mSystemManager = SystemManager::make( mEntities, mEvents );
  mSystemManager->add<ExpiresSystem>();
  mSystemManager->add<MovementSystem>();
  mSystemManager->add<ParticleSystem>();
  auto physics = mSystemManager->add<PhysicsSystem>();
  physics->createBoundaryRect( getWindowBounds() );
  auto renderer = mSystemManager->add<RenderSystem>();
  renderer->setTexture( atlas->getTexture() );
  shared_ptr<SpriteAnimationSystem> sprite_system{ new SpriteAnimationSystem{ atlas, animations } };
  mSystemManager->add( sprite_system );
  mSystemManager->configure();

  Rand r;
  Vec2f center = getWindowCenter();
  Entity entity;
  vector<Entity> entity_vector;
  for( int i = 0; i < 20000; ++i )
  {
    entity = mEntities->create();
    auto loc = shared_ptr<Locus>{ new Locus };
    // get an animation out of the sprite system
    auto anim = sprite_system->createSpriteAnimation( "dot" );
    anim->current_index = r.nextInt( 0, 10 );
    loc->position = { r.nextFloat( getWindowWidth() ), r.nextFloat( getWindowHeight() ) };
    loc->rotation = r.nextFloat( M_PI * 2 );
    loc->registration_point = { 20.0f, 10.0f }; // center of the mesh created below
    float dist = loc->position.distance( center );
    loc->render_layer = dist;
//    auto color = ColorA::gray( math<float>::clamp( lmap( dist, 0.0f, max_dist - 10.0f, 0.0f, 1.0f ) ) );
    auto color = Color( CM_HSV, r.nextFloat( 0.4f, 1.0f ), 0.8f, 0.8f );
//    entity.assign( physics->createCircle( loc->position, atlas->get( "d-0001" ).size.x / 16.0f ) );
    auto mesh = entity.assign<RenderMesh>( 4 );
    mesh->setAsBox( { 0.0f, 0.0f, 40.0f, 20.0f } );
    for( auto &v : mesh->vertices )
    {
      v.color = color;
    }
//    entity.assign( anim );
    entity.assign( loc );
    RenderPass pass = eNormalPass;
    if( r.nextFloat() < 0.5f )
    {
      pass = r.nextFloat() < 0.5f ? eMultiplyPass : eAdditivePass;
    }
    entity.assign<RenderData>( mesh, loc, pass );
    // randomized expire time, weighted toward end
    entity.assign<Expires>( easeOutQuad( r.nextFloat() ) * 9.0f + 1.0f );
    entity_vector.push_back( entity );
  }

  vector<Entity> empty_vec;
  Timer performance_timer;
  double vector_avg = 0.0;
  double empty_avg = 0.0;
  double clear_avg = 0.0;
  double query_avg = 0.0;
  double mquery_avg = 0.0;
  const int iterations = 100;
  for( int i = 0; i < iterations; ++i )
  {
    performance_timer.start();
    for( auto entity : entity_vector )
    {
      auto loc = entity.component<Locus>();
      loc->position.x += 0.1f;
    }
    performance_timer.stop();
    vector_avg += performance_timer.getSeconds();

    performance_timer.start();
    vector_erase_if( &entity_vector, [](Entity entity){ return !entity.valid(); } );
    performance_timer.stop();
    clear_avg += performance_timer.getSeconds();

    performance_timer.start();
    for( auto entity : empty_vec )
    {
      auto loc = entity.component<Locus>();
      loc->position.x += 0.1f;
    }
    performance_timer.stop();
    empty_avg += performance_timer.getSeconds();

    performance_timer.start();
    for( auto entity : mEntities->entities_with_components<Locus>() )
    {
      auto loc = entity.component<Locus>();
      loc->position.x += 0.1f;
    }
    performance_timer.stop();
    query_avg += performance_timer.getSeconds();

    performance_timer.start();
    for( auto entity : mEntities->entities_with_components<Locus, Expires, RenderData, SpriteAnimation>() )
    {
      auto loc = entity.component<Locus>();
      loc->position.x += 0.1f;
    }
    performance_timer.stop();
    mquery_avg += performance_timer.getSeconds();
  }
  vector_avg /= iterations;
  empty_avg /= iterations;
  query_avg /= iterations;
  mquery_avg /= iterations;
  cout << "Vector AVG: " << vector_avg * 1000 << endl;
  cout << "Empty  AVG: " << empty_avg * 1000 << endl;
  cout << "Clear  AVG: " << clear_avg * 1000 << endl;
  cout << "Vector Tot: " << ( clear_avg + vector_avg ) * 1000 << endl;
  cout << "Query  AVG: " << query_avg * 1000 << endl;
  cout << "MQuery AVG: " << mquery_avg * 1000 << endl;

  renderer->checkOrdering();

  getWindow()->getSignalMouseDown().connect( [=]( MouseEvent &event ) mutable
  {
    if( entity.valid() )
    {
      if( entity.component<SpriteAnimation>() )
      {
        cout << "Removing Sprite Animation component: " << entity << endl;
        entity.remove<SpriteAnimation>();
      }
      else
      {
        cout << "Adding Mesh component: " << entity << endl;
        auto loc = entity.component<Locus>();
        if( loc )
        {
          loc->render_layer = 1000;
        }
        auto mesh = RenderMeshRef{ new RenderMesh{ 4 } };
        // perhaps have a component to hang on to texturing data
        mesh->matchTexture( atlas->get( "dl-0001" ) );
        ColorA color{ 1.0f, 1.0f, 1.0f, 1.0f };
        for( auto &v : mesh->vertices )
        {
          v.color = color;
        }
        entity.assign<RenderMesh>( mesh );
        entity.component<RenderData>()->mesh = mesh;
      }
    }
  });

  mTimer.start();
}

void PupTentApp::update()
{
  double dt = mTimer.getSeconds();
  mTimer.start();
  Timer up;
  up.start();
//  mSystemManager->system<PhysicsSystem>()->stepPhysics(); // could parallelize this with sprite animation and some other things...
//  mSystemManager->update<PhysicsSystem>( dt );
  mSystemManager->update<ExpiresSystem>( dt );
  mSystemManager->update<MovementSystem>( dt );
  mSystemManager->update<SpriteAnimationSystem>( dt );
  mSystemManager->update<ParticleSystem>( dt );
  mSystemManager->update<RenderSystem>( dt );
  double ms = up.getSeconds() * 1000;
  mAverageUpdateTime = (mAverageUpdateTime * 59.0 + ms) / 60.0;
  if( getElapsedFrames() % 90 == 0 )
  {
    cout << "Update: " << mAverageUpdateTime << ", " << ms << endl;
  }
}

void PupTentApp::draw()
{
	gl::clear( Color::black() );
  gl::color( Color::white() );
  Timer dr;
  dr.start();
//  mSystemManager->system<PhysicsSystem>()->debugDraw();
  mSystemManager->system<RenderSystem>()->draw();
  double ms = dr.getSeconds() * 1000;
  mAverageRenderTime = (mAverageRenderTime * 59.0 + ms) / 60.0;
  if( getElapsedFrames() % 90 == 0 )
  {
    cout << "Render: " << mAverageRenderTime << ", " << ms << endl;
  }
}

CINDER_APP_NATIVE( PupTentApp, RendererGl( RendererGl::AA_MSAA_4 ) )
<|endoftext|>