Index: simwerkz.cc =================================================================== --- simwerkz.cc (revision 2484) +++ simwerkz.cc (working copy) @@ -1794,9 +1794,11 @@ return NULL; } -bool wkz_wayobj_t::init( karte_t *welt, spieler_t *sp ) +bool wkz_wayobj_t::init( karte_t *welt_, spieler_t *sp_ ) { - const way_obj_besch_t *besch = default_param ? wayobj_t::find_besch(default_param) : NULL; + welt = welt_; + sp = sp_; + besch = default_param ? wayobj_t::find_besch(default_param) : NULL; if(besch==NULL) { besch = default_electric; if(besch==NULL) { @@ -1806,62 +1808,164 @@ else { default_electric = besch; } + if( besch ) { + cursor = besch->get_cursor()->get_bild_nr(0); + } erster = true; welt->show_distance = start = koord3d::invalid; - if(wkz_wayobj_bauer != NULL) { + + cleanup( true ); + return besch!=NULL; +} + +void wkz_wayobj_t::cleanup( bool delete_wayobj_bauer ) +{ + // delete marker. + if(wkz_wayobj_bauer != NULL && delete_wayobj_bauer ) { wkz_wayobj_bauer->mark_image_dirty( skinverwaltung_t::bauigelsymbol->get_bild_nr(0), 0 ); delete wkz_wayobj_bauer; wkz_wayobj_bauer = NULL; } - return besch!=NULL; + // delete old route. + while(!marked.empty()) { + zeiger_t *z = marked.remove_first(); + z->mark_image_dirty( z->get_bild(), 0 ); + z->mark_image_dirty( z->get_after_bild(), 0 ); + delete z; + } + + // delete tooltip. + win_set_static_tooltip( NULL ); } -const char *wkz_wayobj_t::work( karte_t *welt, spieler_t *sp, koord3d pos ) +void wkz_wayobj_t::start_at( grund_t *new_start ) { - const way_obj_besch_t *besch = wayobj_t::find_besch(default_param); - if(besch==NULL) { - besch = default_electric; + erster = false; + welt->show_distance = start = new_start->get_pos(); + wkz_wayobj_bauer = new zeiger_t(welt, start, sp); + wkz_wayobj_bauer->set_bild( besch->get_cursor()->get_bild_nr(0) ); + new_start->obj_add(wkz_wayobj_bauer); + DBG_MESSAGE("wkz_wayobj()", "Setting start to %d,%d,%d",start.x, start.y,start.z); +} + +bool wkz_wayobj_t::calc_route( route_t &verbindung, const grund_t *to ) +{ + // get a default vehikel + vehikel_besch_t remover_besch( besch->get_wtyp(), 500, vehikel_besch_t::diesel ); + vehikel_t* test_driver = vehikelbauer_t::baue(start, sp, NULL, &remover_besch); + bool can_built = verbindung.calc_route(welt, start, to->get_pos(), test_driver, 0); + delete test_driver; + return can_built; +} + +const char *wkz_wayobj_t::move( karte_t * /*welt*/, spieler_t * /*sp*/, uint16 /* buttonstate */, koord3d pos ) +{ + // search for starting ground + grund_t *gr=wkz_intern_koord_to_weg_grund(sp,welt,pos, besch->get_wtyp() ); + if(gr==NULL) { + cleanup( false ); + DBG_MESSAGE("wkz_wayobj()", "no ground on %i,%i",pos.x, pos.y); + // wrong ground or not this way here => exit, but no error message (while dragging) + return NULL; } - waytype_t wt=besch->get_wtyp(); - koord3d end; + // ignore start == pos. + if( start == pos ) { + init( welt, sp ); + } + + if( start == koord3d::invalid ) { + // start dragging. + cleanup( true ); + start_at( gr ); + } + else { + // continue dragging. + cleanup( false ); + + display_show_load_pointer(true); + route_t verbindung; + bool can_built = calc_route( verbindung, gr ); + if( can_built ) { + sint32 cost_estimate = 0; + + for( uint32 j = 0; j <= verbindung.get_max_n(); j++ ) { + koord3d pos = verbindung.position_bei(j); + grund_t *gr = welt->lookup(pos); + + cost_estimate += besch->get_preis(); + + ribi_t::ribi show = ribi_t::keine; + // Search a matching catenary on gr. + wayobj_t *wayobj = gr->get_wayobj( besch->get_wtyp() ); + if( wayobj ) { + show = wayobj->get_dir(); + // Already a catenary here -> costs only, if new catenary is faster (this case is neglected here): + cost_estimate -= besch->get_preis(); + } + + if(j>0) { + show |= ribi_typ( verbindung.position_bei(j-1).get_2d()-pos.get_2d() ); + } + if(jget_weg_hang() ) { + way_obj->set_after_bild( besch->get_front_slope_image_id(gr->get_weg_hang()) ); + way_obj->set_bild( besch->get_back_slope_image_id(gr->get_weg_hang()) ); + } + else if( ribi_t::ist_kurve(show) && besch->has_diagonal_bild() ) { + way_obj->set_after_bild( besch->get_front_diagonal_image_id(show) ); + way_obj->set_bild( besch->get_back_diagonal_image_id(show) ); + } + else { + way_obj->set_after_bild( besch->get_front_image_id(show) ); + way_obj->set_bild( besch->get_back_image_id(show) ); + } + way_obj->mark_image_dirty( way_obj->get_bild(), 0 ); + gr->obj_add( way_obj ); + marked.insert( way_obj ); + + } + win_set_static_tooltip( tooltip_with_price("Building costs estimates", cost_estimate ) ); + } + display_show_load_pointer(false); + } + return NULL; +} + +const char *wkz_wayobj_t::work( karte_t * /*welt*/, spieler_t * /*sp*/, koord3d pos ) +{ + // remove marker + cleanup( true ); + // search for starting ground - grund_t *gr=wkz_intern_koord_to_weg_grund(sp,welt,pos,wt); + grund_t *gr=wkz_intern_koord_to_weg_grund(sp,welt,pos, besch->get_wtyp() ); if(gr==NULL) { - DBG_MESSAGE("wkz_wayremover()", "no ground on %i,%i",pos.x, pos.y); + DBG_MESSAGE("wkz_wayobj()", "no ground on %i,%i",pos.x, pos.y); // wrong ground or not this way here => exit return ""; } if( erster ) { // set start position - erster = false; - welt->show_distance = start = gr->get_pos(); - wkz_wayobj_bauer = new zeiger_t(welt, start, sp); - wkz_wayobj_bauer->set_bild( besch->get_cursor()->get_bild_nr(0) ); - gr->obj_add(wkz_wayobj_bauer); - DBG_MESSAGE("wkz_wayremover()", "Setting start to %d,%d,%d",start.x, start.y,start.z); + start_at( gr ); } else { - DBG_MESSAGE("wkz_wayremover()", "Setting end to %d,%d,%d",gr->get_pos().x, gr->get_pos().y,gr->get_pos().z); + DBG_MESSAGE("wkz_wayobj()", "Setting end to %d,%d,%d",gr->get_pos().x, gr->get_pos().y,gr->get_pos().z); - // remove marker - wkz_wayobj_bauer->mark_image_dirty( skinverwaltung_t::bauigelsymbol->get_bild_nr(0), 0 ); - delete wkz_wayobj_bauer ; - wkz_wayobj_bauer = NULL; erster = true; - // get a default vehikel - vehikel_besch_t remover_besch(wt, 500, vehikel_besch_t::diesel ); - vehikel_t* test_driver = vehikelbauer_t::baue(start, sp, NULL, &remover_besch); route_t verbindung; - bool can_built = verbindung.calc_route(welt, start, gr->get_pos(), test_driver, 0); - delete test_driver; + bool can_built = calc_route( verbindung, gr ); + welt->show_distance = start = koord3d::invalid; - DBG_MESSAGE("wkz_wayremover()","route search returned %d",can_built); + DBG_MESSAGE("wkz_wayobj()","route search returned %d",can_built); if(!can_built) { - DBG_MESSAGE("wkz_wayremover()","no route found"); + DBG_MESSAGE("wkz_wayobj()","no route found"); return "Ways not connected"; } Index: simwerkz.h =================================================================== --- simwerkz.h (revision 2484) +++ simwerkz.h (working copy) @@ -230,16 +230,26 @@ class wkz_wayobj_t : public werkzeug_t { private: + static const way_obj_besch_t *default_electric; + koord3d start; bool erster; zeiger_t *wkz_wayobj_bauer; - static const way_obj_besch_t *default_electric; + slist_tpl< zeiger_t* > marked; + karte_t *welt; + spieler_t *sp; + const way_obj_besch_t *besch; + + void cleanup( bool delete_wayobj_bauer ); + void start_at( grund_t *new_start ); + bool calc_route( route_t &, const grund_t *to ); public: wkz_wayobj_t() : werkzeug_t() { wkz_wayobj_bauer=NULL; } const char *get_tooltip(spieler_t *); bool init( karte_t *, spieler_t * ); bool exit( karte_t *w, spieler_t *s ) { return init(w,s); } virtual const char *work( karte_t *, spieler_t *, koord3d ); + virtual const char *move( karte_t *, spieler_t *, uint16 buttonstate, koord3d ); }; class wkz_station_t : public werkzeug_t { Index: boden/grund.cc =================================================================== --- boden/grund.cc (revision 2484) +++ boden/grund.cc (working copy) @@ -1256,3 +1256,27 @@ { return freelist_t::putback_node(s, p); } + +wayobj_t *grund_t::get_wayobj( waytype_t wt ) const +{ + waytype_t wt1 = ( wt == tram_wt ) ? track_wt : wt; + + wayobj_t *wayobj; + if( find() ) { + // since there might be more than one, we have to iterate through all of them + for( uint8 i = 0; i < get_top(); i++ ) { + ding_t *d = obj_bei(i); + if( d && d->get_typ() == ding_t::wayobj ) { + wayobj = (wayobj_t *)d; + waytype_t wt2 = wayobj->get_besch()->get_wtyp(); + if( wt2 == tram_wt ) { + wt2 = track_wt; + } + if( wt1 == wt2 ) { + return wayobj; + } + } + } + } + return NULL; +} Index: boden/grund.h =================================================================== --- boden/grund.h (revision 2484) +++ boden/grund.h (working copy) @@ -535,6 +535,11 @@ virtual hang_t::typ get_weg_hang() const { return get_grund_hang(); } + /* + * Search a matching wayobj + */ + wayobj_t *get_wayobj( waytype_t wt ) const; + /** * Interface zur Bauen der Wege * ============================= Index: dings/zeiger.cc =================================================================== --- dings/zeiger.cc (revision 2484) +++ dings/zeiger.cc (working copy) @@ -19,6 +19,7 @@ changed = false; richtung = ribi_t::alle; bild = IMG_LEER; + after_bild = IMG_LEER; area = koord(0,0); center = 0; rdwr(file); @@ -32,13 +33,13 @@ set_besitzer( sp ); richtung = ribi_t::alle; bild = IMG_LEER; + after_bild = IMG_LEER; area = koord(0,0); center = 0; } -void -zeiger_t::change_pos(koord3d k ) +void zeiger_t::change_pos(koord3d k ) { if(k!=get_pos()) { // remove from old position @@ -54,6 +55,7 @@ welt->mark_area( get_pos()-(area*center)/2, area, false ); } mark_image_dirty( get_bild(), 0 ); + mark_image_dirty( get_after_bild(), 0 ); set_flag(ding_t::dirty); ding_t::set_pos(k); @@ -77,8 +79,7 @@ } -void -zeiger_t::set_richtung(ribi_t::ribi r) +void zeiger_t::set_richtung(ribi_t::ribi r) { if(richtung != r) { richtung = r; @@ -86,8 +87,7 @@ } -void -zeiger_t::set_bild( image_id b ) +void zeiger_t::set_bild( image_id b ) { // mark dirty mark_image_dirty( bild, 0 ); @@ -103,9 +103,24 @@ } +void zeiger_t::set_after_bild( image_id b ) +{ + // mark dirty + mark_image_dirty( after_bild, 0 ); + mark_image_dirty( b, 0 ); + after_bild = b; + if( (area.x|area.y)>1 ) { + welt->mark_area( get_pos()-(area*center)/2, area, false ); + } + if(!changed) { + area = koord(0,0); + center = 0; + } +} + + /* change the marked area around the cursor */ -void -zeiger_t::set_area(koord new_area, uint8 new_center) +void zeiger_t::set_area(koord new_area, uint8 new_center) { changed = true; if(new_area==area && (new_center^center)) { Index: dings/zeiger.h =================================================================== --- dings/zeiger.h (revision 2484) +++ dings/zeiger.h (working copy) @@ -18,7 +18,7 @@ uint8 center; bool changed; ribi_t::ribi richtung; - image_id bild; + image_id bild, after_bild; public: void set_richtung(ribi_t::ribi r); @@ -42,6 +42,9 @@ void set_bild( image_id b ); image_id get_bild() const {return bild;} + + void set_after_bild( image_id b ); + image_id get_after_bild() const {return after_bild;} }; #endif Index: dings/wayobj.cc =================================================================== --- dings/wayobj.cc (revision 2484) +++ dings/wayobj.cc (working copy) @@ -214,7 +214,7 @@ grund_t *to; ribi_t::ribi r1 = ribi_t::keine; if(start->get_neighbour(to,wt,dir)) { - const wayobj_t* wo = to->find(); + const wayobj_t* wo = to->get_wayobj( wt ); if(wo) { r1 = wo->get_dir(); } @@ -304,7 +304,7 @@ rekursion++; for(int r = 0; r < 4; r++) { if(gr->get_neighbour(to, wt, koord::nsow[r])) { - wayobj_t* wo = to->find(); + wayobj_t* wo = to->get_wayobj( wt ); if(wo) { wo->calc_bild(); } @@ -331,41 +331,28 @@ /* better use this constrcutor for new wayobj; it will extend a matching obj or make an new one */ -void -wayobj_t::extend_wayobj_t(karte_t *welt, koord3d pos, spieler_t *besitzer, ribi_t::ribi dir, const way_obj_besch_t *besch) +void wayobj_t::extend_wayobj_t(karte_t *welt, koord3d pos, spieler_t *besitzer, ribi_t::ribi dir, const way_obj_besch_t *besch) { grund_t *gr=welt->lookup(pos); - waytype_t wt1 = besch->get_wtyp()==tram_wt ? track_wt : besch->get_wtyp(); if(gr) { - if (gr->find()) { - // since there might be more than one, we have to iterate through all of them - for( uint8 i=0; iget_top(); i++ ) { - ding_t *d=gr->obj_bei(i); - if(d && d->get_typ()==ding_t::wayobj ) { - waytype_t wt2 = ((wayobj_t *)d)->get_besch()->get_wtyp(); - if(wt2==tram_wt) { - wt2 = track_wt; - } - if( wt1==wt2 ) { - if(((wayobj_t *)d)->get_besch()->get_topspeed()get_topspeed() && spieler_t::check_owner(besitzer, d->get_besitzer())) { - // replace slower by faster - gr->obj_remove(d); - gr->set_flag(grund_t::dirty); - delete d; - break; - } - else { - // extend this one instead - ((wayobj_t *)d)->set_dir(dir|((wayobj_t *)d)->get_dir()); - d->calc_bild(); - d->mark_image_dirty( d->get_after_bild(), 0 ); - d->set_flag(ding_t::dirty); - return; - } - } - } + wayobj_t *existing_wayobj = gr->get_wayobj( besch->get_wtyp() ); + if( existing_wayobj ) { + if(existing_wayobj->get_besch()->get_topspeed()get_topspeed() && spieler_t::check_owner(besitzer, existing_wayobj->get_besitzer())) { + // replace slower by faster + gr->obj_remove(existing_wayobj); + gr->set_flag(grund_t::dirty); + delete existing_wayobj; } + else { + // extend this one instead + existing_wayobj->set_dir(dir|existing_wayobj->get_dir()); + existing_wayobj->calc_bild(); + existing_wayobj->mark_image_dirty( existing_wayobj->get_after_bild(), 0 ); + existing_wayobj->set_flag(ding_t::dirty); + return; + } } + // nothing found => make a new one wayobj_t *wo = new wayobj_t(welt,pos,besitzer,dir,besch); gr->obj_add(wo);