QB64.org Forum

Active Forums => QB64 Discussion => Topic started by: Pete on August 15, 2021, 09:15:17 pm

Title: Hey graphic gurus, top this!!!
Post by: Pete on August 15, 2021, 09:15:17 pm
Going through some age old QB4.5 stuff I made during the Jurassic Period, and I came across this little ge I used back then to get a cursor effect in SCREEN 12. So is there a better way now in QB64?

Code: QB64: [Select]
  1. startpos% = 5
  2. word$ = "This is a demo of a flashing cursor for a graphics screen."
  3. LOCATE 5, startpos%: PRINT word$;
  4.  
  5. cur$ = "_"
  6. z1 = TIMER
  7.     flag = 0
  8.     _LIMIT 30
  9.     b$ = INKEY$
  10.     IF b$ = CHR$(27) THEN SYSTEM
  11.  
  12.     IF LEN(b$) THEN
  13.         IF b$ = CHR$(0) + "R" THEN
  14.             IF cur$ = "_" THEN
  15.                 cur$ = CHR$(219)
  16.             ELSE
  17.                 cur$ = "_"
  18.             END IF
  19.         END IF
  20.  
  21.         IF b$ = CHR$(0) + "K" THEN
  22.             IF POS(0) > startpos% THEN
  23.                 GOSUB reprint
  24.                 LOCATE , POS(0) - 1
  25.             ELSE
  26.                 flag = 0
  27.             END IF
  28.         END IF
  29.  
  30.         IF b$ = CHR$(0) + "M" THEN
  31.             IF POS(0) < startpos% + LEN(word$) THEN
  32.                 flag = 1
  33.                 GOSUB reprint
  34.             ELSE
  35.                 flag = 0
  36.             END IF
  37.         END IF
  38.  
  39.     END IF
  40.  
  41.     IF ABS(z1 - TIMER) > .4 OR flag THEN
  42.         SELECT CASE cursor
  43.             CASE 0
  44.                 cursor = -1
  45.                 PRINT cur$;
  46.                 LOCATE , POS(0) - 1
  47.             CASE -1
  48.                 cursor = 0
  49.                 GOSUB reprint
  50.         END SELECT
  51.         z1 = TIMER
  52.     END IF
  53.  
  54. reprint:
  55. c$ = MID$(word$, POS(0) - (startpos% - 1), 1)
  56. IF c$ = "" THEN PRINT " "; ELSE PRINT c$;
  57. IF flag <> 1 THEN LOCATE , POS(0) - 1
  58. flag = -1
  59.  


Use arrow left and right, or press Insert key to change from a line to a full block cursor.

Pete
Title: Re: Hey graphic gurus, top this!!!
Post by: bplus on August 15, 2021, 10:47:06 pm
Could probably do this before:
Code: QB64: [Select]
  1. start = 5
  2. word$ = "This is a demo of a flashing cursor for a graphics screen."
  3. Locate 5, start: Print word$;
  4. On Timer(.4) GoSub cursim
  5. cur = start + Len(word$)
  6.     b$ = InKey$
  7.     If b$ = Chr$(27) Then
  8.         System
  9.     ElseIf b$ = Chr$(0) + "R" Then
  10.         insert = 1 - insert
  11.     ElseIf b$ = Chr$(0) + "K" Then
  12.         If cur > start Then cur = cur - 1
  13.     ElseIf b$ = Chr$(0) + "M" Then
  14.         If cur < start + Len(word$) Then cur = cur + 1
  15.     End If
  16.     _Limit 20
  17. cursim:
  18. If insert Then c$ = Chr$(219) Else c$ = "_"
  19. blink = 1 - blink
  20. If blink Then Locate , cur: Print c$; Else Locate 5, start: Print word$; " ";
  21.  
Title: Re: Hey graphic gurus, top this!!!
Post by: Pete on August 16, 2021, 03:22:43 am
Same method... just more optimistic! :D

What's funny is using SELECT CASE instead of IF/THEN/ELSE actually would have added one extra line.

Anyway, optimization aside, and that was a nice job, btw, I'm still wondering if anyone has devised, or if QB64 has a native way, of putting a working cursor into a graphics word processor, other than this???

Pete

Title: Re: Hey graphic gurus, top this!!!
Post by: Petr on August 16, 2021, 01:19:33 pm
If graphic mode cursor, so why LOCATE? Oh i see, it is program created using QB4.5!

So here is my version (modified @bplus version), it calculate graphics coordinates from text coordinates and then use _PRINTSTRING.

