Skip to content

Commit 519e41c

Browse files
committed
💡 More animations
1 parent 7f8b05a commit 519e41c

2 files changed

Lines changed: 156 additions & 75 deletions

File tree

lua/wire/client/node_editor/nodeeditor.lua

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ local Editor = {}
22

33
FPGATypeColor = {
44
NORMAL = Color(190, 190, 255, 255), --Very light blue nearing white
5-
VECTOR2 = Color(150, 255, 255, 255), --Light blue
5+
VECTOR2 = Color(255, 150, 255), --Pink
66
VECTOR = Color(70, 160, 255, 255), --Blue
7-
VECTOR4 = Color(0, 50, 255, 255), --Dark blue
7+
VECTOR4 = Color(0, 212, 177), --Cyan
88
ANGLE = Color(100, 200, 100, 255), --Light green
99
STRING = Color(250, 160, 90, 255), --Orange
10-
ARRAY = Color(20, 110, 20, 255), --Dark green
10+
ARRAY = Color(255, 255, 0), --Yellow
1111
ENTITY = Color(255, 100, 100, 255), --Dark red
12-
RANGER = Color(130, 100, 60, 255), --Brown
12+
RANGER = Color(255, 255, 255), --White
1313
WIRELINK = Color(200, 80, 200, 255), --Deep purple
1414
}
1515

lua/wire/stools/fpga.lua

Lines changed: 152 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -393,60 +393,45 @@ if CLIENT then
393393

394394
end
395395

396-
local busy_players = WireLib.RegisterPlayerTable()
397-
net.Receive("wire_fpga_editor_status", function(len)
398-
local ply = net.ReadEntity()
399-
local status = net.ReadBit() ~= 0
400-
if not IsValid(ply) or ply == LocalPlayer() then return end
401-
402-
busy_players[ply] = status or nil
403-
end)
404-
405396
local min = math.min
406397
local surface_DrawPoly = surface.DrawPoly
407398
local surface_SetDrawColor = surface.SetDrawColor
408399

