Un spirographe animé

Programmation d'applications complexes
Avatar de l’utilisateur
plabouro472
Messages : 38
Inscription : sam. 23/juil./2022 10:17

Un spirographe animé

Message par plabouro472 »

Bonjour à tous.
Je vous propose aujourd’hui une application simple d’emploi, qui devrait ravir petit et grand, un Spirographe.

Image

Il suffit d’ajuster les paramètres à l’aide de quelques curseurs et cases à cocher, de cliquer sur le bouton <Dessine> puis, d’ admirer le résultat.

Selon les paramètres sélectionnés, le tracé peut durer plusieurs minutes. Pour interrompre le tracé prématurément, un bouton <Stop> a été prévu.

Le curseur <Temporisation> peut être manipulé en cours de tracé afin de faire varier la vitesse de l'animation.

Exemple de dessin : Passe 1
Rayon roue fixe = 270
Rayon roue mobile = 20
Distance du crayon = 0
Pas de rotation = 5°
Angle de départ = 0°
Vitesse de déplacement R.M. = 80%
Temporisation , c’est vous qui voyez.

Roue mobile à l’intérieur = Coche
Inverser le sens = coche

Contour = coche
Couleur du contour = un Vert foncé
Animer le spirographe, c’est vous qui voyez.

Cliquez sur <Dessine>

Sans effacer, Paramètres suivants : Passe 2
Rayon roue fixe = 230
Rayon roue mobile = 50
Distance du crayon = 0
Pas de rotation = 7°
Angle de départ = 0°
Vitesse de déplacement R.M. = 60%
Temporisation , c’est vous qui voyez.

Roue mobile à l’intérieur = Coche
Inverser le sens = coche

Remplissage = coche
Couleur du remplissage = un bleu vif
Animer le spirographe, c’est vous qui voyez.

Cliquez sur <Dessine>

Sans effacer, Paramètres suivants : Passe 3
Rayon roue fixe = 125
Rayon roue mobile = 50
Distance du crayon = 0
Pas de rotation = 7°
Angle de départ = 0°
Vitesse de déplacement R.M. = 40%
Temporisation , c’est vous qui voyez.

Roue mobile à l’intérieur = Coche
Inverser le sens = décoche

Remplissage = coche
Couleur du remplissage = un rouge vif
Animer le spirographe, c’est vous qui voyez.

Cliquez sur <Dessine>

Sans effacer, Paramètres suivants : Passe 4
Rayon roue fixe = 20
Rayon roue mobile = 10
Distance du crayon = 0
Pas de rotation = 3°
Angle de départ = 0°
Vitesse de déplacement R.M. = 140%
Temporisation , c’est vous qui voyez.

Roue mobile à l’intérieur = Coche
Inverser le sens = décoche

Contour = coche
Couleur du remplissage = un violet
Animer le spirographe, c’est vous qui voyez.

Cliquez sur <Dessine>

Terminé.

Reste à sauvegarder en BMP pour imprimer.

Note : préférence de l'éditeur pour le source
Taille des tabulations = 2 |X| ASCII 9

Code : Tout sélectionner

 
; **********************************
; ***          SpiroPat          ***
; *       Version : 20250215       *
; *  PureBasic 6.20 pour windows   *
;
;
Global	.s	Titre						= "SpiroPat-V20250215."

Global	.s	FichierIni 			= GetCurrentDirectory() + "Spirographe.ini"
Global	.s	FichierBmp			= GetCurrentDirectory() + ""
Global	.s	FichierSpr			= GetCurrentDirectory() + ""

Global	.i	RayonMaxi						= 300 / 5
Global	.i	RayonMini						= 1
Global	.i	PasMini							= 3
Global	.i	PasMaxi							= 10
Global	.i	VitesseMaxi					= 20
Global	.i	CouleurRemplissage	= #Green
Global	.i	CouleurContour			= #Black
Global	.i	Sens								=  1
Global	.i	PositionRf					= -1

Global	.i	Image_ArretUrgence
Global	.i	Image_CouleurRemplissage
Global	.i	Image_CouleurContour
Global	.i	LargeurButtonImage
Global	.i	HauteurButtonImage

Global	.a	TraceEnRun					= #False
Global	.a	Passe


; **********************************
; ***     Module Spirographe     ***
; *       Version : 20250215       *
; *  PureBasic 6.20 pour windows   *
;
DeclareModule	Spirographe
	; ******** Constantes et variables Publiques ***************
	
	
	; ******** Declaration des procedures Publiques ***************
	Declare			Init								( _WinMere.i , _X.i , _Y.i , _Dimension.i )
	Declare			ExportBmp						( _NomFichier.s )
	Declare			ImportBmp						( _NomFichier.s )
	Declare			SetRayonFixe				( _Val.f 	)
	Declare			SetRayonMobile			( _Val.f	)
	Declare			SetPas							( _Val.f	)
	Declare			SetPositionCrayon		( _Val.f	)
	Declare			SetVitesse					( _Val.f	)
	Declare			SetPasse						( _Val.a	)
	Declare			SetTempo						( _Val.i	)
	Declare			SetVisu							( _Val.a	)
	Declare			SetPenColor					( _Val.i	)
	Declare			SetFillColor				( _Val.i	)
	Declare			SetAngleDepart			( _Val.f	)
	Declare			Cls									(				)
	
	Declare			InitTrace						(				)
	Declare			NextTrace						(				)
	Declare	.a	EndTrace						(				)
	