Code: QB64: [Select]
  1. start = 5
  2. word$ = "This is a demo of a flashing cursor for a graphics screen."
  3. LOCATE 5, start: PRINT word$;
  4. StartGraphicX = _FONTWIDTH * (POS(_DEST) - LEN(word$) - 1)
  5. StartGraphicY = _FONTHEIGHT * CSRLIN - (_FONTHEIGHT)
  6. CursorY = _FONTHEIGHT * CSRLIN - (_FONTHEIGHT - 2) 'draw cursor two pixels under text
  7.  
  8. ON TIMER(.08) GOSUB cursim
  9. cur = start + LEN(word$)
  10.  
  11.     b$ = INKEY$
  12.     IF b$ = CHR$(27) THEN
  13.         SYSTEM
  14.     ELSEIF b$ = CHR$(0) + "R" THEN
  15.         insert = 1 - insert
  16.     ELSEIF b$ = CHR$(0) + "K" THEN
  17.         IF cur > start THEN cur = cur - 1
  18.     ELSEIF b$ = CHR$(0) + "M" THEN
  19.         IF cur < start + LEN(word$) THEN cur = cur + 1
  20.     END IF
  21.     _LIMIT 20
  22. cursim:
  23. CursorX = _FONTWIDTH * (cur - 1)
  24. IF blink THEN c$ = " " ELSE c$ = "_"
  25. blink = 1 - blink
  26.  
  27. _PRINTSTRING (StartGraphicX, StartGraphicY), word$ + " "
  28. IF blink THEN _PRINTSTRING (CursorX, CursorY), c$
  29.  
Title: Re: Hey graphic gurus, top this!!!
Post by: Petr on August 16, 2021, 01:48:44 pm
Or faster:

Code: QB64: [Select]
  1. start = 5
  2. word$ = "This is a demo of a flashing cursor for a graphics screen."
  3. LOCATE 5, start: PRINT word$;
  4. StartGraphicX = _FONTWIDTH * (POS(_DEST) - LEN(word$) - 1)
  5. StartGraphicY = _FONTHEIGHT * CSRLIN - (_FONTHEIGHT)
  6. CursorY = _FONTHEIGHT * CSRLIN - (_FONTHEIGHT - 2) 'draw cursor two pixels under text
  7. StartTime = TIMER + .4
  8.  
  9. cur = start + LEN(word$)
  10.  
  11.     b$ = INKEY$
  12.     IF b$ = CHR$(27) THEN
  13.         SYSTEM
  14.     ELSEIF b$ = CHR$(0) + "R" THEN
  15.         insert = 1 - insert
  16.         GOSUB cursim
  17.     ELSEIF b$ = CHR$(0) + "K" THEN
  18.         IF cur > start THEN cur = cur - 1: GOSUB cursim
  19.     ELSEIF b$ = CHR$(0) + "M" THEN
  20.         IF cur < start + LEN(word$) THEN cur = cur + 1: GOSUB cursim
  21.     END IF
  22.     IF TIMER > StartTime THEN
  23.         StartTime = TIMER + .4
  24.         GOSUB cursim
  25.     END IF
  26.  
  27.     _PRINTSTRING (StartGraphicX, StartGraphicY), word$ + " "
  28.     IF blink THEN _PRINTSTRING (CursorX, CursorY), c$
  29.     _LIMIT 20
  30.  
  31. cursim:
  32. CursorX = _FONTWIDTH * (cur - 1)
  33. IF blink THEN c$ = " " ELSE c$ = "_"
  34. blink = 1 - blink
  35.  
Title: Re: Hey graphic gurus, top this!!!
Post by: Pete on August 16, 2021, 03:12:22 pm
Cool! You got the cursor to move under the characters, without the characters swapping out with the cursor (my blinking effect for when the cursor was under a character). That's a performance improvement on top of Mark's optimization improvement.

Oh wait, the insert wasn't completed in your example, so we can't change the cursor to a block by pressing the Insert key....

This part:

    ELSEIF b$ = CHR$(0) + "R" THEN
        insert = 1 - insert
        GOSUB cursim

So if you could add a way to show the cursor as a block instead of an underscore, when the Inert key is press once, that would be amazing, but I wonder if there is a way the block cursor could be made translucent, like it is in a SCREEN 0 app? Again, my approach in the old days was to swap out the letter characters with the block character to make an alternating blinking cursor and letter effect.

