Author Topic: Mouse pointers  (Read 12305 times)

0 Members and 1 Guest are viewing this topic.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Mouse pointers
« Reply #15 on: August 23, 2018, 03:13:12 pm »
Today something similar, yet much more fun. The program will allow you to use animated ANI cursors (this first version know only one type, but of course this is not last version) What do you say about an animated Windows cursor under Linux?

Code: QB64: [Select]
  1. 'ANI reader - 32 bit files only.    Linux compatible.
  2.  
  3. file$ = "aero_working_xl.ani"
  4.  
  5.  
  6.  
  7. '1] Test, if this is ANI file
  8. '------------------------------
  9. TYPE ANI_Acon_Header
  10.     ID1 AS STRING * 4 'RIFF
  11.     Size AS LONG '     ?
  12.     ID2 AS STRING * 4 'ACON
  13. DIM Ani_Head AS ANI_Acon_Header
  14.     ch = FREEFILE
  15.     OPEN file$ FOR BINARY AS #ch
  16.     GET #ch, , Ani_Head
  17.     IF Ani_Head.ID1 = "RIFF" AND Ani_Head.ID2 = "ACON" THEN PRINT file$; " is valid. Size: "; Ani_Head.Size + 8
  18. ELSE PRINT file$; " not exists.": END
  19.  
  20. '2] Finding in file position for flag "anih" and reading this head
  21. '-----------------------------------------------------------------
  22. TYPE anih
  23.     ID AS STRING * 4 'anih
  24.     Width AS LONG
  25.     Height AS LONG
  26.     NumFrames AS LONG
  27.     NumSteps AS LONG
  28.     Frame_Size AS LONG
  29.     HeaderSize AS LONG
  30.     BitCount AS LONG
  31.     NumPlanes AS LONG 'always 1
  32.     DisplayRate AS LONG 'default rate = 60/anih.displayrate fps
  33.     Flags AS STRING * 4 'currently used 2 bits: bit 31 to 2 are reserved,
  34.     'bit 1: if true, then file contains sequence data,
  35.     'bit 0: True = Frames are icon or cursor dat, False: Frames are RAW data
  36. DIM anih AS anih
  37. REDIM a_rec(0)
  38. Scan file$, "anih", a_rec(), 1
  39. GET #ch, a_rec(0), anih
  40.  
  41. Frames = anih.NumFrames
  42. Width = anih.Width
  43. Height = anih.Height
  44. BpP = anih.BitCount
  45. Rate = anih.DisplayRate
  46.  
  47. '3] Finding start positions for all frames (search flag "icon")
  48. '--------------------------------------------------------------
  49. REDIM a_rec(0)
  50. Scan file$, "icon", a_rec(), Frames 'ok
  51.  
  52. '4] By the BpP (bites per pixel) value now i set output pixelsize and create array with frames. Record 0 contains video LIMIT between frames.
  53. '--------------------------------------------------------------------------------------------------------------------------------------------
  54. TYPE Icon
  55.     icon AS STRING * 4
  56.     cosi AS LONG
  57.     Reserved AS INTEGER '       2 bytes, always 00
  58.     Image_Type AS INTEGER '     1 = ICO format, 2 = CUR format, others are invalid
  59.     Number_images AS INTEGER '  number images in file
  60.  
  61. TYPE Structure '
  62.     Image_Width AS _UNSIGNED _BYTE
  63.     Image_Height AS _UNSIGNED _BYTE
  64.     Image_Color_Palette AS _UNSIGNED _BYTE
  65.     Reserved AS _UNSIGNED _BYTE 'always zero
  66.     Planes AS INTEGER '          In ICO format: Specifies color planes. Should be 0 or 1.
  67.     '                            In CUR format: Specifies the horizontal coordinates of the hotspot in number of pixels from the left.
  68.     Bpp AS INTEGER '             In ICO format: Specifies bits per pixel.
  69.     '                            In CUR format: Specifies the vertical coordinates of the hotspot in number of pixels from the top.
  70.     Size_of_image_data AS LONG
  71.     Offset_from_begin AS LONG
  72.  
  73. DIM icon AS Icon
  74. DIM structure AS Structure
  75.     CASE 32
  76.         DIM Video32(Frames) AS LONG
  77.         Video32(0) = 60 / Rate
  78.         FOR Create_all_frames = 1 TO Frames
  79.             SEEK #ch, a_rec(Create_all_frames - 1)
  80.             GET #ch, , icon
  81.             GET #ch, , structure
  82.             REDIM record AS LONG
  83.             Video32(Create_all_frames) = _NEWIMAGE(structure.Image_Width, structure.Image_Height, 32)
  84.             x = -structure.Image_Width / 4
  85.             Y = structure.Image_Height - 1
  86.             _DEST Video32(Create_all_frames)
  87.             CLS
  88.             FOR frm = 1 TO structure.Image_Height * structure.Image_Width * 4
  89.                 GET #ch, , record&
  90.                 PSET (x, Y), record&
  91.                 x = x + 1: IF x >= structure.Image_Width AND x MOD 4 = 0 THEN Y = Y - 1: x = 0
  92.             NEXT frm
  93.         NEXT
  94.         _DEST 0
  95.     CASE ELSE
  96.         PRINT "Support for other than 32 bit ANI i prepare.": SLEEP 2: END
  97. CLOSE #ch
  98.  
  99. '5] Is time for display it:
  100. '--------------------------
  101. SCREEN _NEWIMAGE(800, 600, 32)
  102.     CLS
  103.     showANI Video32(), _MOUSEX, _MOUSEY, structure.Image_Width, structure.Image_Height
  104.     _LIMIT Video32(0)
  105.     _DISPLAY
  106.  
  107. FOR Erase_memory = 1 TO UBOUND(video32)
  108.     _FREEIMAGE Video32(Erase_memory)
  109.  
  110.  
  111. SUB showANI (arr() AS LONG, x, y, Xres, Yres)
  112.     SHARED internalindex0
  113.     IF internalindex0 = 0 THEN internalindex0 = 1
  114.     _PUTIMAGE (x - (Xres / 2), y - (Yres / 2)), arr(internalindex0)
  115.     internalindex0 = internalindex0 + 1: IF internalindex0 > UBOUND(arr) THEN internalindex0 = 1
  116.  
  117. SUB Scan (file AS STRING, text AS STRING, result(), RECORDS) 'Records = number of records, which are searched
  118.     IF _FILEEXISTS(file$) THEN
  119.         g = FREEFILE
  120.         OPEN file$ FOR BINARY AS #g
  121.         content$ = SPACE$(LOF(g))
  122.         GET #g, , content$
  123.         REDIM result(0)
  124.         FOR S = 1 TO LEN(content$)
  125.             num = INSTR(S, content$, text$)
  126.             IF num THEN
  127.                 REDIM _PRESERVE result(i)
  128.                 result(i) = num
  129.                 S = num
  130.                 num = 0
  131.                 i = i + 1
  132.                 IF RECORDS = i THEN EXIT SUB
  133.             END IF
  134.         NEXT S
  135.         CLOSE #g
  136.     ELSE
  137.         PRINT "File "; file$; "not exist.": END
  138.     END IF
  139.     content$ = ""
  140.  
  141.  
