<commit_before>/*
 * Copyright (C) 2004, 2006-2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/// \brief Sample image acquisition urbi client.

/* This simple demonstration program display or save images from an
 * Urbi server.
 */

#include <libport/cstdio>
#include <libport/csignal>

#include <libport/cli.hh>
#include <libport/program-name.hh>
#include <libport/option-parser.hh>
#include <libport/sysexits.hh>

#include <urbi/uconversion.hh>
#include <urbi/usyncclient.hh>

#include "monitor.hh"

using libport::program_name;

size_t imcount;
Monitor* mon = 0;
float scale;
urbi::UImage im;

/* Our callback function */
namespace
{
  static
  urbi::UCallbackAction
  showImage(const urbi::UMessage &msg)
  {
    if (msg.type != urbi::MESSAGE_DATA
        || msg.value->type != urbi::DATA_BINARY
        || msg.value->binary->type != urbi::BINARY_IMAGE)
      return urbi::URBI_CONTINUE;

    urbi::UImage& img = msg.value->binary->image;
    im.width = static_cast<int>(static_cast<float>(img.width) * scale);
    im.height = static_cast<int>(static_cast<float>(img.height) * scale);
    convert(img, im);

    size_t sz = 3*im.width*im.height;
    /* Calculate framerate. */
    if (!(imcount % 20))
      {
        static int tme = 0;
        if (tme)
  	{
  	  float it = msg.client.getCurrentTime() - tme;
  	  it = 20000.0 / it;
  	  printf("***Framerate: %f fps***\n", it);
  	}
        tme = msg.client.getCurrentTime();
      }

    if (!mon)
      mon = new Monitor(im.width, im.height, "image");

    mon->setImage((bits8 *) im.data, sz);
    ++imcount;
    return urbi::URBI_CONTINUE;
  }

  static void
  closeandquit (int)
  {
    delete urbi::getDefaultClient();
    urbi::exit(0);
  }

  static void
  usage(libport::OptionParser& parser)
  {
    std::cout <<
      "usage: " << program_name() << " [options]\n"
      "Display images from an urbi server, or save one image if -o is given\n";
    parser.options_doc(std::cout);
    std::cout << std::endl <<
      "transfer Format : jpeg=transfer jpeg, raw=transfer raw\n"
      "save     Format : rgb , ycrcb, jpeg, ppm"
                << std::endl;
    ::exit(EX_OK);
  }

  static
  int
  format(const std::string& s)
  {
    switch (s[0])
    {
    case 'r': return urbi::IMAGE_RGB;
    case 'y': return urbi::IMAGE_YCbCr;
    case 'p': return urbi::IMAGE_PPM;
    case 'j': return urbi::IMAGE_JPEG;
    default:
      std::cerr << program_name() << ": invalid format :"
                << s << std::endl
                << libport::exit(EX_USAGE);
    };
  }
}

int
main (int argc, char *argv[])
{
  libport::program_initialize(argc, argv);
  signal(SIGINT, closeandquit);
  const char* fileName = 0;
  mon = NULL;
  im.width = im.height = 0;
  im.size = 0;
  im.data = 0;
  im.imageFormat = urbi::IMAGE_RGB;

  libport::OptionValue
    arg_period("query images at given period (in milliseconds)",
               "period", 'p', "PERIOD"),
    arg_jpeg("jpeg compression factor (from 0 to 100, def 70)",
             "jpeg", 'j', "FACTOR"),
    arg_dev("query image on DEVICE.val (default: camera.val)",
            "device", 'd', "DEVICE"),
    arg_out("query and save one image to FILE",
            "output", 'o', "FILE"),
    arg_scale("rescale image with given FACTOR (display only)",
              "scale", 's', "FACTOR"),
    arg_form("select format of the image (rgb, ycrcb, jpeg, ppm)",
             "format", 'F', "FORMAT"),
    arg_resolution("select resolution of the image (0=biggest)",
                   "resolution", 'R', "RESOLUTION");
  libport::OptionFlag
    arg_rec("use reconstruct mode (for aibo)",
            "reconstruct", 'r');

  libport::OptionParser opt_parser;
  opt_parser << "Options:"
	     << libport::opts::help
	     << libport::opts::host
	     << libport::opts::port
	     << arg_period
	     << arg_form
	     << arg_rec
	     << arg_jpeg
	     << arg_dev
	     << arg_out
	     << arg_resolution
	     << arg_scale;

  opt_parser(libport::program_arguments());

  if (libport::opts::help.get())
    usage(opt_parser);

  std::string device = arg_dev.value("camera");

  std::string arg_format;
  if (arg_form.filled())
    arg_format = arg_form.value();
  scale = arg_scale.get<float>(1.0);

  if (arg_out.filled())
    fileName = arg_out.value().c_str();

  urbi::USyncClient
    client(libport::opts::host.value(urbi::UClient::default_host()),
           libport::opts::port.get<int>(urbi::UClient::URBI_PORT));
  if (client.error())
    std::cerr << libport::program_name() << ": client failed to set up"
	      << std::endl
              << libport::exit(1);

  if (1 < client.kernelMajor())
    client.send("var uimg = Channel.new(\"uimg\")|;\n");
  client.setCallback(showImage, "uimg");

  client.send("%s.resolution = %s;\n",
              device.c_str(), arg_resolution.value("0").c_str());
  client.send("%s.jpegfactor = %d;\n",
              device.c_str(), arg_jpeg.get<int>(70));
  client.send("%s.reconstruct = %d;\n",
              device.c_str(), arg_rec.get() ? 1 : 0);

  if (fileName)
  {
    FILE *f = fopen(fileName, "w");
    if (!f)
      std::cerr << program_name() << ": cannot create file " << fileName
                << ": " << strerror(errno)
                << libport::exit(EX_OSERR);

    int fmt = format(arg_format);
    /* Use syncGetImage to save one image to a file. */
    char buff[1000000];
    size_t sz = sizeof buff;
    size_t w, h;
    client.syncGetImage(device.c_str(), buff, sz,
			fmt,
			(fmt == urbi::IMAGE_JPEG
			 ? urbi::URBI_TRANSMIT_JPEG
			 : urbi::URBI_TRANSMIT_YCbCr),
			w, h);
    size_t written = fwrite(buff, 1, sz, f);
    (void) written;
    assert_eq(sz, written);
    fclose(f);
  }
  else
  {
    imcount = 0;
    int fmt = (arg_format[0] == 'r') ? 0 : 1;
    client.send("%s.format = %d;\n", device.c_str(), fmt);
    client.waitForKernelVersion(true);
    if (int period = arg_period.get<int>(0))
      client.send("every (%dms) uimg << %s.val,", period, device.c_str());
    else if (1 < client.kernelMajor())
      client.send("var handle = WeakPointer.new;\n"
                  "%s.getSlot(\"val\").notifyChange(handle, closure() {\n"
                  "  connectionTag:\n"
                  "    this.send(%s.val.asString, \"uimg\")\n"
                  "});",
                  device.c_str(), device.c_str());
    else
      client.send("loop { uimg << %s.val; noop },", device.c_str());
    urbi::execute();
  }

  return 0;
}
<commit_msg>Formatting changes.<commit_after>/*
 * Copyright (C) 2004, 2006-2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/// \brief Sample image acquisition urbi client.

/* This simple demonstration program display or save images from an
 * Urbi server.
 */

#include <libport/cstdio>
#include <libport/csignal>

#include <libport/cli.hh>
#include <libport/program-name.hh>
#include <libport/option-parser.hh>
#include <libport/sysexits.hh>

#include <urbi/uconversion.hh>
#include <urbi/usyncclient.hh>

#include "monitor.hh"

using libport::program_name;

size_t imcount;
Monitor* mon = 0;
float scale;
urbi::UImage im;

/* Our callback function */
namespace
{
  static
  urbi::UCallbackAction
  showImage(const urbi::UMessage &msg)
  {
    if (msg.type != urbi::MESSAGE_DATA
        || msg.value->type != urbi::DATA_BINARY
        || msg.value->binary->type != urbi::BINARY_IMAGE)
      return urbi::URBI_CONTINUE;

    urbi::UImage& img = msg.value->binary->image;
    im.width = static_cast<int>(static_cast<float>(img.width) * scale);
    im.height = static_cast<int>(static_cast<float>(img.height) * scale);
    convert(img, im);

    size_t sz = 3*im.width*im.height;
    /* Calculate framerate. */
    if (!(imcount % 20))
      {
        static int tme = 0;
        if (tme)
        {
          float it = msg.client.getCurrentTime() - tme;
          it = 20000.0 / it;
          printf("***Framerate: %f fps***\n", it);
        }
        tme = msg.client.getCurrentTime();
      }

    if (!mon)
      mon = new Monitor(im.width, im.height, "image");

    mon->setImage((bits8 *) im.data, sz);
    ++imcount;
    return urbi::URBI_CONTINUE;
  }

  static void
  closeandquit (int)
  {
    delete urbi::getDefaultClient();
    urbi::exit(0);
  }