409-
local nodeColor = Color(100,100,100,255)
410-
local lineColor = Color(70, 160, 255, 255)
400+
local function tableValue(t, v)
401+
local keys = {}
402+
for k in pairs(t) do
403+
keys[#keys+1] = k
404+
end
405+
return t[keys[(v - 1) % #keys + 1]]
406+
end
407+
408+
local nodeColor = Color(100, 100, 100, 255)
411409

412410
local size = 100
413411
local padding = 100
414412

415413
local node1x, node1y = -padding * 1.5, padding
416-
local node2x, node2y = padding * 1.5, -padding
417-
418-
local anim = {
419-
tStart = 0,
420-
tEnd = 0,
421-
dir = 1,
422-
phase = 1,
423-
speed = 1,
424-
holdTime = 2.5,
425-
holdTimer = 0
426-
}
427-
local reversed = false
414+
local node2x, node2y = padding * 1.5, -padding
428415

429-
local node1 = { offset = 0, vel = 0 }
430-
local node2 = { offset = 0, vel = 0 }
416+
local springStrength = 40
417+
local damping = 3
418+
local impulsePower = 200
431419

432-
local springStrength = 35
433-
local damping = 4
434-
local impulsePower = 100
420+
local radialSpringStrength = 16
421+
local radialDamping = 6
422+
423+
local curveSegments = 30
424+
local thickness = 10
425+
local half = thickness * 0.5
435426

436427
local function UpdateSpring(node, ft)
437428
local force = -(springStrength * node.offset + damping * node.vel)
438429
node.vel = node.vel + force * ft
439430
node.offset = node.offset + node.vel * ft
440431
end
441432

442-
local curveSegments = 20
443-
local baseCurve = {}
444-
local thickness = 10
445-
local half = thickness * 0.5
446-
447-
local function BuildBaseCurve(dir)
448-
449-
baseCurve = {}
433+
local function BuildBaseCurve(state, dir)
434+
state.baseCurve = {}
450435

451436
local startX, startY, endX, endY
452437
local cx1, cy1, cx2, cy2
@@ -460,7 +445,7 @@ if CLIENT then
460445
cx1, cy1 = 0, startY
461446
cx2, cy2 = 0, endY
462447

463-
reversed = false
448+
state.reversed = false
464449
else
465450
startX = node2x + size * 0.5
466451
startY = node2y
@@ -470,7 +455,7 @@ if CLIENT then
470455
cx1, cy1 = startX + size * 2, startY + size * 2
471456
cx2, cy2 = endX - size * 2, endY - size * 2
472457

473-
reversed = true
458+
state.reversed = true
474459
end
475460

476461
local prevX, prevY
@@ -497,37 +482,70 @@ if CLIENT then
497482
t3 * endY
498483

499484
if prevX then
500-
baseCurve[#baseCurve + 1] = {
485+
state.baseCurve[#state.baseCurve + 1] = {
501486
x1 = prevX,
502487
y1 = prevY,
503488
x2 = x,
504489
y2 = y,
505-
t1 = (i-1)/curveSegments,
506-
t2 = i/curveSegments
490+
t1 = (i - 1) / curveSegments,
491+
t2 = i / curveSegments
507492
}
508493
end
509494

510495
prevX, prevY = x, y
511496
end
512497
end
513498

514-
BuildBaseCurve(anim.dir)
499+
local function NewAnimState()
500+
local state = {
501+
tStart = 0,
502+
tEnd = 0,
503+
dir = 1,
504+
phase = 1,
505+
speed = 2.5,
506+
holdTime = 1,
507+
holdTimer = 0,
508+
reversed = false,
509+
baseCurve = {},
510+
node1 = { offset = 0, vel = 0 },
511+
node2 = { offset = 0, vel = 0 },
512+
lastFrame = 0,
513+
color = 1,
514+
swapSpringPos = 0,
515+
swapSpringVel = 0,
516+
lastUpdateTime = 0
517+
}
518+
BuildBaseCurve(state, 1)
519+
return state
520+
end
521+
522+
local busy_players = WireLib.RegisterPlayerTable()
523+
net.Receive("wire_fpga_editor_status", function(len)
524+
local ply = net.ReadEntity()
525+
local status = net.ReadBit() ~= 0
526+
if not IsValid(ply) then return end
527+
528+
busy_players[ply] = status and NewAnimState() or nil
529+
end)
515530

516-
local function DrawCachedCurve(tStart, tEnd)
531+
local function DrawCachedCurve(state)
532+
surface_SetDrawColor(tableValue(FPGATypeColor, state.color))
517533

518-
surface_SetDrawColor(lineColor)
534+
local tStart = state.tStart
535+
local tEnd = state.tEnd
536+
local node1 = state.node1
537+
local node2 = state.node2
519538

520539
local startIndex = math.floor(tStart * curveSegments)
521540
local endIndex = math.floor(tEnd * curveSegments)
522541

523542
for i = startIndex + 1, endIndex do
524-
local seg = baseCurve[i]
543+
local seg = state.baseCurve[i]
525544
if seg then
526-
527545
local t1 = seg.t1
528546
local t2 = seg.t2
529547

530-
if reversed then
548+
if state.reversed then
531549
t1 = 1 - t1
532550
t2 = 1 - t2
533551
end
@@ -560,21 +578,17 @@ if CLIENT then
560578
end
561579
end
562580

563-
hook.Add("PostPlayerDraw","wire_fpga_editor_status",function(ply)
564-
565-
if not busy_players[ply] then return end
566-
567-
local pos = ply:GetPos() + ply:GetUp() * (ply:OBBMaxs().z + 10)
568-
569-
local angle = (pos - EyePos()):GetNormalized():Angle()
570-
angle = Angle(0, angle.y, 0)
571-
angle:RotateAroundAxis(angle:Up(), -90)
572-
angle:RotateAroundAxis(angle:Forward(), 90)
581+
local pi = math.pi
582+
local function ArcPos(t, cx, cy, r, a0, a1)
583+
local a = a0 + (a1 - pi - a0) * t
584+
return cx + math.cos(a) * r, cy + math.sin(a) * r
585+
end
573586

574-
local ft = FrameTime()
587+
local function UpdateAnim(state, ft)
588+
local anim = state
575589

576-
UpdateSpring(node1, ft)
577-
UpdateSpring(node2, ft)
590+
UpdateSpring(anim.node1, ft)
591+
UpdateSpring(anim.node2, ft)
578592

579593
if anim.phase == 1 then
580594
anim.tEnd = min(1, anim.tEnd + anim.speed * ft)
@@ -583,9 +597,9 @@ if CLIENT then
583597
anim.holdTimer = 0
584598

585599
if anim.dir == 1 then
586-
node2.vel = node2.vel - impulsePower
600+
anim.node2.vel = anim.node2.vel - impulsePower
587601
else
588-
node1.vel = node1.vel - impulsePower
602+
anim.node1.vel = anim.node1.vel - impulsePower
589603
end
590604
end
591605

@@ -600,33 +614,100 @@ if CLIENT then
600614
if anim.tStart >= 1 then
601615
anim.tStart = 0
602616
anim.tEnd = 0
603-
anim.phase = 1
617+
anim.phase = anim.dir == -1 and 4 or 1
618+
anim.swapTimer = 0
604619
anim.dir = -anim.dir
620+
anim.color = anim.color + 1
621+
BuildBaseCurve(anim, anim.dir)
605622

606-
BuildBaseCurve(anim.dir)
623+
end
624+
625+
elseif anim.phase == 4 then
626+
627+
local force = -(radialSpringStrength * (anim.swapSpringPos - 1) + radialDamping * anim.swapSpringVel)
628+
anim.swapSpringVel = anim.swapSpringVel + force * ft
629+
anim.swapSpringPos = anim.swapSpringPos + anim.swapSpringVel * ft
630+
631+
if math.abs(anim.swapSpringPos - 1) < 0.01 and math.abs(anim.swapSpringVel) < 0.02 then
632+
anim.phase = 1
633+
anim.swapSpringPos = 0
607634
end
608635
end
636+
end
637+
638+
local frameNum
639+
local cx = (node1x + node2x) * 0.5
640+
local cy = (node1y + node2y) * 0.5
641+
642+
local dx = node1x - cx
643+
local dy = node1y - cy
644+
local r = math.sqrt(dx * dx + dy * dy)
645+
646+
local a1 = math.atan2(node1y - cy, node1x - cx)
647+
local a2 = math.atan2(node2y - cy, node2x - cx)
648+
649+
local FPS_LIMIT = 1 / 60
650+
651+
hook.Add("PostPlayerDraw", "wire_fpga_editor_status", function(ply)
652+
local state = busy_players[ply]
653+
if not state then return end
654+
655+
local lastUpdate = state.lastUpdateTime
656+
local now = RealTime()
657+
if now - lastUpdate >= FPS_LIMIT then
658+
UpdateAnim(state, now - lastUpdate)
659+
state.lastUpdateTime = now
660+
end
661+
662+
local BoneIndx = ply:LookupBone("ValveBiped.Bip01_Head1") or ply:LookupBone("ValveBiped.HC_Head_Bone") or 0
663+
local BonePos, _BoneAng = ply:GetBonePosition(BoneIndx)
664+
665+
local pos = BonePos + ply:GetUp() * (16 + state.swapSpringVel * 4)
666+
667+
local angle = (pos - EyePos()):GetNormalized():Angle()
668+
angle = Angle(0, angle.y, 0)
669+
angle:RotateAroundAxis(angle:Up(), -90)
670+
angle:RotateAroundAxis(angle:Forward(), 90)
609671

610672
cam.Start3D2D(pos, angle, 0.05)
611673

674+
local n1x = node1x
675+
local n1y = node1y - size * 0.5 + state.node1.offset
676+
local n2x = node2x
677+
local n2y = node2y - size * 0.5 + state.node2.offset
678+
679+
if state.phase == 4 then
680+
681+
local t = state.swapSpringPos
682+
683+
local an1x, an1y = ArcPos(t, cx, cy, r, a1, a1)
684+
local an2x, an2y = ArcPos(t, cx, cy, r, a2, a2)
685+
686+
n1x = an1x
687+
n1y = an1y - size * 0.5
688+
n2x = an2x
689+
n2y = an2y - size * 0.5
690+
end
691+
692+
if state.phase ~= 4 then
693+
DrawCachedCurve(state)
694+
end
695+
612696
draw.RoundedBox(12,
613-
node1x - size*0.5,
614-
node1y - size*0.5 + node1.offset,
697+
n1x - size * 0.5,
698+
n1y,
615699
size, size,
616700
nodeColor
617701
)
618702

619703
draw.RoundedBox(12,
620-
node2x - size*0.5,
621-
node2y - size*0.5 + node2.offset,
704+
n2x - size * 0.5,
705+
n2y,
622706
size, size,
623707
nodeColor
624708
)
625709

626-
DrawCachedCurve(anim.tStart, anim.tEnd)
627-
628710
cam.End3D2D()
629-
630711
end)
631712

632713
end

0 commit comments

Comments
 (0)