rutui 0.3.1 → 0.4
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.
- data/lib/rutui.rb +38 -0
- data/lib/rutui/axx.rb +86 -0
- data/lib/rutui/figlet.rb +158 -0
- data/lib/rutui/objects.rb +285 -0
- data/lib/rutui/pixel.rb +22 -0
- data/lib/rutui/screen.rb +107 -0
- data/lib/rutui/screenmanager.rb +76 -0
- data/lib/rutui/sprites.rb +64 -0
- data/lib/rutui/table.rb +209 -0
- data/lib/rutui/textfield.rb +112 -0
- data/lib/rutui/theme.rb +55 -0
- data/lib/rutui/util.rb +78 -0
- metadata +15 -5
- data/rutui.rb +0 -684
@@ -0,0 +1,112 @@
|
|
1
|
+
## Textfield Object Class
|
2
|
+
# Creates an Textfield element
|
3
|
+
#
|
4
|
+
# Methods:
|
5
|
+
# :set_focus Set focus to this textfield
|
6
|
+
# :write CHAR Write char to textfield (if has focus)
|
7
|
+
# :set_text TEXT Set text
|
8
|
+
# :get_text Returns text
|
9
|
+
# :count Text count
|
10
|
+
#
|
11
|
+
# Attributes (all accessible):
|
12
|
+
# :x MUST
|
13
|
+
# :y MUST
|
14
|
+
# :pixel - pixel from which colors get inherted
|
15
|
+
# :allow - allowed chars
|
16
|
+
# :password - boolean: is password field?
|
17
|
+
# :focus - has focus?
|
18
|
+
#
|
19
|
+
class Textfield < BaseObject
|
20
|
+
attr_accessor :focus, :password, :border, :allow
|
21
|
+
|
22
|
+
def initialize options
|
23
|
+
@width = 14
|
24
|
+
@width = options[:width] if !options[:width].nil?
|
25
|
+
|
26
|
+
@pixel = options[:pixel]
|
27
|
+
@pixel = Theme.get(:border) if @pixel.nil?
|
28
|
+
|
29
|
+
@x = options[:x]
|
30
|
+
@x = 1 if @x.nil?
|
31
|
+
@y = options[:y]
|
32
|
+
@y = 1 if @y.nil?
|
33
|
+
|
34
|
+
@allow = (0..9).to_a + ('a'..'z').to_a + ('A'..'Z').to_a + [" ", ":", "<", ">", "|", "#",
|
35
|
+
"@", "*", ",", "!", "?", ".", "-", "_", "=", "[", "]", "(", ")", "{", "}", ";"]
|
36
|
+
@allow = options[:allow] if !options[:allow].nil?
|
37
|
+
|
38
|
+
@height = 1
|
39
|
+
|
40
|
+
@focus = false
|
41
|
+
@password = false
|
42
|
+
@password = true if options[:password] == true
|
43
|
+
|
44
|
+
@text = ""
|
45
|
+
|
46
|
+
create
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# set focus
|
51
|
+
def set_focus
|
52
|
+
@focus = true
|
53
|
+
Ansi.position @x, @y
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# count
|
58
|
+
def count
|
59
|
+
@text.size
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# write to textfield
|
64
|
+
def write char
|
65
|
+
if @focus
|
66
|
+
@text += char.chr if @allow.include? char.chr
|
67
|
+
@text = @text[0..-2] if char == 127
|
68
|
+
end
|
69
|
+
create
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# set text
|
74
|
+
def set_text text
|
75
|
+
@text = text
|
76
|
+
create
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# get text
|
81
|
+
def get_text
|
82
|
+
@text
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# create or recreate the table object
|
87
|
+
def create
|
88
|
+
obj = []
|
89
|
+
_obj = []
|
90
|
+
if (@text.size+2) < @width
|
91
|
+
text = @text
|
92
|
+
else
|
93
|
+
text = @text.split(//).last(@width).join("").to_s
|
94
|
+
end
|
95
|
+
|
96
|
+
if password
|
97
|
+
_text = text
|
98
|
+
text = ""
|
99
|
+
_text.size.times do |i|
|
100
|
+
text += "*"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
text.to_s.split("").each do |t|
|
105
|
+
_obj << Pixel.new(@pixel.fg, @pixel.bg, t)
|
106
|
+
end
|
107
|
+
|
108
|
+
_obj << Pixel.new(@pixel.fg, @pixel.bg, "_")
|
109
|
+
obj << _obj
|
110
|
+
@obj = obj
|
111
|
+
end
|
112
|
+
end
|
data/lib/rutui/theme.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Simple themeing engine
|
2
|
+
class Theme
|
3
|
+
@@themes = {}
|
4
|
+
@@use = :default
|
5
|
+
|
6
|
+
# init themes
|
7
|
+
def self.init
|
8
|
+
@@themes[:default] = {
|
9
|
+
:background => Pixel.new(236,234,":"),
|
10
|
+
:border => Pixel.new(144,234,"-"),
|
11
|
+
:textcolor => 11,
|
12
|
+
:rainbow => [1,3,11,2,4,5]
|
13
|
+
}
|
14
|
+
@@themes[:light] = {
|
15
|
+
:background => Pixel.new(251,253,":"),
|
16
|
+
:border => Pixel.new(237,253,"-"),
|
17
|
+
:textcolor => 0,
|
18
|
+
:rainbow => [1,3,11,2,4,5]
|
19
|
+
}
|
20
|
+
@@themes[:basic] = {
|
21
|
+
:background => Pixel.new(0,14," "),
|
22
|
+
:border => Pixel.new(8,14,"-"),
|
23
|
+
:textcolor => 0,
|
24
|
+
:rainbow => [1,2,3,4,5,6]
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
# Create new theme
|
29
|
+
def self.create name, theme
|
30
|
+
@@themes[name] = theme
|
31
|
+
end
|
32
|
+
|
33
|
+
# Delete theme
|
34
|
+
def self.delete name
|
35
|
+
@@themes.delete(name)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Set value from current theme
|
39
|
+
def self.set key, val
|
40
|
+
@@themes[@@use][key] = val
|
41
|
+
end
|
42
|
+
|
43
|
+
# Get value from current theme
|
44
|
+
def self.get val
|
45
|
+
@@themes[@@use][val]
|
46
|
+
end
|
47
|
+
|
48
|
+
# set current theme
|
49
|
+
def self.use name
|
50
|
+
@@use = name if !@@themes[name].nil?
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
Theme.init
|
data/lib/rutui/util.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
#
|
2
|
+
# If you want to port this to other Systems, this is your file of choice
|
3
|
+
# Its heavy unix based in here
|
4
|
+
#
|
5
|
+
|
6
|
+
## Ansi Class
|
7
|
+
# This Class generates ansi strings for the
|
8
|
+
# Terminal based output.
|
9
|
+
#
|
10
|
+
# Its only tested on Linux, should work atleast
|
11
|
+
# on other unix based systems
|
12
|
+
#
|
13
|
+
|
14
|
+
class Ansi
|
15
|
+
# Calculate color from RGB values
|
16
|
+
def self.rgb(red, green, blue); 16 + (red * 36) + (green * 6) + blue; end
|
17
|
+
# Set background color
|
18
|
+
def self.bg color; "\x1b[48;5;#{color}m"; end
|
19
|
+
# Set text color
|
20
|
+
def self.fg color; "\x1b[38;5;#{color}m"; end
|
21
|
+
# "Shortcut" to background color
|
22
|
+
def self.background color; self.bg color; end
|
23
|
+
# "Shortcut" to foreground/text color
|
24
|
+
def self.foreground color; self.fg color; end
|
25
|
+
# Clear all color
|
26
|
+
def self.clear_color; "\x1b[0m"; end
|
27
|
+
# Clear Screen/Terminal
|
28
|
+
def self.clear; "\x1b[2J"; end
|
29
|
+
# set start
|
30
|
+
def self.set_start; "\x1b[s"; end
|
31
|
+
# goto start
|
32
|
+
def self.goto_start; "\x1b[u"; end
|
33
|
+
# Go home
|
34
|
+
def self.go_home; "\x1b[H"; end
|
35
|
+
# Goto position
|
36
|
+
def self.position x,y; "\x1b[#{y};#{x}f"; end
|
37
|
+
end
|
38
|
+
|
39
|
+
## Screen Utils Class
|
40
|
+
# Static Stuff that fits nowhere else
|
41
|
+
#
|
42
|
+
class Utils
|
43
|
+
# Get Windows size
|
44
|
+
def self.winsize
|
45
|
+
# > Ruby 1.9.3
|
46
|
+
#require 'io/console'
|
47
|
+
#IO.console.winsize
|
48
|
+
#rescue LoadError
|
49
|
+
# unix only but each ruby
|
50
|
+
[Integer(`tput lines`), Integer(`tput cols`)]
|
51
|
+
|
52
|
+
#if !ENV["LINES"].nil?
|
53
|
+
# [ENV["LINES"], ENV["COLUMNS"]]
|
54
|
+
#else
|
55
|
+
# [Integer(`tput lines`), Integer(`tput cols`)]
|
56
|
+
#end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Get input char without enter
|
60
|
+
# UNIX only!
|
61
|
+
def self.gets
|
62
|
+
# Win32API.new("crtdll", "_getch", [], "L").Call).chr
|
63
|
+
begin
|
64
|
+
system("stty raw -echo")
|
65
|
+
str = STDIN.getc
|
66
|
+
ensure
|
67
|
+
system("stty -raw echo")
|
68
|
+
end
|
69
|
+
return str.ord
|
70
|
+
end
|
71
|
+
|
72
|
+
# Hides the cursor
|
73
|
+
def self.init
|
74
|
+
system("tput civis")
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rutui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.4'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-07-22 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Create Pure Ruby textbased interfaces of all kinds (Unix only)
|
15
15
|
email: roman.pramberger@gmail.com
|
@@ -17,7 +17,18 @@ executables: []
|
|
17
17
|
extensions: []
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
|
-
- rutui.rb
|
20
|
+
- lib/rutui.rb
|
21
|
+
- lib/rutui/util.rb
|
22
|
+
- lib/rutui/pixel.rb
|
23
|
+
- lib/rutui/theme.rb
|
24
|
+
- lib/rutui/objects.rb
|
25
|
+
- lib/rutui/screen.rb
|
26
|
+
- lib/rutui/screenmanager.rb
|
27
|
+
- lib/rutui/figlet.rb
|
28
|
+
- lib/rutui/axx.rb
|
29
|
+
- lib/rutui/sprites.rb
|
30
|
+
- lib/rutui/table.rb
|
31
|
+
- lib/rutui/textfield.rb
|
21
32
|
homepage: http://rubygems.org/gems/rutui
|
22
33
|
licenses: []
|
23
34
|
post_install_message:
|
@@ -38,9 +49,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
38
49
|
version: '0'
|
39
50
|
requirements: []
|
40
51
|
rubyforge_project:
|
41
|
-
rubygems_version: 1.8.
|
52
|
+
rubygems_version: 1.8.23
|
42
53
|
signing_key:
|
43
54
|
specification_version: 3
|
44
55
|
summary: RUby Textbased User Interface
|
45
56
|
test_files: []
|
46
|
-
has_rdoc:
|
data/rutui.rb
DELETED
@@ -1,684 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# encoding: UTF-8
|
3
|
-
# Generated one file script of rutui
|
4
|
-
# This file is commandless and stripped down
|
5
|
-
# For full source please visit:
|
6
|
-
# https://github.com/b1nary/rutui
|
7
|
-
#
|
8
|
-
# Author: Roman Pramberger (roman.pramberger@gmail.com)
|
9
|
-
# License: MIT
|
10
|
-
#
|
11
|
-
# Mon Jul 1 13:54:29 CEST 2013
|
12
|
-
#
|
13
|
-
class RuTui
|
14
|
-
class Color
|
15
|
-
# Calculate color from RGB values
|
16
|
-
def self.rgb(red, green, blue); 16 + (red * 36) + (green * 6) + blue; end
|
17
|
-
# Set background color
|
18
|
-
def self.bg color; "\x1b[48;5;#{color}m"; end
|
19
|
-
# Set text color
|
20
|
-
def self.fg color; "\x1b[38;5;#{color}m"; end
|
21
|
-
# "Shortcut" to background color
|
22
|
-
def self.background color; self.bg color; end
|
23
|
-
# "Shortcut" to foreground/text color
|
24
|
-
def self.foreground color; self.fg color; end
|
25
|
-
# Clear all color
|
26
|
-
def self.clear_color; "\x1b[0m"; end
|
27
|
-
# Clear Screen/Terminal
|
28
|
-
def self.clear; "\e[2J\e[1;1H"; end
|
29
|
-
end
|
30
|
-
class Utils
|
31
|
-
# Get Windows size
|
32
|
-
def self.winsize
|
33
|
-
# > Ruby 1.9.3
|
34
|
-
#require 'io/console'
|
35
|
-
#IO.console.winsize
|
36
|
-
#rescue LoadError
|
37
|
-
# unix only but each ruby
|
38
|
-
[Integer(`tput lines`), Integer(`tput cols`)]
|
39
|
-
#if !ENV["LINES"].nil?
|
40
|
-
# [ENV["LINES"], ENV["COLUMNS"]]
|
41
|
-
#else
|
42
|
-
# [Integer(`tput lines`), Integer(`tput cols`)]
|
43
|
-
#end
|
44
|
-
end
|
45
|
-
# Get input char without enter
|
46
|
-
# UNIX only!
|
47
|
-
def self.gets
|
48
|
-
# Win32API.new("crtdll", "_getch", [], "L").Call).chr
|
49
|
-
begin
|
50
|
-
system("stty raw -echo")
|
51
|
-
str = STDIN.getc
|
52
|
-
ensure
|
53
|
-
system("stty -raw echo")
|
54
|
-
end
|
55
|
-
return str.ord
|
56
|
-
end
|
57
|
-
# Hides the cursor
|
58
|
-
def self.init
|
59
|
-
system("tput civis")
|
60
|
-
end
|
61
|
-
# Brings the cursor back
|
62
|
-
def self.clear
|
63
|
-
system("tput cnorm")
|
64
|
-
end
|
65
|
-
end
|
66
|
-
class Pixel
|
67
|
-
attr_accessor :fg, :bg, :symbol
|
68
|
-
def initialize foreground = 15, background = nil, symbol = " "
|
69
|
-
@fg = foreground
|
70
|
-
@bg = background
|
71
|
-
@symbol = symbol
|
72
|
-
end
|
73
|
-
def self.random sym = "#"
|
74
|
-
Pixel.new(rand(255),rand(255),sym)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
class Theme
|
78
|
-
@@themes = {}
|
79
|
-
@@use = :default
|
80
|
-
# init themes
|
81
|
-
def self.init
|
82
|
-
@@themes[:default] = {
|
83
|
-
:background => Pixel.new(236,234,":"),
|
84
|
-
:border => Pixel.new(144,234,"-"),
|
85
|
-
:textcolor => 11,
|
86
|
-
:rainbow => [1,3,11,2,4,5]
|
87
|
-
}
|
88
|
-
@@themes[:light] = {
|
89
|
-
:background => Pixel.new(251,253,":"),
|
90
|
-
:border => Pixel.new(237,253,"-"),
|
91
|
-
:textcolor => 0,
|
92
|
-
:rainbow => [1,3,11,2,4,5]
|
93
|
-
}
|
94
|
-
end
|
95
|
-
# Create new theme
|
96
|
-
def self.create name, theme
|
97
|
-
@@themes[name] = theme
|
98
|
-
end
|
99
|
-
# Delete theme
|
100
|
-
def self.delete name
|
101
|
-
@@themes.delete(name)
|
102
|
-
end
|
103
|
-
# Set value from current theme
|
104
|
-
def self.set key, val
|
105
|
-
@@themes[@@use][key] = val
|
106
|
-
end
|
107
|
-
# Get value from current theme
|
108
|
-
def self.get val
|
109
|
-
@@themes[@@use][val]
|
110
|
-
end
|
111
|
-
# set current theme
|
112
|
-
def self.use name
|
113
|
-
@@use = name if !@@themes[name].nil?
|
114
|
-
end
|
115
|
-
end
|
116
|
-
Theme.init
|
117
|
-
class BaseObject
|
118
|
-
attr_accessor :x, :y, :width, :height, :obj
|
119
|
-
# Ex.: BaseObject.new({ :x => 1, :y => 20, :obj => [[Pixel.new(1),Pixel.new(2,4,"#")]] })
|
120
|
-
def initialize options
|
121
|
-
@obj = options[:obj]
|
122
|
-
@obj = Array.new(height){ Array.new(width) } if @obj.nil?
|
123
|
-
@x = options[:x]
|
124
|
-
@y = options[:y]
|
125
|
-
@height = @obj.size
|
126
|
-
@width = @obj[0].size
|
127
|
-
end
|
128
|
-
# Move object X and Y (modifiers like: -2, 2)
|
129
|
-
def move x, y; @x += x; @y += y; end
|
130
|
-
# Set object position X Y
|
131
|
-
def set_position x, y; @x = x; @y = y; end
|
132
|
-
# Set pixel on position on object
|
133
|
-
def set_pixel x, y, pixel
|
134
|
-
@obj[x][y] = pixel if !@obj[x].nil? and !@obj[x][y].nil?
|
135
|
-
end
|
136
|
-
# Get pixel by position
|
137
|
-
def get_pixel x, y
|
138
|
-
@obj[x][y] if !@obj[x].nil? and !@obj[x][y].nil?
|
139
|
-
end
|
140
|
-
# "special" each methods for objects
|
141
|
-
def each
|
142
|
-
@obj.each_with_index do |row,row_count|
|
143
|
-
row.each_with_index do |pixel,col_count|
|
144
|
-
yield row_count, col_count, pixel
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
class Box < RuTui::BaseObject
|
150
|
-
attr_accessor :fill, :width, :height, :vertical, :horizontal, :corner
|
151
|
-
# initialize object (see above)
|
152
|
-
def initialize options
|
153
|
-
@x = options[:x]
|
154
|
-
@y = options[:y]
|
155
|
-
@width = options[:width]
|
156
|
-
@height = options[:height]
|
157
|
-
return if @x.nil? or @y.nil? or @width.nil? or @height.nil?
|
158
|
-
@fill = options[:fill]
|
159
|
-
@vertical = options[:vertical]
|
160
|
-
@horizontal = options[:horizontal]
|
161
|
-
@corner = options[:corner]
|
162
|
-
ref = Theme.get(:border)
|
163
|
-
@horizontal = Pixel.new(ref.fg,ref.bg,"-") if options[:horizontal].nil?
|
164
|
-
@vertical = Pixel.new(ref.fg,ref.bg,"|") if options[:vertical].nil?
|
165
|
-
@corner = Pixel.new(ref.fg,ref.bg,"*") if options[:corner].nil?
|
166
|
-
@width = 3 if @width < 3
|
167
|
-
@height = 3 if @height < 3
|
168
|
-
create
|
169
|
-
end
|
170
|
-
# Create Box
|
171
|
-
# can be recalled any time on attribute changes
|
172
|
-
def create
|
173
|
-
if !@fill.nil?
|
174
|
-
backpixel = Pixel.new(@fill.fg,@fill.bg,@fill.symbol)
|
175
|
-
obj = Array.new(@height){ Array.new(@width) { backpixel } }
|
176
|
-
else
|
177
|
-
obj = Array.new(@height){ Array.new(@width) }
|
178
|
-
end
|
179
|
-
(@width-2).times do |i|
|
180
|
-
obj[0][i+1] = @horizontal
|
181
|
-
obj[@height-1][i+1] = @horizontal
|
182
|
-
end
|
183
|
-
(@height-2).times do |i|
|
184
|
-
obj[i+1][0] = @vertical
|
185
|
-
obj[i+1][@width-1] = @vertical
|
186
|
-
end
|
187
|
-
obj[0][0] = @corner
|
188
|
-
obj[0][@width-1] = @corner
|
189
|
-
obj[@height-1][0] = @corner
|
190
|
-
obj[@height-1][@width-1] = @corner
|
191
|
-
@height = obj.size
|
192
|
-
@width = obj[0].size
|
193
|
-
@obj = obj
|
194
|
-
end
|
195
|
-
end
|
196
|
-
class Line < BaseObject
|
197
|
-
attr_accessor :length, :pixel, :endpixel, :direction
|
198
|
-
def initialize options
|
199
|
-
@x = options[:x]
|
200
|
-
@y = options[:y]
|
201
|
-
@length = options[:length]
|
202
|
-
@direction = options[:direction]
|
203
|
-
@direction = :horizontal if @direction.nil?
|
204
|
-
return if @x.nil? or @y.nil? or @width.nil?
|
205
|
-
@pixel = options[:pixel]
|
206
|
-
@endpixel = options[:endpixel]
|
207
|
-
@pixel = Theme.get(:border) if @pixel.nil?
|
208
|
-
create
|
209
|
-
end
|
210
|
-
# Create Line
|
211
|
-
# can be recalled any time on attribute changes
|
212
|
-
def create
|
213
|
-
if @direction == :horizontal
|
214
|
-
@obj = [Array.new(@length){ @pixel }]
|
215
|
-
else
|
216
|
-
@obj = Array.new(@length){ [@pixel] }
|
217
|
-
end
|
218
|
-
if !@endpixel.nil?
|
219
|
-
@obj[0][0] = @endpixel
|
220
|
-
@obj[0][@length-1] = @endpixel
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
224
|
-
class Circle < BaseObject
|
225
|
-
attr_accessor :radius, :pixel, :fill
|
226
|
-
# Initialize circle (see above)
|
227
|
-
def initialize options
|
228
|
-
@x = options[:x]
|
229
|
-
@y = options[:y]
|
230
|
-
@radius = options[:radius]
|
231
|
-
@pixel = options[:pixel]
|
232
|
-
@fill = options[:fill_pixel]
|
233
|
-
@pixel = Theme.get(:border) if @pixel.nil?
|
234
|
-
return if @x.nil? or @y.nil? or @radius.nil?
|
235
|
-
@width = options[:radius]*2 # needed?
|
236
|
-
@height = @width # needed?
|
237
|
-
create
|
238
|
-
end
|
239
|
-
# Create Circle
|
240
|
-
# can be recalled any time on attribute changes
|
241
|
-
def create
|
242
|
-
obj = []
|
243
|
-
(0..(@radius*2)).each do |x|
|
244
|
-
(0..(@radius*2)).each do |y|
|
245
|
-
obj[y] = [] if obj[y].nil?
|
246
|
-
obj[y][x] = distance_from_center(x,y).round == @radius ? @pixel : @fill
|
247
|
-
end
|
248
|
-
end
|
249
|
-
@obj = obj
|
250
|
-
end
|
251
|
-
private
|
252
|
-
def distance_from_center(x,y)
|
253
|
-
a = calc_side(x)
|
254
|
-
b = calc_side(y)
|
255
|
-
return Math.sqrt(a**2 + b**2)
|
256
|
-
end
|
257
|
-
def calc_side(z)
|
258
|
-
z < @radius ? (@radius - z) : (z - @radius)
|
259
|
-
end
|
260
|
-
end
|
261
|
-
class Text < BaseObject
|
262
|
-
attr_accessor :bg, :fg, :text, :do_rainbow
|
263
|
-
@@rainbow = nil
|
264
|
-
def initialize options
|
265
|
-
@@rainbow = Theme.get(:rainbow) if @@rainbow.nil?
|
266
|
-
@do_rainbow = options[:rainbow]
|
267
|
-
@text = options[:text]
|
268
|
-
@x = options[:x]
|
269
|
-
@y = options[:y]
|
270
|
-
@bg = options[:background]
|
271
|
-
@fg = options[:foreground]
|
272
|
-
@bg = Theme.get(:background).bg if @bg.nil?
|
273
|
-
@fg = Theme.get(:textcolor) if @fg.nil?
|
274
|
-
return if @x.nil? or @y.nil?
|
275
|
-
@height = 1
|
276
|
-
create
|
277
|
-
end
|
278
|
-
# Create Text
|
279
|
-
# can be recalled any time on attribute changes
|
280
|
-
def create
|
281
|
-
if @do_rainbow
|
282
|
-
rainbow = 0
|
283
|
-
end
|
284
|
-
@width = @text.size
|
285
|
-
@obj = []
|
286
|
-
tmp = []
|
287
|
-
@text.split("").each do |t|
|
288
|
-
if @do_rainbow
|
289
|
-
tmp << Pixel.new(@@rainbow[rainbow],@bg,t)
|
290
|
-
rainbow += 1
|
291
|
-
rainbow = 0 if rainbow >= @@rainbow.size
|
292
|
-
else
|
293
|
-
tmp << Pixel.new(@fg,@bg,t)
|
294
|
-
end
|
295
|
-
end
|
296
|
-
@obj << tmp
|
297
|
-
end
|
298
|
-
def set_text text
|
299
|
-
@text = text
|
300
|
-
create
|
301
|
-
end
|
302
|
-
end
|
303
|
-
class Screen
|
304
|
-
# Initialize me with a default pixel, if you want
|
305
|
-
def initialize default_pixel = Theme.get(:background)
|
306
|
-
size = Utils.winsize
|
307
|
-
@smap = Array.new(size[0]){ Array.new(size[1]) }
|
308
|
-
@map = @smap.dup
|
309
|
-
@default = default_pixel
|
310
|
-
@objects = []
|
311
|
-
@statics = []
|
312
|
-
# Set as default if first screen
|
313
|
-
ScreenManager.add :default, self if ScreenManager.size == 0
|
314
|
-
end
|
315
|
-
# regen screen (size change?)
|
316
|
-
def rescreen
|
317
|
-
size = Utils.winsize
|
318
|
-
@smap = Array.new(size[0]){ Array.new(size[1]) }
|
319
|
-
@statics.each do |s|
|
320
|
-
self.add_static s
|
321
|
-
end
|
322
|
-
@map = @smap.dup
|
323
|
-
end
|
324
|
-
# Set default/background pixel
|
325
|
-
# Ex.: screen.set_default Pixel.new(244,1,";")
|
326
|
-
def set_default pixel
|
327
|
-
@default = pixel
|
328
|
-
end
|
329
|
-
# Get default/background pixel
|
330
|
-
def get_default
|
331
|
-
@default
|
332
|
-
end
|
333
|
-
# add object that doesnt change over time
|
334
|
-
def add_static object
|
335
|
-
@statics << object if !@statics.include? object
|
336
|
-
object.each do |ri,ci,pixel|
|
337
|
-
@smap[object.y+ri][object.x+ci] = pixel if !pixel.nil? and object.y+ri > 0 and object.y+ci > 0
|
338
|
-
end
|
339
|
-
end
|
340
|
-
# add dynamic object
|
341
|
-
def add object
|
342
|
-
@objects << object
|
343
|
-
end
|
344
|
-
# draw the pixel-screen map
|
345
|
-
def draw
|
346
|
-
lastpixel = Pixel.new(rand(255), rand(255), ".")
|
347
|
-
@map = Marshal.load( Marshal.dump( @smap )) # Deep copy
|
348
|
-
# get all the objects
|
349
|
-
@objects.each do |o|
|
350
|
-
next if o.x.nil? or o.y.nil?
|
351
|
-
o.each do |ri,ci,pixel|
|
352
|
-
@map[o.y + ri][o.x + ci] = pixel if !pixel.nil? and o.y+ri > 0 and o.x+ci > 0 and o.y+ri < @map.size and o.x+ci < @map[0].size
|
353
|
-
end
|
354
|
-
end
|
355
|
-
# an DRAW!
|
356
|
-
@map.each do |line|
|
357
|
-
line.each do |pixel|
|
358
|
-
if pixel != lastpixel
|
359
|
-
print Color.clear_color if lastpixel != 0
|
360
|
-
if pixel.nil?
|
361
|
-
lastpixel = pixel
|
362
|
-
print "#{Color.bg(@default.bg)}#{Color.fg(@default.fg)}#{@default.symbol}"
|
363
|
-
else
|
364
|
-
lastpixel = pixel
|
365
|
-
print "#{Color.bg(pixel.bg)}#{Color.fg(pixel.fg)}#{pixel.symbol}"
|
366
|
-
end
|
367
|
-
else
|
368
|
-
if pixel.nil?
|
369
|
-
print @default.symbol
|
370
|
-
else
|
371
|
-
print pixel.symbol
|
372
|
-
end
|
373
|
-
end
|
374
|
-
end
|
375
|
-
end
|
376
|
-
end
|
377
|
-
end
|
378
|
-
class ScreenManager
|
379
|
-
@@screens = {}
|
380
|
-
@@current = :default
|
381
|
-
# Set a screen
|
382
|
-
# Ex.: ScreenManager.set :default, Screen.new
|
383
|
-
def self.add name, screen
|
384
|
-
@@screens[name] = screen
|
385
|
-
end
|
386
|
-
# Get count of existing screens
|
387
|
-
def self.size
|
388
|
-
@@screens.size
|
389
|
-
end
|
390
|
-
# Delete screen by name
|
391
|
-
def self.delete name
|
392
|
-
@@screens.delete(name) if !@@screens[name].nil?
|
393
|
-
end
|
394
|
-
# Set current screen
|
395
|
-
def self.set_current name
|
396
|
-
@@current = name
|
397
|
-
end
|
398
|
-
# Get current screen
|
399
|
-
def self.get_current
|
400
|
-
# Fix size and others of screen here
|
401
|
-
@@current
|
402
|
-
end
|
403
|
-
# Get the complete screen by name
|
404
|
-
def self.get_screen name
|
405
|
-
@@screens[name]
|
406
|
-
end
|
407
|
-
# Refit screen size
|
408
|
-
def self.refit
|
409
|
-
size = Utils.winsize
|
410
|
-
if @autofit or size != @lastsize
|
411
|
-
@@screens[@@current].rescreen
|
412
|
-
@lastsize = size
|
413
|
-
end
|
414
|
-
end
|
415
|
-
# draw current screen
|
416
|
-
def self.draw
|
417
|
-
print Color.clear
|
418
|
-
@@screens[@@current].draw
|
419
|
-
end
|
420
|
-
# Raw Game Loop
|
421
|
-
# Ex.: ScreenManager.loop({ :autodraw => true, :autofit => true }){ |key| p key }
|
422
|
-
def self.loop options
|
423
|
-
autodraw = options[:autodraw]
|
424
|
-
@autofit = options[:autofit]
|
425
|
-
@autofit = true if @autofit.nil?
|
426
|
-
@lastsize = nil
|
427
|
-
Utils.init
|
428
|
-
ScreenManager.draw
|
429
|
-
while true
|
430
|
-
key = Utils.gets
|
431
|
-
yield key
|
432
|
-
ScreenManager.refit if @autofit
|
433
|
-
ScreenManager.draw if autodraw
|
434
|
-
end
|
435
|
-
end
|
436
|
-
end
|
437
|
-
class Figlet < BaseObject
|
438
|
-
attr_accessor :text, :rainbow, :font, :colors
|
439
|
-
# Figlet font: '!" #$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz[|]~ÄÖÜäöüß'
|
440
|
-
@@chars = '!!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz[|]~ÄÖÜäöüß'.split("")
|
441
|
-
@@rainbow = nil
|
442
|
-
@@fonts = {}
|
443
|
-
# Initialize (see above)
|
444
|
-
def initialize options
|
445
|
-
@x = options[:x]
|
446
|
-
@y = options[:y]
|
447
|
-
@@rainbow = Theme.get(:rainbow) if @@rainbow.nil?
|
448
|
-
return if @x.nil? or @y.nil?
|
449
|
-
@font = options[:font]
|
450
|
-
@text = options[:text]
|
451
|
-
@rainbow = options[:rainbow]
|
452
|
-
@space = options[:space]
|
453
|
-
@space = 0 if @space.nil?
|
454
|
-
@colors = options[:colors]
|
455
|
-
@colors = [Pixel.new(Theme.get(:textcolor), Theme.get(:background).bg, Theme.get(:background).symbol)] if @colors.nil?
|
456
|
-
create
|
457
|
-
end
|
458
|
-
|
459
|
-
# Create Figlet text object
|
460
|
-
# Recall it any time when attributes have changed
|
461
|
-
def create
|
462
|
-
obj = []
|
463
|
-
@@fonts[@font]['n'].size.times do
|
464
|
-
obj << []
|
465
|
-
end
|
466
|
-
current = 0
|
467
|
-
count = 0
|
468
|
-
@text.each_byte do |c|
|
469
|
-
if @@chars.include? c.chr
|
470
|
-
@@fonts[@font][c.chr].each_with_index do |fr,ri|
|
471
|
-
fr.each do |fc|
|
472
|
-
if @rainbow
|
473
|
-
obj[ri] << Pixel.new(@@rainbow[current], @colors[0].bg,fc)
|
474
|
-
else
|
475
|
-
obj[ri] << Pixel.new(@colors[current].fg,@colors[current].bg,fc)
|
476
|
-
end
|
477
|
-
if @rainbow != true
|
478
|
-
current += 1 if @colors.size > 1
|
479
|
-
current = 0 if current > @colors.size
|
480
|
-
end
|
481
|
-
end
|
482
|
-
end
|
483
|
-
if @rainbow
|
484
|
-
current += 1
|
485
|
-
current = 0 if current >= @@rainbow.size
|
486
|
-
end
|
487
|
-
if count < @text.size-1
|
488
|
-
@@fonts[@font]['n'].size.times do |ri|
|
489
|
-
@space.times do
|
490
|
-
if @rainbow
|
491
|
-
obj[ri] << Pixel.new(@@rainbow[current], @colors[0].bg,Theme.get(:background).symbol)
|
492
|
-
else
|
493
|
-
obj[ri] << Pixel.new(@colors[current].fg,@colors[current].bg,Theme.get(:background).symbol)
|
494
|
-
end
|
495
|
-
end
|
496
|
-
end
|
497
|
-
end
|
498
|
-
# SPace
|
499
|
-
else
|
500
|
-
@@fonts[@font]['n'].size.times do |ri|
|
501
|
-
3.times do
|
502
|
-
if @rainbow
|
503
|
-
obj[ri] << Pixel.new(@@rainbow[current], @colors[0].bg, Theme.get(:background).symbol)
|
504
|
-
else
|
505
|
-
obj[ri] << Pixel.new(@colors[current].fg,@colors[current].bg, Theme.get(:background).symbol)
|
506
|
-
end
|
507
|
-
end
|
508
|
-
end
|
509
|
-
end
|
510
|
-
count += 1
|
511
|
-
end
|
512
|
-
@obj = obj
|
513
|
-
end
|
514
|
-
# Static methods to add/load new Fonts
|
515
|
-
def self.add name, file
|
516
|
-
if File.exists?(file)
|
517
|
-
data = File.new(file, "r").read.split("\n")
|
518
|
-
config = data[0].split(" ")
|
519
|
-
# Remove Comments (Size is in info line)
|
520
|
-
config[5].to_i.times do
|
521
|
-
data.delete_at(0)
|
522
|
-
end
|
523
|
-
# Remove empty line if exist
|
524
|
-
data.delete_at(0) if data[0].strip() == ""
|
525
|
-
height = config[2].to_i
|
526
|
-
rest = config[1].to_i - height
|
527
|
-
@@fonts[name] = {}
|
528
|
-
|
529
|
-
@@chars.each do |i|
|
530
|
-
out = []
|
531
|
-
(data.delete_at(0); rest -= 1) if data.size > 0 and data[0].gsub('$@','').gsub(' ','') == ''
|
532
|
-
height.times do |x|
|
533
|
-
break if data.size < 1
|
534
|
-
xdata = data[0].gsub("$"," ").gsub("@","").gsub("\r","").split("")
|
535
|
-
out << xdata if xdata.size > 0
|
536
|
-
data.delete_at(0)
|
537
|
-
end
|
538
|
-
rest.times do
|
539
|
-
data.delete_at(0)
|
540
|
-
end
|
541
|
-
@@fonts[name][i] = out
|
542
|
-
end
|
543
|
-
return true
|
544
|
-
else
|
545
|
-
return false
|
546
|
-
end
|
547
|
-
end
|
548
|
-
end
|
549
|
-
class Axx < BaseObject
|
550
|
-
def initialize options
|
551
|
-
@x = options[:x]
|
552
|
-
@y = options[:y]
|
553
|
-
@file = options[:file]
|
554
|
-
@attr, @xx, @yy, @save_x, @save_y, @attr = 0,0,0,0,0,0
|
555
|
-
return if @x.nil? or @y.nil? or @file.nil?
|
556
|
-
return if !File.exists? @file
|
557
|
-
@img = File.open(@file).read
|
558
|
-
self.parse
|
559
|
-
end
|
560
|
-
def parse
|
561
|
-
|
562
|
-
end
|
563
|
-
end
|
564
|
-
class Axx < BaseObject
|
565
|
-
def initialize options
|
566
|
-
@file = options[:file]
|
567
|
-
@x = options[:x]
|
568
|
-
@y = options[:y]
|
569
|
-
|
570
|
-
return if @file.nil?
|
571
|
-
return if !File.exists? @file
|
572
|
-
@img = File.open(@file).read
|
573
|
-
parse
|
574
|
-
end
|
575
|
-
def parse
|
576
|
-
out = []
|
577
|
-
@img.split("\n").each_with_index do |line,li|
|
578
|
-
if !line.match(/^#/)
|
579
|
-
out[li] = []
|
580
|
-
line.split("|").each_with_index do |elem,ei|
|
581
|
-
ele = elem.split(":")
|
582
|
-
if ele.size == 3
|
583
|
-
out[li][ei] = Pixel.new(ele[1].to_i,ele[2].to_i,ele[0])
|
584
|
-
elsif ele.size == 2
|
585
|
-
out[li][ei] = Pixel.new(ele[1].to_i,nil,ele[0])
|
586
|
-
else
|
587
|
-
if ele[0] == "nil"
|
588
|
-
out[li][ei] = nil
|
589
|
-
else
|
590
|
-
out[li][ei] = Pixel.new(nil,nil,ele[0])
|
591
|
-
end
|
592
|
-
end
|
593
|
-
end
|
594
|
-
end
|
595
|
-
end
|
596
|
-
out.each do |o|
|
597
|
-
out.delete(o) if o.nil?
|
598
|
-
end
|
599
|
-
@obj = out
|
600
|
-
@height = out.size
|
601
|
-
@width = out.size
|
602
|
-
end
|
603
|
-
def self.parse data
|
604
|
-
out = []
|
605
|
-
data.split("\n").each_with_index do |line,li|
|
606
|
-
if !line.match(/^#/)
|
607
|
-
out[li] = []
|
608
|
-
line.split("|").each_with_index do |elem,ei|
|
609
|
-
ele = elem.split(":")
|
610
|
-
if ele.size == 3
|
611
|
-
out[li][ei] = Pixel.new(ele[1].to_i,ele[2].to_i,ele[0])
|
612
|
-
elsif ele.size == 2
|
613
|
-
out[li][ei] = Pixel.new(ele[1].to_i,nil,ele[0])
|
614
|
-
else
|
615
|
-
if ele[0] == "nil"
|
616
|
-
out[li][ei] = nil
|
617
|
-
else
|
618
|
-
out[li][ei] = Pixel.new(nil,nil,ele[0])
|
619
|
-
end
|
620
|
-
end
|
621
|
-
end
|
622
|
-
end
|
623
|
-
end
|
624
|
-
out.each do |o|
|
625
|
-
out.delete(o) if o.nil? or o == []
|
626
|
-
end
|
627
|
-
return out
|
628
|
-
end
|
629
|
-
end
|
630
|
-
class Sprite < BaseObject
|
631
|
-
attr_accessor :tick, :current, :sprites, :ticks, :object
|
632
|
-
@@spr = []
|
633
|
-
def initialize options
|
634
|
-
@x = options[:x]
|
635
|
-
@y = options[:y]
|
636
|
-
@x = 0 if @x.nil?
|
637
|
-
@y = 0 if @y.nil?
|
638
|
-
@tick = 0
|
639
|
-
@object = options[:obj]
|
640
|
-
@file = options[:file]
|
641
|
-
@current = nil
|
642
|
-
@@spr << self
|
643
|
-
@sprites = {}
|
644
|
-
create_from_file if !@file.nil?
|
645
|
-
end
|
646
|
-
def create_from_file
|
647
|
-
if File.exists? @file
|
648
|
-
data = File.open(@file).read
|
649
|
-
# AXX Format
|
650
|
-
if data.include? '---' and data.include? '| :'
|
651
|
-
out = []
|
652
|
-
data = data.split("---")
|
653
|
-
while data.size > 0
|
654
|
-
while data[0].match(/^#/)
|
655
|
-
data.shift
|
656
|
-
end
|
657
|
-
name = data.shift
|
658
|
-
content = data.shift
|
659
|
-
@sprites[name] = [] if @sprites[name].nil?
|
660
|
-
@sprites[name] << Axx.parse(content)
|
661
|
-
@current = name if @current.nil? # first sprite gets default
|
662
|
-
@obj = @sprites[@current][0]
|
663
|
-
end
|
664
|
-
end
|
665
|
-
end
|
666
|
-
end
|
667
|
-
# set current animation
|
668
|
-
def set_current name
|
669
|
-
@current = name
|
670
|
-
@obj = @sprites[@current][0]
|
671
|
-
end
|
672
|
-
# Add sprite
|
673
|
-
def add name, images
|
674
|
-
@current = name if @current.nil? # first sprite gets default
|
675
|
-
@sprites[name] = images
|
676
|
-
end
|
677
|
-
# Update ticker
|
678
|
-
def update
|
679
|
-
@tick += 1
|
680
|
-
@tick = 0 if @tick >= ( @sprites[@current].size )
|
681
|
-
@obj = @sprites[@current][@tick]
|
682
|
-
end
|
683
|
-
end
|
684
|
-
end
|