Pete
Title: Re: Hey graphic gurus, top this!!!
Post by: bplus on August 16, 2021, 03:35:00 pm
In 32 color mode:
Code: QB64: [Select]
  1. Screen _NewImage(800, 600, 32)
  2. start = 5
  3. word$ = "This is a demo of a flashing cursor for a graphics screen."
  4. Locate 5, start: Print word$;
  5. On Timer(.4) GoSub cursim
  6. cur = start + Len(word$)
  7.     b$ = InKey$
  8.     If b$ = Chr$(27) Then
  9.         System
  10.     ElseIf b$ = Chr$(0) + "R" Then
  11.         insert = 1 - insert
  12.     ElseIf b$ = Chr$(0) + "K" Then
  13.         If cur > start Then cur = cur - 1
  14.     ElseIf b$ = Chr$(0) + "M" Then
  15.         If cur < start + Len(word$) Then cur = cur + 1
  16.     End If
  17.     _Limit 20
  18. cursim:
  19. If insert Then c$ = Chr$(219): Else c$ = "_"
  20. Locate 5, start: Print word$; " ";
  21. blink = 1 - blink
  22. If blink Then
  23.     Color _RGB32(255, 255, 255, 160), 0
  24.     Locate 5, cur: Print c$;
  25.     Color &HFFFFFFFF
  26.  
Title: Re: Hey graphic gurus, top this!!!
Post by: Petr on August 16, 2021, 03:45:39 pm
INSERT key supported now:


Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(640, 240, 32)
  2. start = 5
  3. word$ = "This is a demo of a flashing cursor for a graphics screen."
  4. LOCATE 5, start: PRINT word$;
  5. StartGraphicX = _FONTWIDTH * (POS(_DEST) - LEN(word$) - 1)
  6. StartGraphicY = _FONTHEIGHT * CSRLIN - (_FONTHEIGHT)
  7. CursorY = _FONTHEIGHT * CSRLIN - (_FONTHEIGHT - 2) 'draw cursor two pixels under text
  8. StartTime = TIMER + .4
  9.  
  10. cur = start + LEN(word$)
  11.  
  12.     b$ = INKEY$
  13.     IF b$ = CHR$(27) THEN
  14.         SYSTEM
  15.     ELSEIF b$ = CHR$(0) + "R" THEN
  16.         insert = 1 - insert
  17.         GOSUB cursim
  18.     ELSEIF b$ = CHR$(0) + "K" THEN
  19.         IF cur > start THEN cur = cur - 1: GOSUB cursim
  20.     ELSEIF b$ = CHR$(0) + "M" THEN
  21.         IF cur < start + LEN(word$) THEN cur = cur + 1: GOSUB cursim
  22.     END IF
  23.     IF TIMER > StartTime THEN
  24.         StartTime = TIMER + .4
  25.         GOSUB cursim
  26.     END IF
  27.  
  28.  
  29.     _PRINTSTRING (StartGraphicX, StartGraphicY), word$ + " "
  30.  
  31.  
  32.     COLOR _RGB32(255)
  33.     IF insert THEN c$ = CHR$(219)
  34.     IF insert AND blink THEN COLOR _RGBA32(255, 255, 255, 127): _PRINTSTRING (CursorX, StartGraphicY), c$: _LIMIT 20: _CONTINUE 'character Ű is printed to the same coordinates as word$ characters
  35.     IF insert AND NOT blink THEN COLOR _RGB32(255): _PRINTSTRING (CursorX, StartGraphicY), c$: _LIMIT 20: _CONTINUE
  36.     IF blink THEN _PRINTSTRING (CursorX, CursorY), c$
  37.     _LIMIT 20
  38.  
  39. cursim:
  40. CursorX = _FONTWIDTH * (cur - 1)
  41. IF blink THEN c$ = " " ELSE c$ = "_"
  42. blink = 1 - blink
  43.  
Title: Re: Hey graphic gurus, top this!!!
Post by: Pete on August 16, 2021, 04:27:55 pm
Wow, we're certainly getting somewhere with this. I do know my system is the slowest of the bunch here, and as such, the CLS in Mark's example makes the sentence jump around a bit. Also, the arrow keys are not quite as smooth. The translucent cursor appearance, however, is reMarkable! I wish the QB64 IDE switched to it.

While Petr is twice as much code, the absence of CLS makes it so there is no jittery effects on my slow-ascii system and the arrow keys create a smooth movement, better than my initial SCREEN 12 example. I'm not sure if the cursor could be made to look like the effect mark posted, or not. I tried to fiddle with a marriage between the two, but since graphics isn't my thing, I came up empty.

