ifmapper 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/HISTORY.txt +2 -0
  2. data/IFMapper.gemspec +21 -0
  3. data/IFMapper.rb +27 -0
  4. data/icons/copy.png +0 -0
  5. data/icons/cut.png +0 -0
  6. data/icons/filenew.png +0 -0
  7. data/icons/fileopen.png +0 -0
  8. data/icons/filesave.png +0 -0
  9. data/icons/filesaveas.png +0 -0
  10. data/icons/help.png +0 -0
  11. data/icons/kill.png +0 -0
  12. data/icons/nextpage.png +0 -0
  13. data/icons/paste.png +0 -0
  14. data/icons/prevpage.png +0 -0
  15. data/icons/printicon.png +0 -0
  16. data/icons/redo.png +0 -0
  17. data/icons/saveas.png +0 -0
  18. data/icons/undo.png +0 -0
  19. data/icons/winapp.png +0 -0
  20. data/icons/zoom.png +0 -0
  21. data/lib/IFMapper/Connection.rb +63 -0
  22. data/lib/IFMapper/FXAboutDialogBox.rb +32 -0
  23. data/lib/IFMapper/FXConnection.rb +283 -0
  24. data/lib/IFMapper/FXConnectionDialogBox.rb +126 -0
  25. data/lib/IFMapper/FXMap.rb +1614 -0
  26. data/lib/IFMapper/FXMapDialogBox.rb +51 -0
  27. data/lib/IFMapper/FXMapFileDialog.rb +29 -0
  28. data/lib/IFMapper/FXMapperSettings.rb +45 -0
  29. data/lib/IFMapper/FXMapperWindow.rb +1051 -0
  30. data/lib/IFMapper/FXPage.rb +24 -0
  31. data/lib/IFMapper/FXPageDialogBox.rb +38 -0
  32. data/lib/IFMapper/FXRoom.rb +218 -0
  33. data/lib/IFMapper/FXRoomDialogBox.rb +119 -0
  34. data/lib/IFMapper/FXSearchDialogBox.rb +51 -0
  35. data/lib/IFMapper/FXSpline.rb +54 -0
  36. data/lib/IFMapper/FXWarningBox.rb +45 -0
  37. data/lib/IFMapper/IFMReader.rb +613 -0
  38. data/lib/IFMapper/Map.rb +110 -0
  39. data/lib/IFMapper/PDFMapExporter.rb +315 -0
  40. data/lib/IFMapper/Page.rb +158 -0
  41. data/lib/IFMapper/Room.rb +104 -0
  42. data/maps/Bureaucracy.ifm +75 -0
  43. data/maps/Hollywood_Hijinx.ifm +149 -0
  44. data/maps/Jigsaw.ifm +806 -0
  45. data/maps/LGOP.ifm +705 -0
  46. data/maps/Mercy.ifm +76 -0
  47. data/maps/Planetfall.ifm +186 -0
  48. data/maps/Plundered_Hearts.ifm +251 -0
  49. data/maps/Ralph.ifm +50 -0
  50. data/maps/Robots_of_Dawn.ifm +224 -0
  51. data/maps/Seastalker.ifm +149 -0
  52. data/maps/Sherlock.ifm +209 -0
  53. data/maps/SoFar.ifm +72 -0
  54. data/maps/Starcross.ifm +170 -0
  55. data/maps/Suspended.ifm +82 -0
  56. data/maps/Wishbringer.ifm +277 -0
  57. data/maps/Wishbringer2.ifm +246 -0
  58. data/maps/Zork1.ifm +410 -0
  59. data/maps/Zork2.ifm +150 -0
  60. data/maps/Zork3.ifm +136 -0
  61. data/maps/Zork_Zero.ifm +557 -0
  62. data/maps/anchor.ifm +645 -0
  63. data/maps/atrox.ifm +134 -0
  64. data/maps/awaken.ifm +116 -0
  65. data/maps/babel.ifm +279 -0
  66. data/maps/bse.ifm +150 -0
  67. data/maps/change.ifm +128 -0
  68. data/maps/curses.ifm +307 -0
  69. data/maps/curves.ifm +529 -0
  70. data/maps/edifice.ifm +158 -0
  71. data/maps/frozen.ifm +126 -0
  72. data/maps/glow.ifm +101 -0
  73. data/maps/library.ifm +93 -0
  74. data/maps/mindelec.ifm +89 -0
  75. data/maps/minster.ifm +234 -0
  76. data/maps/muse.ifm +154 -0
  77. data/maps/paperchase.ifm +110 -0
  78. data/maps/space_st.ifm +104 -0
  79. data/maps/stationfall.ifm +320 -0
  80. data/maps/theatre.ifm +182 -0
  81. data/maps/toonesia.ifm +54 -0
  82. data/maps/tortoise.ifm +72 -0
  83. data/maps/vgame.ifm +219 -0
  84. data/maps/weather.ifm +98 -0
  85. data/maps/windhall.ifm +154 -0
  86. data/maps/zebulon.ifm +68 -0
  87. metadata +144 -0
