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