From c0c5a34d1056eabdebd350da3534e24c902c0dac Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 21 Feb 2010 22:00:50 +0000 Subject: [PATCH] Add an internal layout to Catalogue for selecting tracks Restructure Designer init/deinit code Add tracks to Layout3D when it's created --- source/3d/layout.cpp | 49 +++----- source/designer/designer.cpp | 201 ++++++++++++++------------------ source/designer/designer.h | 23 ++-- source/designer/manipulator.cpp | 26 ++--- source/designer/manipulator.h | 6 +- source/libmarklin/catalogue.cpp | 9 +- source/libmarklin/catalogue.h | 4 + tracks.dat | 167 +++++++++++++++++++++++++- 8 files changed, 299 insertions(+), 186 deletions(-) diff --git a/source/3d/layout.cpp b/source/3d/layout.cpp index 1b54e4b..b95d4e5 100644 --- a/source/3d/layout.cpp +++ b/source/3d/layout.cpp @@ -7,6 +7,8 @@ Distributed under the GPL #include #include +#include +#include #include #include #include @@ -25,6 +27,10 @@ Layout3D::Layout3D(Layout &l): { layout.signal_track_added.connect(sigc::mem_fun(this, &Layout3D::track_added)); layout.signal_track_removed.connect(sigc::mem_fun(this, &Layout3D::track_removed)); + + const set <racks = layout.get_tracks(); + for(set::iterator i=ltracks.begin(); i!=ltracks.end(); ++i) + track_added(**i); } Layout3D::~Layout3D() @@ -65,41 +71,22 @@ Track3D *Layout3D::pick_track(float x, float y, float size) const GL::select_buffer(select_buf); GL::render_mode(GL::SELECT); - glPushMatrix(); - glLoadIdentity(); - - double clip[4]; - clip[0] = 1; - clip[1] = 0; - clip[2] = x-size; - clip[3] = 0; - glClipPlane(GL_CLIP_PLANE0, clip); - glEnable(GL_CLIP_PLANE0); - - clip[0] = -1; - clip[2] = -(x+size); - glClipPlane(GL_CLIP_PLANE1, clip); - glEnable(GL_CLIP_PLANE1); - - clip[0] = 0; - clip[1] = 1; - clip[2] = y-size; - glClipPlane(GL_CLIP_PLANE2, clip); - glEnable(GL_CLIP_PLANE2); - - clip[1] = -1; - clip[2] = -(y+size); - glClipPlane(GL_CLIP_PLANE3, clip); - glEnable(GL_CLIP_PLANE3); + { + GL::PushMatrix push_mat; + GL::load_identity(); - glPopMatrix(); + GL::ClipPlane(1, 0, x-size, 0).apply_to(0); + GL::ClipPlane(-1, 0, -x-size, 0).apply_to(1); + GL::ClipPlane(0, 1, y-size, 0).apply_to(2); + GL::ClipPlane(0, -1, -y-size, 0).apply_to(3); + } scene.render(0); - glDisable(GL_CLIP_PLANE0); - glDisable(GL_CLIP_PLANE1); - glDisable(GL_CLIP_PLANE2); - glDisable(GL_CLIP_PLANE3); + GL::ClipPlane::disable(0); + GL::ClipPlane::disable(1); + GL::ClipPlane::disable(2); + GL::ClipPlane::disable(3); GL::render_mode(GL::RENDER); Track3D *track = 0; diff --git a/source/designer/designer.cpp b/source/designer/designer.cpp index a28811f..02563f8 100644 --- a/source/designer/designer.cpp +++ b/source/designer/designer.cpp @@ -8,6 +8,7 @@ Distributed under the GPL #include #include #include +#include #include #include #include @@ -38,11 +39,12 @@ using namespace Msp; Application::RegApp Designer::reg; Designer::Designer(int argc, char **argv): - screen_w(1280), - screen_h(960), + window(1280, 960), base_object(0), cur_route(0), mode(SELECT), + manipulator(*this, selection), + measure(*this), input(0), cam_yaw(M_PI/2), cam_pitch(-M_PI/4), @@ -54,24 +56,22 @@ Designer::Designer(int argc, char **argv): rotate(0), pitch(0) { + window.set_title("Railway Designer"); + window.signal_close.connect(sigc::bind(sigc::mem_fun(this, &Designer::exit), 0)); + window.signal_key_press.connect(sigc::mem_fun(this, &Designer::key_press)); + window.signal_key_release.connect(sigc::mem_fun(this, &Designer::key_release)); + window.signal_button_press.connect(sigc::mem_fun(this, &Designer::button_press)); + window.signal_pointer_motion.connect(sigc::mem_fun(this, &Designer::pointer_motion)); + + manipulator.signal_status.connect(sigc::mem_fun(this, &Designer::manipulation_status)); + manipulator.signal_done.connect(sigc::mem_fun(this, &Designer::manipulation_done)); + measure.signal_changed.connect(sigc::mem_fun(this, &Designer::measure_changed)); + measure.signal_done.connect(sigc::mem_fun(this, &Designer::measure_done)); + + // Setup catalogue and layout DataFile::load(catalogue, "tracks.dat"); - cat_layout = new Layout(catalogue); - cat_layout_3d = new Layout3D(*cat_layout); - - const map &ctracks = catalogue.get_tracks(); - unsigned n = 0; - for(map::const_iterator i=ctracks.begin(); i!=ctracks.end(); ++i, ++n) - { - Track *track = new Track(*i->second); - track->set_position(Point((n%11)*0.1-0.5, 0.2-n/11*0.3, 0)); - track->set_rotation(M_PI/2); - cat_layout->add_track(*track); - } - - manipulator = new Manipulator(*this); - manipulator->signal_status.connect(sigc::mem_fun(this, &Designer::manipulation_status)); - manipulator->signal_done.connect(sigc::mem_fun(this, &Designer::manipulation_done)); + cat_layout_3d = new Layout3D(catalogue.get_layout()); layout = new Layout(catalogue); layout_3d = new Layout3D(*layout); @@ -91,42 +91,13 @@ Designer::Designer(int argc, char **argv): } } - selection = new Selection; - manipulator->set_selection(selection); - - measure = new Measure(*this); - measure->signal_changed.connect(sigc::mem_fun(this, &Designer::measure_changed)); - measure->signal_done.connect(sigc::mem_fun(this, &Designer::measure_done)); -} - -Designer::~Designer() -{ - delete manipulator; - delete selection; - delete layout; - delete layout_3d; - delete cat_layout; - delete cat_layout_3d; - delete measure; -} - -int Designer::main() -{ - dpy = new Graphics::Display; - wnd = new Graphics::Window(*dpy, screen_w, screen_h); - glc = new Graphics::GLContext(*wnd); - wnd->set_title("Railway Designer"); - - wnd->signal_close.connect(sigc::bind(sigc::mem_fun(this, &Designer::exit), 0)); - wnd->show(); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnable(GL_DEPTH_TEST); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_CULL_FACE); + // Setup OpenGL + GL::enable(GL::DEPTH_TEST); + GL::enable(GL::BLEND); + GL::blend_func(GL::SRC_ALPHA, GL::ONE_MINUS_SRC_ALPHA); + GL::enable(GL_CULL_FACE); - pipeline = new GL::Pipeline(screen_w, screen_h, false); + pipeline = new GL::Pipeline(window.get_width(), window.get_height(), false); pipeline->add_renderable(layout_3d->get_scene()); if(base_object) pipeline->add_renderable(*base_object); @@ -137,8 +108,9 @@ int Designer::main() GL::PipelinePass *pass = &pipeline->add_pass(GL::Tag()); pass->lighting = &lighting; + // Setup UI DataFile::load(ui_res, "marklin.res"); - root = new GLtk::Root(ui_res, *wnd); + root = new GLtk::Root(ui_res, window); lbl_tooltip = new GLtk::Label(ui_res); lbl_tooltip->set_style("tooltip"); @@ -147,26 +119,25 @@ int Designer::main() toolbar = new Toolbar(*this); root->add(*toolbar); - toolbar->set_position(0, screen_h-toolbar->get_geometry().h); + toolbar->set_position(0, window.get_height()-toolbar->get_geometry().h); toolbar->set_visible(true); +} +Designer::~Designer() +{ + delete root; + delete layout; + delete layout_3d; + delete cat_layout_3d; +} - wnd->signal_key_press.connect(sigc::mem_fun(this, &Designer::key_press)); - wnd->signal_key_release.connect(sigc::mem_fun(this, &Designer::key_release)); - wnd->signal_button_press.connect(sigc::mem_fun(this, &Designer::button_press)); - wnd->signal_pointer_motion.connect(sigc::mem_fun(this, &Designer::pointer_motion)); +int Designer::main() +{ + window.show(); mode = SELECT; - Application::main(); - - delete root; - - delete glc; - delete wnd; - delete dpy; - - return exit_code; + return Application::main(); } void Designer::save() @@ -194,7 +165,7 @@ void Designer::add_selection_to_route() try { - const set &stracks = selection->get_tracks(); + const set &stracks = selection.get_tracks(); set tracks(stracks.begin(), stracks.end()); cur_route->add_tracks(tracks); } @@ -218,8 +189,8 @@ void Designer::map_pointer_coords(int x, int y, float &gx, float &gy) float uy = sin_yaw*-sin_pitch*0.41421; float uz = cos_pitch*0.41421; - float xf = static_cast(x)*2/screen_w-1; - float yf = static_cast(y)*2/screen_h-1; + float xf = static_cast(x)*2/window.get_width()-1; + float yf = static_cast(y)*2/window.get_height()-1; float vx = cos_yaw*cos_pitch + xf*rx + yf*ux; float vy = sin_yaw*cos_pitch + xf*ry + yf*uy; @@ -235,7 +206,7 @@ void Designer::tick() float dt = (t-last_tick)/Msp::Time::sec; last_tick = t; - dpy->tick(); + window.get_display().tick(); if(move_y) { @@ -312,7 +283,7 @@ void Designer::tick() render(); - glc->swap_buffers(); + window.swap_buffers(); } void Designer::key_press(unsigned code, unsigned mod, wchar_t) @@ -329,24 +300,24 @@ void Designer::key_press(unsigned code, unsigned mod, wchar_t) mode = CATALOGUE; else if(key==Msp::Input::KEY_G) { - manipulator->start_move(); + manipulator.start_move(); mode = MANIPULATE; } else if(key==Msp::Input::KEY_R) { - manipulator->start_rotate(); + manipulator.start_rotate(); mode = MANIPULATE; } else if(key==Msp::Input::KEY_D) { - manipulator->duplicate(); - manipulator->start_move(); + manipulator.duplicate(); + manipulator.start_move(); mode = MANIPULATE; } else if(key==Msp::Input::KEY_W) save(); else if(key==Msp::Input::KEY_PLUS) - selection->select_more(); + selection.select_more(); else if(key==Msp::Input::KEY_L && (mod&1)) { const set &tracks = layout->get_tracks(); @@ -356,30 +327,30 @@ void Designer::key_press(unsigned code, unsigned mod, wchar_t) IO::print("Total length: %.1fm\n", len); } else if(key==Msp::Input::KEY_L) - selection->select_linked(); + selection.select_linked(); else if(key==Msp::Input::KEY_M) { - measure->start(); + measure.start(); mode = MEASURE; } else if(key==Msp::Input::KEY_Z) { - manipulator->start_elevate(); + manipulator.start_elevate(); mode = MANIPULATE; } else if(key==Msp::Input::KEY_ESC) { if(mode==MANIPULATE) - manipulator->cancel(); + manipulator.cancel(); else if(mode==CATALOGUE) mode = SELECT; else - selection->clear(); + selection.clear(); } else if(key==Msp::Input::KEY_X) { - set tracks = selection->get_tracks(); - selection->clear(); + set tracks = selection.get_tracks(); + selection.clear(); for(set::iterator i=tracks.begin(); i!=tracks.end(); ++i) { layout->remove_track(**i); @@ -388,7 +359,7 @@ void Designer::key_press(unsigned code, unsigned mod, wchar_t) } else if(key==Msp::Input::KEY_F && (mod&1)) { - const set &tracks = selection->get_tracks(); + const set &tracks = selection.get_tracks(); const set <racks = layout->get_tracks(); for(set::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) { @@ -402,15 +373,15 @@ void Designer::key_press(unsigned code, unsigned mod, wchar_t) } } else if(key==Msp::Input::KEY_F) - manipulator->flatten(); + manipulator.flatten(); else if(key==Msp::Input::KEY_E && (mod&1)) - manipulator->even_slope(true); + manipulator.even_slope(true); else if(key==Msp::Input::KEY_E) - manipulator->even_slope(); + manipulator.even_slope(); else if(key==Msp::Input::KEY_T) { - Track *track = selection->get_track(); - if(selection->size()==1 && track->get_type().get_n_paths()>1) + Track *track = selection.get_track(); + if(selection.size()==1 && track->get_type().get_n_paths()>1) { input = new ::Input(*this, "Turnout ID", lexical_cast(track->get_turnout_id())); input->signal_cancel.connect(sigc::mem_fun(this, &Designer::input_dismiss)); @@ -420,7 +391,7 @@ void Designer::key_press(unsigned code, unsigned mod, wchar_t) } else if(key==Msp::Input::KEY_S) { - const set &tracks = selection->get_tracks(); + const set &tracks = selection.get_tracks(); bool ok = false; int id = -1; for(set::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) @@ -490,7 +461,7 @@ void Designer::key_release(unsigned code, unsigned) void Designer::button_press(int x, int y, unsigned btn, unsigned) { - y = screen_h-y-1; + y = window.get_height()-y-1; float gx, gy; map_pointer_coords(x, y, gx, gy); @@ -506,8 +477,8 @@ void Designer::button_press(int x, int y, unsigned btn, unsigned) track->set_position(Point(gx, gy, 0)); layout->add_track(*track); - selection->clear(); - selection->add_track(track); + selection.clear(); + selection.add_track(track); mode = SELECT; } @@ -523,20 +494,20 @@ void Designer::button_press(int x, int y, unsigned btn, unsigned) if(track) { if(!shift) - selection->clear(); - selection->toggle_track(&track->get_track()); + selection.clear(); + selection.toggle_track(&track->get_track()); } } } else if(mode==MANIPULATE) - manipulator->button_press(x, y, gx, gy, btn); + manipulator.button_press(x, y, gx, gy, btn); else if(mode==MEASURE) - measure->button_press(x, y, gx, gy, btn); + measure.button_press(x, y, gx, gy, btn); } void Designer::pointer_motion(int x, int y) { - y = screen_h-y-1; + y = window.get_height()-y-1; pointer_x = x; pointer_y = y; @@ -550,8 +521,8 @@ void Designer::pointer_motion(int x, int y) { float gx, gy; map_pointer_coords(x, y, gx, gy); - manipulator->pointer_motion(x, y, gx, gy); - measure->pointer_motion(x, y, gx, gy); + manipulator.pointer_motion(x, y, gx, gy); + measure.pointer_motion(x, y, gx, gy); } } @@ -609,14 +580,14 @@ void Designer::render() } }*/ - manipulator->render(); + manipulator.render(); if(mode==MEASURE) - measure->render(); + measure.render(); } GL::matrix_mode(GL::PROJECTION); GL::load_identity(); - GL::ortho_bottomleft(screen_w, screen_h); + GL::ortho_bottomleft(window.get_width(), window.get_height()); GL::matrix_mode(GL::MODELVIEW); GL::load_identity(); @@ -631,9 +602,9 @@ Track3D *Designer::pick_track(int x, int y) if(mode==CATALOGUE) l = cat_layout_3d; - float xx = (static_cast(x-static_cast(screen_w)/2)/screen_h)*0.82843; - float yy = (static_cast(y)/screen_h-0.5)*0.82843; - float size = 4.0/screen_h*0.82843; + float xx = ((float(x)-window.get_width()/2)/window.get_height())*0.82843; + float yy = (float(y)/window.get_height()-0.5)*0.82843; + float size = 4.0/window.get_height()*0.82843; project_3d(); apply_camera(); @@ -670,10 +641,10 @@ void Designer::manipulation_done(bool) void Designer::measure_changed() { - float pard = measure->get_parallel_distance()*1000; - float perpd = measure->get_perpendicular_distance()*1000; + float pard = measure.get_parallel_distance()*1000; + float perpd = measure.get_perpendicular_distance()*1000; float d = sqrt(pard*pard+perpd*perpd); - float adiff = measure->get_angle_difference()*180/M_PI; + float adiff = measure.get_angle_difference()*180/M_PI; string info = format("Par %.1fmm - Perp %.1fmm - Total %.1fmm - Angle %.1f°", pard, perpd, d, adiff); set_tooltip(pointer_x, pointer_y, info); } @@ -688,8 +659,8 @@ void Designer::set_tooltip(int x, int y, const std::string &text) int fontsize = ui_res.get_default_font().get_default_size(); int h = fontsize+6; int w = static_cast(ui_res.get_default_font().get_string_width(text)*fontsize)+6; - x = max(min(static_cast(screen_w)-w, x), 0); - y = max(min(static_cast(screen_h)-h, y), 0); + x = max(min(static_cast(window.get_width())-w, x), 0); + y = max(min(static_cast(window.get_height())-h, y), 0); lbl_tooltip->set_text(text); lbl_tooltip->set_geometry(GLtk::Geometry(x, y, w, h)); lbl_tooltip->set_visible(true); @@ -709,7 +680,7 @@ void Designer::save_accept() void Designer::turnout_id_accept() { - Track *track = selection->get_track(); + Track *track = selection.get_track(); unsigned id = lexical_cast(input->get_text()); track->set_turnout_id(id); @@ -720,7 +691,7 @@ void Designer::turnout_id_accept() void Designer::sensor_id_accept() { - const set &tracks = selection->get_tracks(); + const set &tracks = selection.get_tracks(); unsigned id = lexical_cast(input->get_text()); for(set::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) { diff --git a/source/designer/designer.h b/source/designer/designer.h index 1407d50..37a4a1e 100644 --- a/source/designer/designer.h +++ b/source/designer/designer.h @@ -10,9 +10,7 @@ Distributed under the GPL #include #include -#include -#include -#include +#include #include #include #include @@ -26,11 +24,11 @@ Distributed under the GPL #include "libmarklin/layout.h" #include "3d/layout.h" #include "3d/track.h" +#include "manipulator.h" +#include "measure.h" +#include "selection.h" class Input; -class Manipulator; -class Measure; -class Selection; class Toolbar; class Designer: public Msp::Application @@ -45,11 +43,7 @@ private: INPUT }; - Msp::Graphics::Display *dpy; - Msp::Graphics::Window *wnd; - Msp::Graphics::GLContext *glc; - unsigned screen_w; - unsigned screen_h; + Msp::Graphics::SimpleGLWindow window; Msp::GLtk::Resources ui_res; Msp::GLtk::Root *root; @@ -58,7 +52,6 @@ private: Msp::Time::TimeStamp tooltip_timeout; Marklin::Catalogue catalogue; - Marklin::Layout *cat_layout; Marklin::Layout3D *cat_layout_3d; std::string filename; Marklin::Layout *layout; @@ -70,9 +63,9 @@ private: Msp::GL::Light light; Mode mode; - Selection *selection; - Manipulator *manipulator; - Measure *measure; + Selection selection; + Manipulator manipulator; + Measure measure; Input *input; float cam_yaw; diff --git a/source/designer/manipulator.cpp b/source/designer/manipulator.cpp index 09d32fd..e690c1d 100644 --- a/source/designer/manipulator.cpp +++ b/source/designer/manipulator.cpp @@ -19,23 +19,14 @@ using namespace std; using namespace Marklin; using namespace Msp; -Manipulator::Manipulator(Designer &d): +Manipulator::Manipulator(Designer &d, Selection &s): designer(d), - selection(0), + selection(s), wrap_rot(0), mode(NONE), angle(0) -{ } - -void Manipulator::set_selection(Selection *s) { - selection_changed_conn.disconnect(); - - selection = s; - if(selection) - selection_changed_conn = selection->signal_changed.connect(sigc::mem_fun(this, &Manipulator::selection_changed)); - - selection_changed(); + selection.signal_changed.connect(sigc::mem_fun(this, &Manipulator::selection_changed)); } void Manipulator::start_move() @@ -81,10 +72,10 @@ void Manipulator::duplicate() new_tracks.push_back(track); } - selection->clear(); + selection.clear(); for(list::iterator i=new_tracks.begin(); i!=new_tracks.end(); ++i) { - selection->add_track(*i); + selection.add_track(*i); for(list::iterator j=i; j!=new_tracks.end(); ++j) if(j!=i) (*i)->snap_to(**j, true); @@ -372,11 +363,8 @@ void Manipulator::selection_changed() cancel(); tracks.clear(); - if(selection) - { - const set &stracks = selection->get_tracks(); - tracks.insert(tracks.end(), stracks.begin(), stracks.end()); - } + const set &stracks = selection.get_tracks(); + tracks.insert(tracks.end(), stracks.begin(), stracks.end()); update_neighbors(); update_wrap(); diff --git a/source/designer/manipulator.h b/source/designer/manipulator.h index 9177f97..2ed49fb 100644 --- a/source/designer/manipulator.h +++ b/source/designer/manipulator.h @@ -56,7 +56,7 @@ public: private: Designer &designer; - Selection *selection; + Selection &selection; std::vector tracks; Marklin::Point center; @@ -72,12 +72,10 @@ private: float rot_origin; int elev_origin; std::set neighbors; - sigc::connection selection_changed_conn; public: - Manipulator(Designer &); + Manipulator(Designer &, Selection &); - void set_selection(Selection *); void start_move(); void start_rotate(); void start_elevate(); diff --git a/source/libmarklin/catalogue.cpp b/source/libmarklin/catalogue.cpp index 3c9cf7d..cce5ef0 100644 --- a/source/libmarklin/catalogue.cpp +++ b/source/libmarklin/catalogue.cpp @@ -18,7 +18,8 @@ namespace Marklin { Catalogue::Catalogue(): scale(1), - gauge(1.524) + gauge(1.524), + layout(*this) { } Catalogue::~Catalogue() @@ -53,6 +54,7 @@ Catalogue::Loader::Loader(Catalogue &c): { add("ballast_profile", &Loader::ballast_profile); add("gauge", &Loader::gauge); + add("layout", &Loader::layout); add("locomotive", &Loader::locomotive); add("rail_profile", &Loader::rail_profile); add("scale", &Loader::scale); @@ -69,6 +71,11 @@ void Catalogue::Loader::gauge(float g) obj.gauge = g/1000; } +void Catalogue::Loader::layout() +{ + load_sub(obj.layout); +} + void Catalogue::Loader::locomotive(unsigned art_nr) { if(obj.locos.count(art_nr)) diff --git a/source/libmarklin/catalogue.h b/source/libmarklin/catalogue.h index 5d88c28..e531941 100644 --- a/source/libmarklin/catalogue.h +++ b/source/libmarklin/catalogue.h @@ -10,6 +10,7 @@ Distributed under the GPL #include #include +#include "layout.h" #include "profile.h" namespace Marklin { @@ -27,6 +28,7 @@ public: private: void ballast_profile(); void gauge(float); + void layout(); void locomotive(unsigned); void rail_profile(); void scale(float, float); @@ -40,6 +42,7 @@ private: Profile ballast_profile; std::map tracks; std::map locos; + Layout layout; public: Catalogue(); @@ -53,6 +56,7 @@ public: const std::map &get_tracks() const { return tracks; } LocoType &get_locomotive(unsigned) const; const std::map &get_locomotives() const { return locos; } + Layout &get_layout() { return layout; } }; } // namespace Marklin diff --git a/tracks.dat b/tracks.dat index 7b7ba57..7c800f1 100644 --- a/tracks.dat +++ b/tracks.dat @@ -30,7 +30,7 @@ track 24064 track 24071 { - description "Straight, 70.3mm (for slim turnouts)"; + description "Straight, 70.8mm (for slim turnouts)"; part { length 70.8; @@ -446,3 +446,168 @@ track 24977 }; }; +// Layout for selecting tracks + +layout +{ + track 24115 + { + position 0.0806517 0.139002 0; + rotation 2.22529; + }; + track 24612 + { + position -0.310086 -0.38055 0; + rotation 1.5708; + }; + track 24172 + { + position -0.232565 -0.0797749 0; + rotation 1.5708; + }; + track 24611 + { + position -0.387608 -0.380475 0; + rotation 1.5708; + }; + track 24130 + { + position 0.155044 -0.08015 0; + rotation 1.5708; + }; + track 24230 + { + position 0.232566 -0.0802249 0; + rotation 1.5708; + }; + track 24107 + { + position -0.0249545 0.231617 0; + rotation 2.61799; + }; + track 24224 + { + position -0.465131 -0.38055 0; + rotation 1.5708; + }; + track 24330 + { + position 0.310088 -0.0803 0; + rotation 1.5708; + }; + track 24215 + { + position 0.142158 0.186105 0; + rotation 2.2253; + }; + track 24207 + { + position 0.0138165 0.298658 0; + rotation 2.61799; + }; + track 24711 + { + position 0.374455 -0.381008 0; + rotation 1.5708; + }; + track 24530 + { + position 0.438821 -0.0809179 0; + rotation 1.5708; + }; + track 24430 + { + position 0.374455 -0.080609 0; + rotation 1.5708; + }; + track 24630 + { + position -0.19005 -0.380551 0; + rotation 1.5708; + }; + track 24712 + { + position 0.438821 -0.381316 0; + rotation 1.5708; + }; + track 24624 + { + position -0.0775215 -0.380625 0; + rotation 1.5708; + }; + track 24640 + { + position -0.232565 0.185972 0; + rotation 1.5708; + }; + track 24671 + { + position 0.0775225 -0.380624 0; + rotation 1.5708; + }; + track 24977 + { + position -0.465131 0.186196 0; + rotation 1.5708; + }; + track 24672 + { + position 0.155044 -0.380699 0; + rotation 1.5708; + }; + track 24649 + { + position -0.348827 0.194312 0; + rotation 1.99491; + }; + track 24064 + { + position 0.0775223 -0.080075 0; + rotation 1.5708; + }; + track 24077 + { + position -0.0775215 -0.079925 0; + rotation 1.5708; + }; + track 24229 + { + position -0.387609 -0.079626 0; + rotation 1.5708; + }; + track 24071 + { + position 2.56295e-07 -0.0799999 0; + rotation 1.5708; + }; + track 24094 + { + position -0.155042 -0.07985 0; + rotation 1.5708; + }; + track 24188 + { + position -0.310087 -0.0797 0; + rotation 1.5708; + }; + track 24236 + { + position -0.465131 -0.0795509 0; + rotation 1.5708; + }; + track 24912 + { + position 0.310088 -0.380699 0; + rotation 1.5708; + }; + track 24206 + { + position -0.446223 -0.161726 0; + rotation 2.0944; + }; + track 24740 + { + position -0.112537 0.138174 0; + rotation 1.5708; + }; +}; -- 2.43.0