ifmapper 1.0.0 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. data/HISTORY.txt +648 -627
  2. data/IFMapper.gemspec +29 -28
  3. data/IFMapper.rbw +31 -31
  4. data/TODO.txt +8 -7
  5. data/bin/IFMapper +31 -31
  6. data/docs/en/index.html +0 -0
  7. data/docs/en/start.html +3 -2
  8. data/docs/en/start.html~ +516 -0
  9. data/docs/es/index.html +0 -0
  10. data/docs/es/start.html +13 -14
  11. data/docs/es/start.html~ +1280 -0
  12. data/docs/images/IFMapper_main.gif +0 -0
  13. data/docs/images/automap.gif +0 -0
  14. data/docs/images/complex_connection.gif +0 -0
  15. data/docs/images/connection.gif +0 -0
  16. data/docs/images/connection_menu.gif +0 -0
  17. data/docs/images/room_description.gif +0 -0
  18. data/docs/images/room_small.gif +0 -0
  19. data/icons/copy.png +0 -0
  20. data/icons/cut.png +0 -0
  21. data/icons/filenew.png +0 -0
  22. data/icons/fileopen.png +0 -0
  23. data/icons/filesave.png +0 -0
  24. data/icons/filesaveas.png +0 -0
  25. data/icons/help.png +0 -0
  26. data/icons/kill.png +0 -0
  27. data/icons/nextpage.png +0 -0
  28. data/icons/paste.png +0 -0
  29. data/icons/prevpage.png +0 -0
  30. data/icons/printicon.png +0 -0
  31. data/icons/redo.png +0 -0
  32. data/icons/room_e.gif +0 -0
  33. data/icons/room_e.xpm +0 -0
  34. data/icons/room_n.gif +0 -0
  35. data/icons/room_n.xpm +0 -0
  36. data/icons/room_ne.gif +0 -0
  37. data/icons/room_ne.xpm +0 -0
  38. data/icons/room_nw.gif +0 -0
  39. data/icons/room_nw.xpm +0 -0
  40. data/icons/room_s.gif +0 -0
  41. data/icons/room_s.xpm +0 -0
  42. data/icons/room_se.gif +0 -0
  43. data/icons/room_se.xpm +0 -0
  44. data/icons/room_sw.gif +0 -0
  45. data/icons/room_sw.xpm +0 -0
  46. data/icons/room_w.gif +0 -0
  47. data/icons/room_w.xpm +0 -0
  48. data/icons/saveas.png +0 -0
  49. data/icons/undo.png +0 -0
  50. data/icons/winapp.png +0 -0
  51. data/icons/zoom.png +0 -0
  52. data/lib/IFMapper/AStar.rb +250 -250
  53. data/lib/IFMapper/Connection.rb +202 -202
  54. data/lib/IFMapper/FXAboutDialogBox.rb +32 -32
  55. data/lib/IFMapper/FXConnection.rb +364 -364
  56. data/lib/IFMapper/FXConnectionDialogBox.rb +124 -124
  57. data/lib/IFMapper/FXDCPostscript.rb +404 -404
  58. data/lib/IFMapper/FXDCPrint.rb +15 -15
  59. data/lib/IFMapper/FXItemList.rb +108 -0
  60. data/lib/IFMapper/FXMap.rb +2147 -2116
  61. data/lib/IFMapper/FXMapColorBox.rb +88 -88
  62. data/lib/IFMapper/FXMapDialogBox.rb +127 -127
  63. data/lib/IFMapper/FXMapFileDialog.rb +34 -34
  64. data/lib/IFMapper/FXMapperSettings.rb +206 -205
  65. data/lib/IFMapper/FXMapperWindow.rb +1592 -1571
  66. data/lib/IFMapper/FXPDFMapExporterOptionsDialogBox.rb +46 -0
  67. data/lib/IFMapper/FXRoom.rb +263 -263
  68. data/lib/IFMapper/FXRoomDialogBox.rb +159 -159
  69. data/lib/IFMapper/FXRoomList.rb +95 -95
  70. data/lib/IFMapper/FXSearchDialogBox.rb +51 -51
  71. data/lib/IFMapper/FXSection.rb +33 -33
  72. data/lib/IFMapper/FXSectionDialogBox.rb +38 -38
  73. data/lib/IFMapper/FXSpline.rb +52 -52
  74. data/lib/IFMapper/FXWarningBox.rb +51 -50
  75. data/lib/IFMapper/GUEReader.rb +445 -445
  76. data/lib/IFMapper/IFMReader.rb +584 -584
  77. data/lib/IFMapper/IFMWriter.rb +245 -227
  78. data/lib/IFMapper/Inform7Writer.rb +579 -573
  79. data/lib/IFMapper/InformReader.rb +478 -478
  80. data/lib/IFMapper/InformWriter.rb +364 -359
  81. data/lib/IFMapper/Map.rb +202 -200
  82. data/lib/IFMapper/MapPrinting.rb +162 -162
  83. data/lib/IFMapper/MapReader.rb +900 -900
  84. data/lib/IFMapper/PDFMapExporter.rb +526 -483
  85. data/lib/IFMapper/Room.rb +153 -151
  86. data/lib/IFMapper/Section.rb +234 -234
  87. data/lib/IFMapper/TADSReader.rb +474 -471
  88. data/lib/IFMapper/TADSWriter.rb +375 -370
  89. data/lib/IFMapper/TranscriptDialogBox.rb +0 -0
  90. data/lib/IFMapper/TranscriptReader.rb +1361 -1359
  91. data/lib/IFMapper/locales/en/Messages.rb +446 -435
  92. data/lib/IFMapper/locales/es/Messages.rb +451 -440
  93. data/lib/IFMapper/locales/es/Messages_iso-8859-1.rb +455 -440
  94. data/lib/IFMapper/locales/es/runme.sh +3 -3
  95. data/maps/A New Life.map b/data/maps/A New → Life.map +0 -0
  96. data/maps/AMFV.map +0 -0
  97. data/maps/AllRoads.map +0 -0
  98. data/maps/Aotearoa.map +0 -0
  99. data/maps/Bronze.map +0 -0
  100. data/maps/Bureaucracy.ifm +0 -0
  101. data/maps/Bureaucracy.map +0 -0
  102. data/maps/CityOfSecrets.map +0 -0
  103. data/maps/DDIV.map +0 -0
  104. data/maps/Following_A_Star.map +0 -0
  105. data/maps/Heated.map +0 -0
  106. data/maps/Heroine.map +0 -0
  107. data/maps/History Repeating.map b/data/maps/History → Repeating.map +0 -0
  108. data/maps/Hollywood_Hijinx.ifm +0 -0
  109. data/maps/Janitor.map +0 -0
  110. data/maps/Jigsaw.ifm +0 -0
  111. data/maps/Jigsaw.map +0 -0
  112. data/maps/LGOP.ifm +0 -0
  113. data/maps/Mercy.ifm +0 -0
  114. data/maps/Ninjas_Fate.map +0 -0
  115. data/maps/Pen_and_Paint.map +0 -0
  116. data/maps/Planetfall.ifm +0 -0
  117. data/maps/Planetfall.map +0 -0
  118. data/maps/Plundered_Hearts.ifm +0 -0
  119. data/maps/QuietEvening.map +0 -0
  120. data/maps/Ralph.ifm +0 -0
  121. data/maps/Reliques_of_Tolti_Alph.map +0 -0
  122. data/maps/Revolution.map +0 -0
  123. data/maps/Robots_of_Dawn.ifm +0 -0
  124. data/maps/SavoirFare.map +0 -0
  125. data/maps/Seastalker.ifm +0 -0
  126. data/maps/Seastalker.map +0 -0
  127. data/maps/Sherlock.ifm +0 -0
  128. data/maps/SoFar.ifm +0 -0
  129. data/maps/Starcross.ifm +0 -0
  130. data/maps/Suspended.ifm +0 -0
  131. data/maps/Tangle.map +0 -0
  132. data/maps/The_Lost_Sheep.map +0 -0
  133. data/maps/Unforgotten.map +0 -0
  134. data/maps/Warbler's Nest.map +0 -0
  135. data/maps/Warbler's_Nest.map +0 -0
  136. data/maps/Westminster_Abbey.map +0 -0
  137. data/maps/WinterWonderland.map +0 -0
  138. data/maps/Wishbringer.ifm +0 -0
  139. data/maps/Wishbringer2.ifm +0 -0
  140. data/maps/Zork1.ifm +0 -0
  141. data/maps/Zork2.ifm +0 -0
  142. data/maps/Zork3.ifm +0 -0
  143. data/maps/Zork_Zero.ifm +0 -0
  144. data/maps/anchor.ifm +0 -0
  145. data/maps/anchor.map +0 -0
  146. data/maps/atrox.ifm +0 -0
  147. data/maps/awaken.ifm +0 -0
  148. data/maps/babel.ifm +0 -0
  149. data/maps/balances.map +0 -0
  150. data/maps/ballerina.map +0 -0
  151. data/maps/bear.map +0 -0
  152. data/maps/bluechairs.map +0 -0
  153. data/maps/break_in.map +0 -0
  154. data/maps/bse.ifm +0 -0
  155. data/maps/building.map +0 -0
  156. data/maps/change.ifm +0 -0
  157. data/maps/christminster.map +0 -0
  158. data/maps/curses.ifm +0 -0
  159. data/maps/curves.ifm +0 -0
  160. data/maps/deadline.map +0 -0
  161. data/maps/delusions.map +0 -0
  162. data/maps/devours.map +0 -0
  163. data/maps/distress.map +0 -0
  164. data/maps/djinni.map +0 -0
  165. data/maps/dreamhold.map +0 -0
  166. data/maps/drift3.map +0 -0
  167. data/maps/eas.map +0 -0
  168. data/maps/eas2.map +0 -0
  169. data/maps/eas3.map +0 -0
  170. data/maps/edifice.ifm +0 -0
  171. data/maps/fallacy.map +0 -0
  172. data/maps/frozen.ifm +0 -0
  173. data/maps/gamlet.map +0 -0
  174. data/maps/glow.ifm +0 -0
  175. data/maps/guilty_bastards.map +0 -0
  176. data/maps/heist.map +0 -0
  177. data/maps/heroes.map +0 -0
  178. data/maps/inhumane.map +0 -0
  179. data/maps/kaged.map +0 -0
  180. data/maps/library.ifm +0 -0
  181. data/maps/lurkinghorror.map +0 -0
  182. data/maps/metamorphoses.map +0 -0
  183. data/maps/mindelec.ifm +0 -0
  184. data/maps/minster.ifm +0 -0
  185. data/maps/mite.map +0 -0
  186. data/maps/moonmist.map +0 -0
  187. data/maps/muldoon_legacy.map +0 -0
  188. data/maps/muse.ifm +0 -0
  189. data/maps/paperchase.ifm +0 -0
  190. data/maps/party.map +0 -0
  191. data/maps/pawn.map +0 -0
  192. data/maps/photograph.map +0 -0
  193. data/maps/pkgirl.map +0 -0
  194. data/maps/pytho.map +0 -0
  195. data/maps/risorgimento.map +0 -0
  196. data/maps/sherbet.map +0 -0
  197. data/maps/simple.map +0 -0
  198. data/maps/slouch.map +0 -0
  199. data/maps/space_st.ifm +0 -0
  200. data/maps/splashdown.map +0 -0
  201. data/maps/spring.map +0 -0
  202. data/maps/squarecircle.map +0 -0
  203. data/maps/stationfall.ifm +0 -0
  204. data/maps/theatre.ifm +0 -0
  205. data/maps/toonesia.ifm +0 -0
  206. data/maps/tortoise.ifm +0 -0
  207. data/maps/trinity.map +0 -0
  208. data/maps/vespers.map +0 -0
  209. data/maps/vgame.ifm +0 -0
  210. data/maps/wasp.map +0 -0
  211. data/maps/weather.ifm +0 -0
  212. data/maps/windhall.ifm +0 -0
  213. data/maps/worlds.map +0 -0
  214. data/maps/xtcontest.map +0 -0
  215. data/maps/zdungeon.map +0 -0
  216. data/maps/zebulon.ifm +0 -0
  217. data/maps/zerosum.map +0 -0
  218. metadata +226 -183