  static void
  usage(libport::OptionParser& parser)
  {
    std::cout <<
      "usage: " << program_name() << " [options]\n"
      "Display images from an urbi server, or save one image if -o is given\n";
    parser.options_doc(std::cout);
    std::cout << std::endl <<
      "transfer Format : jpeg=transfer jpeg, raw=transfer raw\n"
      "save     Format : rgb , ycrcb, jpeg, ppm"
                << std::endl;
    ::exit(EX_OK);
  }

  static
  int
  format(const std::string& s)
  {
    switch (s[0])
    {
    case 'r': return urbi::IMAGE_RGB;
    case 'y': return urbi::IMAGE_YCbCr;
    case 'p': return urbi::IMAGE_PPM;
    case 'j': return urbi::IMAGE_JPEG;
    default:
      std::cerr << program_name() << ": invalid format :"
                << s << std::endl
                << libport::exit(EX_USAGE);
    };
  }
}

int
main (int argc, char *argv[])
{
  libport::program_initialize(argc, argv);
  signal(SIGINT, closeandquit);
  const char* fileName = 0;
  mon = NULL;
  im.width = im.height = 0;
  im.size = 0;
  im.data = 0;
  im.imageFormat = urbi::IMAGE_RGB;

  libport::OptionValue
    arg_period("query images at given period (in milliseconds)",
               "period", 'p', "PERIOD"),
    arg_jpeg("jpeg compression factor (from 0 to 100, def 70)",
             "jpeg", 'j', "FACTOR"),
    arg_dev("query image on DEVICE.val (default: camera.val)",
            "device", 'd', "DEVICE"),
    arg_out("query and save one image to FILE",
            "output", 'o', "FILE"),
    arg_scale("rescale image with given FACTOR (display only)",
              "scale", 's', "FACTOR"),
    arg_form("select format of the image (rgb, ycrcb, jpeg, ppm)",
             "format", 'F', "FORMAT"),
    arg_resolution("select resolution of the image (0=biggest)",
                   "resolution", 'R', "RESOLUTION");
  libport::OptionFlag
    arg_rec("use reconstruct mode (for aibo)",
            "reconstruct", 'r');

  libport::OptionParser opt_parser;
  opt_parser << "Options:"
	     << libport::opts::help
	     << libport::opts::host
	     << libport::opts::port
	     << arg_period
	     << arg_form
	     << arg_rec
	     << arg_jpeg
	     << arg_dev
	     << arg_out
	     << arg_resolution
	     << arg_scale;

  opt_parser(libport::program_arguments());

  if (libport::opts::help.get())
    usage(opt_parser);

  std::string device = arg_dev.value("camera");

  std::string arg_format;
  if (arg_form.filled())
    arg_format = arg_form.value();
  scale = arg_scale.get<float>(1.0);

  if (arg_out.filled())
    fileName = arg_out.value().c_str();

  urbi::USyncClient
    client(libport::opts::host.value(urbi::UClient::default_host()),
           libport::opts::port.get<int>(urbi::UClient::URBI_PORT));
  if (client.error())
    std::cerr << libport::program_name() << ": client failed to set up"
	      << std::endl
              << libport::exit(1);

  if (1 < client.kernelMajor())
    client.send("var uimg = Channel.new(\"uimg\")|;\n");
  client.setCallback(showImage, "uimg");

  client.send("%s.resolution = %s;\n",
              device.c_str(), arg_resolution.value("0").c_str());
  client.send("%s.jpegfactor = %d;\n",
              device.c_str(), arg_jpeg.get<int>(70));
  client.send("%s.reconstruct = %d;\n",
              device.c_str(), arg_rec.get() ? 1 : 0);

  if (fileName)
  {
    FILE *f = fopen(fileName, "w");
    if (!f)
      std::cerr << program_name() << ": cannot create file " << fileName
                << ": " << strerror(errno)
                << libport::exit(EX_OSERR);

    int fmt = format(arg_format);
    /* Use syncGetImage to save one image to a file. */
    char buff[1000000];
    size_t sz = sizeof buff;
    size_t w, h;
    client.syncGetImage(device.c_str(), buff, sz,
			fmt,
			(fmt == urbi::IMAGE_JPEG
			 ? urbi::URBI_TRANSMIT_JPEG
			 : urbi::URBI_TRANSMIT_YCbCr),
			w, h);
    size_t written = fwrite(buff, 1, sz, f);
    (void) written;
    assert_eq(sz, written);
    fclose(f);
  }
  else
  {
    imcount = 0;
    int fmt = (arg_format[0] == 'r') ? 0 : 1;
    client.send("%s.format = %d;\n", device.c_str(), fmt);
    client.waitForKernelVersion(true);
    if (int period = arg_period.get<int>(0))
      client.send("every (%dms) uimg << %s.val,", period, device.c_str());
    else if (1 < client.kernelMajor())
      client.send("var handle = WeakPointer.new;\n"
                  "%s.getSlot(\"val\").notifyChange(handle, closure() {\n"
                  "  connectionTag:\n"
                  "    this.send(%s.val.asString, \"uimg\")\n"
                  "});",
                  device.c_str(), device.c_str());
    else
      client.send("loop { uimg << %s.val; noop },", device.c_str());
    urbi::execute();
  }

  return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: JoinTableView.hxx,v $
 *
 *  $Revision: 1.23 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 15:29:33 $
 *
 *  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 DBAUI_JOINTABLEVIEW_HXX
#define DBAUI_JOINTABLEVIEW_HXX

#ifndef _SV_WINDOW_HXX
#include <vcl/window.hxx>
#endif
#ifndef _SV_TIMER_HXX
#include <vcl/timer.hxx>
#endif
#ifndef _SV_SCRBAR_HXX
#include <vcl/scrbar.hxx>
#endif
#ifndef _RTTI_HXX
#include <tools/rtti.hxx>
#endif
#ifndef _TRANSFER_HXX
#include <svtools/transfer.hxx>
#endif

#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif
#ifndef _DBACCESS_UI_CALLBACKS_HXX_
#include "callbacks.hxx"
#endif

#include <memory>
#include <vector>

struct AcceptDropEvent;
struct ExecuteDropEvent;
class SfxUndoAction;
namespace dbaui
{
    class OTableConnection;
    class OTableWindow;
    struct OJoinExchangeData;
    class OJoinDesignView;
    class OTableWindowData;
    class OJoinDesignViewAccess;

    // this class conatins only the scrollbars to avoid that the tablewindows clip the scrollbars
    class OJoinTableView;
    class OScrollWindowHelper : public Window
    {
        ScrollBar           m_aHScrollBar;
        ScrollBar           m_aVScrollBar;
        Window*             m_pCornerWindow;
        OJoinTableView*     m_pTableView;

    protected:
        virtual void Resize();
    public:
        OScrollWindowHelper( Window* pParent);
        ~OScrollWindowHelper();

        void setTableView(OJoinTableView* _pTableView);

        // own methods
        ScrollBar* GetHScrollBar() { return &m_aHScrollBar; }
        ScrollBar* GetVScrollBar() { return &m_aVScrollBar; }
    };

    class OJoinTableView :  public Window
                            ,public IDragTransferableListener
                            ,public DropTargetHelper
    {
        friend class OJoinMoveTabWinUndoAct;
    public:
        DECLARE_STL_USTRINGACCESS_MAP(OTableWindow*,OTableWindowMap);
    private:
        OTableWindowMap     m_aTableMap;
        ::std::vector<OTableConnection*>    m_vTableConnection;

        Timer               m_aDragScrollTimer;
        Rectangle           m_aDragRect;
        Rectangle           m_aSizingRect;
        Point               m_aDragOffset;
        Point               m_aScrollOffset;
        Point               m_ptPrevDraggingPos;
        Size                m_aOutputSize;

        OTableWindow*           m_pDragWin;
        OTableWindow*           m_pSizingWin;
        OTableConnection*       m_pSelectedConn;

        BOOL                    m_bTrackingInitiallyMoved;

        DECL_LINK(OnDragScrollTimer, void*);

    protected:
        OTableWindow*               m_pLastFocusTabWin;
        OJoinDesignView*            m_pView;
        OJoinDesignViewAccess*      m_pAccessible;

    public:
        TYPEINFO();
        OJoinTableView( Window* pParent, OJoinDesignView* pView );
        virtual ~OJoinTableView();

        // window override
        virtual void StateChanged( StateChangedType nStateChange );
        virtual void GetFocus();
        virtual void LoseFocus();
        virtual void KeyInput( const KeyEvent& rEvt );
        // Accessibility
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible();

        // own methods
        ScrollBar* GetHScrollBar() { return static_cast<OScrollWindowHelper*>(GetParent())->GetHScrollBar(); }
        ScrollBar* GetVScrollBar() { return static_cast<OScrollWindowHelper*>(GetParent())->GetVScrollBar(); }
        DECL_LINK( ScrollHdl, ScrollBar* );

        void DrawConnections( const Rectangle& rRect );
        void InvalidateConnections();

        void BeginChildMove( OTableWindow* pTabWin, const Point& rMousePos );
        void BeginChildSizing( OTableWindow* pTabWin, const Pointer& rPointer );

        void NotifyTitleClicked( OTableWindow* pTabWin, const Point rMousePos );

        virtual void AddTabWin(const ::rtl::OUString& _rComposedName, const ::rtl::OUString& rWinName, BOOL bNewTable = FALSE);
        virtual void RemoveTabWin( OTableWindow* pTabWin );

        // alle TabWins verstecken (NICHT loeschen, sie werden in eine Undo-Action gepackt)
        virtual void    HideTabWins();

        virtual void AddConnection(const OJoinExchangeData& jxdSource, const OJoinExchangeData& jxdDest);

        /** RemoveConnection allows to remove connections from join table view, it implies that the same as addConnection

            @param  _pConnection
                    the connection which should be removed
            @param  _bDelete
                    when truie then the connection will be deleted

            @return an iterator to next valid connection, so it can be used in any loop
        */
        virtual ::std::vector<OTableConnection*>::const_iterator RemoveConnection(OTableConnection* _pConnection,sal_Bool _bDelete);

        /** allows to add new connections to join table view, it implies an invalidation of the features
            ID_BROWSER_ADDTABLE and SID_RELATION_ADD_RELATION also the modified flag will be set to true
            @param  _pConnection
                    the connection which should be added
            @param  _bAddData
                    <TRUE/> when the data should also be appended
        */
        void addConnection(OTableConnection* _pConnection,sal_Bool _bAddData = sal_True);

        BOOL            Scroll( long nDelta, BOOL bHoriz, BOOL bPaintScrollBars );
        ULONG           GetTabWinCount();
        Point           GetScrollOffset() const { return m_aScrollOffset; }

        OJoinDesignView*            getDesignView() const { return m_pView; }
        OTableWindow*               GetWindow( const String& rName );

        OTableConnection*           GetSelectedConn() { return m_pSelectedConn; }
        void                        DeselectConn(OTableConnection* pConn);  // NULL ist ausdruecklich zugelassen, dann passiert nichts
        void                        SelectConn(OTableConnection* pConn);

        OTableWindowMap*            GetTabWinMap() { return &m_aTableMap; }
        const OTableWindowMap*      GetTabWinMap() const { return &m_aTableMap; }

        /** gives a read only access to the connection vector
        */
        const ::std::vector<OTableConnection*>* getTableConnections() const { return &m_vTableConnection; }

        BOOL                        ExistsAConn(const OTableWindow* pFromWin) const;

        /** getTableConnections searchs for all connections of a table
            @param  _pFromWin   the table for which connections should be found

            @return an iterator which can be used to travel all connections of the table
        */
        ::std::vector<OTableConnection*>::const_iterator getTableConnections(const OTableWindow* _pFromWin) const;

        /** getConnectionCount returns how many connection belongs to single table
            @param  _pFromWin   the table for which connections should be found

            @return the count of connections wich belongs to this table
        */
        sal_Int32 getConnectionCount(const OTableWindow* _pFromWin) const;

        OTableConnection*           GetTabConn(const OTableWindow* pLhs,const OTableWindow* pRhs,const OTableConnection* _rpFirstAfter = NULL) const;

        // clears the window map and connection vector without destroying it
        // that means teh data of the windows and connection will be untouched
        void clearLayoutInformation();

        // set the focus to that tab win which most recently had it (or to the first available one)
        void GrabTabWinFocus();

        // ReSync ist dazu gedacht, aus dem Dokument alle WinData und ConnData zu holen und entsprechend Wins und Conns anzulegen
        virtual void ReSync() { }
        // ClearAll implementiert ein hartes Loeschen, es werden alle Conns und alle Wins aus ihren jeweiligen Listen geloescht
        // sowie die entsprechenden Datas aus dem Dokument ausgetragen
        virtual void ClearAll();

        // wird vom AddTabDlg benutzt, um festzustellen, ob noch Tabellen hinzugefuegt werden duerfen
        virtual BOOL IsAddAllowed();
        virtual long PreNotify(NotifyEvent& rNEvt);

        // DnD stuff
        virtual void        StartDrag( sal_Int8 nAction, const Point& rPosPixel );
        virtual sal_Int8    AcceptDrop( const AcceptDropEvent& rEvt );
        virtual sal_Int8    ExecuteDrop( const ExecuteDropEvent& rEvt );

        /**
            can be used in derevied classes to make some special ui handling
            after d&d
        */
        virtual void lookForUiActivities();

        // wird nach Verschieben/Groessenaenderung der TabWins aufgerufen (die Standardimplementation reicht die neuen Daten einfach
        // an die Daten des Wins weiter)
        virtual void TabWinMoved(OTableWindow* ptWhich, const Point& ptOldPosition);
            // die Position ist "virtuell" : der Container hat sozusagen eine virtuelle Flaeche, von der immer nur ein bestimmter Bereich
            // - der mittels der Scrollbar veraendert werden kann - zu sehen ist. Insbesondere hat ptOldPosition immer positive Koordinaten,
            // auch wenn er einen Punkt oberhalb des aktuell sichtbaren Bereichs bezeichnet, dessen physische Ordinate eigentlich
            // negativ ist.
        virtual void TabWinSized(OTableWindow* ptWhich, const Point& ptOldPosition, const Size& szOldSize);

        void modified();

        /** returns if teh given window is visible.
            @param  _rPoint
                The Point to check
            @param  _rSize
                The Size to be check as well
            @return
                <TRUE/> if the area is visible otherwise <FALSE/>

        */
        BOOL isMovementAllowed(const Point& _rPoint,const Size& _rSize);

        Size getRealOutputSize() const { return m_aOutputSize; }

        virtual void EnsureVisible(const OTableWindow* _pWin);
        virtual void EnsureVisible(const Point& _rPoint,const Size& _rSize);

    protected:
        virtual void MouseButtonUp( const MouseEvent& rEvt );
        virtual void MouseButtonDown( const MouseEvent& rEvt );
        virtual void Tracking( const TrackingEvent& rTEvt );
        virtual void Paint( const Rectangle& rRect );
        virtual void ConnDoubleClicked( OTableConnection* pConnection );
        virtual void SetDefaultTabWinPosSize( OTableWindow* pTabWin );
        virtual void DataChanged( const DataChangedEvent& rDCEvt );

        virtual void Resize();

        virtual void dragFinished( );
        // hier ist die Position (die sich waehrend des Sizings aendern kann) physisch, da waehrend des Sizens nicht gescrollt wird
        virtual void Command(const CommandEvent& rEvt);

        virtual OTableWindowData* CreateImpl(const ::rtl::OUString& _rComposedName,
                                             const ::rtl::OUString& _rWinName);

        /** factory method to create table windows
            @param  _pData
                The data corresponding to the window.
            @return
                The new TableWindow
        */
        virtual OTableWindow* createWindow(OTableWindowData* _pData) = 0;

    private:
        void    InitColors();
        BOOL    ScrollWhileDragging();

        /** executePopup opens the context menu to delate a connection
            @param  _aPos               the position where the popup menu should appear
            @param  _pSelConnection     the connection which should be deleted
        */
        void executePopup(const Point& _aPos,OTableConnection* _pSelConnection);

        /** invalidateAndModify invalidates this window without children and
            set the controller modified
            @param  _pAction a possible undo action to add at the controller
        */
        void invalidateAndModify(SfxUndoAction *_pAction=NULL);
    };
}
#endif // DBAUI_JOINTABLEVIEW_HXX
<commit_msg>INTEGRATION: CWS warnings01 (1.23.48); FILE MERGED 2006/03/24 15:36:15 fs 1.23.48.1: #i57457# warning-free code (unxlngi6/.pro + unxsoli4.pro)<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: JoinTableView.hxx,v $
 *
 *  $Revision: 1.24 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 03:12:15 $
 *
 *  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 DBAUI_JOINTABLEVIEW_HXX
#define DBAUI_JOINTABLEVIEW_HXX

#ifndef _SV_WINDOW_HXX
#include <vcl/window.hxx>
#endif
#ifndef _SV_TIMER_HXX
#include <vcl/timer.hxx>
#endif
#ifndef _SV_SCRBAR_HXX
#include <vcl/scrbar.hxx>
#endif
#ifndef _RTTI_HXX
#include <tools/rtti.hxx>
#endif
#ifndef _TRANSFER_HXX
#include <svtools/transfer.hxx>
#endif

#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif
#ifndef _DBACCESS_UI_CALLBACKS_HXX_
#include "callbacks.hxx"
#endif

#include <memory>
#include <vector>

struct AcceptDropEvent;
struct ExecuteDropEvent;
class SfxUndoAction;
namespace dbaui
{
    class OTableConnection;
    class OTableWindow;
    struct OJoinExchangeData;
    class OJoinDesignView;
    class OTableWindowData;
    class OJoinDesignViewAccess;

    // this class conatins only the scrollbars to avoid that the tablewindows clip the scrollbars
    class OJoinTableView;
    class OScrollWindowHelper : public Window
    {
        ScrollBar           m_aHScrollBar;
        ScrollBar           m_aVScrollBar;
        Window*             m_pCornerWindow;
        OJoinTableView*     m_pTableView;

    protected:
        virtual void Resize();
    public:
        OScrollWindowHelper( Window* pParent);
        ~OScrollWindowHelper();

        void setTableView(OJoinTableView* _pTableView);

        // own methods
        ScrollBar* GetHScrollBar() { return &m_aHScrollBar; }
        ScrollBar* GetVScrollBar() { return &m_aVScrollBar; }
    };

    class OJoinTableView :  public Window
                            ,public IDragTransferableListener
                            ,public DropTargetHelper
    {
        friend class OJoinMoveTabWinUndoAct;
    public:
        DECLARE_STL_USTRINGACCESS_MAP(OTableWindow*,OTableWindowMap);
    private:
        OTableWindowMap     m_aTableMap;
        ::std::vector<OTableConnection*>    m_vTableConnection;

        Timer               m_aDragScrollTimer;
        Rectangle           m_aDragRect;
        Rectangle           m_aSizingRect;
        Point               m_aDragOffset;
        Point               m_aScrollOffset;
        Point               m_ptPrevDraggingPos;
        Size                m_aOutputSize;

        OTableWindow*           m_pDragWin;
        OTableWindow*           m_pSizingWin;
        OTableConnection*       m_pSelectedConn;

        BOOL                    m_bTrackingInitiallyMoved;

        DECL_LINK(OnDragScrollTimer, void*);

    protected:
        OTableWindow*               m_pLastFocusTabWin;
        OJoinDesignView*            m_pView;
        OJoinDesignViewAccess*      m_pAccessible;

    public:
        TYPEINFO();
        OJoinTableView( Window* pParent, OJoinDesignView* pView );
        virtual ~OJoinTableView();

        // window override
        virtual void StateChanged( StateChangedType nStateChange );
        virtual void GetFocus();
        virtual void LoseFocus();
        virtual void KeyInput( const KeyEvent& rEvt );
        // Accessibility
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible();

        // own methods
        ScrollBar* GetHScrollBar() { return static_cast<OScrollWindowHelper*>(GetParent())->GetHScrollBar(); }
        ScrollBar* GetVScrollBar() { return static_cast<OScrollWindowHelper*>(GetParent())->GetVScrollBar(); }
        DECL_LINK( ScrollHdl, ScrollBar* );

        void DrawConnections( const Rectangle& rRect );
        void InvalidateConnections();

        void BeginChildMove( OTableWindow* pTabWin, const Point& rMousePos );
        void BeginChildSizing( OTableWindow* pTabWin, const Pointer& rPointer );

        void NotifyTitleClicked( OTableWindow* pTabWin, const Point rMousePos );

        virtual void AddTabWin(const ::rtl::OUString& _rComposedName, const ::rtl::OUString& rWinName, BOOL bNewTable = FALSE);
        virtual void RemoveTabWin( OTableWindow* pTabWin );

        // alle TabWins verstecken (NICHT loeschen, sie werden in eine Undo-Action gepackt)
        virtual void    HideTabWins();

        virtual void AddConnection(const OJoinExchangeData& jxdSource, const OJoinExchangeData& jxdDest) = 0;

        /** RemoveConnection allows to remove connections from join table view, it implies that the same as addConnection

            @param  _pConnection
                    the connection which should be removed
            @param  _bDelete
                    when truie then the connection will be deleted

            @return an iterator to next valid connection, so it can be used in any loop
        */
        virtual ::std::vector<OTableConnection*>::const_iterator RemoveConnection(OTableConnection* _pConnection,sal_Bool _bDelete);

        /** allows to add new connections to join table view, it implies an invalidation of the features
            ID_BROWSER_ADDTABLE and SID_RELATION_ADD_RELATION also the modified flag will be set to true
            @param  _pConnection
                    the connection which should be added
            @param  _bAddData
                    <TRUE/> when the data should also be appended
        */
        void addConnection(OTableConnection* _pConnection,sal_Bool _bAddData = sal_True);

        BOOL            ScrollPane( long nDelta, BOOL bHoriz, BOOL bPaintScrollBars );
        ULONG           GetTabWinCount();
        Point           GetScrollOffset() const { return m_aScrollOffset; }

        OJoinDesignView*            getDesignView() const { return m_pView; }
        OTableWindow*               GetTabWindow( const String& rName );

        OTableConnection*           GetSelectedConn() { return m_pSelectedConn; }
        void                        DeselectConn(OTableConnection* pConn);  // NULL ist ausdruecklich zugelassen, dann passiert nichts
        void                        SelectConn(OTableConnection* pConn);

        OTableWindowMap*            GetTabWinMap() { return &m_aTableMap; }
        const OTableWindowMap*      GetTabWinMap() const { return &m_aTableMap; }

        /** gives a read only access to the connection vector
        */
        const ::std::vector<OTableConnection*>* getTableConnections() const { return &m_vTableConnection; }

        BOOL                        ExistsAConn(const OTableWindow* pFromWin) const;

        /** getTableConnections searchs for all connections of a table
            @param  _pFromWin   the table for which connections should be found

            @return an iterator which can be used to travel all connections of the table
        */
        ::std::vector<OTableConnection*>::const_iterator getTableConnections(const OTableWindow* _pFromWin) const;

        /** getConnectionCount returns how many connection belongs to single table
            @param  _pFromWin   the table for which connections should be found

            @return the count of connections wich belongs to this table
        */
        sal_Int32 getConnectionCount(const OTableWindow* _pFromWin) const;

        OTableConnection*           GetTabConn(const OTableWindow* pLhs,const OTableWindow* pRhs,const OTableConnection* _rpFirstAfter = NULL) const;

        // clears the window map and connection vector without destroying it
        // that means teh data of the windows and connection will be untouched
        void clearLayoutInformation();

        // set the focus to that tab win which most recently had it (or to the first available one)
        void GrabTabWinFocus();

        // ReSync ist dazu gedacht, aus dem Dokument alle WinData und ConnData zu holen und entsprechend Wins und Conns anzulegen
        virtual void ReSync() { }
        // ClearAll implementiert ein hartes Loeschen, es werden alle Conns und alle Wins aus ihren jeweiligen Listen geloescht
        // sowie die entsprechenden Datas aus dem Dokument ausgetragen
        virtual void ClearAll();

        // wird vom AddTabDlg benutzt, um festzustellen, ob noch Tabellen hinzugefuegt werden duerfen
        virtual BOOL IsAddAllowed();
        virtual long PreNotify(NotifyEvent& rNEvt);

        // DnD stuff
        virtual void        StartDrag( sal_Int8 nAction, const Point& rPosPixel );
        virtual sal_Int8    AcceptDrop( const AcceptDropEvent& rEvt );
        virtual sal_Int8    ExecuteDrop( const ExecuteDropEvent& rEvt );

        /**
            can be used in derevied classes to make some special ui handling
            after d&d
        */
        virtual void lookForUiActivities();

        // wird nach Verschieben/Groessenaenderung der TabWins aufgerufen (die Standardimplementation reicht die neuen Daten einfach
        // an die Daten des Wins weiter)
        virtual void TabWinMoved(OTableWindow* ptWhich, const Point& ptOldPosition);
            // die Position ist "virtuell" : der Container hat sozusagen eine virtuelle Flaeche, von der immer nur ein bestimmter Bereich
            // - der mittels der Scrollbar veraendert werden kann - zu sehen ist. Insbesondere hat ptOldPosition immer positive Koordinaten,
            // auch wenn er einen Punkt oberhalb des aktuell sichtbaren Bereichs bezeichnet, dessen physische Ordinate eigentlich
            // negativ ist.
        virtual void TabWinSized(OTableWindow* ptWhich, const Point& ptOldPosition, const Size& szOldSize);

        void modified();

        /** returns if teh given window is visible.
            @param  _rPoint
                The Point to check
            @param  _rSize
                The Size to be check as well
            @return
                <TRUE/> if the area is visible otherwise <FALSE/>

        */
        BOOL isMovementAllowed(const Point& _rPoint,const Size& _rSize);

        Size getRealOutputSize() const { return m_aOutputSize; }

        virtual void EnsureVisible(const OTableWindow* _pWin);
        virtual void EnsureVisible(const Point& _rPoint,const Size& _rSize);

    protected:
        virtual void MouseButtonUp( const MouseEvent& rEvt );
        virtual void MouseButtonDown( const MouseEvent& rEvt );
        virtual void Tracking( const TrackingEvent& rTEvt );
        virtual void Paint( const Rectangle& rRect );
        virtual void ConnDoubleClicked( OTableConnection* pConnection );
        virtual void SetDefaultTabWinPosSize( OTableWindow* pTabWin );
        virtual void DataChanged( const DataChangedEvent& rDCEvt );

        virtual void Resize();

        virtual void dragFinished( );
        // hier ist die Position (die sich waehrend des Sizings aendern kann) physisch, da waehrend des Sizens nicht gescrollt wird
        virtual void Command(const CommandEvent& rEvt);

        virtual OTableWindowData* CreateImpl(const ::rtl::OUString& _rComposedName,
                                             const ::rtl::OUString& _rWinName);

        /** factory method to create table windows
            @param  _pData
                The data corresponding to the window.
            @return
                The new TableWindow
        */
        virtual OTableWindow* createWindow(OTableWindowData* _pData) = 0;

    private:
        void    InitColors();
        BOOL    ScrollWhileDragging();

        /** executePopup opens the context menu to delate a connection
            @param  _aPos               the position where the popup menu should appear
            @param  _pSelConnection     the connection which should be deleted
        */
        void executePopup(const Point& _aPos,OTableConnection* _pSelConnection);

        /** invalidateAndModify invalidates this window without children and
            set the controller modified
            @param  _pAction a possible undo action to add at the controller
        */
        void invalidateAndModify(SfxUndoAction *_pAction=NULL);

    private:
        using Window::Scroll;
    };
}
#endif // DBAUI_JOINTABLEVIEW_HXX
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2011 Francois Beaune
//
// 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.
//

// Interface header.
#include "drt.h"

// appleseed.renderer headers.
#include "renderer/kernel/lighting/directlighting.h"
#include "renderer/kernel/lighting/imagebasedlighting.h"
#include "renderer/kernel/lighting/lightsampler.h"
#include "renderer/kernel/lighting/pathtracer.h"
#include "renderer/kernel/shading/shadingcontext.h"
#include "renderer/kernel/shading/shadingpoint.h"
#include "renderer/modeling/bsdf/bsdf.h"
#include "renderer/modeling/edf/edf.h"
#include "renderer/modeling/environment/environment.h"
#include "renderer/modeling/input/inputevaluator.h"
#include "renderer/modeling/material/material.h"
#include "renderer/modeling/scene/scene.h"

// appleseed.foundation headers.
#include "foundation/math/basis.h"
#include "foundation/math/mis.h"
#include "foundation/math/population.h"
#include "foundation/utility/memory.h"
#include "foundation/utility/string.h"

// Forward declarations.
namespace renderer  { class EnvironmentEDF; }
namespace renderer  { class InputParams; }

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Distribution Ray Tracing (DRT) lighting engine.
    //

    class DRTLightingEngine
      : public ILightingEngine
    {
      public:
        DRTLightingEngine(
            const LightSampler&     light_sampler,
            const ParamArray&       params)
          : m_params(params)
          , m_light_sampler(light_sampler)
        {
        }

        ~DRTLightingEngine()
        {
            RENDERER_LOG_DEBUG(
                "distribution ray tracing statistics:\n"
                "  paths            %s\n"
                "  ray tree depth   avg %.1f  min %s  max %s  dev %.1f\n",
                pretty_uint(m_stats.m_path_count).c_str(),
                m_stats.m_ray_tree_depth.get_avg(),
                pretty_uint(m_stats.m_ray_tree_depth.get_min()).c_str(),
                pretty_uint(m_stats.m_ray_tree_depth.get_max()).c_str(),
                m_stats.m_ray_tree_depth.get_dev());
        }

        virtual void release()
        {
            delete this;
        }

        virtual void compute_lighting(
            SamplingContext&        sampling_context,
            const ShadingContext&   shading_context,
            const ShadingPoint&     shading_point,
            Spectrum&               radiance)   // output radiance, in W.sr^-1.m^-2
        {
            typedef PathTracer<
                PathVisitor,
                BSDF::Glossy | BSDF::Specular,
                false                           // not adjoint
            > PathTracer;

            PathVisitor path_visitor(
                m_params,
                m_light_sampler,
                m_light_samples,
                shading_context,
                shading_point.get_scene(),
                radiance);

            PathTracer path_tracer(
                path_visitor,
                m_params.m_minimum_path_length);

            const size_t path_length =
                path_tracer.trace(
                    sampling_context,
                    shading_context.get_intersector(),
                    shading_context.get_texture_cache(),
                    shading_point);

            // Update statistics.
            ++m_stats.m_path_count;
            m_stats.m_ray_tree_depth.insert(path_length);
        }

      private:
        struct Parameters
        {
            const size_t        m_minimum_path_length;      // minimum path length before Russian Roulette is used
            const size_t        m_dl_sample_count;          // number of samples used to estimate direct illumination
            const size_t        m_ibl_bsdf_sample_count;    // number of samples (in BSDF sampling) used to estimate IBL
            const size_t        m_ibl_env_sample_count;     // number of samples (in environment sampling) used to estimate IBL

            // Constructor, extract parameters.
            explicit Parameters(const ParamArray& params)
              : m_minimum_path_length   ( params.get_optional<size_t>("minimum_path_length", 3) )
              , m_dl_sample_count       ( params.get_optional<size_t>("dl_samples", 1) )
              , m_ibl_bsdf_sample_count ( params.get_optional<size_t>("ibl_bsdf_samples", 2) )
              , m_ibl_env_sample_count  ( params.get_optional<size_t>("ibl_env_samples", 2) )
            {
            }
        };

        struct Statistics
        {
            uint64              m_path_count;               // number of paths
            Population<size_t>  m_ray_tree_depth;           // ray tree depth

            Statistics()
              : m_path_count(0)
            {
            }
        };

        class PathVisitor
        {
          public:
            PathVisitor(
                const Parameters&       params,
                const LightSampler&     light_sampler,
                LightSampleVector&      light_samples,
                const ShadingContext&   shading_context,
                const Scene&            scene,
                Spectrum&               path_radiance)
              : m_params(params)
              , m_light_sampler(light_sampler)
              , m_light_samples(light_samples)
              , m_shading_context(shading_context)
              , m_texture_cache(shading_context.get_texture_cache())
              , m_path_radiance(path_radiance)
            {
                const Environment* environment = scene.get_environment();
                m_env_edf = environment ? environment->get_environment_edf() : 0;

                m_path_radiance.set(0.0f);
            }

            bool visit_vertex(
                SamplingContext&        sampling_context,
                const ShadingPoint&     shading_point,
                const Vector3d&         outgoing,
                const BSDF*             bsdf,
                const void*             bsdf_data,
                const BSDF::Mode        bsdf_mode,
                const double            bsdf_prob,
                const Spectrum&         throughput)
            {
                const Vector3d& point = shading_point.get_point();
                const Vector3d& geometric_normal = shading_point.get_geometric_normal();
                const Vector3d& shading_normal = shading_point.get_shading_normal();
                const Basis3d& shading_basis = shading_point.get_shading_basis();
                const Material* material = shading_point.get_material();
                const InputParams& input_params = shading_point.get_input_params();

                // Generate light samples.
                clear_keep_memory(m_light_samples);
                m_light_sampler.sample(
                    sampling_context,
                    m_params.m_dl_sample_count,
                    m_light_samples);

                // Compute direct lighting.
                Spectrum vertex_radiance;
                compute_direct_lighting(
                    sampling_context,
                    m_shading_context,
                    point,
                    geometric_normal,
                    shading_basis,
                    outgoing,
                    *bsdf,
                    bsdf_data,
                    m_light_samples,
                    vertex_radiance,
                    &shading_point);

                if (m_env_edf)
                {
                    // Compute image-based lighting.
                    Spectrum ibl_radiance;
                    compute_image_based_lighting(
                        sampling_context,
                        m_shading_context,
                        *m_env_edf,
                        point,
                        geometric_normal,
                        shading_basis,
                        outgoing,
                        *bsdf,
                        bsdf_data,
                        m_params.m_ibl_bsdf_sample_count,
                        m_params.m_ibl_env_sample_count,
                        ibl_radiance,
                        &shading_point);
                    vertex_radiance += ibl_radiance;
                }

                // Retrieve the EDF.
                const EDF* edf = material->get_edf();

                if (edf)
                {
                    // Evaluate the input values of the EDF (if any).
                    InputEvaluator edf_input_evaluator(m_texture_cache);
                    const void* edf_data =
                        edf_input_evaluator.evaluate(
                            edf->get_inputs(),
                            input_params);

                    // Compute the emitted radiance.
                    Spectrum emitted_radiance;
                    edf->evaluate(
                        edf_data,
                        geometric_normal,
                        shading_basis,
                        outgoing,
                        emitted_radiance);

                    const double distance = shading_point.get_distance();

                    if (bsdf_mode != BSDF::Specular && distance > 0.0)
                    {
                        // Compute the probability density with respect to surface area
                        // of choosing this point through sampling of the light sources.
                        const double sample_probability =
                            m_light_sampler.evaluate_pdf(shading_point);

                        // Compute the probability density with respect to surface area
                        // of the direction obtained through sampling of the BSDF.
                        double px = bsdf_prob;
                        px *= max(dot(outgoing, shading_normal), 0.0);
                        px /= square(distance);

                        // Multiply the emitted radiance by the MIS weight.
                        const double mis_weight = mis_power2(px, sample_probability);
                        emitted_radiance *= static_cast<float>(mis_weight);
                    }

                    vertex_radiance += emitted_radiance;
                }

                // Update the path radiance.
                vertex_radiance *= throughput;
                m_path_radiance += vertex_radiance;

                // Proceed with this path.
                return true;
            }

            void visit_environment(
                const ShadingPoint&     shading_point,
                const Vector3d&         outgoing,
                const Spectrum&         throughput)
            {
            }

          private:
            const Parameters&       m_params;
            const LightSampler&     m_light_sampler;
            LightSampleVector&      m_light_samples;
            const ShadingContext&   m_shading_context;
            TextureCache&           m_texture_cache;
            const EnvironmentEDF*   m_env_edf;
            Spectrum&               m_path_radiance;
        };

        const Parameters        m_params;
        Statistics              m_stats;
        const LightSampler&     m_light_sampler;
        LightSampleVector       m_light_samples;
    };
}

