hedgewars/uChat.pas
changeset 15665 63e2b7b2ec47
parent 15592 46b7b2c821d0
parent 15664 0b99e220568a
child 15669 783959a6810b
equal deleted inserted replaced
15662:41121e2f5c03 15665:63e2b7b2ec47
    33 procedure SendHogSpeech(s: shortstring);
    33 procedure SendHogSpeech(s: shortstring);
    34 procedure CopyToClipboard(var newContent: shortstring);
    34 procedure CopyToClipboard(var newContent: shortstring);
    35 procedure TextInput(var event: TSDL_TextInputEvent);
    35 procedure TextInput(var event: TSDL_TextInputEvent);
    36 
    36 
    37 implementation
    37 implementation
    38 uses uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO, uScript, uRenderUtils, uLocale
    38 uses uConsts, uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO, uScript, uRenderUtils, uStore, uLocale
    39      {$IFDEF USE_VIDEO_RECORDING}, uVideoRec{$ENDIF};
    39      {$IFDEF USE_VIDEO_RECORDING}, uVideoRec{$ENDIF};
    40 
    40 
    41 const MaxStrIndex = 27;
    41 const MaxStrIndex = 27;
    42       MaxInputStrLen = 200;
    42       MaxInputStrLen = 200;
    43 
    43 
    92             (ChatCmd: '/history'; ProcedureCallChatCmd: 'history'),
    92             (ChatCmd: '/history'; ProcedureCallChatCmd: 'history'),
    93             (ChatCmd: '/fullscreen'; ProcedureCallChatCmd: 'fullscr')
    93             (ChatCmd: '/fullscreen'; ProcedureCallChatCmd: 'fullscr')
    94             );
    94             );
    95 
    95 
    96 
    96 
    97 const Padding  = 2;
    97 const PaddingFactor = 0.125; // relative to font size in pixels
    98       ClHeight = 2 * Padding + 16; // font height
    98 
       
    99 var Padding, ClHeight: integer;
       
   100     LastChatScaleValue, LastUIScaleValue: real;
       
   101     SkipNextInput: boolean;
       
   102 
       
   103 procedure UpdateInputLinePrefix(); forward;
       
   104 procedure UpdateCursorCoords(); forward;
    99 
   105 
   100 // relevant for UTF-8 handling
   106 // relevant for UTF-8 handling
   101 function IsFirstCharByte(c: char): boolean; inline;
   107 function IsFirstCharByte(c: char): boolean; inline;
   102 begin
   108 begin
   103     // based on https://en.wikipedia.org/wiki/UTF-8#Description
   109     // based on https://en.wikipedia.org/wiki/UTF-8#Description
   110 end;
   116 end;
   111 
   117 
   112 procedure ResetSelection();
   118 procedure ResetSelection();
   113 begin
   119 begin
   114     selectedPos:= -1;
   120     selectedPos:= -1;
       
   121 end;
       
   122 
       
   123 procedure AdjustToUIScale();
       
   124 var fntSize, fntSizePx: integer;
       
   125 begin
       
   126     // don't do anything if no change
       
   127     if (ChatScaleValue = LastChatScaleValue) and (UIScaleValue = LastUIScaleValue) then
       
   128         exit;
       
   129 
       
   130     LastChatScaleValue:= ChatScaleValue;
       
   131     LastUIScaleValue:= UIScaleValue;
       
   132 
       
   133     fntSize:= max(1, round(UIScaleValue * ChatScaleValue * cBaseChatFontHeight));
       
   134 
       
   135     if Fontz[fntChat].Height <> fntSize then
       
   136         begin
       
   137         // adjust associated heights
       
   138         Fontz[fntChat].Height:= fntSize;
       
   139         Fontz[CJKfntChat].Height:= fntSize;
       
   140         // reload if initialized already
       
   141         if Fontz[fntChat].Handle <> nil then
       
   142             LoadFont(fntChat);
       
   143         if Fontz[CJKfntChat].Handle <> nil then
       
   144             LoadFont(CJKfntChat);
       
   145         end;
       
   146 
       
   147     // adjust line height etc.
       
   148     fntSizePx:= round(cFontPxToPtRatio * fntSize);
       
   149     Padding:= max(1, round(PaddingFactor * fntSizePx));
       
   150 
       
   151     ClHeight:= 2 * Padding + fntSizePx;
       
   152 
       
   153     // clear cache of already rendered lines
       
   154     ReloadLines();
       
   155     UpdateInputLinePrefix();
       
   156     UpdateCursorCoords();
       
   157 end;
       
   158 
       
   159 procedure ChatSizeInc(pxprecise: boolean);
       
   160 var fntSize: integer;
       
   161 begin
       
   162 if pxprecise then
       
   163     begin
       
   164     fntSize:= Fontz[fntChat].Height;
       
   165     inc(fntSize);
       
   166     ChatScaleValue:= 1.0 * fntSize / cBaseChatFontHeight;
       
   167     end
       
   168 else
       
   169     ChatScaleValue:= ChatScaleValue * (1.0 + cChatScaleRelDelta);
       
   170 if ChatScaleValue > cMaxChatScaleValue then
       
   171     ChatScaleValue:= cMaxChatScaleValue;
       
   172 AdjustToUIScale();
       
   173 end;
       
   174 
       
   175 procedure ChatSizeDec(pxprecise: boolean);
       
   176 var fntSize: integer;
       
   177 begin
       
   178 if pxprecise then
       
   179     begin
       
   180     fntSize:= Fontz[fntChat].Height;
       
   181     dec(fntSize);
       
   182     ChatScaleValue:= 1.0 * fntSize / cBaseChatFontHeight;
       
   183     end
       
   184 else
       
   185     ChatScaleValue:= ChatScaleValue / (1.0 + cChatScaleRelDelta);
       
   186 if ChatScaleValue < cMinChatScaleValue then
       
   187     ChatScaleValue:= cMinChatScaleValue;
       
   188 AdjustToUIScale();
       
   189 end;
       
   190 
       
   191 procedure chatSizeReset();
       
   192 begin
       
   193 ChatScaleValue:= cDefaultChatScale;
       
   194 AdjustToUIScale();
       
   195 end;
       
   196 
       
   197 function GetChatFont(str: shortstring): THWFONT;
       
   198 begin
       
   199     GetChatFont:= CheckCJKFont(ansistring(str), fntChat);
   115 end;
   200 end;
   116 
   201 
   117 procedure UpdateCursorCoords();
   202 procedure UpdateCursorCoords();
   118 var font: THWFont;
   203 var font: THWFont;
   119     str : shortstring;
   204     str : shortstring;
   120     coff, soff: LongInt;
   205     coff, soff: LongInt;
   121 begin
   206 begin
       
   207     AdjustToUIScale();
       
   208 
   122     if cursorPos = selectedPos then
   209     if cursorPos = selectedPos then
   123         ResetSelection();
   210         ResetSelection();
   124 
   211 
   125     // calculate cursor offset
   212     // calculate cursor offset
   126 
   213 
   127     str:= InputStr.s;
   214     str:= InputStr.s;
   128     font:= CheckCJKFont(ansistring(str), fnt16);
   215     font:= GetChatFont(str);
   129 
   216 
   130     // get only substring before cursor to determine length
   217     // get only substring before cursor to determine length
   131     // SetLength(str, cursorPos); // makes pas2c unhappy
   218     // SetLength(str, cursorPos); // makes pas2c unhappy
   132     str[0]:= char(cursorPos);
   219     str[0]:= char(cursorPos);
   133     // get render size of text
   220     // get render size of text
   134     TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @coff, nil);
   221     TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @coff, nil);
   135 
   222     cursorX:= Padding + coff;
   136     cursorX:= 2 + coff;
       
   137 
   223 
   138     // calculate selection width on screen
   224     // calculate selection width on screen
   139     if selectedPos >= 0 then
   225     if selectedPos >= 0 then
   140         begin
   226         begin
   141         if selectedPos > cursorPos then
   227         if selectedPos > cursorPos then
   169     shadowint  = $80 shl AShift;
   255     shadowint  = $80 shl AShift;
   170 begin
   256 begin
   171 
   257 
   172 FreeAndNilTexture(cl.Tex);
   258 FreeAndNilTexture(cl.Tex);
   173 
   259 
   174 font:= CheckCJKFont(ansistring(str), fnt16);
   260 font:= GetChatFont(str);
   175 
   261 
   176 // get render size of text
   262 // get render size of text
   177 TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @cl.Width, nil);
   263 TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @cl.Width, nil);
   178 
   264 
   179 // calculate and save size
   265 // calculate and save size
   243 
   329 
   244 // For uStore texture recreation
   330 // For uStore texture recreation
   245 procedure ReloadLines;
   331 procedure ReloadLines;
   246 var i: LongWord;
   332 var i: LongWord;
   247 begin
   333 begin
   248     if InputStr.s <> '' then
   334     // also reload empty input line (as chat size/scaling might have changed)
   249         SetLine(InputStr, InputStr.s, true);
   335     //if InputStr.s <> '' then
       
   336     SetLine(InputStr, InputStr.s, true);
   250     for i:= 0 to MaxStrIndex do
   337     for i:= 0 to MaxStrIndex do
   251         if Strs[i].s <> '' then
   338         if Strs[i].s <> '' then
   252             begin
   339             begin
   253             RenderChatLineTex(Strs[i], Strs[i].s);
   340             RenderChatLineTex(Strs[i], Strs[i].s);
   254             end;
   341             end;
   292 procedure DrawChat;
   379 procedure DrawChat;
   293 var i, t, left, top, cnt: LongInt;
   380 var i, t, left, top, cnt: LongInt;
   294     selRect: TSDL_Rect;
   381     selRect: TSDL_Rect;
   295     c: char;
   382     c: char;
   296 begin
   383 begin
       
   384 AdjustToUIScale();
       
   385 
   297 ChatReady:= true; // maybe move to somewhere else?
   386 ChatReady:= true; // maybe move to somewhere else?
   298 
   387 
   299 if ChatHidden and (not showAll) then
   388 if ChatHidden and (not showAll) then
   300     visibleCount:= 0;
   389     visibleCount:= 0;
   301 
   390 
   327 
   416 
   328     if selectedPos < 0 then
   417     if selectedPos < 0 then
   329         begin
   418         begin
   330         // draw cursor
   419         // draw cursor
   331         if ((RealTicks - LastKeyPressTick) and 512) < 256 then
   420         if ((RealTicks - LastKeyPressTick) and 512) < 256 then
   332             DrawLineOnScreen(left + cursorX, top + 2, left + cursorX, top + ClHeight - 2, 2.0, $00, $FF, $FF, $FF);
   421             DrawLineOnScreen(left + cursorX, top + Padding, left + cursorX, top + ClHeight - Padding, max(2, round(UIScaleValue * ChatScaleValue * 2.0)), $00, $FF, $FF, $FF);
   333         end
   422         end
   334     else // draw selection
   423     else // draw selection
   335         begin
   424         begin
   336         selRect.y:= top + 2;
   425         selRect.y:= top + Padding;
   337         selRect.h:= clHeight - 4;
   426         selRect.h:= clHeight - 2 * Padding;
   338         if selectionDx < 0 then
   427         if selectionDx < 0 then
   339             begin
   428             begin
   340             selRect.x:= left + cursorX + selectionDx;
   429             selRect.x:= left + cursorX + selectionDx;
   341             selRect.w:= -selectionDx;
   430             selRect.w:= -selectionDx;
   342             end
   431             end
  1066         SDL_SCANCODE_PAGEUP, SDL_SCANCODE_PAGEDOWN:
  1155         SDL_SCANCODE_PAGEUP, SDL_SCANCODE_PAGEDOWN:
  1067             begin
  1156             begin
  1068             // ignore me!!!
  1157             // ignore me!!!
  1069             end;
  1158             end;
  1070         // TODO: figure out how to determine those keys better
  1159         // TODO: figure out how to determine those keys better
  1071         SDL_SCANCODE_a:
  1160         SDL_SCANCODE_b:
  1072             begin
  1161             begin
  1073             // select all
  1162             // select all
  1074             if ctrlonly then
  1163             if ctrlonly then
  1075                 begin
  1164                 begin
  1076                 ResetSelection();
  1165                 ResetSelection();
  1102                 begin
  1191                 begin
  1103                 CopySelectionToClipboard();
  1192                 CopySelectionToClipboard();
  1104                 DeleteSelected();
  1193                 DeleteSelected();
  1105                 end
  1194                 end
  1106             end;
  1195             end;
       
  1196             // make chat bigger
       
  1197         SDL_SCANCODE_KP_PLUS, SDL_SCANCODE_EQUALS:
       
  1198             begin
       
  1199             if ctrl then
       
  1200                 begin
       
  1201                 ChatSizeInc(selMode);
       
  1202                 SkipNextInput:= true;
       
  1203                 end;
       
  1204             end;
       
  1205             // make chat smaller
       
  1206         SDL_SCANCODE_KP_MINUS, SDL_SCANCODE_MINUS:
       
  1207             begin
       
  1208             if ctrl then
       
  1209                 begin
       
  1210                 ChatSizeDec(selMode);
       
  1211                 SkipNextInput:= true;
       
  1212                 end;
       
  1213             end;
       
  1214             // revert chat size to default
       
  1215         SDL_SCANCODE_KP_0, SDL_SCANCODE_0:
       
  1216             begin
       
  1217             if ctrl then
       
  1218                 begin
       
  1219                 ChatSizeReset();
       
  1220                 SkipNextInput:= true;
       
  1221                 end;
       
  1222             end;
  1107         end;
  1223         end;
  1108 end;
  1224 end;
  1109 
  1225 
  1110 procedure TextInput(var event: TSDL_TextInputEvent);
  1226 procedure TextInput(var event: TSDL_TextInputEvent);
  1111 var s: shortstring;
  1227 var s: shortstring;
  1112     l: byte;
  1228     l: byte;
  1113     isl: integer;
  1229     isl: integer;
  1114 begin
  1230 begin
       
  1231     if SkipNextInput then
       
  1232         begin
       
  1233         SkipNextInput:= false;
       
  1234         exit;
       
  1235         end;
       
  1236 
  1115     DeleteSelected();
  1237     DeleteSelected();
  1116 
  1238 
       
  1239     s:= '';
  1117     l:= 0;
  1240     l:= 0;
  1118     // fetch all bytes of character/input
  1241     // fetch all bytes of character/input
  1119     while event.text[l] <> #0 do
  1242     while event.text[l] <> #0 do
  1120         begin
  1243         begin
  1121         s[l + 1]:= event.text[l];
  1244         if Length(s) < 255 then
  1122         inc(l)
  1245             begin
  1123         end;
  1246             s[l + 1]:= event.text[l];
  1124 
  1247             inc(l)
       
  1248             end
       
  1249         end;
  1125     if l > 0 then
  1250     if l > 0 then
  1126         begin
  1251         begin
  1127         isl:= Length(InputStr.s);
  1252         isl:= Length(InputStr.s);
  1128         // check if user is typing a redundant closing hog-speech quotation mark
  1253         // check if user is typing a redundant closing hog-speech quotation mark
  1129         if (l = 1) and (isl >= 2) and (cursorPos = isl - 1) and charIsForHogSpeech(s[1])
  1254         if (l = 1) and (isl >= 2) and (cursorPos = isl - 1) and charIsForHogSpeech(s[1])
  1235     missedCount:= 0;
  1360     missedCount:= 0;
  1236     liveLua:= false;
  1361     liveLua:= false;
  1237     ChatHidden:= false;
  1362     ChatHidden:= false;
  1238     firstDraw:= true;
  1363     firstDraw:= true;
  1239 
  1364 
       
  1365     LastChatScaleValue:= 0;
       
  1366     LastUIScaleValue:= 0;
       
  1367     SkipNextInput:= false;
       
  1368 
  1240     InputLinePrefix.Tex:= nil;
  1369     InputLinePrefix.Tex:= nil;
  1241     UpdateInputLinePrefix();
  1370     UpdateInputLinePrefix();
  1242     inputStr.s:= '';
  1371     inputStr.s:= '';
  1243     inputStr.Tex := nil;
  1372     inputStr.Tex := nil;
  1244     for i:= 0 to MaxStrIndex do
  1373     for i:= 0 to MaxStrIndex do