* aero_working_xl.ani (Filesize: 245.28 KB, Downloads: 280)

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Mouse pointers
« Reply #16 on: August 23, 2018, 06:47:07 pm »
Hi Petr,

This is weird, I have a perpetual circle circling over the screen. Is this OK to run on Windows?

I was hoping to see an animated cursor.

Oh maybe that's it, the animation? Ha! I thought it was stuck processing...
aero.PNG
* aero.PNG (Filesize: 5.92 KB, Dimensions: 815x240, Views: 400)
« Last Edit: August 23, 2018, 06:50:37 pm by bplus »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Mouse pointers
« Reply #17 on: August 24, 2018, 12:38:03 pm »
Hi BPlus,
what you see is not the work of windows, but the result of a program that uses an ANI file that contains just this animated icon. I think it's good to be able to use CUR and ANI files in programs. Soon I will release both versions with the support of 16 color icons. There is bad documentation, so I often have to look for connections. But this is fun for me.

FellippeHeitor

  • Guest
Re: Mouse pointers
« Reply #18 on: August 24, 2018, 01:22:57 pm »
Very good job on this one, Petr. It's similar to what Zom-B did for viewing animated GIF files.

https://qb64.org/wiki/GIF_Images

Do you think you could streamline your code so it'd behave more like a library? Maybe a reduced set of methods like Load, Display, Unload, so that the actual inner workings could be hidden away in a $INCLUDE file? That'd be interesting to have.

I have added Zom-B's code to the next release of InForm. Here's the readme that'll come with Beta 8 showing how to display animated GIFs in a form: https://github.com/FellippeHeitor/InForm/blob/Beta8/InForm/extensions/README%20-%20gifplay.txt