//
// DRTLightingEngineFactory class implementation.
//

DRTLightingEngineFactory::DRTLightingEngineFactory(
    const LightSampler& light_sampler,
    const ParamArray&   params)
  : m_light_sampler(light_sampler)
  , m_params(params)
{
}

void DRTLightingEngineFactory::release()
{
    delete this;
}

ILightingEngine* DRTLightingEngineFactory::create()
{
    return new DRTLightingEngine(m_light_sampler, m_params);
}

ILightingEngine* DRTLightingEngineFactory::create(
    const LightSampler& light_sampler,
    const ParamArray&   params)
{
    return new DRTLightingEngine(light_sampler, params);
}

}   // namespace renderer
<commit_msg>added a comment.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2011 Francois Beaune
//
// 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.
//

// Interface header.
#include "drt.h"

// appleseed.renderer headers.
#include "renderer/kernel/lighting/directlighting.h"
#include "renderer/kernel/lighting/imagebasedlighting.h"
#include "renderer/kernel/lighting/lightsampler.h"
#include "renderer/kernel/lighting/pathtracer.h"
#include "renderer/kernel/shading/shadingcontext.h"
#include "renderer/kernel/shading/shadingpoint.h"
#include "renderer/modeling/bsdf/bsdf.h"
#include "renderer/modeling/edf/edf.h"
#include "renderer/modeling/environment/environment.h"
#include "renderer/modeling/input/inputevaluator.h"
#include "renderer/modeling/material/material.h"
#include "renderer/modeling/scene/scene.h"

