git.s-ol.nu watch-cad / 5934b80
make things work s-ol 18 days ago
8 changed file(s) with 212 addition(s) and 49 deletion(s). Raw diff Collapse all Expand all
11 { graphics: lg } = love
22
33 import vec2, bound2 from require 'cpml'
4 import is_once, is_live, are_live, Once from require 'state'
45
56 random =
67 point: ->
1112 vec2 math.random! * 200 + 100, math.random! * 200 + 100
1213
1314 draw =
14 rect: (mode, min, max) ->
15 cross: (pos) ->
16 hs = vec2 8, 8
17 mx, my = (pos - hs)\unpack!
18 Mx, My = (pos + hs)\unpack!
19
20 lg.setColor 1, 1, 1
21 lg.line mx, my, Mx, My
22 lg.line mx, My, Mx, my
23
24 contains = (INPUT.mouse - pos)\len2! < hs\len2!
25 INPUT\mouse_event! if contains
26
27 rect: (min, max) ->
1528 x, y = min\unpack!
1629 w, h = (max - min)\unpack!
1730 lg.setColor 1, 1, 1
1932
2033 rect = bound2 min, max
2134 contains = rect\contains INPUT.mouse
22 contains and (not mode or INPUT["mouse_#{mode}"] INPUT, 1)
35 INPUT\mouse_event! if contains
2336
24 circle: (mode, center, r) ->
37 circle: (center, r) ->
2538 x, y = center\unpack!
2639 lg.setColor 1, 1, 1
2740 lg.circle 'line', x, y, r
2841
2942 contains = (INPUT.mouse - center)\len! < r
30 contains and (not mode or INPUT["mouse_#{mode}"] INPUT, 1)
43 INPUT\mouse_event! if contains
3144
3245 half_handle = vec2 15, 15
3346 input =
34 dot: (init, fixed) =>
35 init or= random.point!
47 point: (fixed={}) =>
48 if vec = is_once fixed
49 fixed = {
50 x: Once vec.x
51 y: Once vec.y
52 }
3653
37 if fixed == true
38 return init
39
40 fixed or= x: false, y: false
41 @pos = (rawget @, 'pos') or init
54 init = random.point!
55 @store 'x', fixed.x, init.x
56 @store 'y', fixed.y, init.y
57 pos = vec2 @x, @y
4258
43 if draw.rect 'held', @pos - half_handle, @pos + half_handle
44 delta = INPUT\mouse_delta!
45 @pos = @pos + delta
59 -- both values are 'live', no UI necessary
60 if are_live fixed.x, fixed.y
61 draw.cross pos
62 return pos
4663
47 @pos.x = init.x if fixed.x
48 @pos.y = init.y if fixed.y
64 hh = half_handle\clone!
65 hh.x /= 2 if is_live fixed.x
66 hh.y /= 2 if is_live fixed.y
4967
50 @pos
68 @init 'drag', false
69 if 'down' == draw.rect pos - hh, pos + hh
70 @drag = true
5171
52 rectangle: (init={}, fixed={}) =>
53 init.min or= random.point! * 0.8
54 init.max or= init.min + random.size!
55 @last_min = (rawget @, 'last_min') or init.min
72 if @drag
73 @drag = false if INPUT\mouse_up!
5674
57 max = input.dot @max, init.max, fixed.max
58 min = input.dot @min, init.min, fixed.min
59 delta = @last_min - min
60 max += delta
61 @last_min = min
75 pos += INPUT\mouse_delta!
6276
63 draw.rect nil, min, max
77 @store 'x', pos.x unless is_live fixed.x
78 @store 'y', pos.y unless is_live fixed.y
79
80 vec2 @x, @y
81
82 point_relative_to: (other, fixed) =>
83 assert (is_live other), "other needs to be live!"
84
85 @init 'last_other', other
86 @init 'last', fixed or random.point!
87 delta = other - @last_other
88
89 val = if delta\len2! > 0 and not is_live fixed
90 input.point @, @last + delta
91 else
92 input.point @, fixed or Once @last
93
94 @store 'last_other', other
95 @store 'last', val
96
97 val
98
99 rectangle: (fixed={}) =>
100 min = input.point @min, fixed.min or Once random.point! * 0.8
101 max = input.point_relative_to @max, min, fixed.max or Once min + random.size!
102
103 draw.rect min, max
64104 { :min, :max }
65105
66 circle: (init={}, fixed={}) =>
67 init.center or= random.point!
68 init.radius or= math.random! * 100 + 50
69 init.tangent or= do
70 angle = math.random! * math.pi * 2
71 init.center + vec2.from_cartesian init.radius, angle
72
73 center = input.dot @c, init.center, fixed.center
106 circle: (fixed={}) =>
107 local tangent
108 center = input.point @center, fixed.center
109 radius = (is_live fixed.radius) or do
110 radius = (is_once fixed.radius) or math.random! * 100 + 50
111 init_tangent = vec2.from_cartesian radius, math.random! * 2 * math.pi
112 tangent = input.point_relative_to @tangent, center, fixed.tangent or Once center + init_tangent
113 center\dist tangent
74114
75 local tangent, radius
76 if fixed.radius
77 radius = init.radius
78 else
79 tangent = input.dot @t, init.tangent, fixed.tangent
80 radius = (tangent - center)\len!
81
82 draw.circle nil, center, radius
83
84 { center, tangent, :radius }
115 draw.circle center, radius
116 { :center, :tangent, :radius }
85117
86118 selection: (init, fixed) =>
87119 init or= {o for o in *OBJS when match and o.name\match init}
1 Submodule commit 74de1154aa32b9c7348b95faff3228512c0a2e1c
1 Submodule commit 6c4991511228758da7a0d9f647adefa5632e8902
1 import vec2 from require 'cpml'
2
3 =>
4 a = input.point @point, x: 200
5 rect = input.rectangle @rect, min: a + (vec2 30, 0), max: { y: 200 }
6
7 circle = input.circle @circ, center: rect.min, tangent: rect.max
1616 love[event] = (...) -> INPUT[event] INPUT, ...
1717
1818 love.draw = SESSION\frame
19
20 require 'moon.all'
2119
2220 -- Move = (obj, x, y) ->
2321 -- if COMMIT
1111 mouse_down: (button=1) => @key_down "mouse-#{button}"
1212 mouse_up: (button=1) => @key_up "mouse-#{button}"
1313 mouse_held: (button=1) => @key_held "mouse-#{button}"
14
15 mouse_event: (button=1) =>
16 return 'down' if @mouse_down button
17 return 'up' if @mouse_up button
18 return 'held' if @mouse_held button
1419
1520 key_down: (key) => @keys[key] and not @last_keys[key]
1621 key_up: (key) => not @keys[key] and @last_keys[key]
11 lfs = require 'lfs'
2 moon = require 'moonscript.base'
23
34 trace = (msg) -> debug.traceback msg, 2
45
4647
4748 if @last_modification < modification
4849 @last_modification = modification
49 module, msg = loadfile @file
50 module, msg = if @file\match '%.moon$' then moon.loadfile @file else loadfile @file
5051 if not module
5152 @error = at: 'parse', :msg
5253 return
1 import Once, State from require 'state'
2
3 describe "Once", ->
4 it "stores a value", ->
5 a = Once 3
6 assert.is.equal 3, a.value
7
8 it "can test for itself", ->
9 assert.is_true Once.is_once Once 3
10 assert.is_true Once.is_once Once 2
11 assert.is_true Once.is_once Once nil
12 assert.is_true Once.is_once Once { a: 3 }
13
14 it "can test other types", ->
15 assert.is_falsy Once.is_once nil
16 assert.is_falsy Once.is_once 3
17 assert.is_falsy Once.is_once "once impostor"
18 assert.is_falsy Once.is_once { a: 3 }
19
20 describe "State", ->
21 local S
22 before_each ->
23 state = State!
24 S = state.state
25
26 it "can be indexed infinitely", ->
27 assert.is_table S.a.b.c.d
28
29 describe ":init", ->
30 it "stores default until changed", ->
31 S\init 'test', 2
32 assert.is.equal 2, S.test
33
34 S.test = 4
35 assert.is.equal 4, S.test
36
37 S\init 'test', 2
38 assert.is.equal 4, S.test
39
40 describe ":store", ->
41 it "stores defaults until changed", ->
42 S\store 'test', nil, 3
43 assert.is.equal 3, S.test
44
45 S\store 'test', nil, 4
46 assert.is.equal 3, S.test
47
48 it "follows live inputs", ->
49 S\store 'test', 3, 'nope'
50 assert.is.equal 3, S.test
51
52 S\store 'test', 4, 'nope'
53 assert.is.equal 4, S.test
54
55 it "lets Once() inputs override defaults", ->
56 S\store 'test', (Once 3), 'nope'
57 assert.is.equal 3, S.test
58
59 S\store 'test', 'changed'
60
61 S\store 'test', (Once 4), 'nope'
62 assert.is.equal 'changed', S.test
1 unpack = unpack or table.unpack
2
3 class Once
4 new: (@value) =>
5
6 @is_once: (val) ->
7 return unless val
8 return unless 'table' == type val
9 val.__class == @@
10
11 all = (f) -> (...) ->
12 values = for i = 1, select '#', ...
13 val = f select i, ...
14 return unless val
15 val
16
17 unpack values
18
19 is_once = (val) -> (Once.is_once val) and val.value
20 is_live = (val) -> (not is_once val) and val
21
22 are_once = all is_once
23 are_live = all is_live
24
125 class State
226 @mt: {
327 __index: (t, k) ->
28 if v = @[k]
29 return v
30
431 with v = setmetatable {}, @@mt
532 rawset t, k, v
633 }
34
35 -- initialize state under 'key' with 'default' unless already set
36 init: (key, default) =>
37 if val = is_once default
38 default = val
39 rawset @, key, (rawget @, key) or default
40
41 -- store and return a piece of state under 'key'.
42 -- the current and stored value is the first of the following:
43 -- * 'fixed', if it is a 'live' value
44 -- * current state, if set
45 -- * 'fixed', if it is a 'once' value
46 -- * 'default'
47 store: (key, fixed, default) =>
48 state = rawget @, key
49 once = Once.is_once fixed
50
51 next_state = if is_live fixed
52 fixed
53 elseif state
54 state
55 elseif once
56 fixed.value
57 else
58 default
59
60 with next_state
61 rawset @, key, next_state
762
863 new: =>
964 @reset!
1267 @state = setmetatable {}, @@mt
1368
1469 {
70 :is_once, :are_once
71 :is_live, :are_live
72 :Once
1573 :State
1674 }