data/HISTORY.txt ADDED
@@ -0,0 +1,2 @@
1
+
2
+ v0.5 - First public release on Rubyforge.
data/IFMapper.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ require "rubygems"
2
+
3
+ spec = Gem::Specification.new do |spec|
4
+ spec.name = "ifmapper"
5
+ spec.version = '0.5'
6
+ spec.author = "Gonzalo Garramuno"
7
+ spec.email = 'GGarramuno@aol.com or ggarram@advance.dsl.com.ar'
8
+ spec.homepage = 'http://www.rubyforge.org/projects/ifmapper/'
9
+ spec.summary = 'Interactive Fiction Mapping Tool.'
10
+ spec.require_path = "lib"
11
+ spec.files = ['IFMapper.rb'] + Dir.glob("lib/IFMapper/*.rb") + Dir.glob("maps/*.ifm") + Dir.glob("icons/*")
12
+ spec.description = <<-EOF
13
+ Interactive Fiction Mapping Tool.
14
+ EOF
15
+ spec.add_dependency("fxruby", ">= 1.2.6")
16
+ spec.add_dependency("pdf-writer", ">= 1.1.1")
17
+ spec.extra_rdoc_files = ["HISTORY.txt", "IFMapper.gemspec"]
18
+ spec.has_rdoc = true
19
+ spec.rubyforge_project = 'ifmapper'
20
+ spec.required_ruby_version = '>= 1.6.8'
21
+ end
data/IFMapper.rb ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Add current path, so modules are found locally
4
+ $LOAD_PATH << './lib'
5
+ require 'IFMapper/FXMapperWindow'
6
+
7
+ if __FILE__ == $0
8
+ # Make application
9
+ application = FXApp.new("IFMapper", "gga")
10
+
11
+ # Make window
12
+ m = FXMapperWindow.new(application)
13
+
14
+ # Create the application windows
15
+ application.create
16
+
17
+ # Run the application
18
+ begin
19
+ application.run
20
+ rescue => e
21
+ m.autosave
22
+ $stderr.puts e
23
+ $stderr.flush
24
+ raise e
25
+ end
26
+ end
27
+
data/icons/copy.png ADDED
Binary file
data/icons/cut.png ADDED
Binary file
data/icons/filenew.png ADDED
Binary file
Binary file
Binary file
Binary file
data/icons/help.png ADDED
Binary file
data/icons/kill.png ADDED
Binary file
Binary file
data/icons/paste.png ADDED
Binary file
Binary file
Binary file
data/icons/redo.png ADDED
Binary file
data/icons/saveas.png ADDED
Binary file
data/icons/undo.png ADDED
Binary file
data/icons/winapp.png ADDED
Binary file
data/icons/zoom.png ADDED
Binary file
@@ -0,0 +1,63 @@
1
+
2
+ #
3
+ # Class used to represent a connection between one
4
+ # room and another
5
+ #
6
+ class Connection
7
+ attr_accessor :type
8
+ attr_accessor :dir
9
+ attr_accessor :roomA, :roomB
10
+ attr_accessor :exitAtext, :exitBtext
11
+
12
+ # Type constants
13
+ FREE = 0
14
+ LOCKED_DOOR = 1
15
+ SPECIAL = 2
16
+
17
+ # Direction constants
18
+ BOTH = 0
19
+ AtoB = 1
20
+ BtoA = 2
21
+
22
+ # Text near connection (to indicate other dir)
23
+ EXIT_TEXT = [
24
+ '',
25
+ 'U',
26
+ 'D',
27
+ 'I',
28
+ 'O'
29
+ ]
30
+
31
+ def initialize( roomA, roomB, dir = BOTH, type = FREE )
32
+ @roomA = roomA
33
+ @roomB = roomB
34
+ @dir = dir
35
+ @type = type
36
+ @exitAtext = 0
37
+ @exitBtext = 0
38
+ end
39
+
40
+ def to_s
41
+ dirA = dirB = ''
42
+ a = @roomA? @roomA.name : 'nil'
43
+ b = @roomB? @roomB.name : 'nil'
44
+ if exitAtext > 0
45
+ dirA = EXIT_TEXT[exitBtext]
46
+ else
47
+ if @roomA
48
+ idx = @roomA.exits.index(self)
49
+ dirA = Room::DIRECTIONS[idx] if idx
50
+ end
51
+ end
52
+ if exitBtext > 0
53
+ dirB = EXIT_TEXT[exitBtext]
54
+ else
55
+ if @roomB
56
+ idx = @roomB.exits.rindex(self)
57
+ dirB = Room::DIRECTIONS[idx] if idx
58
+ end
59
+ end
60
+ "#{a} #{dirA}<->#{b} #{dirB}"
61
+ end
62
+ end
63
+
@@ -0,0 +1,32 @@
1
+
2
+
3
+ class FXAboutDialogBox < FXDialogBox
4
+
5
+ def initialize(parent, title, text)
6
+ decor = DECOR_TITLE|DECOR_BORDER|DECOR_CLOSE
7
+
8
+ super( parent, title, decor, 40, 40, 0, 0 )
9
+ mainFrame = FXVerticalFrame.new(self,
10
+ FRAME_SUNKEN|FRAME_THICK|
11
+ LAYOUT_FILL_X|LAYOUT_FILL_Y)
12
+
13
+ frame = FXHorizontalFrame.new(mainFrame, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
14
+
15
+ FXLabel.new(frame, text, nil, 0, LAYOUT_FILL_ROW)
16
+
17
+ # c = FXText.new(frame, nil, 0, LAYOUT_FILL_ROW)
18
+ # c.visibleRows = 10
19
+ # c.visibleColumns = 80
20
+ # c.editable = false
21
+ # c.text = text
22
+
23
+ buttons = FXHorizontalFrame.new(mainFrame,
24
+ LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|
25
+ PACK_UNIFORM_WIDTH)
26
+ # Accept
27
+ FXButton.new(buttons, "&Super!", nil, self, FXDialogBox::ID_ACCEPT,
28
+ FRAME_RAISED|LAYOUT_FILL_X|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
29
+
30
+ create
31
+ end
32
+ end
@@ -0,0 +1,283 @@
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 initialize( roomA, roomB, dir = Connection::BOTH,
42
+ type = Connection::FREE )
43
+ super( roomA, roomB, dir, type )
44
+ @selected = @failed = false
45
+ @pts = @gpts = []
46
+ end
47
+
48
+ def marshal_load(vars)
49
+ @selected, @type, @dir, @roomA, @roomB,
50
+ @exitAtext, @exitBtext = vars
51
+ @pts = @gpts = []
52
+ end
53
+
54
+ def marshal_dump
55
+ [ @selected, @type, @dir, @roomA, @roomB, @exitAtext, @exitBtext ]
56
+ end
57
+
58
+ def selected=(value)
59
+ if value and @@win
60
+ @@win.copy_from(self)
61
+ end
62
+ @selected = value
63
+ end
64
+
65
+ def toggle_direction
66
+ # If a self-loop, we cannot change dir
67
+ if @roomA == @roomB
68
+ return if @roomA.exits.index(self) == @roomA.exits.rindex(self)
69
+ end
70
+
71
+ @dir += 1
72
+ if @dir > BtoA
73
+ @dir = BOTH
74
+ end
75
+
76
+ if @@win
77
+ @@win.copy_from(self)
78
+ end
79
+ end
80
+
81
+ #
82
+ # Is this a complex path. Check if connection is
83
+ # contiguous
84
+ #
85
+ def complex?()
86
+ return false if not @roomB
87
+ return true if @roomB == @roomA
88
+ return true unless @roomA.next_to?(@roomB)
89
+
90
+ # Even if rooms are next to each other, we need to
91
+ # verify that following the exits does indeed take us to next room.
92
+ exitA = @roomA.exits.index(self)
93
+ dir = Room::DIR_TO_VECTOR[exitA]
94
+
95
+ if @roomA.x + dir[0] == @roomB.x and
96
+ @roomA.y + dir[1] == @roomB.y
97
+ exitB = @roomB.exits.rindex(self)
98
+ dir = Room::DIR_TO_VECTOR[exitB]
99
+ if @roomB.x + dir[0] == @roomA.x and
100
+ @roomB.y + dir[1] == @roomA.y
101
+ return false
102
+ else
103
+ return true
104
+ end
105
+ else
106
+ return true
107
+ end
108
+ end
109
+
110
+ def draw_complex_as_lines(dc, zoom)
111
+ p = []
112
+ @pts.each { |pt|
113
+ p << FXPoint.new( (pt[0] * zoom).to_i, (pt[1] * zoom).to_i )
114
+ }
115
+ dc.drawLines( p )
116
+ return p
117
+ end
118
+
119
+ def draw_complex_as_bspline(dc, zoom)
120
+ p = []
121
+ p << [ @pts[0][0] * zoom, @pts[0][1] * zoom ]
122
+ p << p[0]
123
+ p << p[0]
124
+ @pts.each { |pt|
125
+ p << [ pt[0] * zoom, pt[1] * zoom ]
126
+ }
127
+ p << p[-1]
128
+ p << p[-1]
129
+ p << p[-1]
130
+ return dc.drawBSpline( p )
131
+ end
132
+
133
+ def draw_complex(dc, zoom, opt)
134
+ if opt['Paths as Curves']
135
+ p = draw_complex_as_bspline(dc, zoom)
136
+ else
137
+ p = draw_complex_as_lines(dc, zoom)
138
+ end
139
+
140
+ x1, y1 = [p[0].x, p[0].y]
141
+ x2, y2 = [p[-1].x, p[-1].y]
142
+ draw_arrow(dc, zoom, x1, y1, x2, y2)
143
+ end
144
+
145
+ def draw_simple(dc, zoom)
146
+ dir = @roomA.exits.index(self)
147
+ x1, y1 = @roomA.corner(self, zoom, dir)
148
+ if @roomB
149
+ x2, y2 = @roomB.corner(self, zoom)
150
+ dc.drawLine( x1, y1, x2, y2 )
151
+ draw_arrow(dc, zoom, x1, y1, x2, y2)
152
+ if @type == LOCKED_DOOR
153
+ v = [ (x2-x1)*0.25, (y2-y1)*0.25 ]
154
+ m = [ (x2+x1)/2, (y2+y1)/2 ]
155
+ x1, y1 = [m[0] + v[1], m[1] - v[0]]
156
+ x2, y2 = [m[0] - v[1], m[1] + v[0]]
157
+ dc.drawLine(x1, y1, x2, y2)
158
+ end
159
+ else
160
+ v = FXRoom::DIR_TO_VECTOR[dir]
161
+ x2, y2 = [ @roomA.x + v[0] * 0.5, @roomA.y + v[1] * 0.5 ]
162
+ x2 *= WW * zoom
163
+ y2 *= HH * zoom
164
+ x2 += WW / 2 * zoom
165
+ y2 += HH / 2 * zoom
166
+ dc.drawLine( x1, y1, x2, y2 )
167
+ end
168
+ end
169
+
170
+ RAD_45 = 45 * Math::PI / 180
171
+ SIN_45 = Math.sin(RAD_45)
172
+ COS_45 = Math.cos(RAD_45)
173
+
174
+ def _arrow_info( x1, y1, x2, y2, zoom = 1.0 )
175
+ pt1 = []
176
+ dir = 0
177
+ if @dir == AtoB
178
+ dir = @roomB.exits.rindex(self)
179
+ pt1 = [ x2, y2 ]
180
+ else
181
+ dir = @roomA.exits.index(self)
182
+ pt1 = [ x1, y1 ]
183
+ end
184
+ x, y = Room::DIR_TO_VECTOR[dir]
185
+ arrow_len = 20.0 / Math.sqrt(x * x + y * y)
186
+ x *= arrow_len * zoom
187
+ y *= arrow_len * -zoom
188
+
189
+ d = [
190
+ x * COS_45 + y * SIN_45,
191
+ x * SIN_45 - y * COS_45
192
+ ]
193
+ return pt1, d
194
+ end
195
+
196
+
197
+ def draw_arrow( dc, zoom, x1, y1, x2, y2 )
198
+ return if @dir == BOTH
199
+ pt1, d = _arrow_info( x1, y1, x2, y2, zoom )
200
+
201
+ p = []
202
+ p << FXPoint.new( pt1[0].to_i, pt1[1].to_i )
203
+ pt2 = [ pt1[0] + d[0], pt1[1] + d[1] ]
204
+ p << FXPoint.new( pt2[0].to_i, pt2[1].to_i )
205
+ pt2 = [ pt1[0] + d[1], pt1[1] - d[0] ]
206
+ p << FXPoint.new( pt2[0].to_i, pt2[1].to_i )
207
+
208
+ dc.fillPolygon(p)
209
+ end
210
+
211
+ def draw_text(dc, zoom, x, y, dir, text, arrow)
212
+ if dir == 7 or dir < 6 and dir != 1
213
+ if arrow and (dir == 0 or dir == 4)
214
+ x += 10 * zoom
215
+ end
216
+ x += 5 * zoom
217
+ elsif dir == 6 or dir == 1
218
+ x -= 15 * zoom
219
+ end
220
+
221
+ if dir > 5 or dir < 4
222
+ if arrow and (dir == 6 or dir == 2)
223
+ y -= 10 * zoom
224
+ end
225
+ y -= 5 * zoom
226
+ elsif dir == 4 or dir == 5
227
+ y += 15 * zoom
228
+ end
229
+
230
+ dc.drawText(x, y, text)
231
+ end
232
+
233
+ def draw_exit_text(dc, zoom)
234
+ if @exitAtext != 0
235
+ dir = @roomA.exits.index(self)
236
+ x, y = @roomA.corner(self, zoom, dir)
237
+ draw_text( dc, zoom, x, y, dir,
238
+ EXIT_TEXT[@exitAtext], @dir == BtoA)
239
+ end
240
+ if @exitBtext != 0
241
+ dir = @roomB.exits.rindex(self)
242
+ x, y = @roomB.corner(self, zoom, dir)
243
+ draw_text( dc, zoom, x, y, dir,
244
+ EXIT_TEXT[@exitBtext], @dir == AtoB)
245
+ end
246
+ end
247
+
248
+ def draw(dc, zoom, opt)
249
+ if @selected
250
+ dc.foreground = 'yellow'
251
+ elsif @failed
252
+ dc.foreground = 'red'
253
+ else
254
+ dc.foreground = opt['Arrow Color']
255
+ end
256
+
257
+ draw_exit_text(dc, zoom)
258
+ if @type == SPECIAL
259
+ dc.lineStyle = LINE_ONOFF_DASH
260
+ else
261
+ dc.lineStyle = LINE_SOLID
262
+ end
263
+ if pts.size > 0
264
+ draw_complex(dc, zoom, opt)
265
+ else
266
+ draw_simple(dc, zoom)
267
+ end
268
+ end
269
+
270
+
271
+ def properties(map, event = nil)
272
+ if not @@win
273
+ @@win = FXConnectionDialogBox.new(map, self, event)
274
+ else
275
+ @@win.map = map
276
+ end
277
+ @@win.copy_from(self)
278
+ @@win.show
279
+ return
280
+ end
281
+
282
+ end
283
+