// appleseed.foundation headers.
#include "foundation/math/basis.h"
#include "foundation/math/mis.h"
#include "foundation/math/population.h"
#include "foundation/utility/memory.h"
#include "foundation/utility/string.h"

// Forward declarations.
namespace renderer  { class EnvironmentEDF; }
namespace renderer  { class InputParams; }

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Distribution Ray Tracing (DRT) lighting engine.
    //

    class DRTLightingEngine
      : public ILightingEngine
    {
      public:
        DRTLightingEngine(
            const LightSampler&     light_sampler,
            const ParamArray&       params)
          : m_params(params)
          , m_light_sampler(light_sampler)
        {
        }

        ~DRTLightingEngine()
        {
            RENDERER_LOG_DEBUG(
                "distribution ray tracing statistics:\n"
                "  paths            %s\n"
                "  ray tree depth   avg %.1f  min %s  max %s  dev %.1f\n",
                pretty_uint(m_stats.m_path_count).c_str(),
                m_stats.m_ray_tree_depth.get_avg(),
                pretty_uint(m_stats.m_ray_tree_depth.get_min()).c_str(),
                pretty_uint(m_stats.m_ray_tree_depth.get_max()).c_str(),
                m_stats.m_ray_tree_depth.get_dev());
        }

        virtual void release()
        {
            delete this;
        }

        virtual void compute_lighting(
            SamplingContext&        sampling_context,
            const ShadingContext&   shading_context,
            const ShadingPoint&     shading_point,
            Spectrum&               radiance)   // output radiance, in W.sr^-1.m^-2
        {
            typedef PathTracer<
                PathVisitor,
                BSDF::Glossy | BSDF::Specular,
                false                           // not adjoint
            > PathTracer;

            PathVisitor path_visitor(
                m_params,
                m_light_sampler,
                m_light_samples,
                shading_context,
                shading_point.get_scene(),
                radiance);

            PathTracer path_tracer(
                path_visitor,
                m_params.m_minimum_path_length);

            const size_t path_length =
                path_tracer.trace(
                    sampling_context,
                    shading_context.get_intersector(),
                    shading_context.get_texture_cache(),
                    shading_point);

            // Update statistics.
            ++m_stats.m_path_count;
            m_stats.m_ray_tree_depth.insert(path_length);
        }

      private:
        struct Parameters
        {
            const size_t        m_minimum_path_length;      // minimum path length before Russian Roulette is used
            const size_t        m_dl_sample_count;          // number of samples used to estimate direct illumination
            const size_t        m_ibl_bsdf_sample_count;    // number of samples (in BSDF sampling) used to estimate IBL
            const size_t        m_ibl_env_sample_count;     // number of samples (in environment sampling) used to estimate IBL

            // Constructor, extract parameters.
            explicit Parameters(const ParamArray& params)
              : m_minimum_path_length   ( params.get_optional<size_t>("minimum_path_length", 3) )
              , m_dl_sample_count       ( params.get_optional<size_t>("dl_samples", 1) )
              , m_ibl_bsdf_sample_count ( params.get_optional<size_t>("ibl_bsdf_samples", 2) )
              , m_ibl_env_sample_count  ( params.get_optional<size_t>("ibl_env_samples", 2) )
            {
            }
        };

        struct Statistics
        {
            uint64              m_path_count;               // number of paths
            Population<size_t>  m_ray_tree_depth;           // ray tree depth

            Statistics()
              : m_path_count(0)
            {
            }
        };

        class PathVisitor
        {
          public:
            PathVisitor(
                const Parameters&       params,
                const LightSampler&     light_sampler,
                LightSampleVector&      light_samples,
                const ShadingContext&   shading_context,
                const Scene&            scene,
                Spectrum&               path_radiance)
              : m_params(params)
              , m_light_sampler(light_sampler)
              , m_light_samples(light_samples)
              , m_shading_context(shading_context)
              , m_texture_cache(shading_context.get_texture_cache())
              , m_path_radiance(path_radiance)
            {
                const Environment* environment = scene.get_environment();
                m_env_edf = environment ? environment->get_environment_edf() : 0;

                m_path_radiance.set(0.0f);
            }

            bool visit_vertex(
                SamplingContext&        sampling_context,
                const ShadingPoint&     shading_point,
                const Vector3d&         outgoing,
                const BSDF*             bsdf,
                const void*             bsdf_data,
                const BSDF::Mode        bsdf_mode,
                const double            bsdf_prob,
                const Spectrum&         throughput)
            {
                const Vector3d& point = shading_point.get_point();
                const Vector3d& geometric_normal = shading_point.get_geometric_normal();
                const Vector3d& shading_normal = shading_point.get_shading_normal();
                const Basis3d& shading_basis = shading_point.get_shading_basis();
                const Material* material = shading_point.get_material();
                const InputParams& input_params = shading_point.get_input_params();

                // Generate light samples.
                clear_keep_memory(m_light_samples);
                m_light_sampler.sample(
                    sampling_context,
                    m_params.m_dl_sample_count,
                    m_light_samples);

                // Compute direct lighting.
                Spectrum vertex_radiance;
                compute_direct_lighting(
                    sampling_context,
                    m_shading_context,
                    point,
                    geometric_normal,
                    shading_basis,
                    outgoing,
                    *bsdf,
                    bsdf_data,
                    m_light_samples,
                    vertex_radiance,
                    &shading_point);

                if (m_env_edf)
                {
                    // Compute image-based lighting.
                    Spectrum ibl_radiance;
                    compute_image_based_lighting(
                        sampling_context,
                        m_shading_context,
                        *m_env_edf,
                        point,
                        geometric_normal,
                        shading_basis,
                        outgoing,
                        *bsdf,
                        bsdf_data,
                        m_params.m_ibl_bsdf_sample_count,
                        m_params.m_ibl_env_sample_count,
                        ibl_radiance,
                        &shading_point);
                    vertex_radiance += ibl_radiance;
                }

                // Retrieve the EDF.
                const EDF* edf = material->get_edf();

                if (edf)
                {
                    // Handle light sources visible either directly or through
                    // specular/glossy reflections and refractions.

                    // Evaluate the input values of the EDF (if any).
                    InputEvaluator edf_input_evaluator(m_texture_cache);
                    const void* edf_data =
                        edf_input_evaluator.evaluate(
                            edf->get_inputs(),
                            input_params);

                    // Compute the emitted radiance.
                    Spectrum emitted_radiance;
                    edf->evaluate(
                        edf_data,
                        geometric_normal,
                        shading_basis,
                        outgoing,
                        emitted_radiance);

                    const double distance = shading_point.get_distance();

                    if (bsdf_mode != BSDF::Specular && distance > 0.0)
                    {
                        // Compute the probability density with respect to surface area
                        // of choosing this point through sampling of the light sources.
                        const double sample_probability =
                            m_light_sampler.evaluate_pdf(shading_point);

                        // Compute the probability density with respect to surface area
                        // of the direction obtained through sampling of the BSDF.
                        double px = bsdf_prob;
                        px *= max(dot(outgoing, shading_normal), 0.0);
                        px /= square(distance);

                        // Multiply the emitted radiance by the MIS weight.
                        const double mis_weight = mis_power2(px, sample_probability);
                        emitted_radiance *= static_cast<float>(mis_weight);
                    }

                    vertex_radiance += emitted_radiance;
                }

                // Update the path radiance.
                vertex_radiance *= throughput;
                m_path_radiance += vertex_radiance;

                // Proceed with this path.
                return true;
            }

            void visit_environment(
                const ShadingPoint&     shading_point,
                const Vector3d&         outgoing,
                const Spectrum&         throughput)
            {
            }

          private:
            const Parameters&       m_params;
            const LightSampler&     m_light_sampler;
            LightSampleVector&      m_light_samples;
            const ShadingContext&   m_shading_context;
            TextureCache&           m_texture_cache;
            const EnvironmentEDF*   m_env_edf;
            Spectrum&               m_path_radiance;
        };

        const Parameters        m_params;
        Statistics              m_stats;
        const LightSampler&     m_light_sampler;
        LightSampleVector       m_light_samples;
    };
}