@@ -1,364 +1,364 @@
1
-
2
- require 'IFMapper/FXSpline'
3
- require 'IFMapper/Connection'
4
- require 'IFMapper/FXConnectionDialogBox'
5
-
6
- ######################################################
7
- #
8
- # WW
9
- # +---------------------+
10
- # | W |
11
- # | +-------------+ |
12
- # HH | | |WS2|
13
- # | H | |---|
14
- # | +-------------+ |
15
- # | |HS2 |
16
- # +---------------------+
17
- #
18
- #####################################################
19
-
20
- W = 120
21
- H = 75
22
- WS = 40
23
- HS = 40
24
- WW = W+WS
25
- HH = H+HS
26
-
27
- WS_2 = WS / 2
28
- HS_2 = HS / 2
29
-
30
- WIDX = 24
31
- HIDX = 18
32
-
33
-
34
- class FXConnection < Connection
35
- attr_accessor :selected
36
- attr_accessor :failed
37
- attr_accessor :pts, :gpts
38
-
39
- @@win = nil
40
-
41
- def self.no_maps
42
- @@win.hide if @@win
43
- end
44
-
45
- def initialize( roomA, roomB, dir = Connection::BOTH,
46
- type = Connection::FREE )
47
- super( roomA, roomB, dir, type )
48
- @selected = @failed = false
49
- @pts = @gpts = []
50
- end
51
-
52
- def marshal_load(vars)
53
- @pts = @gpts = []
54
- @selected = vars.shift
55
- super(vars)
56
- end
57
-
58
- def marshal_dump
59
- [ @selected ] + super
60
- end
61
-
62
- def flip
63
- super
64
- pts.reverse!
65
- gpts.reverse!
66
- @@win.copy_from(self) if @@win
67
- end
68
-
69
- #
70
- # Change selection state of connection. If Connection Properties
71
- # window is open, copy the connection data to it.
72
- #
73
- def selected=(value)
74
- @@win.copy_from(self) if value and @@win and @@win.shown?
75
- @selected = value
76
- end
77
-
78
- #
79
- # Change direction of connection
80
- #
81
- def toggle_direction
82
- # If a self-loop, we cannot change dir
83
- return if @room[0] == @room[1] and
84
- @room[0].exits.index(self) == @room[0].exits.rindex(self)
85
-
86
- @dir ^= 1
87
- @@win.copy_from(self) if @@win
88
- end
89
-
90
- #
91
- # Is this a complex path. Check if connection is
92
- # contiguous
93
- #
94
- def complex?()
95
- return false if not @room[1]
96
- return true if @room[1] == @room[0]
97
- return true unless @room[0].next_to?(@room[1])
98
-
99
- # Even if rooms are next to each other, we need to
100
- # verify that following the exits does indeed take us to next room.
101
- exitA = @room[0].exits.index(self)
102
- dir = Room::DIR_TO_VECTOR[exitA]
103
-
104
- if @room[0].x + dir[0] == @room[1].x and
105
- @room[0].y + dir[1] == @room[1].y
106
- exitB = @room[1].exits.rindex(self)
107
- dir = Room::DIR_TO_VECTOR[exitB]
108
- if @room[1].x + dir[0] == @room[0].x and
109
- @room[1].y + dir[1] == @room[0].y
110
- return false
111
- else
112
- return true
113
- end
114
- else
115
- return true
116
- end
117
- end
118
-
119
- #
120
- # Main draw function
121
- #
122
- def draw(dc, zoom, opt)
123
- if @selected
124
- dc.foreground = 'yellow'
125
- elsif @failed
126
- dc.foreground = 'red'
127
- else
128
- dc.foreground = opt['Arrow Color']
129
- end
130
-
131
- draw_exit_text(dc, zoom)
132
- if @type == SPECIAL
133
- dc.lineStyle = LINE_ONOFF_DASH
134
- else
135
- dc.lineStyle = LINE_SOLID
136
- end
137
- if pts.size > 0
138
- draw_complex(dc, zoom, opt)
139
- else
140
- draw_simple(dc, zoom)
141
- end
142
- end
143
-
144
-
145
- def update_properties(map)
146
- return if not @@win or not @@win.shown?
147
- @@win.map = map
148
- @@win.copy_from(self)
149
- end
150
-
151
- def properties(map, event = nil)
152
- if not @@win
153
- @@win = FXConnectionDialogBox.new(map, self, event)
154
- end
155
- @@win.show
156
- update_properties(map)
157
- end
158
-
159
- protected
160
-
161
- RAD_45 = 45 * Math::PI / 180
162
- SIN_45 = Math.sin(RAD_45)
163
- COS_45 = Math.cos(RAD_45)
164
-
165
- def _arrow_info( x1, y1, x2, y2, zoom = 1.0 )
166
- pt1 = []
167
- dir = 0
168
- dir = @room[1].exits.rindex(self)
169
- pt1 = [ x2, y2 ]
170
- x, y = Room::DIR_TO_VECTOR[dir]
171
- if @room[0] == @room[1]
172
- size = 15.0
173
- else
174
- size = 20.0
175
- end
176
- arrow_len = size / Math.sqrt(x * x + y * y)
177
- x *= arrow_len * zoom
178
- y *= arrow_len * -zoom
179
-
180
- d = [
181
- x * COS_45 + y * SIN_45,
182
- x * SIN_45 - y * COS_45
183
- ]
184
- return pt1, d
185
- end
186
-
187
-
188
- #
189
- # Draw a complex connection as a line path
190
- #
191
- def draw_complex_as_lines(dc, zoom)
192
- p = []
193
- @pts.each { |pt|
194
- p << FXPoint.new( (pt[0] * zoom).to_i, (pt[1] * zoom).to_i )
195
- }
196
- dc.drawLines( p )
197
- return p
198
- end
199
-
200
- #
201
- # Draw a complex connection as a bspline path
202
- #
203
- def draw_complex_as_bspline(dc, zoom)
204
- p = []
205
- p << [ @pts[0][0] * zoom, @pts[0][1] * zoom ]
206
- p << p[0]
207
- p << p[0]
208
- @pts.each { |pt|
209
- p << [ pt[0] * zoom, pt[1] * zoom ]
210
- }
211
- p << p[-1]
212
- p << p[-1]
213
- p << p[-1]
214
- return dc.drawBSpline( p )
215
- end
216
-
217
- #
218
- # Draw a door
219
- #
220
- def draw_door(dc, zoom, x1, y1, x2, y2)
221
- v = [ (x2-x1), (y2-y1) ]
222
- t = 10 * zoom / Math.sqrt(v[0]*v[0]+v[1]*v[1])
223
- v = [ (v[0]*t).to_i, (v[1]*t).to_i ]
224
- m = [ (x2+x1)/2, (y2+y1)/2 ]
225
- x1, y1 = [m[0] + v[1], m[1] - v[0]]
226
- x2, y2 = [m[0] - v[1], m[1] + v[0]]
227
- if @type == LOCKED_DOOR
228
- # Locked door
229
- dc.drawLine(x1, y1, x2, y2)
230
- else
231
- # open door
232
- v = [ v[0] / 3, v[1] / 3]
233
- x1, y1 = x1.to_i, y1.to_i
234
- x2, y2 = x2.to_i, y2.to_i
235
- pts = []
236
- pts << FXPoint.new(x1 - v[0], y1 - v[1])
237
- pts << FXPoint.new(x1 + v[0], y1 + v[1])
238
- pts << FXPoint.new(x2 + v[0], y2 + v[1])
239
- pts << FXPoint.new(x2 - v[0], y2 - v[1])
240
- pts << pts[0]
241
- width = dc.lineWidth
242
- dc.lineWidth = 0
243
- dc.drawLines(pts)
244
- dc.lineWidth = width
245
- end
246
- end
247
-
248
- #
249
- # Draw a complex connection
250
- #
251
- def draw_complex(dc, zoom, opt)
252
- if opt['Paths as Curves']
253
- if @room[0] == @room[1]
254
- dirA, dirB = dirs
255
- if dirA == dirB
256
- p = draw_complex_as_lines(dc, zoom)
257
- else
258
- p = draw_complex_as_bspline(dc, zoom)
259
- end
260
- else
261
- p = draw_complex_as_bspline(dc, zoom)
262
- end
263
- else
264
- p = draw_complex_as_lines(dc, zoom)
265
- end
266
-
267
- x1, y1 = [p[0].x, p[0].y]
268
- x2, y2 = [p[-1].x, p[-1].y]
269
- draw_arrow(dc, zoom, x1, y1, x2, y2)
270
-
271
- if @type == LOCKED_DOOR or @type == CLOSED_DOOR
272
- t = p.size / 2
273
- x1, y1 = [ p[t].x, p[t].y ]
274
- x2, y2 = [ p[t-2].x, p[t-2].y ]
275
- draw_door(dc, zoom, x1, y1, x2, y2)
276
- end
277
- end
278
-
279
- #
280
- # Draw a simple connection. Simple connections are straight
281
- # line connections or 'stub' connections.
282
- #
283
- def draw_simple(dc, zoom)
284
- dir = @room[0].exits.index(self)
285
- x1, y1 = @room[0].corner(self, zoom, dir)
286
- if @room[1]
287
- x2, y2 = @room[1].corner(self, zoom)
288
- dc.drawLine( x1, y1, x2, y2 )
289
- draw_arrow(dc, zoom, x1, y1, x2, y2)
290
- if @type == LOCKED_DOOR or @type == CLOSED_DOOR
291
- draw_door(dc, zoom, x1, y1, x2, y2)
292
- end
293
- else
294
- # Complex connection in progress or "stub" exit
295
- v = FXRoom::DIR_TO_VECTOR[dir]
296
- x2, y2 = [ x1 + v[0] * WS * zoom * 0.4, y1 + v[1] * HS * zoom * 0.4 ]
297
- dc.drawLine( x1, y1, x2, y2 )
298
- end
299
- end
300
-
301
-
302
- #
303
- # Draw an arrow at one end of the path
304
- #
305
- def draw_arrow( dc, zoom, x1, y1, x2, y2 )
306
- return if @dir == BOTH
307
- pt1, d = _arrow_info( x1, y1, x2, y2, zoom )
308
-
309
- p = []
310
- p << FXPoint.new( pt1[0].to_i, pt1[1].to_i )
311
- pt2 = [ pt1[0] + d[0], pt1[1] + d[1] ]
312
- p << FXPoint.new( pt2[0].to_i, pt2[1].to_i )
313
- pt2 = [ pt1[0] + d[1], pt1[1] - d[0] ]
314
- p << FXPoint.new( pt2[0].to_i, pt2[1].to_i )
315
-
316
- dc.fillPolygon(p)
317
- end
318
-
319
- #
320
- # Draw the connection text next to the arrow ('I', 'O', etc)
321
- #
322
- def draw_text(dc, zoom, x, y, dir, text, arrow)
323
- if dir == 7 or dir < 6 and dir != 1
324
- if arrow and (dir == 0 or dir == 4)
325
- x += 10 * zoom
326
- end
327
- x += 5 * zoom
328
- elsif dir == 6 or dir == 1
329
- x -= 15 * zoom
330
- end
331
-
332
- if dir > 5 or dir < 4
333
- if arrow and (dir == 6 or dir == 2)
334
- y -= 10 * zoom
335
- end
336
- y -= 5 * zoom
337
- elsif dir == 4 or dir == 5
338
- y += 15 * zoom
339
- end
340
-
341
- dc.drawText(x, y, text)
342
- end
343
-
344
- #
345
- # Draw any exit text if available (exit text is 'U', 'D', 'I', 'O', etc)
346
- #
347
- def draw_exit_text(dc, zoom)
348
- return if zoom < 0.5
349
- if @exitText[0] != 0
350
- dir = @room[0].exits.index(self)
351
- x, y = @room[0].corner(self, zoom, dir)
352
- draw_text( dc, zoom, x, y, dir,
353
- DRAW_EXIT_TEXT[@exitText[0]], nil )
354
- end
355
- if @exitText[1] != 0
356
- dir = @room[1].exits.rindex(self)
357
- x, y = @room[1].corner(self, zoom, dir)
358
- draw_text( dc, zoom, x, y, dir,
359
- DRAW_EXIT_TEXT[@exitText[1]], @dir == AtoB)
360
- end
361
- end
362
-
363
- end
364
-
1
+
2
+ require 'IFMapper/FXSpline'
3
+ require 'IFMapper/Connection'
4
+ require 'IFMapper/FXConnectionDialogBox'
5
+
6
+ ######################################################
7
+ #
8
+ # WW
9
+ # +---------------------+
10
+ # | W |
11
+ # | +-------------+ |
12
+ # HH | | |WS2|
13
+ # | H | |---|
14
+ # | +-------------+ |
15
+ # | |HS2 |
16
+ # +---------------------+
17
+ #
18
+ #####################################################
19
+
20
+ W = 120
21
+ H = 75
22
+ WS = 40
23
+ HS = 40
24
+ WW = W+WS
25
+ HH = H+HS
26
+
27
+ WS_2 = WS / 2
28
+ HS_2 = HS / 2
29
+
30
+ WIDX = 24
31
+ HIDX = 18
32
+
33
+
34
+ class FXConnection < Connection
35
+ attr_reader :selected
36
+ attr_accessor :failed
37
+ attr_accessor :pts, :gpts
38
+
39
+ @@win = nil
40
+
41
+ def self.no_maps
42
+ @@win.hide if @@win
43
+ end
44
+
45
+ def initialize( roomA, roomB, dir = Connection::BOTH,
46
+ type = Connection::FREE )
47
+ super( roomA, roomB, dir, type )
48
+ @selected = @failed = false
49
+ @pts = @gpts = []
50
+ end
51
+
52
+ def marshal_load(vars)
53
+ @pts = @gpts = []
54
+ @selected = vars.shift
55
+ super(vars)
56
+ end
57
+
58
+ def marshal_dump
59
+ [ @selected ] + super
60
+ end
61
+
62
+ def flip
63
+ super
64
+ pts.reverse!
65
+ gpts.reverse!
66
+ @@win.copy_from(self) if @@win
67
+ end
68
+
69
+ #
70
+ # Change selection state of connection. If Connection Properties
71
+ # window is open, copy the connection data to it.
72
+ #
73
+ def selected=(value)
74
+ @@win.copy_from(self) if value and @@win and @@win.shown?
75
+ @selected = value
76
+ end
77
+
78
+ #
79
+ # Change direction of connection
80
+ #
81
+ def toggle_direction
82
+ # If a self-loop, we cannot change dir
83
+ return if @room[0] == @room[1] and
84
+ @room[0].exits.index(self) == @room[0].exits.rindex(self)
85
+
86
+ @dir ^= 1
87
+ @@win.copy_from(self) if @@win
88
+ end
89
+
90
+ #
91
+ # Is this a complex path. Check if connection is
92
+ # contiguous
93
+ #
94
+ def complex?()
95
+ return false if not @room[1]
96
+ return true if @room[1] == @room[0]
97
+ return true unless @room[0].next_to?(@room[1])
98
+
99
+ # Even if rooms are next to each other, we need to
100
+ # verify that following the exits does indeed take us to next room.
101
+ exitA = @room[0].exits.index(self)
102
+ dir = Room::DIR_TO_VECTOR[exitA]
103
+
104
+ if @room[0].x + dir[0] == @room[1].x and
105
+ @room[0].y + dir[1] == @room[1].y
106
+ exitB = @room[1].exits.rindex(self)
107
+ dir = Room::DIR_TO_VECTOR[exitB]
108
+ if @room[1].x + dir[0] == @room[0].x and
109
+ @room[1].y + dir[1] == @room[0].y
110
+ return false
111
+ else
112
+ return true
113
+ end
114
+ else
115
+ return true
116
+ end
117
+ end
118
+
119
+ #
120
+ # Main draw function
121
+ #
122
+ def draw(dc, zoom, opt)
123
+ if @selected
124
+ dc.foreground = 'yellow'
125
+ elsif @failed
126
+ dc.foreground = 'red'
127
+ else
128
+ dc.foreground = opt['Arrow Color']
129
+ end
130
+
131
+ draw_exit_text(dc, zoom)
132
+ if @type == SPECIAL
133
+ dc.lineStyle = LINE_ONOFF_DASH
134
+ else
135
+ dc.lineStyle = LINE_SOLID
136
+ end
137
+ if pts.size > 0
138
+ draw_complex(dc, zoom, opt)
139
+ else
140
+ draw_simple(dc, zoom)
141
+ end
142
+ end
143
+
144
+
145
+ def update_properties(map)
146
+ return if not @@win or not @@win.shown?
147
+ @@win.map = map
148
+ @@win.copy_from(self)
149
+ end
150
+
151
+ def properties(map, event = nil)
152
+ if not @@win
153
+ @@win = FXConnectionDialogBox.new(map, self, event)
154
+ end
155
+ @@win.show
156
+ update_properties(map)
157
+ end
158
+
159
+ protected
160
+
161
+ RAD_45 = 45 * Math::PI / 180
162
+ SIN_45 = Math.sin(RAD_45)
163
+ COS_45 = Math.cos(RAD_45)
164
+
165
+ def _arrow_info( x1, y1, x2, y2, zoom = 1.0 )
166
+ pt1 = []
167
+ dir = 0
168
+ dir = @room[1].exits.rindex(self)
169
+ pt1 = [ x2, y2 ]
170
+ x, y = Room::DIR_TO_VECTOR[dir]
171
+ if @room[0] == @room[1]
172
+ size = 15.0
173
+ else
174
+ size = 20.0
175
+ end
176
+ arrow_len = size / Math.sqrt(x * x + y * y)
177
+ x *= arrow_len * zoom
178
+ y *= arrow_len * -zoom
179
+
180
+ d = [
181
+ x * COS_45 + y * SIN_45,
182
+ x * SIN_45 - y * COS_45
183
+ ]
184
+ return pt1, d
185
+ end
186
+
187
+
188
+ #
189
+ # Draw a complex connection as a line path
190
+ #
191
+ def draw_complex_as_lines(dc, zoom)
192
+ p = []
193
+ @pts.each { |pt|
194
+ p << FXPoint.new( (pt[0] * zoom).to_i, (pt[1] * zoom).to_i )
195
+ }
196
+ dc.drawLines( p )
197
+ return p
198
+ end
199
+
200
+ #
201
+ # Draw a complex connection as a bspline path
202
+ #
203
+ def draw_complex_as_bspline(dc, zoom)
204
+ p = []
205
+ p << [ @pts[0][0] * zoom, @pts[0][1] * zoom ]
206
+ p << p[0]
207
+ p << p[0]
208
+ @pts.each { |pt|
209
+ p << [ pt[0] * zoom, pt[1] * zoom ]
210
+ }
211
+ p << p[-1]
212
+ p << p[-1]
213
+ p << p[-1]
214
+ return dc.drawBSpline( p )
215
+ end
216
+
217
+ #
218
+ # Draw a door
219
+ #
220
+ def draw_door(dc, zoom, x1, y1, x2, y2)
221
+ v = [ (x2-x1), (y2-y1) ]
222
+ t = 10 * zoom / Math.sqrt(v[0]*v[0]+v[1]*v[1])
223
+ v = [ (v[0]*t).to_i, (v[1]*t).to_i ]
224
+ m = [ (x2+x1)/2, (y2+y1)/2 ]
225
+ x1, y1 = [m[0] + v[1], m[1] - v[0]]
226
+ x2, y2 = [m[0] - v[1], m[1] + v[0]]
227
+ if @type == LOCKED_DOOR
228
+ # Locked door
229
+ dc.drawLine(x1, y1, x2, y2)
230
+ else
231
+ # open door
232
+ v = [ v[0] / 3, v[1] / 3]
233
+ x1, y1 = x1.to_i, y1.to_i
234
+ x2, y2 = x2.to_i, y2.to_i
235
+ pts = []
236
+ pts << FXPoint.new(x1 - v[0], y1 - v[1])
237
+ pts << FXPoint.new(x1 + v[0], y1 + v[1])
238
+ pts << FXPoint.new(x2 + v[0], y2 + v[1])
239
+ pts << FXPoint.new(x2 - v[0], y2 - v[1])
240
+ pts << pts[0]
241
+ width = dc.lineWidth
242
+ dc.lineWidth = 0
243
+ dc.drawLines(pts)
244
+ dc.lineWidth = width
245
+ end
246
+ end
247
+
248
+ #
249
+ # Draw a complex connection
250
+ #
251
+ def draw_complex(dc, zoom, opt)
252
+ if opt['Paths as Curves']
253
+ if @room[0] == @room[1]
254
+ dirA, dirB = dirs
255
+ if dirA == dirB
256
+ p = draw_complex_as_lines(dc, zoom)
257
+ else
258
+ p = draw_complex_as_bspline(dc, zoom)
259
+ end
260
+ else
261
+ p = draw_complex_as_bspline(dc, zoom)
262
+ end
263
+ else
264
+ p = draw_complex_as_lines(dc, zoom)
265
+ end
266
+
267
+ x1, y1 = [p[0].x, p[0].y]
268
+ x2, y2 = [p[-1].x, p[-1].y]
269
+ draw_arrow(dc, zoom, x1, y1, x2, y2)
270
+
271
+ if @type == LOCKED_DOOR or @type == CLOSED_DOOR
272
+ t = p.size / 2
273
+ x1, y1 = [ p[t].x, p[t].y ]
274
+ x2, y2 = [ p[t-2].x, p[t-2].y ]
275
+ draw_door(dc, zoom, x1, y1, x2, y2)
276
+ end
277
+ end
278
+
279
+ #
280
+ # Draw a simple connection. Simple connections are straight
281
+ # line connections or 'stub' connections.
282
+ #
283
+ def draw_simple(dc, zoom)
284
+ dir = @room[0].exits.index(self)
285
+ x1, y1 = @room[0].corner(self, zoom, dir)
286
+ if @room[1]
287
+ x2, y2 = @room[1].corner(self, zoom)
288
+ dc.drawLine( x1, y1, x2, y2 )
289
+ draw_arrow(dc, zoom, x1, y1, x2, y2)
290
+ if @type == LOCKED_DOOR or @type == CLOSED_DOOR
291
+ draw_door(dc, zoom, x1, y1, x2, y2)
292
+ end
293
+ else
294
+ # Complex connection in progress or "stub" exit
295
+ v = FXRoom::DIR_TO_VECTOR[dir]
296
+ x2, y2 = [ x1 + v[0] * WS * zoom * 0.4, y1 + v[1] * HS * zoom * 0.4 ]
297
+ dc.drawLine( x1, y1, x2, y2 )
298
+ end
299
+ end
300
+
301
+
302
+ #
303
+ # Draw an arrow at one end of the path
304
+ #
305
+ def draw_arrow( dc, zoom, x1, y1, x2, y2 )
306
+ return if @dir == BOTH
307
+ pt1, d = _arrow_info( x1, y1, x2, y2, zoom )
308
+
309
+ p = []
310
+ p << FXPoint.new( pt1[0].to_i, pt1[1].to_i )
311
+ pt2 = [ pt1[0] + d[0], pt1[1] + d[1] ]
312
+ p << FXPoint.new( pt2[0].to_i, pt2[1].to_i )
313
+ pt2 = [ pt1[0] + d[1], pt1[1] - d[0] ]
314
+ p << FXPoint.new( pt2[0].to_i, pt2[1].to_i )
315
+
316
+ dc.fillPolygon(p)
317
+ end
318
+
319
+ #
320
+ # Draw the connection text next to the arrow ('I', 'O', etc)
321
+ #
322
+ def draw_text(dc, zoom, x, y, dir, text, arrow)
323
+ if dir == 7 or dir < 6 and dir != 1
324
+ if arrow and (dir == 0 or dir == 4)
325
+ x += 10 * zoom
326
+ end
327
+ x += 5 * zoom
328
+ elsif dir == 6 or dir == 1
329
+ x -= 15 * zoom
330
+ end
331
+
332
+ if dir > 5 or dir < 4
333
+ if arrow and (dir == 6 or dir == 2)
334
+ y -= 10 * zoom
335
+ end
336
+ y -= 5 * zoom
337
+ elsif dir == 4 or dir == 5
338
+ y += 15 * zoom
339
+ end
340
+
341
+ dc.drawText(x, y, text)
342
+ end
343
+
344
+ #
345
+ # Draw any exit text if available (exit text is 'U', 'D', 'I', 'O', etc)
346
+ #
347
+ def draw_exit_text(dc, zoom)
348
+ return if zoom < 0.5
349
+ if @exitText[0] != 0
350
+ dir = @room[0].exits.index(self)
351
+ x, y = @room[0].corner(self, zoom, dir)
352
+ draw_text( dc, zoom, x, y, dir,
353
+ DRAW_EXIT_TEXT[@exitText[0]], nil )
354
+ end
355
+ if @exitText[1] != 0
356
+ dir = @room[1].exits.rindex(self)
357
+ x, y = @room[1].corner(self, zoom, dir)
358
+ draw_text( dc, zoom, x, y, dir,
359
+ DRAW_EXIT_TEXT[@exitText[1]], @dir == AtoB)
360
+ end
361
+ end
362
+
363
+ end
364
+