EndDeclareModule
Module				Spirographe
	;{ ******** Constantes et variables privées ***************
	Global	_2Pi									.f	; Constante
	
	Global	RayonRoueFixe					.f	; Rayon du cercle fixe toujours positif RayonRoueFixe
	Global	RayonRoueMobile				.f	; Rayon du cercle mobile :Positif vers l'exterieur ,negatif vers l'interieur	RayonRoueMobile
	Global	Pas										.f	; Pas de rotation du cercle mobile en radian toujour positif
	Global	PosCrayon							.f	; Distance du crayon par rapport au bord du cercle mobile
	Global	Vitesse								.f	; Vitesse de deplacement du cercle mobile sur le cercle fixe :Positif=sens direct ,negatif=sens inverse
	Global	AngleDepart						.f	; Angle de départ pour le tracé en Radian
	Global	Rapport								.f	; Pour calcul de position de la roue mobile sur la roue fixe
	Global	AngleRoueFixe					.f
	Global	AngleRoueMobile				.f
	
	Global	Passe									.a	; 1 = Remplissage :	2 = Contour	:	3 = les deux
	Global	Visu									.a	; Affiche l'animation des roues
	
	Global	xRoueMobile						.w
	Global	yRoueMobile						.w
	Global	xCrayon								.w
	Global	yCrayon								.w
	
	Global	Axe										.i	; Centrage du graphique
	Global	ImageDeFond						.i
	Global	ImageEcran						.i
	Global	SpriteEcran						.i
	Global	Ecran									.i
	Global	Dimension							.i
	Global	PenColor							.i	; Couleur contour	
	Global	FillColor							.i	; Couleur remplissage
	Global	Tempo									.i	; Temporise l'affichage image par image en ms
	Global	Chrono								.i	; Compteur
	
	Global	NbTourRoueFixe				.f
	Global	NbTourRoueMobile			.f
	Global	TourCompletRoueFixe		.a
	Global	TourCompletRoueMobile	.a
	Global	TraceComplet					.a
	Global	RemplissageFini				.a
	Global	ContourFini						.a
	Global	PremierPoint					.a
	Global	HoldxRoueMobile				.w
	Global	HoldyRoueMobile				.w
	Global	HoldxCrayon						.w
	Global	HoldyCrayon						.w
	;}
	
	; ******** Procedures Privées ***************
	Procedure			RestaureEcran						(	) ; Restaure ImageEcran avec ImageDeFond
		If ImageEcran		: FreeImage( ImageEcran	)	: EndIf
		ImageEcran			= CopyImage( ImageDeFond, #PB_Any	)
	EndProcedure
	Procedure			CalculPositionSuivante	(	)
		; Calcule la prochaine position des roues
		AngleRoueMobile	= AngleRoueMobile + Pas				; Angle Roue mobile		; REVOIR LE CALCUL DES ANGLES
		AngleRoueFixe		= AngleRoueMobile * Rapport	* Vitesse	; Angle sur la roue fixe de la position axe roue mobile 
	EndProcedure
	Procedure			CalculPositionRoues			(	)
		; Position roue mobile
		xRoueMobile		=  Round( ( RayonRoueFixe		+ RayonRoueMobile ) * Cos( AngleRoueFixe + AngleDepart) , #PB_Round_Nearest )
		yRoueMobile		= -Round( ( RayonRoueFixe 	+ RayonRoueMobile ) * Sin( AngleRoueFixe + AngleDepart) , #PB_Round_Nearest )
		; Position du crayon
		xCrayon				=  Round( ( RayonRoueMobile	- PosCrayon				) * Cos( AngleRoueFixe + AngleRoueMobile  + AngleDepart) , #PB_Round_Nearest )
		yCrayon				= -Round( ( RayonRoueMobile	- PosCrayon				) * Sin( AngleRoueFixe + AngleRoueMobile  + AngleDepart) , #PB_Round_Nearest )
	EndProcedure
	
	Procedure			Frame										(	) ; Création du sprite avec ImageEcran et affiche à l'écran
		StartDrawing	(SpriteOutput( SpriteEcran	)	)
			DrawImage		( ImageID( ImageEcran)	, 0	, 0	)
		StopDrawing		( )
		ClearScreen( #White )
		DisplaySprite	( SpriteEcran	, 0	, 0	)
		FlipBuffers		(	)
	EndProcedure
	Procedure			AfficheRoue							(	)	; Dand l'image ecran
		StartVectorDrawing	( ImageVectorOutput( ImageEcran	)	)
			AddPathCircle( Axe , Axe , RayonRoueFixe	)		; Place la roue fixe
			VectorSourceColor( RGBA( 255	, 0	, 0	, 127		)	)
			StrokePath( 4 )
			
			AddPathCircle( Axe + xRoueMobile , Axe + yRoueMobile , Abs( RayonRoueMobile	)	)	; Place la roue mobile
			VectorSourceColor( RGBA( 255	, 0	, 255	, 127	)	)
			StrokePath( 4	)
			
			MovePathCursor( Axe + xRoueMobile , Axe + yRoueMobile	)										; Place le crayon
			AddPathLine( xCrayon , yCrayon	, #PB_Path_Relative	)
			VectorSourceColor( RGBA( 255	, 0	, 255	, 127	)	)
			StrokePath( 4	)
			
		StopVectorDrawing()
	EndProcedure
	Procedure			NextRemplissage					(	)
		CalculPositionRoues		(	)
		StartDrawing	( ImageOutput( ImageDeFond	)	)
			DrawingMode		( #PB_2DDrawing_Outlined 	)
			LineXY	( Axe + xRoueMobile , Axe + yRoueMobile , Axe + xRoueMobile + xCrayon , Axe + yRoueMobile + yCrayon , FillColor	)
		CalculPositionSuivante		(	)
		
		If Abs( AngleRoueMobile	) > NbTourRoueMobile	* _2Pi
			TourCompletRoueMobile	= #True
			NbTourRoueMobile + 1
		Else
			TourCompletRoueMobile	= #False
		EndIf
		
		If Abs( AngleRoueFixe		) > NbTourRoueFixe		* _2Pi
			TourCompletRoueFixe	= #True
			NbTourRoueFixe + 1
		Else
			TourCompletRoueFixe	= #False
		EndIf
		
		If TourCompletRoueFixe And TourCompletRoueMobile
			RemplissageFini				= -1
			AngleRoueMobile	= 0
			AngleRoueFixe		= 0
			CalculPositionRoues		(	)
			PremierPoint					= #True
			TourCompletRoueFixe		= #False
			TourCompletRoueMobile	= #False
			HoldxRoueMobile				= 0
			HoldyRoueMobile				= 0
			HoldxCrayon						= 0
			HoldyCrayon						= 0
			NbTourRoueFixe				= 1
			NbTourRoueMobile			= 1
		Else
			
		EndIf
		StopDrawing		(	)
	EndProcedure
	Procedure			NextContour							(	)
		StartDrawing	( ImageOutput( ImageDeFond	)	)
		DrawingMode		( #PB_2DDrawing_Outlined 	)
		If PremierPoint		; Positionne le PremierPoint du tracé
		CalculPositionRoues		(	)
			HoldxRoueMobile		= xRoueMobile
			HoldyRoueMobile		= yRoueMobile
			HoldxCrayon				= xCrayon
			HoldyCrayon				= yCrayon
			PremierPoint			= #False
		Else
			CalculPositionSuivante		(	)
			If Abs( AngleRoueMobile	) > NbTourRoueMobile	* _2Pi
				TourCompletRoueMobile	= #True
				NbTourRoueMobile + 1
			Else
				TourCompletRoueMobile	= #False
			EndIf
			If Abs( AngleRoueFixe		) > NbTourRoueFixe		* _2Pi
				TourCompletRoueFixe	= #True
				NbTourRoueFixe + 1
			Else
				TourCompletRoueFixe	= #False
			EndIf
			
			If TourCompletRoueFixe And TourCompletRoueMobile
				ContourFini				= -1
				AngleRoueMobile	= 0
				AngleRoueFixe		= 0
				CalculPositionRoues		(	)
				; Fermeture du tracé
				LineXY	( Axe + HoldxRoueMobile + HoldxCrayon , Axe + HoldyRoueMobile + HoldyCrayon , Axe + xRoueMobile + xCrayon , Axe + yRoueMobile + yCrayon , PenColor	)
				PremierPoint					= #True
				TourCompletRoueFixe		= #False
				TourCompletRoueMobile	= #False
				HoldxRoueMobile				= 0
				HoldyRoueMobile				= 0
				HoldxCrayon						= 0
				HoldyCrayon						= 0
				NbTourRoueFixe				= 1
				NbTourRoueMobile			= 1
			Else
				CalculPositionRoues		(	)
				LineXY	( Axe + HoldxRoueMobile + HoldxCrayon , Axe + HoldyRoueMobile + HoldyCrayon , Axe + xRoueMobile + xCrayon , Axe + yRoueMobile + yCrayon , PenColor	)
				HoldxRoueMobile		= xRoueMobile
				HoldyRoueMobile		= yRoueMobile
				HoldxCrayon				= xCrayon
				HoldyCrayon				= yCrayon
			EndIf
			
		EndIf
	StopDrawing	(	)
	EndProcedure
	
	
	; ******** Procedures Publiques ************
	Procedure 		SetRayonFixe					( _Val.f )
		RayonRoueFixe			= Abs( _Val )
		Rapport		=  RayonRoueMobile / RayonRoueFixe
		RestaureEcran					(	) ; Restaure ImageEcran avec ImageDeFond
		CalculPositionRoues		(	)
		AfficheRoue						( )	; Recadre les Roues en fonction des parametres
		Frame									(	)
	EndProcedure
	Procedure 		SetRayonMobile				( _Val.f )
		RayonRoueMobile	= _Val
		Rapport		= RayonRoueMobile / RayonRoueFixe
		RestaureEcran					(	) ; Restaure ImageEcran avec ImageDeFond
		CalculPositionRoues		(	)
		AfficheRoue						( )	; Recadre les Roues en fonction des parametres
		Frame									(	)
	EndProcedure
	Procedure 		SetPas								( _Val.f )
		Pas		= Radian(  _Val )
		If RayonRoueMobile > RayonRoueFixe
			Pas	= - Pas
		EndIf
		
	EndProcedure
	Procedure 		SetPositionCrayon			( _Val.f )
		PosCrayon	= Abs( Int( _Val )	)
		If RayonRoueMobile < 0	: PosCrayon	= -PosCrayon	: EndIf
		RestaureEcran					(	) ; Restaure ImageEcran avec ImageDeFond
		CalculPositionRoues		(	)
		AfficheRoue						( )	; Recadre les Roues en fonction des parametres
		Frame									(	)
	EndProcedure
	Procedure 		SetVitesse						( _Val.f )
		Vitesse		= _Val
		If Vitesse = 0
			Vitesse	= 0.1
		EndIf
	EndProcedure
	Procedure 		SetPasse							( _Val.a )
		Passe	= _Val
		If Passe < 1
			Passe	= 1
		EndIf
		
		If Passe > 3
			Passe	= 3
		EndIf
		
	EndProcedure
	Procedure 		SetTempo							( _Val.i )	; En millisecondes
		Tempo	= Abs( _Val )														; Temporise l'affichage image par image en ms
	EndProcedure
	Procedure 		SetVisu								( _Val.a )
		Visu	= _Val
	EndProcedure
	Procedure 		SetPenColor						( _Val.i )
		PenColor		= _Val
	EndProcedure
	Procedure 		SetFillColor					( _Val.i )
		FillColor		= _Val
	EndProcedure
	Procedure 		SetAngleDepart				( _Val.f )	; En degrés
		AngleDepart		= Radian( _Val )
		RestaureEcran					(	) ; Restaure ImageEcran avec ImageDeFond
		CalculPositionRoues		(	)
		AfficheRoue						( )	; Recadre les Roues en fonction des parametres
		Frame									(	)
	EndProcedure
	
	Procedure 		Cls										(	)
		StartDrawing		( ImageOutput( ImageDeFond	)	)
			Box						( 0 , 0 , Dimension	, Dimension	, #White	)
		StopDrawing			(	)
		RestaureEcran		(	) ; Restaure ImageEcran avec ImageDeFond
		AfficheRoue			( )	; Recadre les Roues en fonction des parametres
		Frame						(	)
	EndProcedure
	Procedure 		ExportBmp							( _NomFichier.s )
		SaveImage	( ImageDeFond	, _NomFichier	, #PB_ImagePlugin_BMP	)
	EndProcedure
	Procedure 		ImportBmp							( _NomFichier.s )
		If ImageDeFond	: FreeImage( ImageDeFond	)	: EndIf
		If ImageEcran		: FreeImage( ImageEcran	)	: EndIf
		ImageDeFond			= LoadImage( #PB_Any , _NomFichier	)
		ImageEcran			= CopyImage( ImageDeFond, #PB_Any	)
		AfficheRoue		( )	; Recadre les Roues en fonction des parametres
		Frame						(	)
	EndProcedure
	
	Procedure 		Init									( _WinMere.i , _X.i , _Y.i , _Dimension.i )
		Protected	.i	OldGadgetList
		Dimension				= _Dimension
		OldGadgetList 	= UseGadgetList				( WindowID( _WinMere	)	)
		InitSprite()
		Ecran						= OpenWindowedScreen	( WindowID( _WinMere	) , _X	, _Y	, Dimension	, Dimension	)
		ImageDeFond			= CreateImage					( #PB_Any	, Dimension , Dimension , 24	, #White	)
		ImageEcran			= CreateImage					( #PB_Any	, Dimension , Dimension , 24	, #White	)
		SpriteEcran			= CreateSprite				( #PB_Any	, Dimension , Dimension 								)
		UseGadgetList		( OldGadgetList	)
		RayonRoueFixe		=  0.0										; Rayon du cercle fixe toujour positif RayonRoueFixe
		RayonRoueMobile	=  0.0										; Rayon du cercle mobile :Positif vers l'exterieur ,negatif vers l'interieur	RayonRoueMobile
		Pas							=  0.0										; Pas de rotation du cercle mobile en radian toujours positif
		PosCrayon				=  0.0										; Distance du crayon par rapport au bord du cercle mobile toujours positif
		Vitesse					=  0.0										; Vitesse de deplacement du cercle mobile sur le cercle fixe :Positif=sens direct ,negatif=sens inverse
		Passe						= 3												; 1 = Remplissage :	2 = Contour	:	3 = les deux
		Tempo						= 100											; Temporise l'affichage image par image en ms
		Visu						= #True										; Affiche l'animation des roues
		PenColor				= RGB( 1	, 1		, 1	)			; Couleur contour	
		FillColor				= RGB( 0	, 255	, 0	)			; Couleur remplissage
		_2Pi						= 2.0 * #PI								; Constante
		Axe							=  Int( Dimension / 2 )		; Centrage du graphique
		RayonRoueFixe		= 100
		RayonRoueMobile	= 50
		Pas		= Radian(  3 )
		If RayonRoueMobile > RayonRoueFixe
			Pas	= - Pas
		EndIf
		PosCrayon				= 10
		If RayonRoueMobile < 0	: PosCrayon	= -PosCrayon	: EndIf
		Vitesse					= 1
		AngleDepart			= Radian( 0 )
		Rapport					= RayonRoueMobile / RayonRoueFixe
		RestaureEcran		(	) ; Restaure ImageEcran avec ImageDeFond
		AfficheRoue			( )	; Recadre les Roues en fonction des parametres
		Frame						(	)
	EndProcedure
	Procedure			InitTrace							(				)
		PremierPoint					= #True
		TourCompletRoueFixe		= #False
		TourCompletRoueMobile	= #False
		HoldxRoueMobile				= 0
		HoldyRoueMobile				= 0
		HoldxCrayon						= 0
		HoldyCrayon						= 0
		NbTourRoueFixe				= 1
		NbTourRoueMobile			= 1
		
		AngleRoueFixe					= 0
		AngleRoueMobile				= 0
		
		TraceComplet					= 0
		RemplissageFini				= 0
		ContourFini						= 0
		
	EndProcedure
	Procedure 		NextTrace							(				)
		; Dessinne le graphe
		If Not TraceComplet
			If Passe & 1		; Remplissage
				If Not RemplissageFini	: NextRemplissage	( )	: EndIf
			Else
				RemplissageFini	= -1
			EndIf
			
			If Passe & 2		; Contour
				If RemplissageFini And Not ContourFini 			: NextContour			( )	: EndIf
			Else
				ContourFini			= -1
			EndIf
			
			If RemplissageFini And ContourFini	: TraceComplet	= -1	: EndIf
			
			RestaureEcran					(	)
			If Visu
				AfficheRoue		( )													; Recadre les Roues en fonction des parametres
				While ElapsedMilliseconds() < Chrono	: Wend
				Chrono	= ElapsedMilliseconds()	+ Tempo		; Temporisation
			EndIf
			Frame						(	)
  EndIf		
	EndProcedure
	Procedure	.a	EndTrace							(				)
		ProcedureReturn	TraceComplet
	EndProcedure
	
	; ******* Initialisation *******
	
EndModule




; *****************
; Le formulaire
Global Win_0
Global Frame_Parametre, Text_RFixe, String_RFixe, TrackBar_RFixe, Text_RMobile, String_RMobile, TrackBar_RMobile, Text_Crayon, String_Crayon, TrackBar_Crayon, Text_Pas, String_Pas, TrackBar_Pas, Text_AngleDepart, String_AngleDepart, TrackBar_AngleDepart, Text_Vitesse, String_Vitesse, TrackBar_Vitesse, Text_VitesseGenerale, String_VitesseGenerale, TrackBar_VitesseGenerale, Checkbox_RmInterieure, Checkbox_Sens, Frame_Trace, Option_Remplissage, Option_Contour, Option_Tout, ButtonImage_CouleurRemplissage, ButtonImage_CouleurContour, Checkbox_Animation, ButtonImage_ArretUrgence, Frame_Menu, Button_Dessine, Button_Efface, Button_ChargeBmp, Button_SauveBmp, Button_Quitter, Button_ChargeParametres, Button_SauveParametres, Frame_Infos, Editor_Infos
Declare BoutonOnClick(EventType)
Declare Checkbox_RmOnClick(EventType)
Declare TrackBarOnScroll(EventType)
Procedure OpenWin_0(x = 0, y = 0, width = 1040, height = 620)
  Win_0 = OpenWindow(#PB_Any, x, y, width, height, "", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)
  Frame_Parametre = FrameGadget(#PB_Any, 10, 10, 410, 200, "Paramètres")
  Text_RFixe = TextGadget(#PB_Any, 20, 30, 140, 20, "Rayon roue fixe")
  String_RFixe = StringGadget(#PB_Any, 160, 30, 50, 20, "", #PB_String_Numeric | #PB_String_ReadOnly)
  TrackBar_RFixe = TrackBarGadget(#PB_Any, 220, 30, 190, 20, 0, 0)
  Text_RMobile = TextGadget(#PB_Any, 20, 50, 140, 20, "Rayon roue mobile")
  String_RMobile = StringGadget(#PB_Any, 160, 50, 50, 20, "", #PB_String_Numeric | #PB_String_ReadOnly)
  TrackBar_RMobile = TrackBarGadget(#PB_Any, 220, 50, 190, 20, 0, 0)
  Text_Crayon = TextGadget(#PB_Any, 20, 70, 140, 20, "Distance crayon")
  String_Crayon = StringGadget(#PB_Any, 160, 70, 50, 20, "", #PB_String_Numeric | #PB_String_ReadOnly)
  TrackBar_Crayon = TrackBarGadget(#PB_Any, 220, 70, 190, 20, 0, 0)
  GadgetToolTip(TrackBar_Crayon, "Distance qui sépare la pointe du crayon du bord de la roue mobile.")
  Text_Pas = TextGadget(#PB_Any, 20, 90, 140, 20, "Pas de rotation")
  String_Pas = StringGadget(#PB_Any, 160, 90, 50, 20, "", #PB_String_Numeric | #PB_String_ReadOnly)
  TrackBar_Pas = TrackBarGadget(#PB_Any, 220, 90, 190, 20, 0, 0)
  GadgetToolTip(TrackBar_Pas, "Vitesse angulaire de la roue mobile en degrés par cycle.")
  Text_AngleDepart = TextGadget(#PB_Any, 20, 110, 140, 20, "Angle de départ")
  String_AngleDepart = StringGadget(#PB_Any, 160, 110, 50, 20, "", #PB_String_Numeric | #PB_String_ReadOnly)
  TrackBar_AngleDepart = TrackBarGadget(#PB_Any, 220, 110, 190, 20, 0, 0)
  GadgetToolTip(TrackBar_AngleDepart, "Angle de départ du tracé par pas de 15°.")
  Text_Vitesse = TextGadget(#PB_Any, 20, 130, 140, 20, "Vitesse déplacement R.M.")
  String_Vitesse = StringGadget(#PB_Any, 160, 130, 50, 20, "", #PB_String_Numeric | #PB_String_ReadOnly)
  TrackBar_Vitesse = TrackBarGadget(#PB_Any, 220, 130, 190, 20, 0, 0)
  GadgetToolTip(TrackBar_Vitesse, "Vitesse de déplacement de la roue mobile autour la roue fixe.")
  Text_VitesseGenerale = TextGadget(#PB_Any, 20, 150, 140, 20, "Temporisation")
  String_VitesseGenerale = StringGadget(#PB_Any, 160, 150, 50, 20, "", #PB_String_Numeric | #PB_String_ReadOnly)
  TrackBar_VitesseGenerale = TrackBarGadget(#PB_Any, 220, 150, 190, 20, 0, 0)
  GadgetToolTip(TrackBar_VitesseGenerale, "Ralenti l'affichage du tracé.")
  Checkbox_RmInterieure = CheckBoxGadget(#PB_Any, 20, 180, 190, 20, "Roue mobile à l' interieure")
  Checkbox_Sens = CheckBoxGadget(#PB_Any, 220, 180, 190, 20, "Inverser le sens")
  GadgetToolTip(Checkbox_Sens, "Inverse le sens de rotation de la roue mobile.")
  Frame_Trace = FrameGadget(#PB_Any, 10, 210, 410, 90, "Paramètres de traçage")
  Option_Remplissage = OptionGadget(#PB_Any, 20, 230, 130, 20, "Remplissage")
  Option_Contour = OptionGadget(#PB_Any, 20, 250, 130, 20, "Contour")
  Option_Tout = OptionGadget(#PB_Any, 20, 270, 130, 20, "Les deux")
  ButtonImage_CouleurRemplissage = ButtonImageGadget(#PB_Any, 160, 230, 50, 20, 0)
  ButtonImage_CouleurContour = ButtonImageGadget(#PB_Any, 160, 250, 50, 20, 0)
  Checkbox_Animation = CheckBoxGadget(#PB_Any, 220, 240, 190, 20, "Animer le spirographe")
  ButtonImage_ArretUrgence = ButtonImageGadget(#PB_Any, 370, 260, 32, 32, 0)
  Frame_Menu = FrameGadget(#PB_Any, 10, 300, 410, 110, "Menu")
  Button_Dessine = ButtonGadget(#PB_Any, 20, 320, 110, 20, "Dessine")
  Button_Efface = ButtonGadget(#PB_Any, 20, 350, 110, 20, "Efface")
  Button_ChargeBmp = ButtonGadget(#PB_Any, 160, 320, 110, 20, "Charge BMP")
  Button_SauveBmp = ButtonGadget(#PB_Any, 160, 350, 110, 20, "Sauve BMP")
  Button_Quitter = ButtonGadget(#PB_Any, 160, 380, 110, 20, "Quitter")
  Button_ChargeParametres = ButtonGadget(#PB_Any, 300, 320, 110, 20, "Charge Paramètres")
  Button_SauveParametres = ButtonGadget(#PB_Any, 300, 350, 110, 20, "Sauve Paramètres")
  Frame_Infos = FrameGadget(#PB_Any, 10, 410, 410, 190, "Infos")
  Editor_Infos = EditorGadget(#PB_Any, 20, 430, 390, 170, #PB_Editor_ReadOnly | #PB_Editor_WordWrap)
EndProcedure
Procedure Win_0_Events(event)
  Select event
    Case #PB_Event_CloseWindow
      ProcedureReturn #False

    Case #PB_Event_Gadget
      Select EventGadget()
        Case TrackBar_RFixe
          TrackBarOnScroll(EventType())          
        Case TrackBar_RMobile
          TrackBarOnScroll(EventType())          
        Case TrackBar_Crayon
          TrackBarOnScroll(EventType())          
        Case TrackBar_Pas
          TrackBarOnScroll(EventType())          
        Case TrackBar_AngleDepart
          TrackBarOnScroll(EventType())          
        Case TrackBar_Vitesse
          TrackBarOnScroll(EventType())          
        Case TrackBar_VitesseGenerale
          TrackBarOnScroll(EventType())          
        Case Checkbox_RmInterieure
          Checkbox_RmOnClick(EventType())          
        Case ButtonImage_CouleurRemplissage
          BoutonOnClick(EventType())          
        Case ButtonImage_CouleurContour
          BoutonOnClick(EventType())          
        Case ButtonImage_ArretUrgence
          BoutonOnClick(EventType())          
        Case Button_Dessine
          BoutonOnClick(EventType())          
        Case Button_Efface
          BoutonOnClick(EventType())          
        Case Button_ChargeBmp
          BoutonOnClick(EventType())          
        Case Button_SauveBmp
          BoutonOnClick(EventType())          
        Case Button_Quitter
          BoutonOnClick(EventType())          
        Case Button_ChargeParametres
          BoutonOnClick(EventType())          
        Case Button_SauveParametres
          BoutonOnClick(EventType())          
      EndSelect
  EndSelect
  ProcedureReturn #True
EndProcedure



; *****************
;{ Initialisation de la fenêtre
OpenWin_0()		; ( width = 1040, height = 620	)
LargeurButtonImage				= GadgetWidth		( ButtonImage_CouleurRemplissage )
HauteurButtonImage				= GadgetHeight	( ButtonImage_CouleurRemplissage )
Image_CouleurRemplissage	= CreateImage		( #PB_Any , LargeurButtonImage , HauteurButtonImage , 32 )
Image_CouleurContour			= CreateImage		( #PB_Any	, LargeurButtonImage , HauteurButtonImage , 32 )

; L'image du bouton STOP
Global Dim MesCouleurs .l ( 1 )
Restore Color_Bouton_Stop
Read .a N.a
ReDim MesCouleurs( N - 1 )
For I.a = 0 To N -1
	Read .l MesCouleurs( I )
Next
Restore Data_Bouton_Stop
Read .a Larg.a
Read .a Haut.a
Global .i Image_Bouton_Stop = CreateImage( #PB_Any , Larg , Haut )
StartDrawing ( ImageOutput( Image_Bouton_Stop ) )
	For Y.a = 0 To Haut - 1
		For X.a = 0 To Larg - 1
			Read .a C.a
			Plot( X , Y , MesCouleurs( C ) )
		Next
	Next
StopDrawing() 


SetWindowTitle	( Win_0	, Titre	) 
Texte$	= "Les dessins et les paramètres peuvent être sauvegardés sur dique pour être réutilisés par la suite. " 
Texte$	+ "On pourra aussi recharger un dessin afin de le compléter ou compléter le dessin en cours. " + Chr( 10 ) + Chr( 13 )
Texte$	+	"Un bouton <STOP> permet d'interrompre le tracé à tout moment.  " + Chr( 10 ) + Chr( 13 )
Texte$	+ "Seul le curseur <Temporisation> peut être manipulé en cours de tracé afin de faire varier la vitesse de l'animation. "
ClearGadgetItems	( Editor_Infos	)
SetGadgetItemText ( Editor_Infos	, 0	, Texte$ )
SetGadgetAttribute( ButtonImage_ArretUrgence , #PB_Button_Image , ImageID( Image_Bouton_Stop ) )
;}

Procedure DesactiveBouton				( _Val.a	)
	DisableGadget( ButtonImage_CouleurRemplissage	, _Val	)
	DisableGadget( ButtonImage_CouleurContour			, _Val	)
	DisableGadget( Button_Dessine									, _Val	)
	DisableGadget( Button_Efface									, _Val	)
	DisableGadget( Button_SauveBmp								, _Val	)
	DisableGadget( Button_ChargeBmp								, _Val	)
	DisableGadget( Button_Quitter									, _Val	)
	DisableGadget( Button_ChargeParametres				, _Val	)
	DisableGadget( Button_SauveParametres					, _Val	)
	DisableGadget( Checkbox_Animation							, _Val	)
	DisableGadget( Checkbox_Sens									, _Val	)
	DisableGadget( Checkbox_RmInterieure					, _Val	)
	DisableGadget( Option_Remplissage							, _Val	)
	DisableGadget( Option_Contour									, _Val	)
	DisableGadget( Option_Tout										, _Val	)
	DisableGadget( TrackBar_RFixe									, _Val	)
	DisableGadget( TrackBar_RMobile								, _Val	)
	DisableGadget( TrackBar_Crayon								, _Val	)
	DisableGadget( TrackBar_Pas										, _Val	)
	DisableGadget( TrackBar_Vitesse								, _Val	)
	DisableGadget( TrackBar_AngleDepart						, _Val	)
	
EndProcedure
Procedure AfficheValeurs				( )
	SetGadgetText				( String_RFixe					, Str		( GetGadgetState	( TrackBar_RFixe					)	* 5								)					)
	SetGadgetText				( String_RMobile				, Str		( GetGadgetState	( TrackBar_RMobile				)	* 5								)					)
	SetGadgetText				( String_Crayon					, Str		( GetGadgetState	( TrackBar_Crayon					)										)					)
	SetGadgetText				( String_Pas						, Str		( GetGadgetState	( TrackBar_Pas						)										)	+ "°"		)
	SetGadgetText				( String_Vitesse				, Str		( GetGadgetState	( TrackBar_Vitesse				)	* 10							)	+ "%"		)
	SetGadgetText				( String_AngleDepart		, Str		( GetGadgetState	( TrackBar_AngleDepart		)	* 15							)	+ "°"		)
	SetGadgetText				( String_VitesseGenerale, Str		( GetGadgetState	( TrackBar_VitesseGenerale)	* 10							)	+ "ms"	)
	
EndProcedure
Procedure	AfficheCouleur				( Image.i	, Button.i	, Couleur.i	)
	StartDrawing( ImageOutput( Image ) )
		Box( 0 , 0 , LargeurButtonImage , HauteurButtonImage , Couleur )
	StopDrawing()
	SetGadgetAttribute( Button , #PB_Button_Image , ImageID( Image ) )
EndProcedure				
Procedure ChargeParametresIni		( Fichier$	)
	Protected	.i ValTmp
	
	OpenPreferences( Fichier$	)
	PreferenceGroup("Parametre curseurs")
	SetGadgetState			( TrackBar_RFixe				, ReadPreferenceInteger	( "RFixe"		, RayonMaxi 	/ 2 )	)
	SetGadgetState			( TrackBar_RMobile			, ReadPreferenceInteger	( "RMobile"	, RayonMaxi 	/ 4 )	)
	SetGadgetAttribute	( TrackBar_Crayon				, #PB_TrackBar_Maximum	, GetGadgetState( TrackBar_RMobile	) * 5 - 5	)
	SetGadgetState			( TrackBar_Crayon				, ReadPreferenceInteger	( "Crayon"	, 0 							)	)
	SetGadgetState			( TrackBar_Pas					, ReadPreferenceInteger	( "Pas"			, PasMaxi			/ 2	)	)
	SetGadgetState			( TrackBar_Vitesse			, ReadPreferenceInteger	( "Vitesse"	, VitesseMaxi	/ 2	)	)
	SetGadgetState			( TrackBar_AngleDepart	, ReadPreferenceInteger	( "Angle"		, 0								)	)
	
	PreferenceGroup("Parametre Roues")
	If ReadPreferenceInteger	( "Sens"	, 0	)
		SetGadgetState( Checkbox_Sens	, 1	)
		Sens		= -1
	Else 
		SetGadgetState( Checkbox_Sens	, 0	)
		Sens		=  1
	EndIf
	AfficheValeurs			( )
	If ReadPreferenceInteger	( "Interieure"	, 1	)
		SetGadgetState( Checkbox_RmInterieure	, 1	)
		PositionRf		= -1
	Else 
		SetGadgetState( Checkbox_RmInterieure	, 0	)
		PositionRf		= 1
	EndIf
	
	PreferenceGroup("Parametre Traçage")
	ValTmp					= ReadPreferenceInteger	( "Passe"	, 3	)
	If 			ValTmp	= 1 	: SetGadgetState( Option_Remplissage	, 1	)
	ElseIf 	ValTmp	= 2 	:	SetGadgetState( Option_Contour			, 1	)
	ElseIf	ValTmp	= 3 	: SetGadgetState( Option_Tout					, 1	)
	EndIf
	
	CouleurRemplissage		= ReadPreferenceInteger	( "Couleur Remplissage"	, #Green	)
	AfficheCouleur	( Image_CouleurRemplissage	, ButtonImage_CouleurRemplissage	, CouleurRemplissage	)	; 
	CouleurContour				= ReadPreferenceInteger	( "Couleur Contour"			, #Black	)
	AfficheCouleur	( Image_CouleurContour	, ButtonImage_CouleurContour	, CouleurContour	)	; 
	
	ValTmp					= ReadPreferenceInteger	( "Animation"	, 1	)
	If ValTmp	= 1	: SetGadgetState( Checkbox_Animation		, 1	)
	Else 					: SetGadgetState( Checkbox_Animation		, 0	)
	EndIf
	ClosePreferences()
	
EndProcedure
Procedure SauveParametresIni		( Fichier$	)
	OpenPreferences( Fichier$	)
	PreferenceGroup("Parametre curseurs")
	WritePreferenceInteger	( "RFixe"				, GetGadgetState	( TrackBar_RFixe					)	)
	WritePreferenceInteger	( "RMobile"			, GetGadgetState	( TrackBar_RMobile				)	)
	WritePreferenceInteger	( "Crayon"			, GetGadgetState	( TrackBar_Crayon					)	)
	WritePreferenceInteger	( "Pas"					, GetGadgetState	( TrackBar_Pas						)	)
	WritePreferenceInteger	( "Vitesse"			, GetGadgetState	( TrackBar_Vitesse				)	)
	WritePreferenceInteger	( "Angle"				, GetGadgetState	( TrackBar_AngleDepart		)	)
	
	PreferenceGroup("Parametre Roues")
	WritePreferenceInteger	( "Interieure"	, GetGadgetState	( Checkbox_RmInterieure		)	)
	WritePreferenceInteger	( "Sens"				, GetGadgetState	( Checkbox_Sens						)	)
	
	PreferenceGroup("Parametre Traçage")
	If 			GetGadgetState( Option_Remplissage	)	: WritePreferenceInteger	( "Passe"	, 1	)
	ElseIf 	GetGadgetState( Option_Contour			)	: WritePreferenceInteger	( "Passe"	, 2	)
	ElseIf	GetGadgetState( Option_Tout					)	: WritePreferenceInteger	( "Passe"	, 3	)
	EndIf
	WritePreferenceInteger	( "Couleur Remplissage"	, CouleurRemplissage	)
	WritePreferenceInteger	( "Couleur Contour"			, CouleurContour			)
	WritePreferenceInteger	( "Animation"		, GetGadgetState	( Checkbox_Animation			)	)
	ClosePreferences()
EndProcedure
Procedure	AfficheSpiro					(	)
	Spirographe::SetRayonFixe				( GetGadgetState	( TrackBar_RFixe				)	* 5								)
	Spirographe::SetRayonMobile			( GetGadgetState	( TrackBar_RMobile			) * 5 * PositionRf	)
	Spirographe::SetPositionCrayon	( GetGadgetState	( TrackBar_Crayon				)										)
	Spirographe::SetAngleDepart			( GetGadgetState	( TrackBar_AngleDepart	)	* 15								)
EndProcedure

; Initialisation des boutons Image
AfficheCouleur	( Image_CouleurRemplissage	, ButtonImage_CouleurRemplissage	, CouleurRemplissage	)
AfficheCouleur	( Image_CouleurContour			, ButtonImage_CouleurContour			, CouleurContour			)

;{ Initialisation des gadgets
SetGadgetAttribute	( TrackBar_RFixe				, #PB_TrackBar_Minimum	, RayonMini	)
SetGadgetAttribute	( TrackBar_RFixe				, #PB_TrackBar_Maximum	, RayonMaxi	)
SetGadgetState			( TrackBar_RFixe				, RayonMaxi		/ 2	)

SetGadgetAttribute	( TrackBar_RMobile			, #PB_TrackBar_Minimum	, RayonMini	)
SetGadgetAttribute	( TrackBar_RMobile			, #PB_TrackBar_Maximum	, RayonMaxi	)
SetGadgetState			( TrackBar_RMobile			, RayonMaxi		/ 4	)

SetGadgetAttribute	( TrackBar_Crayon				, #PB_TrackBar_Minimum	, 0	)
SetGadgetAttribute	( TrackBar_Crayon				, #PB_TrackBar_Maximum	, GetGadgetState( TrackBar_RMobile	) - 5	)
SetGadgetState			( TrackBar_Crayon				, GetGadgetState( TrackBar_RMobile	)			)

SetGadgetAttribute	( TrackBar_Pas					, #PB_TrackBar_Minimum	, PasMini	)
SetGadgetAttribute	( TrackBar_Pas					, #PB_TrackBar_Maximum	, PasMaxi	)
SetGadgetState			( TrackBar_Pas					, PasMaxi			/ 2	)

SetGadgetAttribute	( TrackBar_Vitesse			, #PB_TrackBar_Minimum	, 1	)
SetGadgetAttribute	( TrackBar_Vitesse			, #PB_TrackBar_Maximum	, VitesseMaxi	)
SetGadgetState			( TrackBar_Vitesse			, VitesseMaxi	/ 2		)

SetGadgetAttribute	( TrackBar_AngleDepart	, #PB_TrackBar_Minimum	, 0	)
SetGadgetAttribute	( TrackBar_AngleDepart	, #PB_TrackBar_Maximum	, 23	)
SetGadgetState			( TrackBar_AngleDepart	, 0	)

SetGadgetAttribute	( TrackBar_VitesseGenerale	, #PB_TrackBar_Minimum	, 0	)
SetGadgetAttribute	( TrackBar_VitesseGenerale	, #PB_TrackBar_Maximum	, 20	)
SetGadgetState			( TrackBar_VitesseGenerale	, 10	)

AfficheValeurs			( )

SetGadgetState			( Option_Tout							, 1	)
SetGadgetState			( Checkbox_Animation			, 1	)
SetGadgetState			( Checkbox_Sens						, 0	)
SetGadgetState			( Checkbox_RmInterieure		, 1	)
;}

; Zone de dessin	: x = 430, y = 10, width = height = 600
Spirographe::Init	( Win_0 , 430	, 10	, 600 )
ChargeParametresIni				( FichierIni	)
AfficheSpiro			(	)
Spirographe::Cls	( )


; *****************
; Les procédures d'événements
Procedure BoutonOnClick				(EventType)
	DesactiveBouton							( #True	)
	Select EventGadget()
		Case ButtonImage_CouleurRemplissage	;{
			Couleur = ColorRequester()
			If Couleur > -1
				CouleurRemplissage	= Couleur
				AfficheCouleur	( Image_CouleurRemplissage	, ButtonImage_CouleurRemplissage	, CouleurRemplissage	)
			EndIf
			;}
		Case ButtonImage_CouleurContour			;{
			Couleur = ColorRequester()
			If Couleur > -1
				CouleurContour	= Couleur
				AfficheCouleur	( Image_CouleurContour	, ButtonImage_CouleurContour	, CouleurContour	)
			EndIf
			;}
		Case Button_Dessine									;{
			If			GetGadgetState( Option_Remplissage  )	: Passe	= 1
			ElseIf	GetGadgetState( Option_Contour  		)	: Passe	= 2
			ElseIf	GetGadgetState( Option_Tout  				)	: Passe	= 3
			EndIf
			Spirographe::SetPasse	( Passe )
			Spirographe::SetFillColor		( CouleurRemplissage )
			Spirographe::SetPenColor		( CouleurContour )
			If	GetGadgetState( Checkbox_RmInterieure	)	: PositionRf		= -1
			Else																				: PositionRf		=  1
			EndIf
			If	GetGadgetState( Checkbox_Sens	)				: Sens					= -1
			Else																			: Sens					=  1
			EndIf
			Spirographe::SetRayonFixe				( GetGadgetState	( TrackBar_RFixe				)	* 5								)
			Spirographe::SetRayonMobile			( GetGadgetState	( TrackBar_RMobile			) * 5 * PositionRf	)
			Spirographe::SetPositionCrayon	( GetGadgetState	( TrackBar_Crayon				)										)
			Spirographe::SetPas							( GetGadgetState	( TrackBar_Pas					) 									)
			Spirographe::SetVitesse					( GetGadgetState	( TrackBar_Vitesse			)	* 0.1	* Sens						)
			Spirographe::SetAngleDepart			( GetGadgetState	( TrackBar_AngleDepart	)	* 15							)
			If	GetGadgetState( Checkbox_Animation	)
				Spirographe::SetVisu	( #True )
				Spirographe::SetTempo( GetGadgetState( TrackBar_VitesseGenerale	) * 10	)
			Else
				Spirographe::SetVisu	( #False )
			EndIf
			Spirographe::InitTrace	(	)
			TraceEnRun	= #True
			;}
    Case ButtonImage_ArretUrgence				;{
    	TraceEnRun	= #False							; mettre fin au tracé
			Spirographe::InitTrace	(	)
    	Spirographe::SetRayonFixe( GetGadgetState	( TrackBar_RFixe	)	* 5	)

			;}
		Case Button_Efface									;{
			Spirographe::Cls				( )
			;}
		Case Button_SauveBmp								;{
			FichierBmp = SaveFileRequester("Fichier à sauvegarder", FichierBmp, "BitMap (*.bmp)|*.bmp|Tous les fichiers (*.*)|*.*", 0	)
			If FichierBmp And (FileSize(FichierBmp) = -1 Or MessageRequester("Fichier existant", "Ecraser celui-ci ? " + FichierBmp, #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes)
				If GetExtensionPart( FichierBmp ) = ""	: FichierBmp + ".bmp"	: EndIf
				Spirographe::ExportBmp	( FichierBmp	)
			EndIf
			;}
		Case Button_ChargeBmp								;{
			FichierBmp = OpenFileRequester("Fichier à charger", FichierBmp, "BitMap (*.bmp)|*.bmp|Tous les fichiers (*.*)|*.*", 0	)
			If FichierBmp
				Spirographe::ImportBmp	( FichierBmp	)
			EndIf
			;}
		Case Button_Quitter									;{
			SauveParametresIni				( FichierIni	)
			End
			;}
		Case Button_ChargeParametres				;{
			FichierSpr = OpenFileRequester("Fichier à charger", FichierSpr, "Spiro (*.spr)|*.spr|Tous les fichiers (*.*)|*.*", 0	)
			If FichierSpr
				SetWindowTitle	( Win_0	, Titre + " | " + GetFilePart( FichierSpr	)	) 
				ChargeParametresIni				( FichierSpr	)
				Spirographe::InitTrace	(	)
				AfficheSpiro	(	)
			EndIf
			;}
		Case Button_SauveParametres					;{
			FichierSpr = SaveFileRequester("Fichier à sauvegarder", FichierSpr, "Spiro (*.spr)|*.spr|Tous les fichiers (*.*)|*.*", 0	)
			If FichierSpr And (FileSize(FichierSpr) = -1 Or MessageRequester("Fichier existant", "Ecraser celui-ci ? " + FichierSpr, #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes)
				If GetExtensionPart( FichierSpr ) = ""	: FichierSpr + ".spr"	: EndIf
				SetWindowTitle	( Win_0	, Titre + " | " + GetFilePart( FichierSpr	)	) 
				SauveParametresIni				( FichierSpr	)
			EndIf
			;}
	EndSelect
	If Not TraceEnRun	: DesactiveBouton				( #False	)	: EndIf
	
EndProcedure
Procedure TrackBarOnScroll		(EventType)
	SetGadgetAttribute	( TrackBar_Crayon				, #PB_TrackBar_Maximum	, GetGadgetState( TrackBar_RMobile	) * 5	-5 )
	AfficheValeurs	( )
	Select EventGadget()
		Case TrackBar_RFixe					;{
			Spirographe::setRayonFixe	( GetGadgetState( TrackBar_RFixe	) * 5	)
			;}
		Case TrackBar_RMobile				;{
			If GetGadgetState( Checkbox_RmInterieure	)
				PositionRf		= -1
			Else 
				PositionRf		= 1
			EndIf
			Spirographe::SetRayonMobile			( GetGadgetState( TrackBar_RMobile			) * 5	 * PositionRf	)
			Spirographe::SetPositionCrayon	( GetGadgetState( TrackBar_Crayon				)										)
				;}
		Case TrackBar_Crayon				;{
			Spirographe::SetPositionCrayon	( GetGadgetState( TrackBar_Crayon				)										)	
				;}
		Case TrackBar_AngleDepart		;{
			Spirographe::SetAngleDepart			( GetGadgetState( TrackBar_AngleDepart	)	* 15							)
				;}
		Case TrackBar_VitesseGenerale		;{
			Spirographe::SetTempo( GetGadgetState( TrackBar_VitesseGenerale	) * 10	)
				;}
	EndSelect
EndProcedure
Procedure Checkbox_RmOnClick	(EventType)
	Select EventGadget()
		Case Checkbox_RmInterieure		;{
			If GetGadgetState( Checkbox_RmInterieure	)
				PositionRf		= -1
			Else 
				PositionRf		= 1
			EndIf
			;}
	EndSelect
	Spirographe::SetRayonMobile			( GetGadgetState	( TrackBar_RMobile	) * 5 * PositionRf	)
	Spirographe::SetPositionCrayon	( GetGadgetState	( TrackBar_Crayon		)										)			 
EndProcedure



; *****************
; La boucle principale
Repeat
	; Le cycle peut durer plus d'une minute selon les paramètres
	If TraceEnRun											; Le dessin est-il toujour en cours ?
		If Spirographe::EndTrace()			; Si le cycle est términé
			TraceEnRun	= #False					; mettre fin au tracé
			DesactiveBouton	( #False	)		; Réactiver les boutons
			Spirographe::SetRayonFixe( GetGadgetState	( TrackBar_RFixe	)	* 5	)
		Else														; Sinon
			Spirographe::NextTrace( )			; on trace l'image suivante
		EndIf
	EndIf
	
; événementielle automtiquement générée pour la fenêtre.
	Event = WindowEvent()
	Select EventWindow()
		Case Win_0		;{
			Win_0_Events(Event)
			;}
	EndSelect
	Delay( 1 )
Until Event = #PB_Event_CloseWindow

DataSection
	Color_Bouton_Stop:
	Data .a 7
	Data .l $00FFFFFF
	Data .l $00000000
	Data .l $00C0C0C0
	Data .l $00808080
	Data .l $00000080
	Data .l $000000FF
	Data .l $00800080
	
	Data_Bouton_Stop:
	Data .a 32 , 32
	Data .a $00,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$00
	Data .a $01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$02,$01
	Data .a $01,$00,$02,$02,$02,$02,$02,$02,$02,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$02,$02,$02,$02,$02,$02,$02,$02,$03,$01
	Data .a $01,$00,$02,$02,$02,$02,$02,$02,$03,$03,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$03,$02,$02,$02,$02,$02,$02,$02,$03,$01
	Data .a $01,$00,$02,$02,$02,$02,$02,$03,$03,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$03,$02,$02,$02,$02,$02,$02,$03,$01
	Data .a $01,$00,$02,$02,$02,$02,$03,$03,$04,$04,$04,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$04,$03,$02,$02,$02,$02,$02,$03,$01
	Data .a $01,$00,$02,$02,$02,$03,$03,$04,$04,$04,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$04,$03,$02,$02,$02,$02,$03,$01
	Data .a $01,$00,$02,$02,$03,$03,$04,$04,$04,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$04,$03,$02,$02,$02,$03,$01
	Data .a $01,$00,$02,$03,$03,$04,$04,$04,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$04,$03,$02,$02,$03,$01
	Data .a $01,$00,$03,$03,$04,$04,$04,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$04,$03,$02,$03,$01
	Data .a $01,$00,$03,$04,$04,$04,$05,$00,$00,$06,$05,$00,$00,$00,$00,$00,$06,$05,$00,$00,$06,$05,$05,$00,$00,$00,$06,$05,$04,$02,$03,$01
	Data .a $01,$00,$03,$04,$04,$05,$00,$06,$06,$00,$06,$06,$06,$00,$06,$06,$06,$00,$06,$06,$00,$06,$05,$00,$06,$06,$00,$06,$05,$00,$03,$01
	Data .a $01,$00,$03,$04,$04,$05,$00,$06,$05,$00,$06,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$00,$03,$01
	Data .a $01,$00,$03,$04,$04,$05,$00,$06,$05,$06,$06,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$00,$03,$01
	Data .a $01,$00,$03,$04,$04,$05,$00,$06,$05,$05,$05,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$00,$03,$01
	Data .a $01,$00,$03,$04,$04,$05,$06,$00,$00,$06,$05,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$00,$00,$06,$06,$05,$00,$03,$01
	Data .a $01,$00,$03,$04,$04,$05,$05,$06,$06,$00,$06,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$06,$06,$06,$05,$05,$00,$03,$01
	Data .a $01,$00,$03,$04,$04,$05,$05,$05,$05,$00,$06,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$05,$05,$05,$00,$03,$01
	Data .a $01,$00,$03,$04,$04,$05,$00,$06,$05,$00,$06,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$05,$05,$05,$00,$03,$01
	Data .a $01,$00,$03,$04,$04,$05,$00,$06,$05,$00,$06,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$05,$05,$05,$00,$03,$01
	Data .a $01,$00,$03,$04,$04,$05,$00,$06,$05,$00,$06,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$05,$05,$05,$00,$03,$01
	Data .a $01,$00,$03,$04,$04,$05,$06,$00,$00,$06,$06,$05,$05,$00,$06,$05,$05,$06,$00,$00,$06,$06,$05,$00,$06,$05,$05,$05,$05,$00,$03,$01
	Data .a $01,$00,$02,$00,$04,$05,$05,$06,$06,$06,$05,$05,$05,$06,$06,$05,$05,$05,$06,$06,$06,$05,$05,$06,$06,$05,$05,$05,$00,$00,$03,$01
	Data .a $01,$00,$02,$02,$00,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$00,$00,$02,$03,$01
	Data .a $01,$00,$02,$02,$02,$00,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$00,$00,$02,$02,$03,$01
	Data .a $01,$00,$02,$02,$02,$02,$00,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$00,$00,$02,$02,$02,$03,$01
	Data .a $01,$00,$02,$02,$02,$02,$02,$00,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$00,$00,$02,$02,$02,$02,$03,$01
	Data .a $01,$00,$02,$02,$02,$02,$02,$02,$00,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$00,$00,$02,$02,$02,$02,$02,$03,$01
	Data .a $01,$00,$02,$02,$02,$02,$02,$02,$02,$00,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$00,$00,$02,$02,$02,$02,$02,$02,$03,$01
	Data .a $01,$00,$02,$02,$02,$02,$02,$02,$02,$02,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$02,$02,$02,$02,$02,$02,$02,$03,$01
	Data .a $01,$02,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$01
	Data .a $00,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$00
EndDataSection
Dernière modification par plabouro472 le dim. 23/févr./2025 9:45, modifié 1 fois.
Avatar de l’utilisateur
Mindphazer
Messages : 693
Inscription : mer. 24/août/2005 10:42

Re: Un spirographe animé

Message par Mindphazer »

Super sympa, bravo !

Pour info, ça fonctionne très bien sur MacOS.
J'ai testé rapidement sur Linux (Ubuntu) mais là ça a planté...
Bureau : Win10 64bits
Maison : Macbook Pro M3 16" SSD 512 Go / Ram 24 Go - iPad Pro 32 Go (pour madame) - iPhone 15 Pro Max 256 Go
Avatar de l’utilisateur
plabouro472
Messages : 38
Inscription : sam. 23/juil./2022 10:17

Re: Un spirographe animé

Message par plabouro472 »

Mindphazer a écrit : lun. 17/févr./2025 8:01 Super sympa, bravo !

Pour info, ça fonctionne très bien sur MacOS.
J'ai testé rapidement sur Linux (Ubuntu) mais là ça a planté...
Merci pour le compliment.
Avatar de l’utilisateur
kernadec
Messages : 1606
Inscription : ven. 25/avr./2008 11:14

Re: Un spirographe animé

Message par kernadec »

bonjour plabouro472
voilà j ai un petit soucis avec ton code 8O
après avoir installer la derniere version de PB 6.20 x64 sur windows 10
et avec le debogueur j' obtient ce resultat

[19 :40 :14] Attente du démarrage du programme...
[19 :40 :13] Type d'exécutable: Windows - x64 (64bit, Unicode)
[19 :40 :14] Exécutable démarré.
[19 :40 :14] [ERREUR] spiro graph -plabouro472.pb (Ligne: 137)
[19 :40 :14] [ERREUR] StartDrawing(): La sortie spécifiée est NULL (valeur 0).
[19 :50 :12] Le programme a été arrêté.

Ps: pas installé PB x86, et donc pas essay'é en 32bit
Cordialement
Avatar de l’utilisateur
plabouro472
Messages : 38
Inscription : sam. 23/juil./2022 10:17

Re: Un spirographe animé

Message par plabouro472 »

kernadec a écrit : lun. 17/févr./2025 19:48 bonjour plabouro472
voilà j ai un petit soucis avec ton code 8O
après avoir installer la derniere version de PB 6.20 x64 sur windows 10
et avec le debogueur j' obtient ce resultat

[19 :40 :14] Attente du démarrage du programme...
[19 :40 :13] Type d'exécutable: Windows - x64 (64bit, Unicode)
[19 :40 :14] Exécutable démarré.
[19 :40 :14] [ERREUR] spiro graph -plabouro472.pb (Ligne: 137)
[19 :40 :14] [ERREUR] StartDrawing(): La sortie spécifiée est NULL (valeur 0).
[19 :50 :12] Le programme a été arrêté.

Ps: pas installé PB x86, et donc pas essay'é en 32bit
Cordialement
Bonsoir kernadec, j'ai rechargé le code publié ici puis je l'ai essayé avec les versions 32 et 64 bits de PB avec windows 10, je n'ai pas constaté d'erreur.
Essaye de rechargé le code et si cela se reproduit, vois dans quelle circonstance ça arrive, au démarrage, en cliquant ici ou là où autres manipulations.
Bien à toi.
Avatar de l’utilisateur
kernadec
Messages : 1606
Inscription : ven. 25/avr./2008 11:14

Re: Un spirographe animé

Message par kernadec »

@plabouro472
ok, j ai réssayé de recharger le code et c est pareil
c est pas grave,
je vais l essayé sur une autre machine dans la semaine.
merci.
cordialement
Avatar de l’utilisateur
plabouro472
Messages : 38
Inscription : sam. 23/juil./2022 10:17

Re: Un spirographe animé

Message par plabouro472 »

kernadec a écrit : lun. 17/févr./2025 20:44 @plabouro472
ok, j ai réssayé de recharger le code et c est pareil
c est pas grave,
je vais l essayé sur une autre machine dans la semaine.
merci.
cordialement
Ton sprite ne s'est pas initialisé peut être à cause de la raison suivante :
Windows : Par défaut, c’est DirectX9 qui utilise l’accélération matérielle, si elle est disponible.
Sous Windows, une version récente de DirectX 9 doit être installée (voir ici : DirectX 9 runtime installer).
En fonction des besoins, deux autres sous-systèmes sont également disponibles. Il s’agit de ”OpenGL” et
de ”DirectX11”. À utiliser dans le menu ”Compilateur\Options du Compilateur \Option de
Compilation\Bibliothèque sous-système”.
Linux : OpenGL est utilisé pour gérer l’écran ce qui permet d’utiliser l’accélération matérielle.
MacOS X : OpenGL est utilisé pour gérer l’écran ce qui permet d’utiliser l’accélération matérielle.

Bien cordialement.
Avatar de l’utilisateur
kernadec
Messages : 1606
Inscription : ven. 25/avr./2008 11:14

Re: Un spirographe animé

Message par kernadec »

bjr
@plabouro472
je n avez pas le temps ces jours ci de tester ton programme car trop d'occupation annexes...
j ai installe dirextx11 mais pas opengl car ma catre graphique est une intel(R) et je n ai pas reussi a trouver le bon opengl pour cette carte
cependant avec directx11 ajoute en option compilateur
j ai encore une un code d'erreur sur le sprite...mais bon c est comme ca.. :mrgreen:

[09 :29 :14] Attente du démarrage du programme...
[09 :29 :14] Type d'exécutable: Windows - x64 (64bit, Unicode)
[09 :29 :14] Exécutable démarré.
[09 :29 :15] [ERREUR] spirograph01.pb (Ligne: 348)
[09 :29 :15] [ERREUR] Accès mémoire invalide. (erreur de lecture à l'adresse 0)
[09 :29 :25] Le programme a été arrêté.

Desole, peut etre un autre jours ou je serais plus motive :idea:
je ferais plus de recherche sur le probleme avec un ordi qui auras une carte nvidia

ps: j avais déja fait des trucs sur le sujet en PB avec un code sur les ellipses qui s'appelle "mandalas"

cordialement
pasbel
Messages : 38
Inscription : mer. 10/avr./2019 17:36

Re: Un spirographe animé

Message par pasbel »

Super chouette
Vu un petit bug, quand on choisit une couleur personnalisée, la couleur passe au noir quand on sort de la fenêtre de choix de couleur.
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Un spirographe animé

Message par Kwai chang caine »

Joli travail merci pour le partage 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Répondre