//
// DRTLightingEngineFactory class implementation.
//

DRTLightingEngineFactory::DRTLightingEngineFactory(
    const LightSampler& light_sampler,
    const ParamArray&   params)
  : m_light_sampler(light_sampler)
  , m_params(params)
{
}

void DRTLightingEngineFactory::release()
{
    delete this;
}

ILightingEngine* DRTLightingEngineFactory::create()
{
    return new DRTLightingEngine(m_light_sampler, m_params);
}

ILightingEngine* DRTLightingEngineFactory::create(
    const LightSampler& light_sampler,
    const ParamArray&   params)
{
    return new DRTLightingEngine(light_sampler, params);
}

}   // namespace renderer
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2015 Skorezore

//  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 "frame_buffer.hpp"
#include "game_screen.hpp"
#include "curses.hpp"
#include "entity.hpp"
#include <experimental/string_view>
#include <functional>
#include <sstream>
#include <chrono>
#include <vector>
#include <string>
#include <thread>

using namespace std;
using namespace std::chrono;
using namespace std::experimental;

void draw_frame() {
	addstr(frame_buffer->str().c_str());
	refresh();
}

void reset_buffer() {
	move(0, 0);
	frame_buffer->str("");
}

void clear_screen() {
	clear();
	refresh();
	reset_buffer();
}

