[Racer-svn] SF.net SVN: racer:[69] trunk
Status: Alpha
Brought to you by:
jlegg
From: <jl...@us...> - 2009-11-06 23:48:54
|
Revision: 69 http://racer.svn.sourceforge.net/racer/?rev=69&view=rev Author: jlegg Date: 2009-11-06 23:48:41 +0000 (Fri, 06 Nov 2009) Log Message: ----------- User interface for dragging path vertices. Moves racer_editor/document/ to libtrack/document/ to allow objects in libtrack to make DocumentDeltas. Modified Paths: -------------- trunk/configure.ac trunk/libtrack/DrawableMesh.h trunk/libtrack/Makefile.am trunk/libtrack/Path.cpp trunk/libtrack/Path.h trunk/libtrack/document/DocumentDelta.h trunk/racer_editor/EditorWindow.cpp trunk/racer_editor/EditorWindow.h trunk/racer_editor/Makefile.am trunk/racer_editor/View.cpp trunk/racer_editor/View.h trunk/racer_editor/Viewport.cpp trunk/racer_editor/Viewport.h Added Paths: ----------- trunk/libtrack/Selectable.h trunk/libtrack/document/ trunk/libtrack/document/ChangePropertyDelta.h trunk/libtrack/document/Makefile.am trunk/libtrack/document/MoveNodeDelta.cpp trunk/libtrack/document/MoveNodeDelta.h Removed Paths: ------------- trunk/libtrack/document/Makefile.am trunk/racer_editor/document/ Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2009-11-02 01:35:38 UTC (rev 68) +++ trunk/configure.ac 2009-11-06 23:48:41 UTC (rev 69) @@ -34,7 +34,7 @@ AC_SUBST(EXTRA_CFLAGS, ["$debug_specific_CFLAGS -Wall"]) #Find dependencies for libtrack -PKG_CHECK_MODULES(libtrack, [bullet]) +PKG_CHECK_MODULES(libtrack, [bullet sigc++-2.0]) AC_SUBST(libtrack_LIBS) AC_SUBST(libtrack_CFLAGS) @@ -58,4 +58,4 @@ AC_SUBST(racer_editor_LIBS) #Generate lots of yummy makefiles. -AC_OUTPUT([Makefile libtrack/Makefile racer_editor/Makefile racer/Makefile racer/data/Makefile racer/UI/Makefile racer/Graphics/Makefile racer/Engine/Makefile racer/Engine/GameObjects/Makefile racer/Engine/Physics/Makefile racer_editor/document/Makefile]) +AC_OUTPUT([Makefile libtrack/Makefile libtrack/document/Makefile racer_editor/Makefile racer/Makefile racer/data/Makefile racer/UI/Makefile racer/Graphics/Makefile racer/Engine/Makefile racer/Engine/GameObjects/Makefile racer/Engine/Physics/Makefile]) Modified: trunk/libtrack/DrawableMesh.h =================================================================== --- trunk/libtrack/DrawableMesh.h 2009-11-02 01:35:38 UTC (rev 68) +++ trunk/libtrack/DrawableMesh.h 2009-11-06 23:48:41 UTC (rev 69) @@ -23,7 +23,7 @@ * The mesh's faces are defined using the vertex position, normal, and texture * coordinates. Shaders / texturing / materials etc is left to the user. */ -class DrawableMesh : public Track::Drawable, public Track::MeshFaces +class DrawableMesh : public Drawable, public MeshFaces { public: /** construct by sucking information from an input stream. Modified: trunk/libtrack/Makefile.am =================================================================== --- trunk/libtrack/Makefile.am 2009-11-02 01:35:38 UTC (rev 68) +++ trunk/libtrack/Makefile.am 2009-11-06 23:48:41 UTC (rev 69) @@ -1,3 +1,7 @@ +SUBDIRS = document noinst_LIBRARIES = libtrack.a -libtrack_a_SOURCES = AxisAlignedBoundingBox.cpp AxisAlignedBoundingBox.h Debug.h DecoMesh.cpp DecoMesh.h DecoMeshInstance.cpp DecoMeshInstance.h Drawable.cpp Drawable.h DrawableMesh.cpp DrawableMesh.h MeshFaces.cpp MeshFaces.h Path.cpp Path.h PieceDistortion.cpp PieceDistortion.h SegmentConnection.cpp SegmentConnection.h Segment.cpp Segment.h Skybox.cpp Skybox.h stream_loader.h stream_loader.cpp Texture.cpp Texture.h Theme.cpp Theme.h Track.cpp Track.h TrackMesh.h UniqueIdentifier.h +libtrack_a_SOURCES = AxisAlignedBoundingBox.cpp AxisAlignedBoundingBox.h Debug.h DecoMesh.cpp DecoMesh.h DecoMeshInstance.cpp DecoMeshInstance.h Drawable.cpp Drawable.h DrawableMesh.cpp DrawableMesh.h MeshFaces.cpp MeshFaces.h Path.cpp Path.h PieceDistortion.cpp PieceDistortion.h SegmentConnection.cpp SegmentConnection.h Segment.cpp Segment.h Selectable.cpp Selectable.h Skybox.cpp Skybox.h stream_loader.h stream_loader.cpp Texture.cpp Texture.h Theme.cpp Theme.h Track.cpp Track.h TrackMesh.h UniqueIdentifier.h libtrack_a_CPPFLAGS = $(debug_specific_CFLAGS) $(libtrack_CFLAGS) +libtrack_a_LIBADD = document/libdocument.a +#we need a flattened archive rather than a nested one. +libtrack_a_AR=$(AR) $(ARFLAGS)T Modified: trunk/libtrack/Path.cpp =================================================================== --- trunk/libtrack/Path.cpp 2009-11-02 01:35:38 UTC (rev 68) +++ trunk/libtrack/Path.cpp 2009-11-06 23:48:41 UTC (rev 69) @@ -14,6 +14,8 @@ #include "Path.h" #include "stream_loader.h" +#include "document/MoveNodeDelta.h" + namespace Track { @@ -60,6 +62,40 @@ return angle; } +bool PathVertex::is_here(btVector3 start, btVector3 stop, btScalar radius) const +{ + btVector3 line = stop - start; + btVector3 to_start = position - start; + btScalar u = to_start.dot(line) / line.length2(); + if (u < 0.0 || u > 1.0) + { + //Nearest to one of the end vertices. Not valid selection. + // Is either behind the viewer or depth clipped, either way + // not on screen so can't be selected. + DEBUG_MESSAGE("Vertex not in clipping range"); + return false; + } + btScalar distance2 = (u * line).distance2(to_start); + if (distance2 < radius * radius) + { + return true; + } + DEBUG_MESSAGE("Vertex distance is " << std::sqrt(distance2) << ", must be less than " << radius); + return false; +} + +boost::shared_ptr<Document::DocumentDelta> PathVertex::make_delta(btVector3 new_position) const +{ + return boost::shared_ptr<Document::DocumentDelta> + ( + new Document::MoveNodeDelta + ( + Document::NodePositionFinder(get_name()) + , new_position + ) + ); +} + std::ostream & operator<<(std::ostream & destination, const PathVertex & path_vertex) { destination << path_vertex.position << ' ' @@ -130,6 +166,13 @@ { source = & source_in; target = & target_in; + update(); +} + +void PathEdge::update() +{ + const PathVertex & source_in = *source; + const PathVertex & target_in = *target; // A cubic bezier spline isn't analytically intergratable. // Instead of hard numerical approximations, I'll do a piecewise linear // estimation. @@ -169,7 +212,7 @@ meshes.reserve(number_of_repetions); for (unsigned int i = 0; i < number_of_repetions; i++) { - Track::PieceDistortion transform(*this, i, + PieceDistortion transform(*this, i, segment->get_length(), segment->get_minimum_y()); meshes.push_back(boost::shared_ptr<DrawableMesh>( @@ -309,9 +352,14 @@ // calculate the length of the edges. typedef boost::graph_traits<Graph>::edge_iterator EdgeIterator; std::pair<EdgeIterator, EdgeIterator> edge_range(boost::edges(graph)); - graph[*(edge_range.first)].update(vertex_1, vertex_2); + std::pair<VertexIterator, VertexIterator> vertex_range(boost::vertices(graph)); + // Get references to where the vertices are held. + PathVertex & vertex_1r = graph[*(vertex_range.first)]; + vertex_range.first++; + PathVertex & vertex_2r = graph[*(vertex_range.first)]; + graph[*(edge_range.first)].update(vertex_1r, vertex_2r); edge_range.first++; - graph[*(edge_range.first)].update(vertex_2, vertex_1); + graph[*(edge_range.first)].update(vertex_2r, vertex_1r); } Path::~Path() @@ -386,24 +434,27 @@ PathVertex & Path::get_node(const std::size_t index) { - /// @todo more efficent data structure? - typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator; - std::pair<VertexIterator, VertexIterator> vertex_range; - for (vertex_range = boost::vertices(graph); - vertex_range.first != vertex_range.second; - vertex_range.first++) - { - PathVertex & vertex = graph[*(vertex_range.first)]; - if (vertex.get_name() == index) - { - return vertex; - } - } + return graph[get_node_descriptor(index)]; } const PathVertex & Path::get_node(const std::size_t index) const { - /// @todo share code with above function. + return graph[get_node_descriptor(index)]; +} + +Path::Graph::vertex_descriptor Path::get_node_descriptor(const std::size_t index) +{ + return get_node_descriptor_internal(index); +} + +const Path::Graph::vertex_descriptor Path::get_node_descriptor(const std::size_t index) const +{ + return get_node_descriptor_internal(index); +} + +Path::Graph::vertex_descriptor Path::get_node_descriptor_internal(const std::size_t index) const +{ + /// @todo Use a more efficent data structure? typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator; std::pair<VertexIterator, VertexIterator> vertex_range; for (vertex_range = boost::vertices(graph); @@ -413,7 +464,7 @@ const PathVertex & vertex = graph[*(vertex_range.first)]; if (vertex.get_name() == index) { - return vertex; + return *(vertex_range.first); } } } Modified: trunk/libtrack/Path.h =================================================================== --- trunk/libtrack/Path.h 2009-11-02 01:35:38 UTC (rev 68) +++ trunk/libtrack/Path.h 2009-11-06 23:48:41 UTC (rev 69) @@ -33,13 +33,16 @@ #include "AxisAlignedBoundingBox.h" #include "DrawableMesh.h" #include "UniqueIdentifier.h" +#include "Selectable.h" namespace Track { /** Information to store at the vertices. */ -class PathVertex : public UniqueIdentifier +class PathVertex + : public UniqueIdentifier + , public Selectable { friend std::ostream & operator<<(std::ostream & destination, const PathVertex & path_vertex); @@ -79,6 +82,10 @@ /// The index of the segment in the Theme std::size_t segment_index; + + // Implement virtual functions from Selectable. + virtual bool is_here(btVector3 start, btVector3 stop, btScalar radius) const; + virtual boost::shared_ptr<Document::DocumentDelta> make_delta(btVector3 new_position) const; protected: btVector3 gradient; btVector3 up; @@ -151,7 +158,7 @@ * After this has been called, the length, repetitions, and mesh will be * up to date. * The objects referenced by the parameters must not be freed when this - * object is still being used, unless update() is called again. + * object is still being used, unless this function is called again. * @param source The information stored about the source node of the edge * this PathEdge refers to. * @param target The information stored about the target node. @@ -159,6 +166,14 @@ void update(const PathVertex & source, const PathVertex & target); + /** Update various internal records. + * Behaves like update(const PathVertex & source, const PathVertex & target), + * except it uses the reuses the same source and target previously + * passed in. The other version must have been used first to set + * source and target. + */ + void update(); + /** Get the last calculated length. * Use calculate_length() instead if the Edge or the vertices it connects * have been modified since the last time it was called. @@ -219,7 +234,7 @@ /// Graph of track layout. typedef boost::adjacency_list <boost::vecS, boost::vecS, - boost::directedS, + boost::bidirectionalS, PathVertex, PathEdge> Graph; Graph graph; @@ -235,8 +250,14 @@ PathVertex & get_node(const std::size_t index); /// find a graph node by ID const PathVertex & get_node(const std::size_t index) const; + + /// find a graph node descriptor by ID + Path::Graph::vertex_descriptor get_node_descriptor(const std::size_t index); + /// find a graph node descriptor by ID + const Path::Graph::vertex_descriptor get_node_descriptor(const std::size_t index) const; private: const Theme & theme; + Path::Graph::vertex_descriptor get_node_descriptor_internal(const std::size_t index) const; }; std::ostream & operator<<(std::ostream & destination, Added: trunk/libtrack/Selectable.h =================================================================== --- trunk/libtrack/Selectable.h (rev 0) +++ trunk/libtrack/Selectable.h 2009-11-06 23:48:41 UTC (rev 69) @@ -0,0 +1,55 @@ +/** @file libtrack/Selectable.h + * @brief Declare the Track::Selectable class. + * @author James Legg + */ +/* Copyright © 2009 James Legg. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. +*/ +#ifndef LIBTRACK_SELECTABLE_H_ +#define LIBTRACK_SELECTABLE_H_ + +#include <boost/shared_ptr.hpp> +#include <LinearMath/btVector3.h> +#include "document/DocumentDelta.h" + +/** Object that reacts to mouse clicks in an editor's view of the track. + * A Selectable can be selected by clicking on it. It can also be + * moved by dragging it. + */ +namespace Track +{ + +class Selectable +{ +public: + /** Check if the object lies along a given line segment + * @param start The start position of the line in world space. + * @param stop The end position of the line in world space + * @param radius to consider points near the line + * @return true if it is on or near the line, false otherwise. + */ + virtual bool is_here(btVector3 start, btVector3 stop, btScalar radius) const = 0; + + /** Adjust a position the object was dragged to to the nearest valid + * location. + * @param position to adjust. + * @param normal direction which the user cannot see as their view + * is looking down it. + */ + virtual void snap(btVector3 & position, btVector3 normal) const; + + /** Make a DocumentDelta that moves the object to a new position. + * @param position the desired position of the Selectable after the + * DocumentDelta is applied. + * @return A shared pointer to a DocumentDelta which moves the + * selectable from its current position to the requested position. + */ + virtual boost::shared_ptr<Document::DocumentDelta> make_delta(btVector3 position) const = 0; +}; + +} + +#endif Copied: trunk/libtrack/document/ChangePropertyDelta.h (from rev 68, trunk/racer_editor/document/ChangePropertyDelta.h) =================================================================== --- trunk/libtrack/document/ChangePropertyDelta.h (rev 0) +++ trunk/libtrack/document/ChangePropertyDelta.h 2009-11-06 23:48:41 UTC (rev 69) @@ -0,0 +1,81 @@ +/** @file Document/ChangePropertyDelta.h + * @brief Declare the Document::ChangePropertyDelta class. + * @author James Legg + */ +/* Copyright © 2009 James Legg. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. +*/ + +#ifndef CHANGE_PROPERTY_DELTA_H_ +#define CHANGE_PROPERTY_DELTA_H_ + +#include "DocumentDelta.h" + +namespace Document +{ + +/** Virtual base class to help with the Identifer template parameter of + * ChangePropertyDelta. + * It is not necessary to inherit from this class, but you should write + * a class with read and write properties that do the same thing. + */ +template<class Data> +class PropertyDeltaIdentifier +{ +public: + virtual ~PropertyDeltaIdentifier() + { + } + /** Read the data from track and write it to data. + * @param track The track to extract the data from. + * @param data The variable to store the data too. + */ + virtual void read(const Track::Track & track, Data & data) = 0; + /** Write the data to track. + * @param track The track to write the data to. + * @param data The data to write. + */ + virtual void write(Track::Track & track, const Data & data) = 0; +}; + +/** Generic DocumentDelta for changing a property without adding or + * deleting data. + * @tparam Identifier A class that finds an editable property. + * @tparam Data The class of the editable property. + */ +template <class Identifier, class Data> +class ChangePropertyDelta + : public DocumentDelta +{ +public: + /** Command changes the information found by Identifier to Data. + * @param node_id The unique identifier of the node to move. + * @param destination The desired position of the node after + * applying the command. + */ + ChangePropertyDelta(Identifier identifier, Data data) + : identifier(identifier) + , new_data(data) + { + } + virtual void apply(Track::Track & track) + { + identifier.read(track, old_data); + identifier.write(track, new_data); + } + virtual void unapply(Track::Track & track) + { + identifier.write(track, old_data); + } +protected: + Identifier identifier; + Data new_data; + Data old_data; +}; + +} + +#endif Modified: trunk/libtrack/document/DocumentDelta.h =================================================================== --- trunk/racer_editor/document/DocumentDelta.h 2009-10-25 15:37:42 UTC (rev 66) +++ trunk/libtrack/document/DocumentDelta.h 2009-11-06 23:48:41 UTC (rev 69) @@ -11,7 +11,10 @@ #ifndef DOCUMENT_DELTA_H_ #define DOCUMENT_DELTA_H_ -#include <libtrack/Track.h> +namespace Track +{ + class Track; +} namespace Document { Deleted: trunk/libtrack/document/Makefile.am =================================================================== --- trunk/racer_editor/document/Makefile.am 2009-10-25 15:37:42 UTC (rev 66) +++ trunk/libtrack/document/Makefile.am 2009-11-06 23:48:41 UTC (rev 69) @@ -1,5 +0,0 @@ -noinst_LIBRARIES = libdocument.a -libdocument_a_SOURCES = Document.cpp Document.h DocumentDelta.cpp DocumentDelta.h -libdocument_a_CPPFLAGS = $(racer_editor_CFLAGS) -I@top_srcdir@ -libdocument_a_AR=$(AR) $(ARFLAGS)T - Copied: trunk/libtrack/document/Makefile.am (from rev 68, trunk/racer_editor/document/Makefile.am) =================================================================== --- trunk/libtrack/document/Makefile.am (rev 0) +++ trunk/libtrack/document/Makefile.am 2009-11-06 23:48:41 UTC (rev 69) @@ -0,0 +1,5 @@ +noinst_LIBRARIES = libdocument.a +libdocument_a_SOURCES = ChangePropertyDelta.h Document.cpp Document.h DocumentDelta.cpp DocumentDelta.h MoveNodeDelta.cpp MoveNodeDelta.h +libdocument_a_CPPFLAGS = $(debug_specific_CFLAGS) $(libtrack_CFLAGS) -I@top_srcdir@ +libdocument_a_AR=$(AR) $(ARFLAGS)T + Copied: trunk/libtrack/document/MoveNodeDelta.cpp (from rev 68, trunk/racer_editor/document/MoveNodeDelta.cpp) =================================================================== --- trunk/libtrack/document/MoveNodeDelta.cpp (rev 0) +++ trunk/libtrack/document/MoveNodeDelta.cpp 2009-11-06 23:48:41 UTC (rev 69) @@ -0,0 +1,68 @@ +/** @file Document/MoveNodeDelta.cpp + * @brief Implement the Document::MoveNodeDelta class. + * @author James Legg + */ +/* Copyright © 2009 James Legg. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. +*/ + +#include "MoveNodeDelta.h" +#include "../Track.h" + +namespace Document +{ + +NodePositionFinder::NodePositionFinder(std::size_t node_id) + : node_id(node_id) +{ +} + +void NodePositionFinder::read(const Track::Track & track, btVector3 & new_position) +{ + new_position = track.get_path().get_node(node_id).position; +} + +void NodePositionFinder::write(Track::Track & track, const btVector3 & new_position) +{ + Track::Path & path = track.get_path(); + Track::PathVertex & vertex = path.get_node(node_id); + Track::Path::Graph::vertex_descriptor vertex_descriptor = path.get_node_descriptor(node_id); + Track::Path::Graph & graph = path.graph; + vertex.position = new_position; + //update the connecting edges. + /*typedef boost::graph_traits<Track::Path::Graph>::edge_iterator EdgeIterator; + std::pair<EdgeIterator, EdgeIterator> edge_range; + for (edge_range = boost::edges(graph); + edge_range.first != edge_range.second; + edge_range.first++) + { + //Track::PathVertex vertex_1 = graph[source(*(edge_range.first), graph)]; + //Track::PathVertex vertex_2 = graph[target(*(edge_range.first), graph)]; + Track::PathEdge & edge = path.graph[*(edge_range.first)]; + //edge.update(vertex_1, vertex_2); + edge.update(); + }*/ + typedef boost::graph_traits<Track::Path::Graph>::out_edge_iterator OutEdgeIterator; + std::pair<OutEdgeIterator, OutEdgeIterator> out_edge_range; + for (out_edge_range = boost::out_edges(vertex_descriptor, graph); + out_edge_range.first != out_edge_range.second; + out_edge_range.first++) + { + Track::PathEdge & edge = path.graph[*(out_edge_range.first)]; + edge.update(); + } + typedef boost::graph_traits<Track::Path::Graph>::in_edge_iterator InEdgeIterator; + std::pair<InEdgeIterator, InEdgeIterator> in_edge_range; + for (in_edge_range = boost::in_edges(vertex_descriptor, graph); + in_edge_range.first != in_edge_range.second; + in_edge_range.first++) + { + Track::PathEdge & edge = path.graph[*(in_edge_range.first)]; + edge.update(); + } +} + +} Copied: trunk/libtrack/document/MoveNodeDelta.h (from rev 68, trunk/racer_editor/document/MoveNodeDelta.h) =================================================================== --- trunk/libtrack/document/MoveNodeDelta.h (rev 0) +++ trunk/libtrack/document/MoveNodeDelta.h 2009-11-06 23:48:41 UTC (rev 69) @@ -0,0 +1,38 @@ +/** @file Document/MoveNodeDelta.h + * @brief Declare the Document::MoveNodeDelta class. + * @author James Legg + */ +/* Copyright © 2009 James Legg. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. +*/ + +#ifndef MOVE_NODE_DELTA_H_ +#define MOVE_NODE_DELTA_H_ + +#include "ChangePropertyDelta.h" + +#include <LinearMath/btVector3.h> + +namespace Document +{ + +class NodePositionFinder : public PropertyDeltaIdentifier<btVector3> +{ +public: + NodePositionFinder(std::size_t node_id); + virtual void read(const Track::Track & track, btVector3 & new_position); + virtual void write(Track::Track & track, const btVector3 & new_position); +protected: + std::size_t node_id; +}; + +/** Command for moving control points along the path. +*/ +typedef ChangePropertyDelta<NodePositionFinder, btVector3> MoveNodeDelta; + +} + +#endif Modified: trunk/racer_editor/EditorWindow.cpp =================================================================== --- trunk/racer_editor/EditorWindow.cpp 2009-11-02 01:35:38 UTC (rev 68) +++ trunk/racer_editor/EditorWindow.cpp 2009-11-06 23:48:41 UTC (rev 69) @@ -153,6 +153,8 @@ // the scrollable top down view. m_box.pack_start(m_viewport_top); m_viewport_top.set_angle(View::VIEW_TOP); + m_viewport_top.signal_command().connect( + sigc::mem_fun(*this, &EditorWindow::on_view_command)); m_box.pack_start(m_new_form); m_new_form.show(); @@ -411,6 +413,11 @@ m_viewport_top.update(); } +void EditorWindow::on_view_command(boost::shared_ptr<Document::DocumentDelta> delta) +{ + m_document->do_command(delta); +} + bool EditorWindow::check_clear_document() { // it doesn't matter if the document is already clear. Modified: trunk/racer_editor/EditorWindow.h =================================================================== --- trunk/racer_editor/EditorWindow.h 2009-11-02 01:35:38 UTC (rev 68) +++ trunk/racer_editor/EditorWindow.h 2009-11-06 23:48:41 UTC (rev 69) @@ -24,7 +24,7 @@ #include "NewForm.h" #include "Viewport.h" -#include "document/Document.h" +#include <libtrack/document/Document.h> /** A big window for editing tracks in. * It creates a top level window, managed by the users Window manager. @@ -82,6 +82,9 @@ /// Update after a change in the document. void on_command_run(); + /// Change the document using a command generated by a view + void on_view_command(boost::shared_ptr<Document::DocumentDelta> delta); + /** Check if it is OK to clear the document. If the document has unsaved * changes, this asks the user for the result. If the user agrees but wishes * to save first, the document is saved and true is called. Modified: trunk/racer_editor/Makefile.am =================================================================== --- trunk/racer_editor/Makefile.am 2009-11-02 01:35:38 UTC (rev 68) +++ trunk/racer_editor/Makefile.am 2009-11-06 23:48:41 UTC (rev 69) @@ -1,6 +1,5 @@ -SUBDIRS = document bin_PROGRAMS = racer_editor racer_editor_SOURCES = EditorWindow.cpp NewForm.cpp RacerEditorApp.cpp View.cpp Viewport.cpp EditorWindow.h NewForm.h RacerEditorApp.h View.h Viewport.h main.cpp racer_editor_CPPFLAGS = $(racer_editor_CFLAGS) -I@top_srcdir@ $(debug_specific_CFLAGS) -Wall LIBS = $(racer_editor_LIBS) -racer_editor_LDADD = document/libdocument.a ../libtrack/libtrack.a +racer_editor_LDADD = ../libtrack/libtrack.a Modified: trunk/racer_editor/View.cpp =================================================================== --- trunk/racer_editor/View.cpp 2009-11-02 01:35:38 UTC (rev 68) +++ trunk/racer_editor/View.cpp 2009-11-06 23:48:41 UTC (rev 69) @@ -15,6 +15,9 @@ #include <GL/gl.h> #include <GL/glu.h> +const btScalar back_depth = 5000.0; +const btScalar front_depth = -5000.0; + View::View() : Gtk::GL::DrawingArea(Gdk::GL::Config::create(Gdk::GL::MODE_RGB | Gdk::GL::MODE_DEPTH | @@ -23,8 +26,14 @@ , scale(8.0) , centre(0.0, 0.0, 0.0) , view_angle(VIEW_TOP) + , new_position(centre) + , drag_object(0) { - add_events(Gdk::SCROLL_MASK); + add_events( Gdk::SCROLL_MASK + | Gdk::BUTTON_PRESS_MASK + | Gdk::BUTTON_RELEASE_MASK + | Gdk::POINTER_MOTION_MASK + ); } View::View(View & view) @@ -37,6 +46,8 @@ , scale(view.scale) , centre(view.centre) , view_angle(VIEW_TOP) + , new_position(centre) + , drag_object(0) { add_events(Gdk::SCROLL_MASK); } @@ -112,7 +123,7 @@ glLoadIdentity(); glOrtho(0.5, get_width() + 0.5, 0.5, get_height() + 0.5, - -5000.0, 5000.0); + front_depth, back_depth); glMatrixMode(GL_MODELVIEW); recentre_view(); gldrawable->gl_end(); @@ -146,6 +157,7 @@ glRotatef(90.0, 1.0, 0.0, 0.0); break; } + set_relative_depth(new_position, back_depth); needs_recentre = false; } @@ -156,8 +168,8 @@ Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable(); if (!gldrawable->gl_begin(get_gl_context())) { + DEBUG_MESSAGE(" No gl_drawable."); return false; - DEBUG_MESSAGE(" No gl_drawable."); } if (needs_recentre) @@ -247,3 +259,103 @@ } glEnd(); } + +bool View::on_button_press_event(GdkEventButton * event) +{ + // Is there something under the mouse pointer we can drag? + drag_object = get_selectable_under_mouse(); + if (drag_object) + { + DEBUG_MESSAGE("drag"); + } + return false; +} + +bool View::on_button_release_event(GdkEventButton * event) +{ + if (drag_object) + { + DEBUG_MESSAGE("drop"); + // release the object + boost::shared_ptr<Document::DocumentDelta> delta( + drag_object->make_delta(new_position) + ); + // anonunce the delta so it can be applied. + m_signal_command.emit(delta); + // Go back to coordinates from back plane. + set_relative_depth(new_position, back_depth); + } + return false; +} + +void View::set_relative_depth(btVector3 & position, btScalar depth) +{ + switch (view_angle) + { + case VIEW_TOP: + new_position.setZ(depth + centre.getZ()); + break; + case VIEW_FRONT: + new_position.setY(depth + centre.getY()); + break; + case VIEW_SIDE: + new_position.setX(depth + centre.getX()); + break; + } +} + +bool View::on_motion_notify_event(GdkEventMotion * event) +{ + new_position = mouse_to_scene(event->x, event->y); + return false; +} + +btVector3 View::mouse_to_scene(btScalar x, btScalar y) const +{ + btScalar screen_x = x / scale; + btScalar screen_y = (btScalar(get_height()) - y) / scale; + switch (view_angle) + { + case VIEW_TOP: + return btVector3(screen_x + centre.x(), screen_y + centre.y(), new_position.z()); + case VIEW_FRONT: + return btVector3(screen_x + centre.x(), new_position.y(), screen_y + centre.z()); + case VIEW_SIDE: + return btVector3(new_position.x(), screen_x + centre.y(), screen_y + centre.z()); + default: + DEBUG_MESSAGE("Warning: unhandled view"); + return new_position; + } +} + +const Track::Selectable * View::get_selectable_under_mouse() +{ + btVector3 start = new_position; + set_relative_depth(start, front_depth); + btVector3 stop = new_position; + set_relative_depth(stop, back_depth); + // find the radius of a few pixels close enough to the line + btScalar radius = 5.0 / scale; + const Track::Path & path = document->get_track().get_path(); + typedef boost::graph_traits<Track::Path::Graph>::vertex_iterator VertexIterator; + std::pair<VertexIterator, VertexIterator> vertex_range; + for (vertex_range = boost::vertices(path.graph); + vertex_range.first != vertex_range.second; + vertex_range.first++) + { + const Track::PathVertex & vertex = path.graph[*(vertex_range.first)]; + if (vertex.is_here(start, stop, radius)) + { + // Use this vertex + new_position = vertex.position; + return &vertex; + } + } + // nothing suitable found. + return 0; +} + +sigc::signal<void, boost::shared_ptr<Document::DocumentDelta> > View::signal_command() +{ + return m_signal_command; +} Modified: trunk/racer_editor/View.h =================================================================== --- trunk/racer_editor/View.h 2009-11-02 01:35:38 UTC (rev 68) +++ trunk/racer_editor/View.h 2009-11-06 23:48:41 UTC (rev 69) @@ -11,9 +11,12 @@ #ifndef VIEW_H_ #define VIEW_H_ +#include <boost/shared_ptr.hpp> + #include <gtkglmm.h> -#include <document/Document.h> +#include <libtrack/document/Document.h> +#include <libtrack/Selectable.h> /** A widget that shows a view of the track. */ @@ -88,12 +91,28 @@ { Gtk::GL::DrawingArea::realize(); } + + /** Signal emmited when the user requests a change to the track by + * interacting with the view. + * The singal should be wired to a function + * @code void on_view_command(boost::shared_ptr<Document::DocumentDelta> delta) + * @endcode + * where the delta paramter is the DocumentDelta describing the + * user requested change. + * @return signal that is emmited when the user performs an action + * to the scene by interacting with the view. + */ + sigc::signal<void, boost::shared_ptr<Document::DocumentDelta> > signal_command(); protected: // signal handlers: virtual void on_realize(); virtual bool on_configure_event(GdkEventConfigure* event); virtual bool on_expose_event(GdkEventExpose* event); virtual bool on_scroll_event(GdkEventScroll* event); + // Handle other mouse events + virtual bool on_button_press_event (GdkEventButton* event); + virtual bool on_button_release_event (GdkEventButton* event); + virtual bool on_motion_notify_event (GdkEventMotion* event); /** Set the OpenGL modelview matrix so we can draw the scene with the * correct orientation, scale, and centre. @@ -117,6 +136,32 @@ /// true if recentre_view() needs to be called during the next draw. bool needs_recentre; + + /// Find something under the mouse pointer. + const Track::Selectable * get_selectable_under_mouse(); + + /// Convert window position to scene position + btVector3 mouse_to_scene(btScalar x, btScalar y) const; + + /** New position of object being dragged, or where the line under + * the mouse hits the back plane if none. + */ + btVector3 new_position; + + /** move a position vector so its distance into the screen is the + * view's centre + a given value. + * @param position vector to move + * @param depth distance from screen centre: positive is into the + * screen, negative is out of it. + */ + void set_relative_depth(btVector3 & position, btScalar depth); + + const Track::Selectable * drag_object; + + /** Signal emmited when a command is created through the user's + * interaction. + */ + sigc::signal<void, boost::shared_ptr<Document::DocumentDelta> > m_signal_command; }; #endif /*VIEW_H_*/ Modified: trunk/racer_editor/Viewport.cpp =================================================================== --- trunk/racer_editor/Viewport.cpp 2009-11-02 01:35:38 UTC (rev 68) +++ trunk/racer_editor/Viewport.cpp 2009-11-06 23:48:41 UTC (rev 69) @@ -257,3 +257,8 @@ { m_view.realize(); } + +sigc::signal<void, boost::shared_ptr<Document::DocumentDelta> > Viewport::signal_command() +{ + return m_view.signal_command(); +} Modified: trunk/racer_editor/Viewport.h =================================================================== --- trunk/racer_editor/Viewport.h 2009-11-02 01:35:38 UTC (rev 68) +++ trunk/racer_editor/Viewport.h 2009-11-06 23:48:41 UTC (rev 69) @@ -15,7 +15,7 @@ #include <gtkmm/scrollbar.h> #include <gtkmm/adjustment.h> -#include <document/Document.h> +#include <libtrack/document/Document.h> #include "View.h" @@ -60,6 +60,18 @@ /// Realize the view so it's display lists can be shared. void realize_view(); + + /** Signal emmited when the user requests a change to the track by + * interacting with the viewport. + * The singal should be wired to a function + * @code void on_view_command(boost::shared_ptr<Document::DocumentDelta> delta) + * @endcode + * where the delta paramter is the DocumentDelta describing the + * user requested change. + * @return signal that is emmited when the user performs an action + * to the scene by interacting with the view. + */ + sigc::signal<void, boost::shared_ptr<Document::DocumentDelta> > signal_command(); protected: /// Set scrollbars and events identical in all constructors. void create(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |