Page 2 of 2

Re: vector drawing display list

Posted: Sun Oct 12, 2025 1:37 am
by idle
I'm currently working on Animated Vector Graphics Scene graph
lots to do and refactor but it's slowly coming together. There's still a bug on object reverse direction where it flashes the object on the opposite side of the animation.

The example

Code: Select all

;callbacks
  Procedure OnBoxMouseEnter(*obj.AVGObject, x.d, y.d)
    Debug "Mouse entered : " + *obj\name + " " + Str(*obj\avg\dl()\item\id)
    *obj\params\pauseAnimation = 1 
  EndProcedure
  
  Procedure OnBoxMouseLeave(*obj.AVGObject, x.d, y.d)
    Debug "Mouse left : " + *obj\name
    *obj\params\pauseAnimation = 0 
  EndProcedure
  
  Procedure OnBoxClick(*obj.AVGObject, x.d, y.d, button)
    Debug " clicked: " + *obj\name
    *obj\params\text = "Clicked!"
  EndProcedure
  
  Procedure OnTextUpdate(*obj.AVGObject, deltaTime.d)
    ;custom animation logic 
  EndProcedure
  
  ;Create scene
  Global *scene.AVGScene = CreateAVGScene(800, 600)
  LoadFont(0,"Arial",24,#PB_Font_Italic | #PB_Font_Bold ) 
  
  ;Box with position animation (bouncing with easing)
  Global box1 = AVGCreateObject(*scene, "BouncingBox")
  AVGSetOnMouseEnter(*scene, box1, @OnBoxMouseEnter())
  AVGSetOnMouseLeave(*scene, box1, @OnBoxMouseLeave())
  AVGSetOnMouseClick(*scene, box1, @OnBoxClick())
  
  AVGAddPathBox(*scene, box1, 0, 0, 100, 100)
  AVGVectorSourceColor(*scene, box1, RGBA(255, 128, 0, 255), RGBA(255, 255, 0, 255))
  AVGFillPath(*scene, box1)
  
  AVGVectorFont(*scene,box1,FontID(0),14)
  AVGAddPathText(*scene,box1,"Bouncy box",10,10)  
  AVGVectorSourceColor(*scene,box1,RGBA(0, 255, 0, 255),0)  
  AVGFillPath(*scene, box1)
  ;Animate position with bounce easing, loop and reverse
  AVGAnimatePosition(*scene, box1, 100, 100, 700, 100, 2.0, #Ease_OutBounce, #True, #True)
  
  ;Circle with scale animation
  Global circle1 = AVGCreateObject(*scene, "PulsingCircle")
  
  AVGSetOnMouseEnter(*scene, circle1, @OnBoxMouseEnter())
  AVGSetOnMouseLeave(*scene, circle1, @OnBoxMouseLeave())
   
  AVGSetObjectPosition(*scene, circle1, 400, 300)
  AVGAddPathCircle(*scene, circle1, 0, 0, 50)
  AVGVectorSourceColor(*scene, circle1, RGBA(0, 128, 255, 255),0)
  AVGFillPath(*scene, circle1)
  AVGAddPathCircle(*scene, circle1, 0, 0, 20)
  AVGVectorSourceColor(*scene, circle1, RGBA(128, 128, 255, 255),RGBA(255, 255, 0, 255))
  AVGFillPath(*scene, circle1,#PB_Path_Default)
  
  ;Animate scale with elastic easing, loop
  AVGAnimateScale(*scene, circle1, 1.0, 1.0, 1.5, 1.5, 1.5, #Ease_InOutElastic, #True, #False)
  
  ;Rotating square with alpha fade
  Global square1 = AVGCreateObject(*scene, "RotatingSquare")
  AVGSetObjectPosition(*scene, square1, 600, 400)
  AVGAddPathBox(*scene, square1, -40, -40, 80, 80)
  AVGVectorSourceColor(*scene, square1, RGBA(255, 0, 128, 255))
  AVGFillPath(*scene, square1)
  
  ; Animate rotation with linear easing, loop
  AVGAnimateRotation(*scene, square1, 0, 360, 3.0, #Ease_Linear, #True, #False)
  
  ; Animate alpha with sine easing, loop and reverse
  AVGAnimateAlpha(*scene, square1, 255, 50, 1.5, #Ease_InOutSine, #False, #True)
  
  ;Text with animation and callback
  Global text1 = AVGCreateObject(*scene, "AnimatedText")
  AVGSetObjectPosition(*scene, text1, 300, 500)
  AVGSetOnUpdate(*scene, text1, @OnTextUpdate())
  AVGVectorFont(*scene,text1,FontID(0),24)
  AVGAddPathText(*scene, text1, "Eased Animation!", 0, 0)
  AVGVectorSourceColor(*scene, text1, RGBA(0,255,0, 255))
  AVGFillPath(*scene, text1)
  
  ;Animate position with cubic easing
  AVGAnimatePosition(*scene, text1, 100, 500, 700, 500, 3.0, #Ease_InOutCubic, #False, #True)
  
  ;Child object 
  Global parent = AVGCreateObject(*scene, "Parent")
  AVGSetObjectPosition(*scene, parent, 400, 200)
  AVGAddPathBox(*scene, parent, -50, -50, 100, 100)
  AVGVectorSourceColor(*scene, parent, RGBA(128, 255, 128, 255))
  AVGStrokePath(*scene, parent, 2)
  
  ; Animate parent rotation
  AVGAnimateRotation(*scene, parent, 0, 360, 4.0, #Ease_Linear, #False, #True)
  
  ; Add child that orbits around parent
  Global child = AVGCreateObject(*scene, "Child", parent)
  AVGSetObjectPosition(*scene, child,-200,-200) ; Offset from parent
  AVGAddPathCircle(*scene, child, 0, 0, 15)
  AVGVectorSourceColor(*scene, child, RGBA(255, 0, 0, 255))
  AVGFillPath(*scene, child)
  
  ;Child has its own scale animation
  AVGAnimateScale(*scene, child, 1.0, 1.0, 2.0, 2.0, 1.0, #Ease_InOutQuad, #True, #False)
    
  OpenWindow(0,0,0,800,600,"test txt",#PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget ) 
    AddWindowTimer(0,1,15)
    CanvasGadget(0,0,0,800,600)
    If StartVectorDrawing(CanvasVectorOutput(0))   
      AVGRenderScene(*scene)
      StopVectorDrawing()
    EndIf  
        
    Repeat 
      event = WaitWindowEvent() 
      Select event 
        Case #PB_Event_SizeWindow
          
          ResizeGadget(0,0,0,DesktopScaledX(WindowWidth(0)),DesktopScaledY(WindowHeight(0)))
          *scene\displayWidth = DesktopScaledX(WindowWidth(0))
          *scene\displayHeight = DesktopScaledY(WindowHeight(0)) 
          
          StartVectorDrawing(CanvasVectorOutput(0)) 
            AVGRenderScene(*scene)
          StopVectorDrawing()
          
        Case #PB_Event_Gadget 
          If EventType() = #PB_EventType_MouseWheel         
            x = DesktopScaledX(WindowMouseX(0))
            y = DesktopScaledX(WindowMouseY(0))
            
            ;set scene zoom scale factor 
            dir = GetGadgetAttribute(0,#PB_Canvas_WheelDelta) 
            If dir < 1 
              *scene\sfx / 1.2 
              *scene\sfy / 1.2
            Else 
              *scene\sfx * 1.2
              *scene\sfy * 1.2
            EndIf 
                    
          EndIf 
        Case #PB_Event_Timer
          
          ;Set scene mouse position
            x = DesktopScaledX(WindowMouseX(0))
            y = DesktopScaledX(WindowMouseY(0))
            *scene\mouseX = x 
            *scene\mouseY = y 
            If StartVectorDrawing(CanvasVectorOutput(0))   
             ;render scene 
             AVGRenderScene(*scene)  
             StopVectorDrawing() 
           EndIf    
       Case #PB_Event_CloseWindow  
          Break 
      EndSelect 
    ForEver    
The code
https://Atomicwebserver.com/AvgSceneGraph.pbi

Re: vector drawing display list

Posted: Sun Oct 12, 2025 2:29 am
by skywalk
It's coming together nicely.
Thanks for the concept!

Re: vector drawing display list

Posted: Sun Oct 12, 2025 5:48 pm
by Justin
Nice but you don't use EnableExplicit? :shock:
Also it does not seem to be DPI aware.
If this could be adapted to reverse the animations when the state that trigered the animation ends like css does, it could be used as the basis for an animated UI framework
https://www.w3schools.com/css/css3_transitions.asp

Re: vector drawing display list

Posted: Sun Oct 12, 2025 8:03 pm
by idle
That's the overall plan so it can be used for ui elements and also do animated svg that can be used on a window, canvas, image, sprite or material.

Re: vector drawing display list

Posted: Sun Oct 12, 2025 9:50 pm
by minimy
Great addition to PB, as allways your work is very usefull.
Thanks for share idle!

Re: vector drawing display list

Posted: Sun Oct 12, 2025 10:52 pm
by idle
minimy wrote: Sun Oct 12, 2025 9:50 pm Great addition to PB, as allways your work is very usefull.
Thanks for share idle!
It's a long way to go, I'm trying to make it versatile since I have no idea how people would want to use it and I also want to make it simple to use, maybe with a live embedded designer so you can drag drop assets and draw them and assign behaviors, hook up event callbacks which can then be exported to procedures.

Re: vector drawing display list

Posted: Mon Oct 20, 2025 7:55 pm
by Andre
Impressive, thank you for the code contribution! :D