bool handle_player_movements(game_screen & screen, entity & player) {
	if(kbhit()) {
		char key      = tolower(getch());
		coords newpos = player.position;

		if(key == 'w' && player.position.x > 2 && screen[player.position.below()] != game_screen::filler &&
		   screen[player.position.above()] == game_screen::filler && screen[player.position.above(2)] == game_screen::filler)
			newpos.y -= 2;

		if(key == 'a' && player.position.x > 0 && screen[player.position.left()] == game_screen::filler) {
			--newpos.x;
			if(screen[player.position.below()] == game_screen::filler && screen[player.position.left(2)] == game_screen::filler)
				--newpos.x;
		}

		if(key == 's' && player.position.y < screen.size.y)
			++newpos.y;

		if(key == 'd' && player.position.x < screen.size.x && screen[player.position.right()] == game_screen::filler) {
			++newpos.x;
			if(screen[player.position.below()] == game_screen::filler && screen[player.position.right(2)] == game_screen::filler)
				++newpos.x;
		}

		player.move_to(newpos);

		if(key == 'q')  // Sneaking in that close key
			return true;
	}
	return false;
}

void gravity(game_screen & screen, entity & entity) {
	if(entity.position.y < screen.size.y && screen[entity.position.below()] == game_screen::filler)
		entity.move_to(entity.position.below());
}

