Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Portions of this file are copyright Rebirth contributors and licensed as
  3.  * described in COPYING.txt.
  4.  * Portions of this file are copyright Parallax Software and licensed
  5.  * according to the Parallax license below.
  6.  * See COPYING.txt for license details.
  7.  
  8. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  9. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  10. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  11. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  12. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  13. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  14. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  15. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  16. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  17. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  18. */
  19.  
  20. /*
  21.  *
  22.  * Functions for selecting segments
  23.  *
  24.  */
  25.  
  26. #include <utility>
  27. #include <string.h>
  28.  
  29. #include "inferno.h"
  30. #include "editor/editor.h"
  31. #include "editor/esegment.h"
  32. #include "editor/medmisc.h"
  33. #include "gameseg.h"
  34. #include "kdefs.h"
  35. #include "compiler-range_for.h"
  36. #include "d_range.h"
  37.  
  38. __attribute_warn_unused_result
  39. static vmsegptridx_t get_any_attached_segment(const vmsegptridx_t curseg_num, const uint_fast32_t skipside)
  40. {
  41.         range_for (const uint_fast32_t s, xrange(MAX_SIDES_PER_SEGMENT))
  42.         {
  43.                 if (unlikely(s == skipside))
  44.                         continue;
  45.                 const auto child = curseg_num->children[s];
  46.                 if (IS_CHILD(child))
  47.                         return curseg_num.absolute_sibling(child);
  48.         }
  49.         return curseg_num;
  50. }
  51.  
  52. __attribute_warn_unused_result
  53. static vmsegptridx_t get_previous_segment(const vmsegptridx_t curseg_num, const uint_fast32_t curside)
  54. {
  55.         const auto side_child = curseg_num->children[Side_opposite[curside]];
  56.         if (IS_CHILD(side_child))
  57.                 return curseg_num.absolute_sibling(side_child);
  58.         // no segment on opposite face, connect to anything
  59.         return get_any_attached_segment(curseg_num, curside);
  60. }
  61.  
  62. // ---------------------------------------------------------------------------------------
  63. // Select previous segment.
  64. //      If there is a connection on the side opposite to the current side, then choose that segment.
  65. // If there is no connecting segment on the opposite face, try any segment.
  66. __attribute_warn_unused_result
  67. static std::pair<vmsegptridx_t, uint_fast32_t> get_previous_segment_side(const vmsegptridx_t curseg_num, const uint_fast32_t curside)
  68. {
  69.         const auto &newseg_num = get_previous_segment(curseg_num, curside);
  70.         // Now make Curside point at the segment we just left (unless we couldn't leave it).
  71.         return {newseg_num, newseg_num == curseg_num ? curside : find_connect_side(curseg_num, newseg_num)};
  72. }
  73.  
  74. // --------------------------------------------------------------------------------------
  75. // Select next segment.
  76. //      If there is a connection on the current side, then choose that segment.
  77. // If there is no connecting segment on the current side, try any segment.
  78. __attribute_warn_unused_result
  79. static std::pair<vmsegptridx_t, uint_fast32_t> get_next_segment_side(const vmsegptridx_t curseg_num, uint_fast32_t curside)
  80. {
  81.         const auto side_child = curseg_num->children[curside];
  82.         if (IS_CHILD(side_child))
  83.         {
  84.                 const auto &&newseg_num = curseg_num.absolute_sibling(side_child);
  85.                 // Find out what side we came in through and favor side opposite that
  86.                 const auto newside = Side_opposite[find_connect_side(curseg_num, newseg_num)];
  87.                 // If there is nothing attached on the side opposite to what we came in (*newside), pick any other side
  88.                 if (!IS_CHILD(newseg_num->children[newside]))
  89.                         range_for (const uint_fast32_t s, xrange(MAX_SIDES_PER_SEGMENT))
  90.                         {
  91.                                 const auto cseg = newseg_num->children[s];
  92.                                 if (cseg != curseg_num && IS_CHILD(cseg))
  93.                                         return {newseg_num, s};
  94.                         }
  95.                 return {newseg_num, newside};
  96.         }
  97.         else
  98.         {
  99.                 return {curseg_num, curside};
  100.         }
  101.  
  102. }
  103.  
  104. // ---------- select current segment ----------
  105. int SelectCurrentSegForward()
  106. {
  107.         auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
  108.         auto &Vertices = LevelSharedVertexState.get_vertices();
  109.         const auto p = get_next_segment_side(Cursegp,Curside);
  110.         const auto &newseg_num = p.first;
  111.  
  112.         if (newseg_num != Cursegp)
  113.         {
  114.                 Cursegp = newseg_num;
  115.                 const auto &newside = p.second;
  116.                 Curside = newside;
  117.                 Update_flags |= UF_ED_STATE_CHANGED;
  118.                 if (Lock_view_to_cursegp)
  119.                 {
  120.                         auto &vcvertptr = Vertices.vcptr;
  121.                         set_view_target_from_segment(vcvertptr, Cursegp);
  122.                 }
  123.  
  124.                 med_create_new_segment_from_cursegp();
  125.                 mine_changed = 1;
  126.         }
  127.  
  128.         return 1;
  129. }
  130.  
  131. // -------------------------------------------------------------------------------------
  132. int SelectCurrentSegBackward()
  133. {
  134.         auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
  135.         auto &Vertices = LevelSharedVertexState.get_vertices();
  136.         const auto &p = get_previous_segment_side(Cursegp,Curside);
  137.         Cursegp = p.first;
  138.         Curside = p.second;
  139.  
  140.         if (Lock_view_to_cursegp)
  141.         {
  142.                 auto &vcvertptr = Vertices.vcptr;
  143.                 set_view_target_from_segment(vcvertptr, Cursegp);
  144.         }
  145.         Update_flags |= UF_ED_STATE_CHANGED;
  146.         mine_changed = 1;
  147.         med_create_new_segment_from_cursegp();
  148.  
  149.         return 1;
  150. }
  151.  
  152.  
  153. // ---------- select next/previous side on current segment ----------
  154. int SelectNextSide()
  155. {
  156.         if (++Curside >= MAX_SIDES_PER_SEGMENT)
  157.                 Curside = 0;
  158.         Update_flags |= UF_ED_STATE_CHANGED;
  159.         mine_changed = 1;
  160.         return 1;
  161. }
  162.  
  163. int SelectPrevSide()
  164. {
  165.         if (--Curside < 0)
  166.                 Curside = MAX_SIDES_PER_SEGMENT-1;
  167.         Update_flags |= UF_ED_STATE_CHANGED;
  168.         mine_changed = 1;
  169.         return 1;
  170. }
  171.  
  172. //  ---------- Copy current segment and side to marked segment and side ----------
  173.  
  174. int CopySegToMarked()
  175. {
  176.    autosave_mine(mine_filename);
  177.         undo_status[Autosave_count] = "Mark Segment UNDONE.";
  178.         Markedsegp = Cursegp;
  179.         Markedside = Curside;
  180.         Update_flags |= UF_ED_STATE_CHANGED;
  181.         mine_changed = 1;
  182.         return 1;
  183. }
  184.  
  185. // ---------- select absolute face on segment ----------
  186.  
  187. int SelectBottom()
  188. {
  189.         Curside = WBOTTOM;
  190.         Update_flags |= UF_ED_STATE_CHANGED;
  191.         mine_changed = 1;
  192.         return 1;
  193. }
  194.  
  195. int SelectFront()
  196. {
  197.         Curside = WFRONT;
  198.         Update_flags |= UF_ED_STATE_CHANGED;
  199.         mine_changed = 1;
  200.         return 1;
  201. }
  202.  
  203. int SelectTop()
  204. {
  205.         Curside = WTOP;
  206.         Update_flags |= UF_ED_STATE_CHANGED;
  207.         mine_changed = 1;
  208.         return 1;
  209. }
  210.  
  211. int SelectBack()
  212. {
  213.         Curside = WBACK;
  214.         Update_flags |= UF_ED_STATE_CHANGED;
  215.         mine_changed = 1;
  216.         return 1;
  217. }
  218.  
  219. int SelectLeft()
  220. {
  221.         Curside = WLEFT;
  222.         Update_flags |= UF_ED_STATE_CHANGED;
  223.         mine_changed = 1;
  224.         return 1;
  225. }
  226.  
  227. int SelectRight()
  228. {
  229.         Curside = WRIGHT;
  230.         Update_flags |= UF_ED_STATE_CHANGED;
  231.         mine_changed = 1;
  232.         return 1;
  233. }
  234.  
  235.