Please see the methods I describe in the document above for an idea of what I mean about your animated cursors code.
« Last Edit: August 24, 2018, 01:45:30 pm by FellippeHeitor »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Mouse pointers
« Reply #19 on: August 24, 2018, 02:58:45 pm »
Hi Fellippe,
Yes, I have such an idea. However, it will be necessary to use the BI file at the beginning and the BM at the end due to the input field declarations. Now, during development, I need to get as many CUR and ANI files as possible for thorough testing. It has the following features: Cursor& = LOADCUR ("curfile_name.cur") and then PlayCUR Cursor&,x, y   the same for ANI files. In Inform I'll look at how it's done there.
I could open a detective office literally because it has happened many times that the content that is mentioned in various sources for these files did not correspond to reality.
Of course, the correct placement of the cursor will also be very important.
This version are "direct", but finaly version i write as BI and BM (and then re-testing it in Win and Linux).

I am glad for your reaction.
 

FellippeHeitor

  • Guest
Re: Mouse pointers
« Reply #20 on: August 24, 2018, 03:06:55 pm »
You don't even need to worry about InForm specifics. If it becomes a detachable library, a user of InForm would be able to use it as is, probably.

Again, good investigation job.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Mouse pointers
« Reply #21 on: August 26, 2018, 03:58:10 pm »
Hi. So you say, make it as easy and user-friendly as possible. I tried it. Here is the result, the same thing I do for CUR files, this here is for ANI files. It supports the 16 color ANI and Truecolor ANI, but I have a few ANI files, that do not work right, so I still do it.
I do not have the speed between frames of the shot correct, but that's exactly what I'm doing now.

Code: QB64: [Select]
  1. '$include:'ani.bi'
  2.  
  3. FileA$ = "coin.ani"
  4. FileB$ = "dinosau2.ani"
  5. FileC$ = "horse.ani"
  6.  
  7. A& = LoadAni(FileA$)
  8. B& = LoadAni(FileB$)
  9. C& = LoadAni(FileC$)
  10.  
  11. SCREEN _NEWIMAGE(800, 600, 32)
  12. 'program know playing ANIs and EXTRACT FRAMES from ANI:
  13.  
  14. FOR Extract = 1 TO FrameAni(A&) '               function return number frames in file
  15.     Image& = ExtractAni(A&, Extract) '          function return decoded image
  16.     _PUTIMAGE (50 + Extract * 50, 100), Image&
  17. NEXT Extract
  18. 'this is just option, normal you need not, but it is here for you.
  19.  
  20.  
  21.     PCOPY 1, _DISPLAY
  22.     PutAni A&, 100, 200
  23.     PutAni B&, 300, 500
  24.     PutAni C&, _MOUSEX, _MOUSEY
  25.     _DISPLAY
  26.     _LIMIT 20
  27.  
  28. FreeAni A& 'clear it from memory
  29. FreeAni B&
  30. FreeAni C&
  31.  
  32. '$include:'ani.bm'
  33.  
* ANI BI BM.ZIP (Filesize: 8.61 KB, Downloads: 282)

FellippeHeitor

  • Guest
Re: Mouse pointers
« Reply #22 on: August 26, 2018, 04:53:03 pm »
Nice, Petr!

I do not have the speed between frames of the shot correct, but that's exactly what I'm doing now.

Maybe you'll need to keep track of the last time a frame is served, store TIMER for reference, and only serve a new frame after that frame's delay is reached.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Mouse pointers
« Reply #23 on: August 31, 2018, 03:50:40 pm »
Hi all,
This version is beta. If some CUR or ANI file is not displayed correctly, send it here and i look at it.Program allow using CUR (static mouse cursors) or ANI (animated mouse cursors), extracting frames from ANI and do some experiments.
Usage:
CursorA& = LOADCURSOR("Cursor.cur")
CursorsB& = LOADCURSOR("CursorB.ani")
load cursors to memory. If CursorA& or CursorB& return -1, is something wrong (file not exist?)

For inserting it to screen use PUTCURSOR CursorA&, coordinate X, coordinate Y
For erase it from memory use FREECURSOR CursorB&

If loaded cursor is ANI file, you can extract frames:
LENCURSOR return number of frames in ANI file, DECOMPOSECURSOR (source&, frame_number) return image.

So is possible easy all frames view:

For Show = 1 to LENCURSOR(CursorA&)
Image& = DECOMPOSECURSOR(Show)
_PUTIMAGE (100,100), image&,0
SLEEP
NEXT

If you call LENCURSOR or DECOMPOSECURSOR to CUR file, it return always -1 as error code.

In attachment is BAS file, BI file, BM file and folder CURSORS contains all CUR and ANI files, on which i test this program. So if you found some, which is not right displayed, please send it
here. Thank you.




preview.JPG
* preview.JPG (Filesize: 110.73 KB, Dimensions: 1041x810, Views: 457)
* cursors.zip (Filesize: 224.53 KB, Downloads: 294)