void loop() {
	static const auto time_between_frames = 75ms;

	game_screen screen({16, 16});
	screen.reset();
	screen[{4, 13}]  = '=';
	screen[{5, 13}]  = '=';
	screen[{6, 13}]  = '=';
	screen[{7, 13}]  = '=';
	screen[{8, 13}]  = '=';
	screen[{10, 14}] = '=';
	screen[{11, 14}] = '=';
	// Look at that fancy hardcoded screen ^
	entity player('X');
	bool do_gravity = false;

	curs_set(0);
	noecho();
	while(true) {
		if((do_gravity ^= true) % 2 == 0)
			gravity(screen, player);
		this_thread::sleep_for(time_between_frames);
		reset_buffer();
		for(auto & pos : player.prev_positions)
			screen[pos] = game_screen::filler;
		player.prev_positions.clear();
		screen[player.position] = player.body;
		screen.draw();
		*frame_buffer << "^^^^^^^^^^^^^^^^^^^\n\n"  // Photo-realistic spikes, I know.
		                 "Use WASD for movement\n"
		                 "Press Q to quit\n\n"
		                 "X: "
		              << player.position.x << " Y: " << (-player.position.y + screen.size.y) << "\nWatch out for the spikes below!\n";
		draw_frame();

		if(handle_player_movements(screen, player))
			break;

		if(player.position.y > 14) {
			curs_set(1);
			frame_buffer->str("");
			*frame_buffer << "You fell to your death. Game over!\nPress 'r' to restart: ";
			draw_frame();
			if(tolower(getch()) == 'r') {
				clear();
				loop();
			}
			break;
		}
	}
	echo();
	curs_set(1);
}

function<void()> main_menu() {
	static const vector<pair<string_view, function<void()>>> items({{"Play Gaem", loop}, {"Exit", [&]() {}}});

	size_t idx = 1;
	for(const auto & item : items)
		*frame_buffer << idx++ << ". " << item.first << '\n';
	*frame_buffer << "\nPress the key corresponding to your selection: ";
	draw_frame();

	while(true) {
		int key = getch();
		size_t idx;
		stringstream(string(1, static_cast<char>(key))) >> idx;

		if(isdigit(key) && idx > 0 && items.size() >= idx) {
			clear_screen();
			return items[idx - 1].second;
		}
	}
}

