Le concept de 'ScreenGadget'

Vous avez une idée pour améliorer ou modifier PureBasic ? N'hésitez pas à la proposer.
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Le concept de 'ScreenGadget'

Message par Ollivier »

Je veux en venir, au moins à ce qui est déjà écrit, à savoir disposer d'un code simple pour se retrouver pleinement dans un environnement graphique adéquate à l'OS hôte. Je recopie l'exemple proche de l'en-tête du sujet, et je le commente:

Code : Tout sélectionner

InitSprite() ; Initialise l'accélération matérielle vidéo
OnFullScreen("test") ; Ouvre la zone graphique plein écran
InitKeyboard() ; Initialise le clavier
Repeat ; Début de boucle principale
ClearScreen(0) ; Partie graphique (ici: simple écran noir)
Delay(16) ; Partage des ressources CPU avec les autres tâche de l'OS
FlipBuffers() ; Affichage
If IsScreenActive() = 0 ; Echec de l'affichage?
FullScreenResume("TEST") ; Oui, offrons la main à l'OS...
EndIf ;...car il devait en avoir besoin
ExamineKeyboard() ; Interroge le clavier
Until KeyboardPushed(#PB_Key_Escape) ; Rebelote en début de boucle sauf si touche [Echap]
End ; Dans, ce cas, quitte le programme.
@Falsam

Avec de telles fonctions natives, on aurait vraiment la simplicité et la fiabilité réunies, dès le départ.

Alors peut-être que tu restes un peu sur ta faim avec le pointeur *StandBy qui se cache en une option falcultative.

Je peux préciser. Si l'on quitte un jeu/logiciel plein écran, la 1ère chose qui prend une baffe, après l'instabilité de l'affichage, c'est l'horloge virtuelle que l'on aura mis en place et qui s'étalonne à chaque boucle d'affichage graphique. S'il n'y a plus de charge d'affichage, il y a un 'delta de sortie' et un 'delta d'entrée' de notre tâche plein écran.

Il y a donc au moins une correction d'horloge à effectuer. Et, autant faire ce correctif pendant une période 'lente' (quand le plein écran a été interrompu) une bonne fois pour toute, plutôt que d'aller adapter l'horloge en la complexifiant inutilement au sein même de la boucle principale dont la vélocité doit rester proche de l'absolu (zéro procédure, factorisation des variables, etc... etc...).
Voilà aussi donc pour ce pointeur.
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Le concept de 'ScreenGadget'

Message par Ollivier »

C'est bien pour ça que j'attends patiemment qu'un utilisateur de Linux vienne enterrer mon doux rêve que cela marche partout! :mrgreen:
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Le concept de 'ScreenGadget'

Message par Ollivier »

La présence de ton 'GoTo' me rappelle un débat hallucinant et excellent.

A ce stade, on pourrait s'attendre à une pâle copie de ma part, sournoisement remaniée, pour s'acquérir une 'notoriété'!!

Mais, je suis au contraire très amusé qu'on ait pu aboutir à un concept similaire.
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Le concept de 'ScreenGadget'

Message par Ollivier »

Un notorious bideman... M'enfin, passons et penchons-nous sur ce fameux 'WindowedScreen'...

Car un problème fondamental vient bouleverser la conscience à un dilemne : be or do not be the system bar. Est-ce que tu te souviens avoir rencontré ce problème?

Forcément l'on doit être nombreux et on le sera encore. Cette fameuse barre des tâches qui vient casser les granulés pour un seul petit pixel de plus:

Dans la pratique, ça va. Parce que, justement c'est un seul pixel. Donc : on prend le desktopheight(0), si on le laisse ainsi pour fixer la hauteur de notre fenêtre sans rebord, pas de barre des tâches, alors que si on le décrémente, dich, une barre des tâches...

Ma question plus générale est: est-ce que cet impact de la fenêtre en fonction de son format, et, dans notre cas précis, en rapport avec le format du bureau, se retrouve-t-il changé d'une autre manière sur d'autres OS?

Cette fenêtre, je le rappelle est celle qui est prête à supporter l'écran fenêtré.
Après ce dilemne du format de fenêtre, je tâcherai d'étudier cette astuce de MicroDevWeb.
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Le concept de 'ScreenGadget'

Message par Ollivier »

Ben, en gros teste une fenêtre borderless de la taille de l'écran: la barre des tâches ne s'affiche pas, cachée par la fenêtre.

Ensuite, refait l'expérience, mais avec 1 pixel en moins: pouf, t'as la barre des tâches est là DEVANT ta fenêtre!

Avant même ma question, commençons par, PEUT-ETRE, te faire découvrir ça (je suis sur XP).

Déjà, est-ce que tu arrives à reproduire ou bien je poste un petit code?
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Le concept de 'ScreenGadget'

Message par Ollivier »

Si tu peux faire une vérif visuelle (c'est F12 pour changer de mode).

Code : Tout sélectionner

;______________________________________________________
; /!\ Attention, a priori, ca vous envoie dans le noir. 
;______________________________________________________

Global.I ScreenWindow
Global.I ScreenUID
Global.I ScreenSysBar
Global.I ScreenMode



Procedure DoUntil(Window.I, 
                  Event.I, 
                  *StandBy = 0, 
                  DelayDuration.I = 16)
	Repeat
		Delay(DelayDuration)
		If *StandBy
			CallFunctionFast(*StandBy)
		EndIf
		If WindowEvent() = Event
			If EventWindow() = Window
				Break
			EndIf
		EndIf
	ForEver
EndProcedure



Procedure FullScreen(ScreenTitle.S,
                     ScreenFlipMode.I = #PB_Screen_WaitSynchronization)
	ExamineDesktops()
	ScreenUID = OpenScreen(DesktopWidth(0),
	                       DesktopHeight(0),
	                       DesktopDepth(0),
	                       ScreenTitle,
	                       ScreenFlipMode,
	                       DesktopFrequency(0) )
	ScreenSysBar = 0
EndProcedure



Procedure WindowedScreen(ScreenTitle.S,
                         ScreenFlipMode.I = #PB_Screen_WaitSynchronization,
                         LocalScreenSysBar.I = 1,
                         ScreenWindowFlags.I = #PB_Window_BorderLess)
	Protected.I Width
	Protected.I Height
	Protected.I AutoResize
	Protected.I WindowWidth
	Protected.I WindowHeight
	ScreenSysBar = LocalScreenSysBar
	ExamineDesktops()
	If (ScreenWindowFlags & #PB_Window_SizeGadget)
		ScreenWindowFlags | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget
		AutoResize = LocalScreenSysBar
		Width = DesktopWidth(0) / 2
		Height = DesktopHeight(0) / 2
		ScreenWidth = DesktopWidth(0)
		ScreenHeight = DesktopHeight(0)
	Else
		Width = DesktopWidth(0)
		Height = DesktopHeight(0) - ScreenSysBar
	EndIf
	ScreenWindow = OpenWindow(#PB_Any, 
	                          0,
	                          0,
	                          Width,
	                          Height,
	                          ScreenTitle,
	                          ScreenWindowFlags)
	
	If Not (ScreenWindowFlags & #PB_Window_SizeGadget)
		ScreenWidth = WindowWidth(ScreenWindow)
		ScreenHeight = WindowHeight(ScreenWindow)
	EndIf
	If ScreenWindow
		ScreenUID = OpenWindowedScreen(WindowID(ScreenWindow), 
		                               0, 
		                               0, 
		                               ScreenWidth, 
		                               ScreenHeight, 
		                               AutoResize, 
		                               0, 
		                               0, 
		                               ScreenFlipMode)
		WaitWindowEvent()
	EndIf
EndProcedure


Procedure Screen(Mode.I, 
                 ScreenTitle.S,
                 ScreenFlipMode.I = #PB_Screen_WaitSynchronization)
	ScreenMode = Mode
	If ScreenUID
		CloseScreen()
		If ScreenWindow
			CloseWindow(ScreenWindow)
		EndIf
		ScreenUID = 0
		ScreenWindow = 0
	EndIf
	Select Mode
		Case 0
			ProcedureReturn FullScreen(ScreenTitle,
			                           ScreenFlipMode)
		Case 1
			ProcedureReturn WindowedScreen(ScreenTitle,
			                               ScreenFlipMode, 
			                               0)
		Case 2
			ProcedureReturn WindowedScreen(ScreenTitle,
			                               ScreenFlipMode,
			                               1)
		Case 3
			ProcedureReturn WindowedScreen(ScreenTitle,
			                               ScreenFlipMode,
			                               0,
			                               #PB_Window_Maximize)
		Case 4
			ProcedureReturn WindowedScreen(ScreenTitle,
			                               ScreenFlipMode,
			                               0,
			                               #PB_Window_SizeGadget)
		Case 5
			ProcedureReturn WindowedScreen(ScreenTitle,
			                               ScreenFlipMode,
			                               1,
			                               #PB_Window_SizeGadget)
	EndSelect
EndProcedure


Procedure ScreenResume(ScreenTitle.S,
                       ScreenFlipMode.I = #PB_Screen_WaitSynchronization, 
                       *StandBy = 0,
                       DelayDuration.I = 16)
	
	Protected BackgroundWindow.I
	If ScreenWindow
		Repeat
			Delay(DelayDuration)
			If *StandBy
				CallFunctionFast(*StandBy)
			EndIf
		Until WindowEvent() = #PB_Event_ActivateWindow
	Else
		CloseScreen()
		BackgroundWindow = OpenWindow(#PB_Any, 
		                              0, 
		                              0, 
		                              0, 
		                              0, 
		                              ScreenTitle, 
		                              #PB_Window_BorderLess | 
		                              #PB_Window_NoActivate)
		
		DoUntil(BackgroundWindow, #PB_Event_ActivateWindow, *StandBy, DelayDuration)
		CloseWindow(BackgroundWindow)
		FullScreen(ScreenTitle, ScreenFlipMode)
	EndIf
EndProcedure

Procedure SpriteInit()
	
	Dim A$(5)
	A$(5) = "Plein écran"
	A$(4) = "Graphique adapté à la fenêtre"
	A$(3) = "Redimensionnable"
	A$(2) = "Barre de titre"
	A$(1) = "Fenêtré"
	A$(0) = "Barre des tâches"
	
	B$ = "32;34;35;38;15;31"
	
	For I = 0 To 5
		If IsImage(I + 1) = 0
			StartDrawing(ScreenOutput() )
			DrawingFont(FontID(0) )
			TW = TextWidth("* " + A$(I) )
			TH = TextHeight(A$(I) )
			CreateImage(I + 1, TW, TH)
			StopDrawing()
			If StartDrawing(ImageOutput(I + 1) )
				DrawingFont(FontID(0) )
				W = OutputWidth()
				H = OutputHeight()
				DrawText(0, 0, "* " + A$(I), RGB(0, 255, 255), RGB(0, 127, 127) )
				StopDrawing()
			EndIf
		EndIf
		If IsImage(I + 7) = 0
			A$ = "MODE ECRAN " + Str(I)
			StartDrawing(ScreenOutput() )
			DrawingFont(FontID(0) )
			TW = TextWidth(A$)
			TH = TextHeight(A$)
			CreateImage(I + 7, TW, TH)
			StopDrawing()
			If StartDrawing(ImageOutput(I + 7) )
				DrawingFont(FontID(0) )
				W = OutputWidth()
				H = OutputHeight()
				DrawText(0, 0, A$, RGB(0, 127, 127), RGB(0, 255, 255) )
				StopDrawing()
			EndIf
		EndIf
	Next
	
	CreateSprite(0, ScreenWidth(), ScreenHeight() )
	If StartDrawing(SpriteOutput(0) )
		W = OutputWidth()
		H = OutputHeight()
		X = W / 4
		Y = H / 4
		n = Val(StringField(B$, ScreenMode + 1, ";") )
		DrawImage(ImageID(ScreenMode + 7), X, Y)
		Y + ImageHeight(ScreenMode + 7)
		For J = 0 To 5
			If (n & (1 << J) )
				DrawImage(ImageID(J + 1), X, Y)
				Y + ImageHeight(J + 1)
			EndIf
		Next
		StopDrawing()
	EndIf
	
EndProcedure

InitSprite()
Screen(0, "Test")
InitKeyboard()
InitMouse()

LoadFont(0, "courier", 32, #PB_Font_Bold)
SpriteInit()

Repeat
	ClearScreen(0)
	DisplaySprite(0, 0, 0)
	Delay(16)
	FlipBuffers()
	If IsScreenActive() = 0
		ScreenResume("TEST")
	EndIf
	If ScreenWindow
		ScreenEvent = WindowEvent()
		If ScreenEvent = #PB_Event_CloseWindow
			Break			
		EndIf
	EndIf
	ExamineKeyboard()
	If KeyboardReleased(#PB_Key_F12)
		Mode + 1
		Mode % 6
		Screen(Mode, "Test")
		SpriteInit()
	EndIf
Until KeyboardPushed(#PB_Key_Escape) 

End
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Le concept de 'ScreenGadget'

Message par Ollivier »

C'est une bonne épice ce code.

Mais est-ce que tu observes exactement ce qui est décrit par mon prog, sur un autre OS que XP?
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Le concept de 'ScreenGadget'

Message par Ollivier »

Spock a écrit :j'aime vraiment pas ta façon de présenter le code avec plusieurs lignes par procédure...
Je suis d'accord, cependant 2 raisons me contraignent à ce procédé.

Le 1er c'est que, même si ça éclate les alinéas, les listes verticales aident à voir beaucoup plus rapidement ce qu'il en retourne, au niveau des types.
Ça permet de commenter très précisément en plus.

L'inconvénient, c'est le retour à l'alinéa. Si une longue ligne y est, l'oeil se mélange les pinceaux, donc je suis contraint de passer une ligne pour bien marquer la fin d'une ligne composée.

L'inconvénient majeur, c'est qu'une ligne prend facilement une demi page! Effectivement, ça défile beaucoup!

La 2nde raison c'est que les copier/coller du code source tronquent les lignes et TazNormand se force à corriger, alors je tâche de trouver des soluces pour éviter de trop le solliciter!
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Le concept de 'ScreenGadget'

Message par Ollivier »

Spock a écrit :comment etre plus clair ?
Plus que je ne fûs con, je suis confus, là.

Je te remercie pour ton retour d'information.
Je m'en vais ajouter l'idée judicieuse de MicrodevWeb.
Ça tombe très bien car le "Mode Ecran 4" ne me plaît pas.
Patrick88
Messages : 1564
Inscription : mer. 21/janv./2004 18:24

Re: Le concept de 'ScreenGadget'

Message par Patrick88 »

microdevweb a écrit :Vous pouvez gérer un screen comme un gadget, comme suit.
Windows only (pas testé sur d'autre os)

Code : Tout sélectionner

CanvasGadget(#Canvas,X,Y,W,H,#PB_Canvas_Keyboard)
OpenWindowedScreen(GadgetID(#Canvas),0,0,W,H)
Tous les événements du canvas peuvent être traités, par contre les événements mouse ne sont plus actif, mais ils sont facilement remplacé par GetGadgetAttribute(#Canvas,#PB_Canvas_MouseX) etc...
à priori cela fonctionne avec Ogre... exemple de la doc createmesh

Code : Tout sélectionner

#canvas = 0
  InitEngine3D() 
  InitSprite() 
  
  OpenWindow(0, 0, 0, 640, 480, "Cube example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CanvasGadget(#Canvas,10,10,WindowWidth(0)-20,WindowHeight(0)-20,#PB_Canvas_Keyboard)
  OpenWindowedScreen(GadgetID(#canvas), 0, 0, GadgetWidth(#canvas), GadgetHeight(#canvas), 0, 0, 0)
  
  ; Light
  CreateLight(#PB_Any, RGB(25, 25, 180), -5, 10, 5, #PB_Light_Point)
  
  ; Camera
  CreateCamera(0, 0, 0, 100, 100)
  MoveCamera(0, 2, 1, 3, #PB_Absolute | #PB_Local)
  CameraLookAt(0, 0, 0, 0)
  
  ; Create the cube and attach it to the scene
  CreateCube(0, 1)
  CreateEntity(0, MeshID(0), #PB_Material_None)
  
  Repeat
    RenderWorld()
    FlipBuffers()
  Until WaitWindowEvent(1) = #PB_Event_CloseWindow
mais il ne veut pas de 2 OpenWindowedScreen... mais alors pas du tout...

pat
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Le concept de 'ScreenGadget'

Message par Ollivier »

@Patrick88

Ce n'est pas grave.

Je me répète mais OpenGL et Canvas complètent largement, voire supplantent l'écran pour Ogre selon les critères, le matériel, etc...

@Spock

Je ne sais pas si le ContainerGadget(), c'est le meilleur.
Je tends à penser que 2 simples ascenseurs horizontal et vertical, et un décalage dans les offsetX2 offsetY2 de l'écran fenêtré par rapport à la fenêtre, pour faire la place aux ascenseurs permettent une économie non négligeable de mémoire.
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: Le concept de 'ScreenGadget'

Message par blendman »

Ollivier a écrit :Je me répète mais OpenGL et Canvas complètent largement, voire supplantent l'écran pour Ogre selon les critères, le matériel, etc...
Cependant, l'écran est tout de même absolument nécessaire dans dans des cas , comme lors de l'utilisation des sprites ;).
Pour le moment, ni ogre, ni le canvas ne lui arrive à la cheville avec l'utilisation de sprites
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Le concept de 'ScreenGadget'

Message par falsam »

Spock a écrit :franchement ,de nos jours qui n'a pas 8 go de Ram dans son ordi ?
Moi ... Que 4 Go :mrgreen:
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
Micoute
Messages : 2522
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: Le concept de 'ScreenGadget'

Message par Micoute »

falsam a écrit :
Spock a écrit :franchement ,de nos jours qui n'a pas 8 go de Ram dans son ordi ?
Moi ... Que 4 Go :mrgreen:
Moi de même, je ne crois pas que ça serve à grand chose d'avoir plus de mémoire que le processeur ne peut en adresser !
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 5.73 PB 6.00 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Le concept de 'ScreenGadget'

Message par Ollivier »

134 217 728 octets
Répondre