ifmapper 0.5

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 (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
@@ -0,0 +1,24 @@
1
+
2
+ require 'IFMapper/FXConnection'
3
+ require 'IFMapper/FXRoom'
4
+ require 'IFMapper/Page'
5
+
6
+ class FXPage < Page
7
+ def new_connection( roomA, exitA, roomB, exitB = nil )
8
+ c = FXConnection.new( roomA, roomB )
9
+ return _new_connection(c, roomA, exitA, roomB, exitB)
10
+ end
11
+
12
+ def new_room(x, y)
13
+ r = FXRoom.new( x, y, 'New Location' )
14
+ return _new_room(r, x, y)
15
+ end
16
+
17
+ def properties(map)
18
+ if not @win
19
+ @win = FXPageDialogBox.new(map)
20
+ end
21
+ @win.copy_from(self)
22
+ @win.show
23
+ end
24
+ end
@@ -0,0 +1,38 @@
1
+
2
+
3
+ class FXPageDialogBox < FXDialogBox
4
+
5
+ def copy_to()
6
+ @page.name = @name.text
7
+ @map.update_title
8
+ end
9
+
10
+ def copy_from(page)
11
+ @name.text = page.name.to_s
12
+ @page = page
13
+ end
14
+
15
+ def initialize(map)
16
+ decor = DECOR_TITLE|DECOR_BORDER|DECOR_CLOSE
17
+
18
+ super( map.window, "Page Information", decor, 40, 40, 0, 0 )
19
+ mainFrame = FXVerticalFrame.new(self,
20
+ FRAME_SUNKEN|FRAME_THICK|
21
+ LAYOUT_FILL_X|LAYOUT_FILL_Y)
22
+
23
+ frame = FXHorizontalFrame.new(mainFrame, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
24
+
25
+ FXLabel.new(frame, "Name: ", nil, 0, LAYOUT_FILL_X)
26
+ @name = FXTextField.new(frame, 40, nil, 0, LAYOUT_FILL_ROW)
27
+
28
+ frame = FXVerticalFrame.new(mainFrame,
29
+ LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y)
30
+
31
+
32
+ @name.connect(SEL_CHANGED) { copy_to() }
33
+ @map = map
34
+
35
+ # We need to create the dialog box first, so we can use select text.
36
+ create
37
+ end
38
+ end
@@ -0,0 +1,218 @@
1
+
2
+ require 'IFMapper/Room'
3
+ require 'IFMapper/FXRoomDialogBox'
4
+
5
+ #
6
+ # Class used to reprent an IF room
7
+ #
8
+ class FXRoom < Room
9
+ attr_accessor :x, :y, :xx, :yy
10
+ attr_accessor :selected
11
+
12
+ @@win = nil
13
+
14
+ def initialize(x, y, *opts)
15
+ @xx = x * WW + WS_2
16
+ @yy = y * HH + HS_2
17
+ @selected = false
18
+ super(x, y, *opts)
19
+ end
20
+
21
+ def x=(v)
22
+ @x = v
23
+ @xx = v * WW + WS_2
24
+ end
25
+
26
+ def y=(v)
27
+ @y = v
28
+ @yy = v * HH + HS_2
29
+ end
30
+
31
+ def copy(b)
32
+ @name = b.name
33
+ @objects = b.objects
34
+ @tasks = b.tasks
35
+ @darkness = b.darkness
36
+ end
37
+
38
+ def selected=(value)
39
+ if value and @@win
40
+ @@win.copy_from(self)
41
+ end
42
+ @selected = value
43
+ end
44
+
45
+ def modal_properties(map)
46
+ shown = @@win and @@win.shown?
47
+ if shown
48
+ @@win.hide
49
+ end
50
+ win = FXRoomDialogBox.new(map, self, nil, true)
51
+ # win.setFocus
52
+ win.setFocus
53
+ win.show
54
+ win.copy_from(self)
55
+ if win.execute != 0
56
+ win.copy_to()
57
+ else
58
+ return false
59
+ end
60
+ if shown
61
+ @@win.show
62
+ end
63
+ return true
64
+ end
65
+
66
+ # Open a new requester to change room properties
67
+ def properties( map, event = nil )
68
+ if not @@win
69
+ @@win = FXRoomDialogBox.new(map, self, event, false)
70
+ else
71
+ @@win.map = map
72
+ end
73
+ @@win.setFocus
74
+ @@win.show
75
+ @@win.copy_from(self)
76
+ return
77
+ end
78
+
79
+ #
80
+ # Given a connection and/or an exit index, return the x and y offset
81
+ # multipliers needed from the top corner of the box.
82
+ #
83
+ def _corner(c, idx)
84
+ idx = @exits.index(c) unless idx
85
+ raise "corner: #{c} not found in #{self}" unless idx
86
+ x = y = 0
87
+ case idx
88
+ when 0
89
+ x = 0.5
90
+ when 1
91
+ x = 1
92
+ when 2
93
+ x = 1
94
+ y = 0.5
95
+ when 3
96
+ x = 1
97
+ y = 1
98
+ when 4
99
+ x = 0.5
100
+ y = 1
101
+ when 5
102
+ y = 1
103
+ when 6
104
+ y = 0.5
105
+ when 7
106
+ else
107
+ raise "error wrong index #{idx}"
108
+ end
109
+ return [ x, y ]
110
+ end
111
+
112
+
113
+ # Given a connection belonging to a room, return draw coordinate
114
+ # of that corner.
115
+ def corner( c, zoom, idx = nil )
116
+ x, y = _corner(c, idx)
117
+ x = @xx + W * x
118
+ y = @yy + H * y
119
+ return [x * zoom, y * zoom]
120
+ end
121
+
122
+
123
+ def draw_index(dc, zoom, idx)
124
+ x = (@xx + W - 20 ) * zoom
125
+ y = (@yy + HH - HS - 5 ) * zoom
126
+ dc.drawText(x, y, (idx + 1).to_s)
127
+ end
128
+
129
+
130
+ def draw_box(dc, zoom, idx, opt)
131
+ if @selected
132
+ dc.foreground = 'yellow'
133
+ else
134
+ if @darkness
135
+ dc.foreground = opt['Box Darkness Color']
136
+ else
137
+ dc.foreground = opt['Box BG Color']
138
+ end
139
+ end
140
+
141
+ x = @xx * zoom
142
+ y = @yy * zoom
143
+ w = W * zoom
144
+ h = H * zoom
145
+ dc.fillRectangle(x, y, w, h)
146
+
147
+
148
+ dc.foreground = opt['Box Border Color']
149
+ dc.lineWidth = 2 * zoom
150
+ dc.lineWidth = 2 if dc.lineWidth < 2
151
+ dc.lineStyle = LINE_SOLID
152
+ dc.drawRectangle(x, y, w, h)
153
+
154
+ # Draw grey square for index
155
+ if opt['Location Numbers']
156
+ dc.foreground = opt['Box Number Color']
157
+ x += w # Index goes at bottom right of square
158
+ y += h
159
+ w = WIDX * zoom
160
+ h = HIDX * zoom
161
+ x -= w
162
+ y -= h
163
+ dc.fillRectangle(x, y, w, h)
164
+
165
+ dc.foreground = opt['Box Border Color']
166
+ dc.drawRectangle(x, y, w, h)
167
+
168
+ draw_index(dc, zoom, idx)
169
+ end
170
+ end
171
+
172
+ def draw_text_wrap(dc, x, y, zoom, maxLen, text)
173
+ if text.size > maxLen
174
+ str = text
175
+ fh = dc.font.getFontHeight
176
+ while str and str.size > maxLen
177
+ idx = str.rindex(/[ -]/, maxLen)
178
+ unless idx
179
+ idx = str.index(/[ -]/, maxLen)
180
+ idx = str.size unless idx
181
+ end
182
+ dc.drawText(x, y, str[0..idx])
183
+ str = str[idx+1..-1]
184
+ y += fh
185
+ str = nil if y > (@yy + H) * zoom
186
+ end
187
+ dc.drawText(x, y, str) if str
188
+ else
189
+ dc.drawText(x, y, text)
190
+ end
191
+ return [x, y]
192
+ end
193
+
194
+ def draw_name(dc, zoom)
195
+ x = (@xx + 5) * zoom
196
+ y = (@yy + 15) * zoom
197
+ return draw_text_wrap( dc, x, y, zoom, 15, @name )
198
+ end
199
+
200
+ def draw_objects(dc, zoom, x, y)
201
+ return if @objects == ''
202
+ fh = dc.font.getFontHeight
203
+ y += fh
204
+ objs = @objects.split("\n")
205
+ objs = objs.join(', ')
206
+ return draw_text_wrap( dc, x, y, zoom, 23, objs )
207
+ end
208
+
209
+
210
+ def draw(dc, zoom, idx, opt, data)
211
+ draw_box(dc, zoom, idx, opt)
212
+ dc.font = data['font']
213
+ x, y = draw_name(dc, zoom)
214
+ dc.font = data['objfont']
215
+ draw_objects(dc, zoom, x, y)
216
+ end
217
+
218
+ end
@@ -0,0 +1,119 @@
1
+
2
+
3
+ #
4
+ # Class used to display a room dialog box
5
+ #
6
+ class FXRoomDialogBox < FXDialogBox
7
+
8
+ attr_writer :map
9
+
10
+ def copy_to()
11
+ @room.name = @name.text
12
+ @room.objects = @objects.text
13
+ @room.objects.gsub!(/[\.,\t]+/, "\n")
14
+ @room.tasks = @tasks.text
15
+ @room.darkness = (@darkness.checkState == 1)
16
+
17
+ ## we should do something like:
18
+ ## @room.draw(dc)
19
+ ## for faster updates
20
+ @map.draw
21
+ end
22
+
23
+
24
+ def copy_from(room)
25
+ @name.text = room.name
26
+ @darkness.checkState = room.darkness
27
+ @objects.text = room.objects
28
+ @tasks.text = room.tasks
29
+ # Select text for quick editing if it uses default location name
30
+ @name.setCursorPos room.name.size # - 1 if room.name.size > 0
31
+ if room.name == 'New Location'
32
+ @name.selectAll
33
+ end
34
+ if self.shown?
35
+ @name.setFocus
36
+ end
37
+ @room = room
38
+ if @map.navigation
39
+ @name.disable
40
+ @darkness.disable
41
+ @objects.disable
42
+ @tasks.disable
43
+ else
44
+ @name.enable
45
+ @darkness.enable
46
+ @objects.enable
47
+ @tasks.enable
48
+ end
49
+ end
50
+
51
+ def initialize(map, room, event = nil, modal = nil)
52
+ pos = [40, 40]
53
+ if event
54
+ pos = [ event.last_x, event.last_y ]
55
+ end
56
+ maxW = map.window.width - 390
57
+ maxH = map.window.height - 300
58
+ pos[0] = maxW if pos[0] > maxW
59
+ pos[1] = maxH if pos[1] > maxH
60
+
61
+ if modal
62
+ decor = DECOR_TITLE|DECOR_BORDER
63
+ else
64
+ decor = DECOR_TITLE|DECOR_BORDER|DECOR_CLOSE
65
+ end
66
+
67
+ super( map.window, "Room Information", decor, pos[0], pos[1], 0, 0 )
68
+ mainFrame = FXVerticalFrame.new(self,
69
+ FRAME_SUNKEN|FRAME_THICK|
70
+ LAYOUT_FILL_X|LAYOUT_FILL_Y)
71
+
72
+ frame = FXHorizontalFrame.new(mainFrame, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
73
+
74
+ FXLabel.new(frame, "Location: ", nil, 0, LAYOUT_FILL_X)
75
+ @name = FXTextField.new(frame, 40, nil, 0, LAYOUT_FILL_ROW)
76
+
77
+ frame = FXVerticalFrame.new(mainFrame,
78
+ LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y)
79
+
80
+
81
+ frame2 = FXHorizontalFrame.new(frame, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
82
+ FXLabel.new(frame2, "Objects: ", nil, 0, LAYOUT_FILL_X)
83
+ @darkness = FXCheckButton.new(frame2, "Darkness", nil, 0,
84
+ ICON_BEFORE_TEXT|LAYOUT_CENTER_X|
85
+ LAYOUT_SIDE_RIGHT)
86
+
87
+ @objects = FXText.new(frame, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y)
88
+ @objects.visibleRows = 8
89
+
90
+ frame = FXVerticalFrame.new(mainFrame, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|
91
+ LAYOUT_FILL_Y)
92
+ FXLabel.new(frame, "Tasks: ", nil, 0, LAYOUT_FILL_X)
93
+ @tasks = FXText.new(frame, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y)
94
+ @tasks.visibleRows = 8
95
+
96
+ if modal
97
+ buttons = FXHorizontalFrame.new(mainFrame,
98
+ LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|
99
+ PACK_UNIFORM_WIDTH)
100
+ # Accept
101
+ @ok = FXButton.new(buttons, "&Accept", nil, self, FXDialogBox::ID_ACCEPT,
102
+ FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
103
+
104
+ # Cancel
105
+ cmd = FXButton.new(buttons, "&Cancel", nil, self, FXDialogBox::ID_CANCEL,
106
+ FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
107
+ else
108
+ @name.connect(SEL_CHANGED) { copy_to() }
109
+ @objects.connect(SEL_CHANGED) { copy_to()}
110
+ @tasks.connect(SEL_CHANGED) { copy_to() }
111
+ @darkness.connect(SEL_COMMAND) { copy_to() }
112
+ end
113
+
114
+ @map = map
115
+
116
+ # We need to create the dialog box first, so we can use select text.
117
+ create
118
+ end
119
+ end
@@ -0,0 +1,51 @@
1
+
2
+ #
3
+ # Class used to display a connection dialog box
4
+ #
5
+ class FXSearchDialogBox < FXDialogBox
6
+ attr_accessor :index
7
+
8
+ def text=(x)
9
+ @search.text = x
10
+ @index = 0
11
+ end
12
+
13
+ def text
14
+ return @search.text
15
+ end
16
+
17
+ def proc=(p)
18
+ @search.connect(SEL_CHANGED, p)
19
+ @proc = p
20
+ end
21
+
22
+ def initialize(parent)
23
+ decor = DECOR_TITLE|DECOR_BORDER|DECOR_CLOSE
24
+ super( parent, '', decor, 40, 200, 0, 0 )
25
+ @index = 0
26
+ mainFrame = FXVerticalFrame.new(self,
27
+ FRAME_SUNKEN|FRAME_THICK|
28
+ LAYOUT_FILL_X|LAYOUT_FILL_Y)
29
+
30
+ frame = FXHorizontalFrame.new(mainFrame, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
31
+
32
+ FXLabel.new(frame, "Search String: ", nil, 0, LAYOUT_FILL_X)
33
+ @search = FXTextField.new(frame, 40, nil, 0, LAYOUT_FILL_ROW)
34
+
35
+ frame = FXHorizontalFrame.new(mainFrame, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X)
36
+ @previous = FXButton.new(frame, "Previous Match")
37
+ @previous.connect(SEL_COMMAND) { |sender, sel, e |
38
+ @index -= 1 if @index > 0
39
+ sender.handle(self, MKUINT(message, SEL_CHANGED), nil)
40
+ @proc.call @search, nil, nil if @proc
41
+ }
42
+ @next = FXButton.new(frame, "Next Match")
43
+ @next.connect(SEL_COMMAND) { |sender, sel, e |
44
+ @index += 1
45
+ @proc.call @search, nil, nil if @proc
46
+ }
47
+
48
+ # We need to create the dialog box first, so we can use select text.
49
+ create
50
+ end
51
+ end