int main() {
	initscr();
	main_menu()();
	endwin();
}
<commit_msg>Wait at most 10s for the player to restart (#16)<commit_after>// The MIT License (MIT)

// Copyright (c) 2015 Skorezore

//  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 "frame_buffer.hpp"
#include "game_screen.hpp"
#include "curses.hpp"
#include "entity.hpp"
#include <experimental/string_view>
#include <functional>
#include <sstream>
#include <chrono>
#include <vector>
#include <string>
#include <thread>

using namespace std;
using namespace std::chrono;
using namespace std::experimental;

void draw_frame() {
	addstr(frame_buffer->str().c_str());
	refresh();
}

void reset_buffer() {
	move(0, 0);
	frame_buffer->str("");
}

void clear_screen() {
	clear();
	refresh();
	reset_buffer();
}

bool handle_player_movements(game_screen & screen, entity & player) {
	if(kbhit()) {
		char key      = tolower(getch());
		coords newpos = player.position;

		if(key == 'w' && player.position.x > 2 && screen[player.position.below()] != game_screen::filler &&
		   screen[player.position.above()] == game_screen::filler && screen[player.position.above(2)] == game_screen::filler)
			newpos.y -= 2;

		if(key == 'a' && player.position.x > 0 && screen[player.position.left()] == game_screen::filler) {
			--newpos.x;
			if(screen[player.position.below()] == game_screen::filler && screen[player.position.left(2)] == game_screen::filler)
				--newpos.x;
		}

		if(key == 's' && player.position.y < screen.size.y)
			++newpos.y;

		if(key == 'd' && player.position.x < screen.size.x && screen[player.position.right()] == game_screen::filler) {
			++newpos.x;
			if(screen[player.position.below()] == game_screen::filler && screen[player.position.right(2)] == game_screen::filler)
				++newpos.x;
		}

		player.move_to(newpos);

		if(key == 'q')  // Sneaking in that close key
			return true;
	}
	return false;
}

void gravity(game_screen & screen, entity & entity) {
	if(entity.position.y < screen.size.y && screen[entity.position.below()] == game_screen::filler)
		entity.move_to(entity.position.below());
}

void loop() {
	static const auto time_between_frames = 75ms;

	game_screen screen({16, 16});
	screen.reset();
	screen[{4, 13}]  = '=';
	screen[{5, 13}]  = '=';
	screen[{6, 13}]  = '=';
	screen[{7, 13}]  = '=';
	screen[{8, 13}]  = '=';
	screen[{10, 14}] = '=';
	screen[{11, 14}] = '=';
	// Look at that fancy hardcoded screen ^
	entity player('X');
	bool do_gravity = false;

	curs_set(0);
	noecho();
	while(true) {
		if((do_gravity ^= true) % 2 == 0)
			gravity(screen, player);
		this_thread::sleep_for(time_between_frames);
		reset_buffer();
		for(auto & pos : player.prev_positions)
			screen[pos] = game_screen::filler;
		player.prev_positions.clear();
		screen[player.position] = player.body;
		screen.draw();
		*frame_buffer << "^^^^^^^^^^^^^^^^^^^\n\n"  // Photo-realistic spikes, I know.
		                 "Use WASD for movement\n"
		                 "Press Q to quit\n\n"
		                 "X: "
		              << player.position.x << " Y: " << (-player.position.y + screen.size.y) << "\nWatch out for the spikes below!\n";
		draw_frame();

		if(handle_player_movements(screen, player))
			break;

		if(player.position.y > 14) {
			curs_set(1);
			frame_buffer->str("");
			*frame_buffer << "You fell to your death. Game over!\nPress 'r' to restart (10s): ";
			draw_frame();
			halfdelay(100);
			if(tolower(getch()) == 'r') {
				clear();
				nodelay(stdscr, true);
				loop();
			}
			nodelay(stdscr, true);
			break;
		}
	}
	echo();
	curs_set(1);
}

function<void()> main_menu() {
	static const vector<pair<string_view, function<void()>>> items({{"Play Gaem", loop}, {"Exit", [&]() {}}});

	size_t idx = 1;
	for(const auto & item : items)
		*frame_buffer << idx++ << ". " << item.first << '\n';
	*frame_buffer << "\nPress the key corresponding to your selection: ";
	draw_frame();

	while(true) {
		int key = getch();
		size_t idx;
		stringstream(string(1, static_cast<char>(key))) >> idx;

		if(isdigit(key) && idx > 0 && items.size() >= idx) {
			clear_screen();
			return items[idx - 1].second;
		}
	}
}

int main() {
	initscr();
	main_menu()();
	endwin();
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2015 Skorezore

//  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 "frame_buffer.hpp"
#include "game_screen.hpp"
#include "curses.hpp"
#include "entity.hpp"
#include <experimental/string_view>
#include <functional>
#include <sstream>
#include <chrono>
#include <vector>
#include <string>
#include <thread>

using namespace std;
using namespace std::chrono;
using namespace std::experimental;

void draw_frame() {
	addstr(frame_buffer->str().c_str());
	refresh();
}

void reset_buffer() {
	move(0, 0);
	frame_buffer->str("");
}

void clear_screen() {
	clear();
	refresh();
	reset_buffer();
}

bool handle_player_movements(game_screen & screen, entity & player) {
	if(kbhit()) {
		char key      = tolower(getch());
		coords newpos = player.position;

		if(key == 'w' && player.position.x > 2 && screen[player.position.below()] != game_screen::filler &&
		   screen[player.position.above()] == game_screen::filler && screen[player.position.above(2)] == game_screen::filler)
			newpos.y -= 2;

		if(key == 'a' && player.position.x > 0 && screen[player.position.left()] == game_screen::filler) {
			--newpos.x;
			if(screen[player.position.below()] == game_screen::filler && screen[player.position.left(2)] == game_screen::filler)
				--newpos.x;
		}

		if(key == 's' && player.position.y < screen.size.y)
			++newpos.y;

		if(key == 'd' && player.position.x < screen.size.x && screen[player.position.right()] == game_screen::filler) {
			++newpos.x;
			if(screen[player.position.below()] == game_screen::filler && screen[player.position.right(2)] == game_screen::filler)
				++newpos.x;
		}

		player.move_to(newpos);

		if(key == 'q')  // Sneaking in that close key
			return true;
	}
	return false;
}

void gravity(game_screen & screen, entity & entity) {
	if(entity.position.y < screen.size.y && screen[entity.position.below()] == game_screen::filler)
		entity.move_to(entity.position.below());
}

void loop() {
	static const auto time_between_frames = 75ms;

	game_screen screen({16, 16});
	screen.reset();
	screen[{4, 13}]  = '=';
	screen[{5, 13}]  = '=';
	screen[{6, 13}]  = '=';
	screen[{7, 13}]  = '=';
	screen[{8, 13}]  = '=';
	screen[{10, 14}] = '=';
	screen[{11, 14}] = '=';
	// Look at that fancy hardcoded screen ^
	entity player('X');
	bool do_gravity = false;

	curs_set(0);
	noecho();
	while(true) {
		if((do_gravity ^= true) % 2 == 0)
			gravity(screen, player);
		this_thread::sleep_for(time_between_frames);
		reset_buffer();
		for(auto & pos : player.prev_positions)
			screen[pos] = game_screen::filler;
		player.prev_positions.clear();
		screen[player.position] = player.body;
		screen.draw();
		*frame_buffer << "^^^^^^^^^^^^^^^^^^^\n\n"  // Photo-realistic spikes, I know.
		                 "Use WASD for movement\n"
		                 "Press Q to quit\n\n"
		                 "X: "
		              << player.position.x << " Y: " << (-player.position.y + screen.size.y) << "\nWatch out for the spikes below!\n";
		draw_frame();

		if(handle_player_movements(screen, player))
			break;

		if(player.position.y > 14) {
			curs_set(1);
			frame_buffer->str("");
			*frame_buffer << "You fell to your death. Game over!\nPress 'r' to restart (10s): ";
			draw_frame();
			halfdelay(100);
			if(tolower(getch()) == 'r') {
				clear();
				nodelay(stdscr, true);
				loop();
			}
			nodelay(stdscr, true);
			break;
		}
	}
	echo();
	curs_set(1);
}

function<void()> main_menu() {
	static const vector<pair<string_view, function<void()>>> items({{"Play Gaem", loop}, {"Exit", [&]() {}}});

	size_t idx = 1;
	for(const auto & item : items)
		*frame_buffer << idx++ << ". " << item.first << '\n';
	*frame_buffer << "\nPress the key corresponding to your selection: ";
	draw_frame();

	while(true) {
		int key = getch();
		size_t idx;
		stringstream(string(1, static_cast<char>(key))) >> idx;

		if(isdigit(key) && idx > 0 && items.size() >= idx) {
			clear_screen();
			return items[idx - 1].second;
		}
	}
}

int main() {
	initscr();
	main_menu()();
	endwin();
}
<commit_msg>Remove player coords debug output<commit_after>// The MIT License (MIT)

// Copyright (c) 2015 Skorezore

//  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 "frame_buffer.hpp"
#include "game_screen.hpp"
#include "curses.hpp"
#include "entity.hpp"
#include <experimental/string_view>
#include <functional>
#include <sstream>
#include <chrono>
#include <vector>
#include <string>
#include <thread>

using namespace std;
using namespace std::chrono;
using namespace std::experimental;

void draw_frame() {
	addstr(frame_buffer->str().c_str());
	refresh();
}

void reset_buffer() {
	move(0, 0);
	frame_buffer->str("");
}

void clear_screen() {
	clear();
	refresh();
	reset_buffer();
}

bool handle_player_movements(game_screen & screen, entity & player) {
	if(kbhit()) {
		char key      = tolower(getch());
		coords newpos = player.position;

		if(key == 'w' && player.position.x > 2 && screen[player.position.below()] != game_screen::filler &&
		   screen[player.position.above()] == game_screen::filler && screen[player.position.above(2)] == game_screen::filler)
			newpos.y -= 2;

		if(key == 'a' && player.position.x > 0 && screen[player.position.left()] == game_screen::filler) {
			--newpos.x;
			if(screen[player.position.below()] == game_screen::filler && screen[player.position.left(2)] == game_screen::filler)
				--newpos.x;
		}

		if(key == 's' && player.position.y < screen.size.y)
			++newpos.y;

		if(key == 'd' && player.position.x < screen.size.x && screen[player.position.right()] == game_screen::filler) {
			++newpos.x;
			if(screen[player.position.below()] == game_screen::filler && screen[player.position.right(2)] == game_screen::filler)
				++newpos.x;
		}

		player.move_to(newpos);

		if(key == 'q')  // Sneaking in that close key
			return true;
	}
	return false;
}

void gravity(game_screen & screen, entity & entity) {
	if(entity.position.y < screen.size.y && screen[entity.position.below()] == game_screen::filler)
		entity.move_to(entity.position.below());
}

void loop() {
	static const auto time_between_frames = 75ms;

	game_screen screen({16, 16});
	screen.reset();
	screen[{4, 13}]  = '=';
	screen[{5, 13}]  = '=';
	screen[{6, 13}]  = '=';
	screen[{7, 13}]  = '=';
	screen[{8, 13}]  = '=';
	screen[{10, 14}] = '=';
	screen[{11, 14}] = '=';
	// Look at that fancy hardcoded screen ^
	entity player('X');
	bool do_gravity = false;

	curs_set(0);
	noecho();
	while(true) {
		if((do_gravity ^= true) % 2 == 0)
			gravity(screen, player);
		this_thread::sleep_for(time_between_frames);
		reset_buffer();
		for(auto & pos : player.prev_positions)
			screen[pos] = game_screen::filler;
		player.prev_positions.clear();
		screen[player.position] = player.body;
		screen.draw();
		*frame_buffer << "^^^^^^^^^^^^^^^^^^^\n\n"  // Photo-realistic spikes, I know.
		                 "Use WASD for movement\n"
		                 "Press Q to quit\n\n"
		                 "Watch out for the spikes below!\n";
		draw_frame();

		if(handle_player_movements(screen, player))
			break;

		if(player.position.y > 14) {
			curs_set(1);
			frame_buffer->str("");
			*frame_buffer << "\nYou fell to your death. Game over!\nPress 'r' to restart (10s): ";
			draw_frame();
			halfdelay(100);
			if(tolower(getch()) == 'r') {
				clear();
				nodelay(stdscr, true);
				loop();
			}
			nodelay(stdscr, true);
			break;
		}
	}
	echo();
	curs_set(1);
}

function<void()> main_menu() {
	static const vector<pair<string_view, function<void()>>> items({{"Play Gaem", loop}, {"Exit", [&]() {}}});

	size_t idx = 1;
	for(const auto & item : items)
		*frame_buffer << idx++ << ". " << item.first << '\n';
	*frame_buffer << "\nPress the key corresponding to your selection: ";
	draw_frame();

	while(true) {
		int key = getch();
		size_t idx;
		stringstream(string(1, static_cast<char>(key))) >> idx;

		if(isdigit(key) && idx > 0 && items.size() >= idx) {
			clear_screen();
			return items[idx - 1].second;
		}
	}
}

int main() {
	initscr();
	main_menu()();
	endwin();
}
<|endoftext|>