Now if SCREEN 0 didn't have a native cursor, I'd make a more complex version of this tiny demo:

Code: QB64: [Select]
  1. LOCATE 5, 5
  2. PRINT "This is a flashing block cursor example in SCREEN 0."
  3. LOCATE 5, 24
  4.     COLOR 0, 7: PRINT "b";: LOCATE , POS(0) - 1
  5.     _DELAY .4
  6.     COLOR 7, 0: PRINT "b";: LOCATE , POS(0) - 1
  7.     _DELAY .4

Of course with any build we have to consider printing to the far right edge of the screen (screws with locate) or for a block cursor, especially the one I coded above, what the appearance will be over color or especially already highlighted text.

Pete
Title: Re: Hey graphic gurus, top this!!!
Post by: Richard Frost on August 16, 2021, 11:24:50 pm
For 32 bit screens and a more advanced font:

Code: QB64: [Select]
  1. DEFLNG A-Z
  2. SCREEN _NEWIMAGE(800, 600, 32)
  3. f& = _LOADFONT("liberati.ttf", 16)
  4. x = 100
  5. y = 100
  6. maxchars = 60
  7. _PRINTSTRING (x, y + 99), "Ins, Del, Home, End, arrow keys and Esc active."
  8. z$ = GetField("Mary had a little lamb, some peas, and a salad.", x, y, maxchars)
  9. COLOR Black, White
  10. _PRINTSTRING (x, y + 40), z$
  11.  
  12. FUNCTION GetField$ (t$, x, y, maxchars)
  13.     DIM a, i, p, tx, c$
  14.     t$ = LEFT$(t$ + SPACE$(maxchars), maxchars)
  15.     p = 1
  16.     DO: _LIMIT 20
  17.         tx = x
  18.         LINE (x, y)-(x + _PRINTWIDTH(t$) + 20, y + 16), _RGB32(0), BF
  19.         FOR i = 1 TO maxchars
  20.             c$ = MID$(t$, i, 1)
  21.             COLOR White, _RGB32(0, 0, 0, 0)
  22.             IF i = p THEN
  23.                 sx = x
  24.                 IF TIMER > cc! THEN
  25.                     bit = bit XOR 1
  26.                     cc! = TIMER + .2
  27.                 END IF
  28.                 IF insertmode THEN
  29.                     LINE (tx, y)-(tx + _PRINTWIDTH(c$), y + 16), _RGB32(bit * 200), BF ' insert cursor
  30.                     IF bit THEN COLOR Black, _RGB32(0, 0, 0, 0) '                        black on zip
  31.                 ELSE
  32.                     LINE (tx, y + 16)-STEP(_PRINTWIDTH(c$), 0), _RGB32(bit * 200) '      underline cursor
  33.                 END IF
  34.             END IF
  35.             _PRINTSTRING (tx, y), c$
  36.             tx = tx + _PRINTWIDTH(c$)
  37.         NEXT i
  38.         _DISPLAY '                                                                       text and cursor
  39.         COLOR White, Black '                                                             regular colors
  40.         _PRINTSTRING (x, y), t$ '                                                        text only, preparing for Enter
  41.         i$ = INKEY$
  42.         SELECT CASE LEN(i$)
  43.             CASE IS = 1
  44.                 IF i$ = CHR$(27) THEN SYSTEM '                                           Esc
  45.                 IF i$ = CHR$(13) THEN '                                                  Enter
  46.                     GetField$ = LTRIM$(RTRIM$(t$))
  47.                     _DISPLAY
  48.                     _AUTODISPLAY
  49.                     EXIT FUNCTION
  50.                 END IF
  51.                 IF i$ = CHR$(8) THEN '                                                   backspace
  52.                     p = p - 1 - (p = 1)
  53.                     t$ = LEFT$(t$, p - 1) + RIGHT$(t$, maxchars - p) + " "
  54.                     _CONTINUE
  55.                 END IF
  56.                 IF insertmode THEN
  57.                     t$ = LEFT$(LEFT$(t$, p - 1) + i$ + RIGHT$(t$, LEN(t$) - p + 1) + SPACE$(10), maxchars)
  58.                 ELSE
  59.                     MID$(t$, p, 1) = i$
  60.                 END IF
  61.                 p = p + 1
  62.                 IF p > maxchars THEN p = maxchars: SOUND 4444, 1
  63.             CASE IS = 2
  64.                 a = ASC(RIGHT$(i$, 1))
  65.                 IF a = 71 THEN p = 1 '                                                   Home
  66.                 IF a = 79 THEN p = LEN(RTRIM$(t$)) + 1 '                                 End
  67.                 IF a = 82 THEN insertmode = insertmode XOR 1 '                           Ins
  68.                 IF a = 83 THEN t$ = LEFT$(t$, p - 1) + RIGHT$(t$, maxchars - p) + " " '  Del
  69.                 p = p + (a = 75) - (a = 77) '                                            left or right arrow
  70.                 IF p < 1 THEN p = 1
  71.                 IF p > maxchars THEN p = maxchars
  72.         END SELECT
  73.     LOOP
  74.  
  75.  
