//------------------------------------------------------------------------------------ // прорисовка фонта //------------------------------------------------------------------------------------ void vw_DrawFont(int X, int Y, float FlattenWidth, float MaxWidth, float FontScale, float R, float G, float B, float Transp, const char *Text, ...) { if (Text == 0) return; // учитываем аспект рейшен float AW; float AH; bool ASpresent=false; ASpresent = vw_GetAspectWH(&AW, &AH); // получаем данные текущего вьюпорта int W, H; vw_GetViewport(0, 0, &W, &H); float AHw = H*1.0f; // если текст ниже чем ширина нашего окна - не рисуем if (ASpresent){ if (Y > AH) return;} else {if (Y > H) return;} // если текст выше чем ноль - тоже рисовать его смысла нет if (Y+InternalFontSize*FontScale < 0) return; // FlattenWidth - выравнивать по ширине // если FlattenWidth отрицателен, выравниваем по значению, "сжимая" буквы, если нужно // MaxWidth - рисовать до ширины // смотрим значения параметров в строке char text[1024]; va_list ap; va_start(ap, Text); vsprintf(text, Text, ap); va_end(ap); // в text уже полная строка if (strlen(text) == 0) return; float Xstart = X; // сразу определяем "базовую" ширину пробела, чтобы учитывать в расчетах if (vw_FindFontCharByUTF32(0x020) == 0) vw_LoadFontChar(0x020); float SpaceWidth = vw_FindFontCharByUTF32(0x020)->AdvanceX*FontScale; // чтобы было более читаемо - делаем пробел не менее 2/3 ширины if (SpaceWidth < (InternalFontSize * 0.65f)) SpaceWidth = InternalFontSize * 0.65f; // коэф. изменения букв по ширине float FontWidthScale = 1.0f; if (Transp >= 1.0f) Transp = 1.0f; // если нужно выравнивать, считаем данные пробелов if (FlattenWidth > 0) { float LineWidth = 0; int SpaceCount = 0; const char *CountCheck = text; while (strlen(CountCheck) > 0) { unsigned UTF32; // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке CountCheck = utf8_to_utf32(CountCheck, &UTF32); // находим наш текущий символ eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32); if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32); // считаем кол-во пробелов if (UTF32 == 0x020) SpaceCount++; else LineWidth += DrawChar->AdvanceX; } if (FlattenWidth > LineWidth) if (SpaceCount!=0) SpaceWidth = (FlattenWidth - LineWidth)/SpaceCount; } // если нужно сжать, считаем коэф. сжатия букв if (FlattenWidth < 0) { float LineWidth = 0; const char *CountCheck = text; while (strlen(CountCheck) > 0) { unsigned UTF32; // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке CountCheck = utf8_to_utf32(CountCheck, &UTF32); // находим наш текущий символ eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32); if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32); // считаем длину символов с пробелами if (UTF32 != 0x020) LineWidth += DrawChar->AdvanceX; else LineWidth += SpaceWidth; } if (FlattenWidth*(-1.0f) < LineWidth) FontWidthScale = FlattenWidth/LineWidth*(-1.0f); } float LineWidth = 0; // установка свойств текстуры vw_SetTextureBlend(true, RI_BLEND_SRCALPHA, RI_BLEND_INVSRCALPHA); // ставим цвет vw_SetColor(R, G, B, Transp); // для отрисовки eTexture* CurrentTexture = 0; int k=0; // буфер для последовательности RI_QUADS // войдет RI_2f_XYZ | RI_2f_TEX #ifdef USE_GLES float tmp[(2+2)*6*strlen(text)]; #else float tmp[(2+2)*4*strlen(text)]; #endif // чтобы меньше делать операций умножения, включаем коэф. один в другой сразу для ширины символов FontWidthScale = FontScale*FontWidthScale; // прорисовка текста const char *textdraw = text; // прорисовываем все символы while (strlen(textdraw) > 0) { unsigned UTF32; // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке textdraw = utf8_to_utf32(textdraw, &UTF32); // находим наш текущий символ eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32); if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32); // первый символ - запоминаем его текстуру if (CurrentTexture == 0) CurrentTexture = DrawChar->CharTexture; // проверка на текстуру, если текстура поменялась - отрисовываем все что есть в буфере, если там что-то есть if (CurrentTexture != DrawChar->CharTexture) { // если что-то было в буфере - выводим if (k > 0) { // Установка текстуры vw_SetTexture(0, CurrentTexture); // отрисовываем все что есть в буфере #ifdef USE_GLES vw_SendVertices(RI_QUADS, 6*(k/24), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float)); #else vw_SendVertices(RI_QUADS, 4*(k/16), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float)); #endif } // запоминаем новую текстуру CurrentTexture = DrawChar->CharTexture; // сбрасываем счетчики k=0; } // если не пробел - рисуем if (UTF32 != 0x020) { float DrawX = Xstart + DrawChar->Left*FontWidthScale; float DrawY = Y + GlobalFontOffsetY + (InternalFontSize - DrawChar->Top)*FontScale; // Вычисление поправки по У в зависимости от DrawCorner // - расположения угла начала координат float tmpPosY = 0; // изменяем только в случае RI_UL_CORNER if (ASpresent) tmpPosY = (AH - DrawY - DrawY - DrawChar->Height*FontScale); else tmpPosY = (AHw - DrawY - DrawY - DrawChar->Height*FontScale); float ImageHeight = DrawChar->CharTexture->Height*1.0f; float ImageWidth = DrawChar->CharTexture->Width*1.0f; float FrameHeight = (DrawChar->TexturePositionBottom*1.0f )/ImageHeight; float FrameWidth = (DrawChar->TexturePositionRight*1.0f )/ImageWidth; float Yst = (DrawChar->TexturePositionTop*1.0f)/ImageHeight; float Xst = (DrawChar->TexturePositionLeft*1.0f)/ImageWidth; #ifdef USE_GLES tmp[k++] = DrawX; tmp[k++] = DrawY +tmpPosY + DrawChar->Height*FontScale; tmp[k++] = Xst; tmp[k++] = 1.0f-Yst; tmp[k++] = DrawX; tmp[k++] = DrawY +tmpPosY + DrawChar->Height*FontScale; tmp[k++] = Xst; tmp[k++] = 1.0f-Yst; tmp[k++] = DrawX; tmp[k++] = DrawY +tmpPosY; tmp[k++] = Xst; tmp[k++] = 1.0f-FrameHeight; tmp[k++] = DrawX + DrawChar->Width*FontWidthScale; tmp[k++] = DrawY +tmpPosY + DrawChar->Height*FontScale; tmp[k++] = FrameWidth; tmp[k++] = 1.0f-Yst; tmp[k++] = DrawX + DrawChar->Width*FontWidthScale; tmp[k++] = DrawY +tmpPosY; tmp[k++] = FrameWidth; tmp[k++] = 1.0f-FrameHeight; tmp[k++] = DrawX + DrawChar->Width*FontWidthScale; tmp[k++] = DrawY +tmpPosY; tmp[k++] = FrameWidth; tmp[k++] = 1.0f-FrameHeight; #else tmp[k++] = DrawX; tmp[k++] = DrawY +tmpPosY + DrawChar->Height*FontScale; tmp[k++] = Xst; tmp[k++] = 1.0f-Yst; tmp[k++] = DrawX; tmp[k++] = DrawY +tmpPosY; tmp[k++] = Xst; tmp[k++] = 1.0f-FrameHeight; tmp[k++] = DrawX + DrawChar->Width*FontWidthScale; tmp[k++] = DrawY +tmpPosY; tmp[k++] = FrameWidth; tmp[k++] = 1.0f-FrameHeight; tmp[k++] = DrawX + DrawChar->Width*FontWidthScale; tmp[k++] = DrawY +tmpPosY + DrawChar->Height*FontScale; tmp[k++] = FrameWidth; tmp[k++] = 1.0f-Yst; #endif Xstart += DrawChar->AdvanceX*FontWidthScale; LineWidth += DrawChar->AdvanceX*FontWidthScale; } else { Xstart += SpaceWidth*FontWidthScale; LineWidth += SpaceWidth*FontWidthScale; } // если нужно прорисовывать с ограничением по длине if (MaxWidth != 0.0f) if (LineWidth >= MaxWidth) break; } // если что-то было в буфере - выводим if (k > 0) { // Установка текстуры vw_SetTexture(0, CurrentTexture); // отрисовываем все что есть в буфере #ifdef USE_GLES vw_SendVertices(RI_QUADS, 6*(k/24), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float)); #else vw_SendVertices(RI_QUADS, 4*(k/16), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float)); #endif } vw_SetColor(1.0f, 1.0f, 1.0f, 1.0f); vw_SetTextureBlend(false, 0, 0); vw_BindTexture(0, 0); }
//------------------------------------------------------------------------------------ // инициализация меню //------------------------------------------------------------------------------------ void InitMenu() { CreateCursor(); // установка курсора на центр // получаем размер клиентской области int W, H; vw_GetViewport(0, 0, &W, &H); float AWw = W*1.0f; float AHw = H*1.0f; float ARWidth; float ARHeight; vw_GetAspectWH(&ARWidth, &ARHeight); // установка мышки, чтобы не учитывать перемещения в меню #ifndef USE_GLES SDL_WarpMouse((int)((512.0f+256.0f)/(ARWidth/AWw)), (int)(384.0f/(ARHeight/AHw))); #endif Button1Transp = 1.0f; LastButton1UpdateTime = 0.0f; Button2Transp = 1.0f; LastButton2UpdateTime = 0.0f; Button3Transp = 1.0f; LastButton3UpdateTime = 0.0f; Button4Transp = 1.0f; LastButton4UpdateTime = 0.0f; Button5Transp = 1.0f; LastButton5UpdateTime = 0.0f; Button6Transp = 1.0f; LastButton6UpdateTime = 0.0f; Button7Transp = 1.0f; LastButton7UpdateTime = 0.0f; Button8Transp = 1.0f; LastButton8UpdateTime = 0.0f; Button9Transp = 1.0f; LastButton9UpdateTime = 0.0f; Button10Transp = 1.0f; LastButton10UpdateTime = 0.0f; Button11Transp = 1.0f; LastButton11UpdateTime = 0.0f; Button12Transp = 1.0f; LastButton12UpdateTime = 0.0f; Button13Transp = 1.0f; LastButton13UpdateTime = 0.0f; Button14Transp = 1.0f; LastButton14UpdateTime = 0.0f; LastMenuUpdateTime = 0.0f; MenuContentTransp = 0.0f; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // иним камеру, всегда до работы со скриптом (!!!) //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vw_ResizeScene(45.0f, Setup.fAspectRatioWidth/Setup.fAspectRatioHeight, 1.0f, 2000.0f); InitGameCamera(); vw_SetCameraLocation(VECTOR3D(-50,30,-50)); vw_SetCameraMoveAroundPoint(VECTOR3D(0,0,0), 0.0f, VECTOR3D(0.0f, 0.0f, 0.0f)); if (Script != 0){delete Script; Script = 0;} Script = new ScriptEngine; if (Setup.MenuScript > 2) Setup.MenuScript = 0; switch (Setup.MenuScript) { case 0: Script->RunScript("DATA/SCRIPT/menu1.xml", vw_GetTime()); break; case 1: Script->RunScript("DATA/SCRIPT/menu2.xml", vw_GetTime()); break; case 2: Script->RunScript("DATA/SCRIPT/menu3.xml", vw_GetTime()); break; // на всякий случай default: Script->RunScript("DATA/SCRIPT/menu1.xml", vw_GetTime()); break; } Setup.MenuScript ++; // немного прокручиваем скрипт float Time1 = vw_GetTime(); Script->StartTime = Time1-30; Script->TimeLastOp = Time1-30; for (float i=Time1-30; i<Time1;i+=1.0f) { UpdateAllObject3D(i); Script->Update(i); } Script->StartTime = Time1; Script->TimeLastOp = Time1; // активные частицы космоса psSpace = 0; if (psSpace==0) psSpace = new eParticleSystem; psSpace->ColorStart.r = 0.80f; psSpace->ColorStart.g = 0.80f; psSpace->ColorStart.b = 1.00f; psSpace->ColorEnd.r = 0.70f; psSpace->ColorEnd.g = 0.70f; psSpace->ColorEnd.b = 1.00f; psSpace->AlphaStart = 1.00f; psSpace->AlphaEnd = 0.00f; psSpace->SizeStart = 0.10f; psSpace->SizeVar = 0.05f; psSpace->SizeEnd = 0.30f; psSpace->Speed = 4.00f; psSpace->SpeedVar = 8.00f; psSpace->Theta = 0.00f; psSpace->Life = 10.00f; psSpace->LifeVar = 0.00f; psSpace->CreationType = 1; psSpace->CreationSize = VECTOR3D(2.0f,50.0f,30.0f); psSpace->ParticlesPerSec = 140; psSpace->Texture[0] = vw_FindTextureByName("DATA/GFX/flare3.tga"); psSpace->Direction = VECTOR3D(1.0f, 0.0f, 0.0f); psSpace->Resize = 0.1f; psSpace->SetStartLocation(VECTOR3D(-50,10,-20)); // немного "прокручиваем", чтобы сразу по появлению было заполнено float Time = psSpace->TimeLastUpdate; for (float i=Time; i<Time+20;i+=1.0f) { psSpace->Update(i); } psSpace->TimeLastUpdate = Time; LastMenuUpdateTime = vw_GetTime(); NeedShowMenu = true; NeedHideMenu = false; LastMenuOnOffUpdateTime = vw_GetTime(); MenuBlackTransp = 1.0f; NeedOnMenu = true; // подстраховка, если не укажем меню, перейдем в основное GameStatus = MAIN_MENU; DrawGameCursor = true; StarsTileUpdateTime = vw_GetTime(); StarsTileUpdateTime2 = vw_GetTime(); }