Title: Re: Hey graphic gurus, top this!!!
Post by: bplus on August 17, 2021, 10:36:16 am
@Richard Frost

Nice works fine without the font. This looks better than Pete spec'd as long as doesn't give him the jitters. ;-))

I could use this over my graphics Input fix, better cursor.
Title: Re: Hey graphic gurus, top this!!!
Post by: Pete on August 17, 2021, 03:22:46 pm
@Richard Frost : Very nice! I see it's limited to 32-color use. I'm not sure how that would effect all users. It's very smooth and looks exactly like a SCREEN 0 cursor routine.

I think it works with the block cursor like the example I showed where the background and foreground colors get swapped in a time loop. The only problem I see here is a user always needs a blank space at the end of the sentence, or the cursor disappears. You can see that by trying my stripped down version of it, below...

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 32)
  2. x = 100 ' start column
  3. y = 100 ' start row
  4. sentence$ = "This is a demo of a flashing cursor for a graphics screen."
  5. maxchars = LEN(sentence$)
  6. z$ = GetField(sentence$, x, y, maxchars)
  7. COLOR Black, White
  8. _PRINTSTRING (x, y + 40), z$
  9.  
  10. FUNCTION GetField$ (t$, x, y, maxchars)
  11.     t$ = LEFT$(t$ + SPACE$(maxchars), maxchars)
  12.     DO: _LIMIT 20
  13.         tx = x
  14.         LINE (x, y)-(x + _PRINTWIDTH(t$) + 20, y + 16), _RGB32(0), BF
  15.         FOR i = 1 TO maxchars
  16.             c$ = MID$(t$, i, 1)
  17.             COLOR White, _RGB32(0, 0, 0, 0)
  18.             IF i = POS(0) THEN
  19.                 sx = x
  20.                 IF TIMER > cc! THEN
  21.                     bit = bit XOR 1
  22.                     cc! = TIMER + .2
  23.                 END IF
  24.                 IF insertmode THEN
  25.                     LINE (tx, y)-(tx + _PRINTWIDTH(c$), y + 16), _RGB32(bit * 200), BF ' insert cursor
  26.                     IF bit THEN COLOR Black, _RGB32(0, 0, 0, 0) '                        black on zip
  27.                 ELSE
  28.                     LINE (tx, y + 16)-STEP(_PRINTWIDTH(c$), 0), _RGB32(bit * 200) '      underline cursor
  29.                 END IF
  30.             END IF
  31.             _PRINTSTRING (tx, y), c$
  32.             tx = tx + _PRINTWIDTH(c$)
  33.         NEXT i
  34.         _DISPLAY ' text and cursor
  35.         COLOR White, Black ' default colors
  36.         _PRINTSTRING (x, y), t$
  37.         i$ = INKEY$
  38.         SELECT CASE LEN(i$)
  39.             CASE IS = 1
  40.                 IF i$ = CHR$(27) THEN SYSTEM
  41.                 IF insertmode THEN
  42.                     t$ = LEFT$(LEFT$(t$, POS(0) - 1) + i$ + RIGHT$(t$, LEN(t$) - POS(0) + 1), maxchars)
  43.                 ELSE
  44.                     MID$(t$, POS(0), 1) = i$
  45.                 END IF
  46.             CASE IS = 2
  47.                 IF RIGHT$(i$, 1) = "M" THEN LOCATE , POS(0) + 1 ' No limiter added yet!
  48.                 IF RIGHT$(i$, 1) = "K" THEN if pos(0)> 1 then LOCATE , POS(0) - 1
  49.                 IF ASC(RIGHT$(i$, 1)) = 82 THEN insertmode = insertmode XOR 1 ' Ins
  50.         END SELECT
  51.     LOOP
  52.  


Notes:

I did not make a way to stop the left and right cursor movement.

I replaced the "p" variable with pos(0). It works, but it would need a limitation using maxchars if a way to get the cursor showing after the last character of the sentence is figured out.


Pete