// // R_InitColormaps // void R_InitColormaps (void) { // [RH] Try and convert BOOM colormaps into blending values. // This is a really rough hack, but it's better than // not doing anything with them at all (right?) int lastfakecmap = W_CheckNumForName ("C_END"); firstfakecmap = W_CheckNumForName ("C_START"); if (firstfakecmap == -1 || lastfakecmap == -1) numfakecmaps = 1; else { if(firstfakecmap > lastfakecmap) I_Error("no fake cmaps"); numfakecmaps = lastfakecmap - firstfakecmap; } realcolormaps = (byte *)Z_Malloc (256*(NUMCOLORMAPS+1)*numfakecmaps+255,PU_STATIC,0); realcolormaps = (byte *)(((ptrdiff_t)realcolormaps + 255) & ~255); fakecmaps = (FakeCmap *)Z_Malloc (sizeof(*fakecmaps) * numfakecmaps, PU_STATIC, 0); fakecmaps[0].name[0] = 0; R_SetDefaultColormap ("COLORMAP"); if (numfakecmaps > 1) { int i; size_t j; palette_t *pal = GetDefaultPalette (); for (i = ++firstfakecmap, j = 1; j < numfakecmaps; i++, j++) { if (W_LumpLength (i) >= (NUMCOLORMAPS+1)*256) { int k, r, g, b; byte *map = (byte *)W_CacheLumpNum (i, PU_CACHE); memcpy (realcolormaps+(NUMCOLORMAPS+1)*256*j, map, (NUMCOLORMAPS+1)*256); if(pal->basecolors) { r = RPART(pal->basecolors[*map]); g = GPART(pal->basecolors[*map]); b = BPART(pal->basecolors[*map]); W_GetLumpName (fakecmaps[j].name, i); for (k = 1; k < 256; k++) { r = (r + RPART(pal->basecolors[map[k]])) >> 1; g = (g + GPART(pal->basecolors[map[k]])) >> 1; b = (b + BPART(pal->basecolors[map[k]])) >> 1; } fakecmaps[j].blend = MAKEARGB (255, r, g, b); } }
static int compare (const void *arg1, const void *arg2) { if (RPART(GPalette.BaseColors[*((uint8_t *)arg1)]) * 299 + GPART(GPalette.BaseColors[*((uint8_t *)arg1)]) * 587 + BPART(GPalette.BaseColors[*((uint8_t *)arg1)]) * 114 < RPART(GPalette.BaseColors[*((uint8_t *)arg2)]) * 299 + GPART(GPalette.BaseColors[*((uint8_t *)arg2)]) * 587 + BPART(GPalette.BaseColors[*((uint8_t *)arg2)]) * 114) return -1; else return 1; }
static int STACK_ARGS compare (const void *arg1, const void *arg2) { if (RPART(GPalette.BaseColors[*((BYTE *)arg1)]) * 299 + GPART(GPalette.BaseColors[*((BYTE *)arg1)]) * 587 + BPART(GPalette.BaseColors[*((BYTE *)arg1)]) * 114 < RPART(GPalette.BaseColors[*((BYTE *)arg2)]) * 299 + GPART(GPalette.BaseColors[*((BYTE *)arg2)]) * 587 + BPART(GPalette.BaseColors[*((BYTE *)arg2)]) * 114) return -1; else return 1; }
// Draw a list of player colors on a team. Lines up with player names. void EATeamPlayerColors(int x, int y, const unsigned short w, const unsigned short h, const float scale, const x_align_t x_align, const y_align_t y_align, const x_align_t x_origin, const y_align_t y_origin, const short padding, const short limit, const byte team) { byte drawn = 0; for (size_t i = 0;i < sortedPlayers().size();i++) { // Make sure we're not overrunning our limit. if (limit != 0 && drawn >= limit) { break; } player_t* player = sortedPlayers()[i]; if (inTeamPlayer(player, team)) { int playercolor = CL_GetPlayerColor(player); int color = BestColor(GetDefaultPalette()->basecolors, RPART(playercolor), GPART(playercolor), BPART(playercolor), GetDefaultPalette()->numcolors); hud::Clear(x, y, w, h, scale, x_align, y_align, x_origin, y_origin, color); y += h + padding; drawn += 1; } } }
DColorPickerMenu(DMenu *parent, const char *name, FOptionMenuDescriptor *desc, FColorCVar *cvar) { mStartItem = desc->mItems.Size(); mRed = (float)RPART(DWORD(*cvar)); mGreen = (float)GPART(DWORD(*cvar)); mBlue = (float)BPART(DWORD(*cvar)); mGridPosX = 0; mGridPosY = 0; mCVar = cvar; // This menu uses some featurs that are hard to implement in an external control lump // so it creates its own list of menu items. desc->mItems.Resize(mStartItem+8); desc->mItems[mStartItem+0] = new FOptionMenuItemStaticText(name, false); desc->mItems[mStartItem+1] = new FOptionMenuItemStaticText(" ", false); desc->mItems[mStartItem+2] = new FOptionMenuSliderVar("Red", &mRed, 0, 255, 15, 0); desc->mItems[mStartItem+3] = new FOptionMenuSliderVar("Green", &mGreen, 0, 255, 15, 0); desc->mItems[mStartItem+4] = new FOptionMenuSliderVar("Blue", &mBlue, 0, 255, 15, 0); desc->mItems[mStartItem+5] = new FOptionMenuItemStaticText(" ", false); desc->mItems[mStartItem+6] = new FOptionMenuItemCommand("Undo changes", "undocolorpic"); desc->mItems[mStartItem+7] = new FOptionMenuItemStaticText(" ", false); desc->mSelectedItem = mStartItem + 2; Init(parent, desc); desc->mIndent = 0; desc->CalcIndent(); }
void P_DrawSplash2 (FLevelLocals *Level, int count, const DVector3 &pos, DAngle angle, int updown, int kind) { int color1, color2, zadd; double zvel, zspread; switch (kind) { case 0: // Blood color1 = blood1; color2 = blood2; break; case 1: // Gunshot color1 = grey3; color2 = grey5; break; case 2: // Smoke color1 = grey3; color2 = grey1; break; default: // colorized blood color1 = ParticleColor(kind); color2 = ParticleColor(RPART(kind)/3, GPART(kind)/3, BPART(kind)/3); break; } zvel = -1./512.; zspread = updown ? -6000 / 65536. : 6000 / 65536.; zadd = (updown == 2) ? -128 : 0; for (; count; count--) { FParticle *p = NewParticle (Level); DAngle an; if (!p) break; p->ttl = 12; p->fadestep = FADEFROMTTL(12); p->alpha = 1.f; p->size = 4; p->color = M_Random() & 0x80 ? color1 : color2; p->Vel.Z = M_Random() * zvel; p->Acc.Z = -1 / 22.; if (kind) { an = angle + ((M_Random() - 128) * (180 / 256.)); p->Vel.X = M_Random() * an.Cos() / 2048.; p->Vel.Y = M_Random() * an.Sin() / 2048.; p->Acc.X = p->Vel.X / 16.; p->Acc.Y = p->Vel.Y / 16.; } an = angle + ((M_Random() - 128) * (90 / 256.)); p->Pos.X = pos.X + ((M_Random() & 31) - 15) * an.Cos(); p->Pos.Y = pos.Y + ((M_Random() & 31) - 15) * an.Sin(); p->Pos.Z = pos.Z + (M_Random() + zadd - 128) * zspread; p->renderstyle = STYLE_Translucent; } }
void D_GetPlayerColor (int player, float *h, float *s, float *v, FPlayerColorSet **set) { userinfo_t *info = &players[player].userinfo; FPlayerColorSet *colorset = NULL; uint32 color; int team; if (players[player].mo != NULL) { colorset = P_GetPlayerColorSet(players[player].mo->GetClass()->TypeName, info->GetColorSet()); } if (colorset != NULL) { color = GPalette.BaseColors[GPalette.Remap[colorset->RepresentativeColor]]; } else { color = info->GetColor(); } RGBtoHSV (RPART(color)/255.f, GPART(color)/255.f, BPART(color)/255.f, h, s, v); if (teamplay && TeamLibrary.IsValidTeam((team = info->GetTeam())) && !Teams[team].GetAllowCustomPlayerColor()) { // In team play, force the player to use the team's hue // and adjust the saturation and value so that the team // hue is visible in the final color. float ts, tv; int tcolor = Teams[team].GetPlayerColor (); RGBtoHSV (RPART(tcolor)/255.f, GPART(tcolor)/255.f, BPART(tcolor)/255.f, h, &ts, &tv); *s = clamp(ts + *s * 0.15f - 0.075f, 0.f, 1.f); *v = clamp(tv + *v * 0.5f - 0.25f, 0.f, 1.f); // Make sure not to pass back any colorset in teamplay. colorset = NULL; } if (set != NULL) { *set = colorset; } }
void SDLVideo::SetPalette(DWORD *palette) { for (size_t i = 0; i < sizeof(newPalette)/sizeof(SDL_Color); i++) { newPalette[i].r = RPART(palette[i]); newPalette[i].g = GPART(palette[i]); newPalette[i].b = BPART(palette[i]); } palettechanged = true; }
void r_dimpatchD_MMX(const DCanvas *const cvs, argb_t color, int alpha, int x1, int y1, int w, int h) { int x, y, i; argb_t *line; int invAlpha = 256 - alpha; int dpitch = cvs->pitch / sizeof(DWORD); line = (argb_t *)cvs->buffer + y1 * dpitch; int batches = w / 2; int remainder = w & 1; // MMX temporaries: const __m64 upper8mask = _mm_set_pi16(0, 0xff, 0xff, 0xff); const __m64 blendAlpha = _mm_set_pi16(0, alpha, alpha, alpha); const __m64 blendInvAlpha = _mm_set_pi16(0, invAlpha, invAlpha, invAlpha); const __m64 blendColor = _mm_set_pi16(0, RPART(color), GPART(color), BPART(color)); const __m64 blendMult = _mm_mullo_pi16(blendColor, blendAlpha); for (y = y1; y < y1 + h; y++) { // MMX optimize the bulk in batches of 2 colors: for (i = 0, x = x1; i < batches; ++i, x += 2) { #if 1 const __m64 input = _mm_setr_pi32(line[x + 0], line[x + 1]); #else // NOTE(jsd): No guarantee of 64-bit alignment; cannot use. const __m64 input = *((__m64 *)line[x]); #endif const __m64 output = blend2vs1_mmx(input, blendMult, blendInvAlpha, upper8mask); #if 1 line[x+0] = _mm_cvtsi64_si32(_mm_srli_si64(output, 32*0)); line[x+1] = _mm_cvtsi64_si32(_mm_srli_si64(output, 32*1)); #else // NOTE(jsd): No guarantee of 64-bit alignment; cannot use. *((__m64 *)line[x]) = output; #endif } if (remainder) { // Pick up the remainder: for (; x < x1 + w; x++) { line[x] = alphablend1a(line[x], color, alpha); } } line += dpitch; } // Required to reset FP: _mm_empty(); }
UCVarValue FColorCVar::FromInt2 (int value, ECVarType type) { if (type == CVAR_String) { UCVarValue ret; mysnprintf (cstrbuf, countof(cstrbuf), "%02x %02x %02x", RPART(value), GPART(value), BPART(value)); ret.String = cstrbuf; return ret; } return FromInt (value, type); }
void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int maxpainblend) { int cnt; // [RH] All powerups can affect the screen blending now for (AInventory *item = CPlayer->mo->Inventory; item != NULL; item = item->Inventory) { PalEntry color = item->GetBlend (); if (color.a != 0) { V_AddBlend (color.r/255.f, color.g/255.f, color.b/255.f, color.a/255.f, blend); if (color.a/255.f > maxinvalpha) maxinvalpha = color.a/255.f; } } if (CPlayer->bonuscount) { cnt = CPlayer->bonuscount << 3; V_AddBlend (RPART(gameinfo.pickupcolor)/255.f, GPART(gameinfo.pickupcolor)/255.f, BPART(gameinfo.pickupcolor)/255.f, cnt > 128 ? 0.5f : cnt / 255.f, blend); } PalEntry painFlash = CPlayer->mo->DamageFade; CPlayer->mo->GetClass()->GetPainFlash(CPlayer->mo->DamageTypeReceived, &painFlash); if (painFlash.a != 0) { cnt = DamageToAlpha[MIN (113, CPlayer->damagecount * painFlash.a / 255)]; if (cnt) { if (cnt > maxpainblend) cnt = maxpainblend; V_AddBlend (painFlash.r / 255.f, painFlash.g / 255.f, painFlash.b / 255.f, cnt / 255.f, blend); } } // Unlike Doom, I did not have any utility source to look at to find the // exact numbers to use here, so I've had to guess by looking at how they // affect the white color in Hexen's palette and picking an alpha value // that seems reasonable. // [Gez] The exact values could be obtained by looking how they affect // each color channel in Hexen's palette. if (CPlayer->poisoncount) { cnt = MIN (CPlayer->poisoncount, 64); if (paletteflash & PF_POISON) { V_AddBlend(44/255.f, 92/255.f, 36/255.f, ((cnt + 7) >> 3) * 0.1f, blend); }
void R_GetPlayerTranslation (int color, const FPlayerColorSet *colorset, FPlayerSkin *skin, FRemapTable *table) { float h, s, v; if (colorset != NULL) { color = colorset->RepresentativeColor; } RGBtoHSV (RPART(color)/255.f, GPART(color)/255.f, BPART(color)/255.f, &h, &s, &v); R_CreatePlayerTranslation (h, s, v, colorset, skin, table, NULL, NULL); }
void P_InitEffects () { const struct ColorList *color = Colors; while (color->color) { *(color->color) = ParticleColor(color->r, color->g, color->b); color++; } int kind = gameinfo.defaultbloodparticlecolor; blood1 = ParticleColor(kind); blood2 = ParticleColor(RPART(kind)/3, GPART(kind)/3, BPART(kind)/3); }
static uint32_t ParticleColor(int rgb) { int *val; int stuff; val = ColorSaver.CheckKey(rgb); if (val != NULL) { return *val; } stuff = rgb | (ColorMatcher.Pick(RPART(rgb), GPART(rgb), BPART(rgb)) << 24); ColorSaver[rgb] = stuff; return stuff; }
void D_GetPlayerColor (int player, float *h, float *s, float *v) { userinfo_t *info = &players[player].userinfo; int color = info->color; RGBtoHSV (RPART(color)/255.f, GPART(color)/255.f, BPART(color)/255.f, h, s, v); if (teamplay && TeamLibrary.IsValidTeam(info->team) && !Teams[info->team].GetAllowCustomPlayerColor ()) { // In team play, force the player to use the team's hue // and adjust the saturation and value so that the team // hue is visible in the final color. float ts, tv; int tcolor = Teams[info->team].GetPlayerColor (); RGBtoHSV (RPART(tcolor)/255.f, GPART(tcolor)/255.f, BPART(tcolor)/255.f, h, &ts, &tv); *s = clamp(ts + *s * 0.15f - 0.075f, 0.f, 1.f); *v = clamp(tv + *v * 0.5f - 0.25f, 0.f, 1.f); } }
void r_dimpatchD_ALTIVEC(const DCanvas *const cvs, argb_t color, int alpha, int x1, int y1, int w, int h) { int x, y, i; argb_t *line; int invAlpha = 256 - alpha; int dpitch = cvs->pitch / sizeof(argb_t); line = (argb_t *)cvs->buffer + y1 * dpitch; int batches = w / 4; int remainder = w & 3; // AltiVec temporaries: const vu16 zero = {0, 0, 0, 0, 0, 0, 0, 0}; const vu16 upper8mask = {0, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0xff}; const vu16 blendAlpha = {0, alpha, alpha, alpha, 0, alpha, alpha, alpha}; const vu16 blendInvAlpha = {0, invAlpha, invAlpha, invAlpha, 0, invAlpha, invAlpha, invAlpha}; const vu16 blendColor = {0, RPART(color), GPART(color), BPART(color), 0, RPART(color), GPART(color), BPART(color)}; const vu16 blendMult = vec_mladd(blendColor, blendAlpha, zero); for (y = y1; y < y1 + h; y++) { // AltiVec optimize the bulk in batches of 4 colors: for (i = 0, x = x1; i < batches; ++i, x += 4) { const vu32 input = {line[x + 0], line[x + 1], line[x + 2], line[x + 3]}; const vu32 output = (vu32)blend4vs1_altivec(input, blendMult, blendInvAlpha, upper8mask); vec_ste(output, 0, &line[x]); vec_ste(output, 4, &line[x]); vec_ste(output, 8, &line[x]); vec_ste(output, 12, &line[x]); } if (remainder) { // Pick up the remainder: for (; x < x1 + w; x++) { line[x] = alphablend1a(line[x], color, alpha); } } line += dpitch; } }
int FFont::SimpleTranslation (uint32_t *colorsused, uint8_t *translation, uint8_t *reverse, TArray<double> &Luminosity) { double min, max, diver; int i, j; memset (translation, 0, 256); reverse[0] = 0; for (i = 1, j = 1; i < 256; i++) { if (colorsused[i]) { reverse[j++] = i; } } qsort (reverse+1, j-1, 1, compare); Luminosity.Resize(j); Luminosity[0] = 0.0; // [BL] Prevent uninitalized memory max = 0.0; min = 100000000.0; for (i = 1; i < j; i++) { translation[reverse[i]] = i; Luminosity[i] = RPART(GPalette.BaseColors[reverse[i]]) * 0.299 + GPART(GPalette.BaseColors[reverse[i]]) * 0.587 + BPART(GPalette.BaseColors[reverse[i]]) * 0.114; if (Luminosity[i] > max) max = Luminosity[i]; if (Luminosity[i] < min) min = Luminosity[i]; } diver = 1.0 / (max - min); for (i = 1; i < j; i++) { Luminosity[i] = (Luminosity[i] - min) * diver; } return j; }
int FFont::SimpleTranslation (BYTE *colorsused, BYTE *translation, BYTE *reverse, double **luminosity) { double min, max, diver; int i, j; memset (translation, 0, 256); reverse[0] = 0; for (i = 1, j = 1; i < 256; i++) { if (colorsused[i]) { reverse[j++] = i; } } qsort (reverse+1, j-1, 1, compare); *luminosity = new double[j]; max = 0.0; min = 100000000.0; for (i = 1; i < j; i++) { translation[reverse[i]] = i; (*luminosity)[i] = RPART(GPalette.BaseColors[reverse[i]]) * 0.299 + GPART(GPalette.BaseColors[reverse[i]]) * 0.587 + BPART(GPalette.BaseColors[reverse[i]]) * 0.114; if ((*luminosity)[i] > max) max = (*luminosity)[i]; if ((*luminosity)[i] < min) min = (*luminosity)[i]; } diver = 1.0 / (max - min); for (i = 1; i < j; i++) { (*luminosity)[i] = ((*luminosity)[i] - min) * diver; } return j; }
static int PalFromRGB(uint32 rgb) { if (LastPal >= 0 && LastRGB == rgb) { return LastPal; } // Quick check for black and white. if (rgb == MAKEARGB(255,0,0,0)) { LastPal = GPalette.BlackIndex; } else if (rgb == MAKEARGB(255,255,255,255)) { LastPal = GPalette.WhiteIndex; } else { LastPal = ColorMatcher.Pick(RPART(rgb), GPART(rgb), BPART(rgb)); } LastRGB = rgb; return LastPal; }
void FColorCVar::DoSet (UCVarValue value, ECVarType type) { Value = ToInt2 (value, type); if (screen) Index = ColorMatcher.Pick (RPART(Value), GPART(Value), BPART(Value)); }
FxExpression *ParseParameter(FScanner &sc, PClass *cls, char type, bool constant) { FxExpression *x = NULL; int v; switch(type) { case 'S': case 's': // Sound name sc.MustGetString(); x = new FxConstant(FSoundID(sc.String), sc); break; case 'M': case 'm': // Actor name sc.SetEscape(true); sc.MustGetString(); sc.SetEscape(false); x = new FxClassTypeCast(RUNTIME_CLASS(AActor), new FxConstant(FName(sc.String), sc)); break; case 'T': case 't': // String sc.SetEscape(true); sc.MustGetString(); sc.SetEscape(false); x = new FxConstant(sc.String[0]? FName(sc.String) : NAME_None, sc); break; case 'C': case 'c': // Color sc.MustGetString (); if (sc.Compare("none")) { v = -1; } else if (sc.Compare("")) { v = 0; } else { int c = V_GetColor (NULL, sc.String); // 0 needs to be the default so we have to mark the color. v = MAKEARGB(1, RPART(c), GPART(c), BPART(c)); } { ExpVal val; val.Type = VAL_Color; val.Int = v; x = new FxConstant(val, sc); break; } case 'L': case 'l': { // This forces quotation marks around the state name. sc.MustGetToken(TK_StringConst); if (sc.String[0] == 0 || sc.Compare("None")) { x = new FxConstant((FState*)NULL, sc); } else if (sc.Compare("*")) { if (constant) { x = new FxConstant((FState*)(intptr_t)-1, sc); } else sc.ScriptError("Invalid state name '*'"); } else { x = new FxMultiNameState(sc.String, sc); } break; } case 'X': case 'x': case 'Y': case 'y': x = ParseExpression (sc, cls); if (constant && !x->isConstant()) { sc.ScriptMessage("Default parameter must be constant."); FScriptPosition::ErrorCounter++; } break; default: assert(false); return NULL; } return x; }
void Reset() { mRed = (float)RPART(DWORD(*mCVar)); mGreen = (float)GPART(DWORD(*mCVar)); mBlue = (float)BPART(DWORD(*mCVar)); }
// // P_ArchiveWorld // void P_SerializeWorld (FArchive &arc) { int i, j; sector_t *sec; line_t *li; if (arc.IsStoring ()) { // saving to archive // do sectors for (i = 0, sec = sectors; i < numsectors; i++, sec++) { arc << sec->floorheight << sec->ceilingheight << sec->floorplane.a << sec->floorplane.b << sec->floorplane.c << sec->floorplane.d << sec->ceilingplane.a << sec->ceilingplane.b << sec->ceilingplane.c << sec->ceilingplane.d << sec->floorpic << sec->ceilingpic << sec->lightlevel << sec->special << sec->tag << sec->soundtraversed /*<< sec->soundtarget*/ << sec->friction << sec->movefactor << sec->floordata << sec->ceilingdata << sec->lightingdata << sec->stairlock << sec->prevsec << sec->nextsec << sec->floor_xoffs << sec->floor_yoffs << sec->ceiling_xoffs << sec->ceiling_xoffs << sec->floor_xscale << sec->floor_yscale << sec->ceiling_xscale << sec->ceiling_yscale << sec->floor_angle << sec->ceiling_angle << sec->base_ceiling_angle << sec->base_ceiling_yoffs << sec->base_floor_angle << sec->base_floor_yoffs << sec->heightsec << sec->floorlightsec << sec->ceilinglightsec << sec->bottommap << sec->midmap << sec->topmap << sec->gravity << sec->damage << sec->mod << sec->floorcolormap->color << sec->floorcolormap->fade << sec->ceilingcolormap->color << sec->ceilingcolormap->fade << sec->alwaysfake << sec->waterzone << sec->SecActTarget << sec->MoreFlags; } // do lines for (i = 0, li = lines; i < numlines; i++, li++) { arc << li->flags << li->special << li->lucency << li->id << li->args[0] << li->args[1] << li->args[2] << li->args[3] << li->args[4] << (WORD)0; for (j = 0; j < 2; j++) { if (li->sidenum[j] == R_NOSIDE) continue; side_t *si = &sides[li->sidenum[j]]; arc << si->textureoffset << si->rowoffset << si->toptexture << si->bottomtexture << si->midtexture; } } } else { // loading from archive // do sectors for (i = 0, sec = sectors; i < numsectors; i++, sec++) { unsigned int color=0, fade=0; AActor* SecActTarget; arc >> sec->floorheight >> sec->ceilingheight >> sec->floorplane.a >> sec->floorplane.b >> sec->floorplane.c >> sec->floorplane.d >> sec->ceilingplane.a >> sec->ceilingplane.b >> sec->ceilingplane.c >> sec->ceilingplane.d >> sec->floorpic >> sec->ceilingpic >> sec->lightlevel >> sec->special >> sec->tag >> sec->soundtraversed /*>> sec->soundtarget->netid*/ >> sec->friction >> sec->movefactor >> sec->floordata >> sec->ceilingdata >> sec->lightingdata >> sec->stairlock >> sec->prevsec >> sec->nextsec >> sec->floor_xoffs >> sec->floor_yoffs >> sec->ceiling_xoffs >> sec->ceiling_xoffs >> sec->floor_xscale >> sec->floor_yscale >> sec->ceiling_xscale >> sec->ceiling_yscale >> sec->floor_angle >> sec->ceiling_angle >> sec->base_ceiling_angle >> sec->base_ceiling_yoffs >> sec->base_floor_angle >> sec->base_floor_yoffs >> sec->heightsec >> sec->floorlightsec >> sec->ceilinglightsec >> sec->bottommap >> sec->midmap >> sec->topmap >> sec->gravity >> sec->damage >> sec->mod >> color >> fade; sec->floorcolormap = GetSpecialLights ( RPART(color), GPART(color), BPART(color), RPART(fade), GPART(fade), BPART(fade)); arc >> color >> fade; sec->ceilingcolormap = GetSpecialLights ( RPART(color), GPART(color), BPART(color), RPART(fade), GPART(fade), BPART(fade)); arc >> sec->alwaysfake >> sec->waterzone >> SecActTarget >> sec->MoreFlags; sec->floorplane.invc = FixedDiv(FRACUNIT, sec->floorplane.c); sec->floorplane.sector = sec; sec->ceilingplane.invc = FixedDiv(FRACUNIT, sec->ceilingplane.c); sec->ceilingplane.sector = sec; sec->SecActTarget.init(SecActTarget); } // do lines for (i = 0, li = lines; i < numlines; i++, li++) { WORD dummy; arc >> li->flags >> li->special >> li->lucency >> li->id >> li->args[0] >> li->args[1] >> li->args[2] >> li->args[3] >> li->args[4] >> dummy; for (j = 0; j < 2; j++) { if (li->sidenum[j] == R_NOSIDE) continue; side_t *si = &sides[li->sidenum[j]]; arc >> si->textureoffset >> si->rowoffset >> si->toptexture >> si->bottomtexture >> si->midtexture; } } } }
void FGLRenderer::DrawTexture(FTexture *img, DCanvas::DrawParms &parms) { double xscale = parms.destwidth / parms.texwidth; double yscale = parms.destheight / parms.texheight; double x = parms.x - parms.left * xscale; double y = parms.y - parms.top * yscale; double w = parms.destwidth; double h = parms.destheight; float u1, v1, u2, v2, r, g, b; float light = 1.f; FMaterial * gltex = FMaterial::ValidateTexture(img); const PatchTextureInfo * pti; if (parms.colorOverlay) { // Right now there's only black. Should be implemented properly later light = 1.f - APART(parms.colorOverlay)/255.f; } if (!img->bHasCanvas) { if (!parms.alphaChannel) { int translation = 0; if (parms.remap != NULL && !parms.remap->Inactive) { GLTranslationPalette * pal = static_cast<GLTranslationPalette*>(parms.remap->GetNative()); if (pal) translation = -pal->GetIndex(); } pti = gltex->BindPatch(CM_DEFAULT, translation); } else { // This is an alpha texture pti = gltex->BindPatch(CM_SHADE, 0); } if (!pti) return; u1 = pti->GetUL(); v1 = pti->GetVT(); u2 = pti->GetUR(); v2 = pti->GetVB(); } else { gltex->Bind(CM_DEFAULT, 0, 0); u2=1.f; v2=-1.f; u1 = v1 = 0.f; gl_RenderState.SetTextureMode(TM_OPAQUE); } if (parms.flipX) { float temp = u1; u1 = u2; u2 = temp; } if (parms.windowleft > 0 || parms.windowright < parms.texwidth) { x += parms.windowleft * xscale; w -= (parms.texwidth - parms.windowright + parms.windowleft) * xscale; u1 = float(u1 + parms.windowleft / parms.texwidth); u2 = float(u2 - (parms.texwidth - parms.windowright) / parms.texwidth); } if (parms.style.Flags & STYLEF_ColorIsFixed) { r = RPART(parms.fillcolor)/255.0f; g = GPART(parms.fillcolor)/255.0f; b = BPART(parms.fillcolor)/255.0f; } else { r = g = b = light; } // scissor test doesn't use the current viewport for the coordinates, so use real screen coordinates int btm = (SCREENHEIGHT - screen->GetHeight()) / 2; btm = SCREENHEIGHT - btm; gl.Enable(GL_SCISSOR_TEST); int space = (static_cast<OpenGLFrameBuffer*>(screen)->GetTrueHeight()-screen->GetHeight())/2; gl.Scissor(parms.lclip, btm - parms.dclip + space, parms.rclip - parms.lclip, parms.dclip - parms.uclip); gl_SetRenderStyle(parms.style, !parms.masked, false); if (img->bHasCanvas) { gl_RenderState.SetTextureMode(TM_OPAQUE); } gl.Color4f(r, g, b, FIXED2FLOAT(parms.alpha)); gl_RenderState.EnableAlphaTest(false); gl_RenderState.Apply(); gl.Begin(GL_TRIANGLE_STRIP); gl.TexCoord2f(u1, v1); glVertex2d(x, y); gl.TexCoord2f(u1, v2); glVertex2d(x, y + h); gl.TexCoord2f(u2, v1); glVertex2d(x + w, y); gl.TexCoord2f(u2, v2); glVertex2d(x + w, y + h); gl.End(); gl_RenderState.EnableAlphaTest(true); gl.Scissor(0, 0, screen->GetWidth(), screen->GetHeight()); gl.Disable(GL_SCISSOR_TEST); gl_RenderState.SetTextureMode(TM_MODULATE); gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl_RenderState.BlendEquation(GL_FUNC_ADD); }
FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool constant) { FxExpression *x = NULL; int v; if (type == TypeSound) { sc.MustGetString(); x = new FxConstant(FSoundID(sc.String), sc); } else if (type == TypeBool || type == TypeSInt32 || type == TypeFloat64) { x = ParseExpression (sc, cls, constant); if (constant && !x->isConstant()) { sc.ScriptMessage("Default parameter must be constant."); FScriptPosition::ErrorCounter++; } // Do automatic coercion between bools, ints and floats. if (type == TypeBool) { x = new FxBoolCast(x); } else if (type == TypeSInt32) { x = new FxIntCast(x); } else { x = new FxFloatCast(x); } } else if (type == TypeName || type == TypeString) { sc.SetEscape(true); sc.MustGetString(); sc.SetEscape(false); if (type == TypeName) { x = new FxConstant(sc.String[0] ? FName(sc.String) : NAME_None, sc); } else { x = new FxConstant(strbin1(sc.String), sc); } } else if (type == TypeColor) { sc.MustGetString (); if (sc.Compare("none")) { v = -1; } else if (sc.Compare("")) { v = 0; } else { int c = V_GetColor (NULL, sc.String); // 0 needs to be the default so we have to mark the color. v = MAKEARGB(1, RPART(c), GPART(c), BPART(c)); } ExpVal val; val.Type = TypeColor; val.Int = v; x = new FxConstant(val, sc); } else if (type == TypeState) { // This forces quotation marks around the state name. sc.MustGetToken(TK_StringConst); if (sc.String[0] == 0 || sc.Compare("None")) { x = new FxConstant((FState*)NULL, sc); } else if (sc.Compare("*")) { if (constant) { x = new FxConstant((FState*)(intptr_t)-1, sc); } else sc.ScriptError("Invalid state name '*'"); } else { x = new FxMultiNameState(sc.String, sc); } } else if (type->GetClass() == RUNTIME_CLASS(PClassPointer)) { // Actor name sc.SetEscape(true); sc.MustGetString(); sc.SetEscape(false); x = new FxClassTypeCast(static_cast<PClassPointer *>(type)->ClassRestriction, new FxConstant(FName(sc.String), sc)); } else { assert(false && "Unknown parameter type"); x = NULL; } return x; }
// // R_InitColormaps // void R_InitColormaps (void) { // [RH] Try and convert BOOM colormaps into blending values. // This is a really rough hack, but it's better than // not doing anything with them at all (right?) int lastfakecmap = W_CheckNumForName ("C_END"); firstfakecmap = W_CheckNumForName ("C_START"); if (firstfakecmap == -1 || lastfakecmap == -1) numfakecmaps = 1; else { if(firstfakecmap > lastfakecmap) I_Error("no fake cmaps"); numfakecmaps = lastfakecmap - firstfakecmap; } realcolormaps.colormap = (byte *)Z_Malloc (256*(NUMCOLORMAPS+1)*numfakecmaps,PU_STATIC,0); realcolormaps.shademap = (argb_t *)Z_Malloc (256*sizeof(argb_t)*(NUMCOLORMAPS+1)*numfakecmaps,PU_STATIC,0); fakecmaps = (FakeCmap *)Z_Malloc (sizeof(*fakecmaps) * numfakecmaps, PU_STATIC, 0); fakecmaps[0].name[0] = 0; R_ForceDefaultColormap ("COLORMAP"); if (numfakecmaps > 1) { int i; size_t j; palette_t *pal = GetDefaultPalette (); shaderef_t defpal = shaderef_t(&pal->maps, 0); for (i = ++firstfakecmap, j = 1; j < numfakecmaps; i++, j++) { if (W_LumpLength (i) >= (NUMCOLORMAPS+1)*256) { int k, r, g, b; byte *map = (byte *)W_CacheLumpNum (i, PU_CACHE); byte *colormap = realcolormaps.colormap+(NUMCOLORMAPS+1)*256*j; argb_t *shademap = realcolormaps.shademap+(NUMCOLORMAPS+1)*256*j; // Copy colormap data: memcpy (colormap, map, (NUMCOLORMAPS+1)*256); if(pal->basecolors) { r = RPART(pal->basecolors[*map]); g = GPART(pal->basecolors[*map]); b = BPART(pal->basecolors[*map]); W_GetLumpName (fakecmaps[j].name, i); for (k = 1; k < 256; k++) { r = (r + RPART(pal->basecolors[map[k]])) >> 1; g = (g + GPART(pal->basecolors[map[k]])) >> 1; b = (b + BPART(pal->basecolors[map[k]])) >> 1; } // NOTE(jsd): This alpha value is used for 32bpp in water areas. fakecmaps[j].blend = MAKEARGB (64, r, g, b); // Set up shademap for the colormap: for (k = 0; k < 256; ++k) { argb_t c = pal->basecolors[map[0]]; shademap[k] = alphablend1a(c, MAKERGB(r,g,b), j * (256 / numfakecmaps)); } } else { // Set up shademap for the colormap: for (k = 0; k < 256; ++k)
//========================================================================== // // // //========================================================================== void gl_DrawTexture(FTexInfo *texInfo) { float x, y, w, h; float ox, oy, cx, cy, r, g, b; float light = 1.f; x = texInfo->x; y = texInfo->y; w = texInfo->width; h = texInfo->height; FGLTexture * gltex = FGLTexture::ValidateTexture(texInfo->tex); const PatchTextureInfo * pti; if (!texInfo->tex->bHasCanvas) { if (!texInfo->loadAlpha) { int translationindex; if (texInfo->tex->UseType == FTexture::TEX_FontChar) { // Try to get the true color mapping from the paletted mapping which is being passed here // // Too bad that there is no decent way to get the index directly so the only way to get it // is to analyze the table's contents. byte * index0 = texInfo->font->GetColorTranslation(CR_BRICK); byte * index1 = texInfo->font->GetColorTranslation(CR_TAN); translationindex = (texInfo->translation - index0) / (index1 - index0); if (translationindex<0 || translationindex>=NUM_TEXT_COLORS) { translationindex=CR_UNTRANSLATED; } // now get the corrseponding True Color table from the font. byte * tctstart = index0 + (NUM_TEXT_COLORS * (index1-index0)); texInfo->translation = tctstart + 3 * (index1-index0) * translationindex; } else { // If ZDoom changes its use of translation tables this has to be adjusted for it // because the texture manager doesn't implement a generic translation table handling. // if (texInfo->translation == DIM_MAP) { // reducing the light produces better results than using a palette-limited translation table. light = .5f; translationindex = 0; } else if (texInfo->translation >= translationtables[TRANSLATION_Players] && texInfo->translation < translationtables[TRANSLATION_Players] + (MAXPLAYERS+1)*256) { // Aside from fonts these are the only ones being used by ZDoom and they are better passed by ID. // int in = texInfo->translation - translationtables[TRANSLATION_Players]; translationindex = TRANSLATION(TRANSLATION_Players, in); } else { translationindex=0; } texInfo->translation=NULL; } pti = gltex->BindPatch(CM_DEFAULT, translationindex, texInfo->translation); } else { // This is an alpha texture pti = gltex->BindPatch(CM_SHADE, 0); } if (!pti) return; cx = pti->GetUR(); cy = pti->GetVB(); } else { gltex->Bind(CM_DEFAULT); cx=1.f; cy=-1.f; } ox = oy = 0.f; if (texInfo->flipX) { float temp = ox; ox = cx; cx = temp; } // also take into account texInfo->windowLeft and texInfo->windowRight // just ignore for now... if (texInfo->windowLeft || texInfo->windowRight != texInfo->tex->GetScaledWidth()) return; if (texInfo->fillColor > 0 || texInfo->RenderStyle == STYLE_Shaded || texInfo->RenderStyle == STYLE_TranslucentStencil || texInfo->RenderStyle == STYLE_Stencil) { r = RPART(texInfo->fillColor)/255.0f; g = GPART(texInfo->fillColor)/255.0f; b = BPART(texInfo->fillColor)/255.0f; } else { r = g = b = light; } // scissor test doesn't use the current viewport for the coordinates, so use real screen coordinates int btm = (SCREENHEIGHT - screen->GetHeight()) / 2; btm = SCREENHEIGHT - btm; gl.Enable(GL_SCISSOR_TEST); int space = (static_cast<OpenGLFrameBuffer*>(screen)->GetTrueHeight()-screen->GetHeight())/2; // ugh... gl.Scissor(texInfo->clipLeft, btm - texInfo->clipBottom+space, texInfo->clipRight - texInfo->clipLeft, texInfo->clipBottom - texInfo->clipTop); if (texInfo->RenderStyle == STYLE_TranslucentStencil || texInfo->RenderStyle == STYLE_Stencil) { gl_SetTextureMode(TM_MASK); } else if (!texInfo->masked) { gl_SetTextureMode(TM_OPAQUE); } gl.Color4f(r, g, b, texInfo->alpha); gl.Disable(GL_ALPHA_TEST); gl.Begin(GL_TRIANGLE_STRIP); gl.TexCoord2f(ox, oy); gl.Vertex2i(x, y); gl.TexCoord2f(ox, cy); gl.Vertex2i(x, y + h); gl.TexCoord2f(cx, oy); gl.Vertex2i(x + w, y); gl.TexCoord2f(cx, cy); gl.Vertex2i(x + w, y + h); gl.End(); gl.Enable(GL_ALPHA_TEST); gl.Scissor(0, 0, screen->GetWidth(), screen->GetHeight()); gl.Disable(GL_SCISSOR_TEST); if (!texInfo->masked || texInfo->RenderStyle == STYLE_TranslucentStencil || texInfo->RenderStyle == STYLE_Stencil) { gl_SetTextureMode(TM_MODULATE); } }
void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact) { if (i >= MAXPLAYERS) { WriteByte (0, stream); } else { userinfo_t *info = &players[i].userinfo; const PClass *type = PlayerClasses[info->PlayerClass].Type; if (!compact) { sprintf (*((char **)stream), "\\name\\%s" "\\autoaim\\%g" "\\color\\%x %x %x" "\\skin\\%s" "\\team\\%d" "\\gender\\%s" "\\neverswitchonpickup\\%d" "\\movebob\\%g" "\\stillbob\\%g" "\\playerclass\\%s" , D_EscapeUserInfo(info->netname).GetChars(), (double)info->aimdist / (float)ANGLE_1, RPART(info->color), GPART(info->color), BPART(info->color), D_EscapeUserInfo(skins[info->skin].name).GetChars(), info->team, info->gender == GENDER_FEMALE ? "female" : info->gender == GENDER_NEUTER ? "other" : "male", info->neverswitch, (float)(info->MoveBob) / 65536.f, (float)(info->StillBob) / 65536.f, info->PlayerClass == -1 ? "Random" : D_EscapeUserInfo(type->Meta.GetMetaString (APMETA_DisplayName)).GetChars() ); } else { sprintf (*((char **)stream), "\\" "\\%s" // name "\\%g" // autoaim "\\%x %x %x" // color "\\%s" // skin "\\%d" // team "\\%s" // gender "\\%d" // neverswitchonpickup "\\%g" // movebob "\\%g" // stillbob "\\%s" // playerclass , D_EscapeUserInfo(info->netname).GetChars(), (double)info->aimdist / (float)ANGLE_1, RPART(info->color), GPART(info->color), BPART(info->color), D_EscapeUserInfo(skins[info->skin].name).GetChars(), info->team, info->gender == GENDER_FEMALE ? "female" : info->gender == GENDER_NEUTER ? "other" : "male", info->neverswitch, (float)(info->MoveBob) / 65536.f, (float)(info->StillBob) / 65536.f, info->PlayerClass == -1 ? "Random" : D_EscapeUserInfo(type->Meta.GetMetaString (APMETA_DisplayName)).GetChars() ); } } *stream += strlen (*((char **)stream)) + 1; }
//========================================================================== // // ParseStates // parses a state block // //========================================================================== int ParseStates(FActorInfo * actor, AActor * defaults, Baggage &bag) { FString statestring; intptr_t count = 0; FState state; FState * laststate = NULL; intptr_t lastlabel = -1; int minrequiredstate = -1; SC_MustGetStringName ("{"); SC_SetEscape(false); // disable escape sequences in the state parser while (!SC_CheckString ("}") && !sc_End) { memset(&state,0,sizeof(state)); statestring = ParseStateString(); if (!statestring.CompareNoCase("GOTO")) { do_goto: statestring = ParseStateString(); if (SC_CheckString ("+")) { SC_MustGetNumber (); statestring += '+'; statestring += sc_String; } // copy the text - this must be resolved later! if (laststate != NULL) { // Following a state definition: Modify it. laststate->NextState = (FState*)copystring(statestring); } else if (lastlabel >= 0) { // Following a label: Retarget it. RetargetStates (count+1, statestring); } else { SC_ScriptError("GOTO before first state"); } } else if (!statestring.CompareNoCase("STOP")) { do_stop: if (laststate!=NULL) { laststate->NextState=(FState*)-1; } else if (lastlabel >=0) { RetargetStates (count+1, NULL); } else { SC_ScriptError("STOP before first state"); continue; } } else if (!statestring.CompareNoCase("WAIT") || !statestring.CompareNoCase("FAIL")) { if (!laststate) { SC_ScriptError("%s before first state", sc_String); continue; } laststate->NextState=(FState*)-2; } else if (!statestring.CompareNoCase("LOOP")) { if (!laststate) { SC_ScriptError("LOOP before first state"); continue; } laststate->NextState=(FState*)(lastlabel+1); } else { const char * statestrp; SC_MustGetString(); if (SC_Compare (":")) { laststate = NULL; do { lastlabel = count; AddState(statestring, (FState *) (count+1)); statestring = ParseStateString(); if (!statestring.CompareNoCase("GOTO")) { goto do_goto; } else if (!statestring.CompareNoCase("STOP")) { goto do_stop; } SC_MustGetString (); } while (SC_Compare (":")); // continue; } SC_UnGet (); if (statestring.Len() != 4) { SC_ScriptError ("Sprite names must be exactly 4 characters\n"); } memcpy(state.sprite.name, statestring, 4); state.Misc1=state.Misc2=0; state.ParameterIndex=0; SC_MustGetString(); statestring = (sc_String+1); statestrp = statestring; state.Frame=(*sc_String&223)-'A'; if ((*sc_String&223)<'A' || (*sc_String&223)>']') { SC_ScriptError ("Frames must be A-Z, [, \\, or ]"); state.Frame=0; } SC_MustGetNumber(); sc_Number++; state.Tics=sc_Number&255; state.Misc1=(sc_Number>>8)&255; if (state.Misc1) state.Frame|=SF_BIGTIC; while (SC_GetString() && !sc_Crossed) { if (SC_Compare("BRIGHT")) { state.Frame|=SF_FULLBRIGHT; continue; } if (SC_Compare("OFFSET")) { if (state.Frame&SF_BIGTIC) { SC_ScriptError("You cannot use OFFSET with a state duration larger than 254!"); } // specify a weapon offset SC_MustGetStringName("("); SC_MustGetNumber(); state.Misc1=sc_Number; SC_MustGetStringName (","); SC_MustGetNumber(); state.Misc2=sc_Number; SC_MustGetStringName(")"); continue; } // Make the action name lowercase to satisfy the gperf hashers strlwr (sc_String); int minreq=count; if (DoActionSpecials(state, !statestring.IsEmpty(), &minreq, bag)) { if (minreq>minrequiredstate) minrequiredstate=minreq; goto endofstate; } PSymbol *sym = bag.Info->Class->Symbols.FindSymbol (FName(sc_String, true), true); if (sym != NULL && sym->SymbolType == SYM_ActionFunction) { PSymbolActionFunction *afd = static_cast<PSymbolActionFunction *>(sym); state.Action = afd->Function; if (!afd->Arguments.IsEmpty()) { const char *params = afd->Arguments.GetChars(); int numparams = (int)afd->Arguments.Len(); int v; if (!islower(*params)) { SC_MustGetStringName("("); } else { if (!SC_CheckString("(")) goto endofstate; } int paramindex = PrepareStateParameters(&state, numparams); int paramstart = paramindex; bool varargs = params[numparams - 1] == '+'; if (varargs) { StateParameters[paramindex++] = 0; } while (*params) { switch(*params) { case 'I': case 'i': // Integer SC_MustGetNumber(); v=sc_Number; break; case 'F': case 'f': // Fixed point SC_MustGetFloat(); v=fixed_t(sc_Float*FRACUNIT); break; case 'S': case 's': // Sound name SC_MustGetString(); v=S_FindSound(sc_String); break; case 'M': case 'm': // Actor name case 'T': case 't': // String SC_SetEscape(true); SC_MustGetString(); SC_SetEscape(false); v = (int)(sc_String[0] ? FName(sc_String) : NAME_None); break; case 'L': case 'l': // Jump label if (SC_CheckNumber()) { if (strlen(statestring)>0) { SC_ScriptError("You cannot use A_Jump commands with a jump index on multistate definitions\n"); } v=sc_Number; if (v<1) { SC_ScriptError("Negative jump offsets are not allowed"); } { int minreq=count+v; if (minreq>minrequiredstate) minrequiredstate=minreq; } } else { if (JumpParameters.Size()==0) JumpParameters.Push(NAME_None); v = -(int)JumpParameters.Size(); // This forces quotation marks around the state name. SC_MustGetToken(TK_StringConst); FString statestring = sc_String; // ParseStateString(); const PClass *stype=NULL; int scope = statestring.IndexOf("::"); if (scope >= 0) { FName scopename = FName(statestring, scope, false); if (scopename == NAME_Super) { // Super refers to the direct superclass scopename = actor->Class->ParentClass->TypeName; } JumpParameters.Push(scopename); statestring = statestring.Right(statestring.Len()-scope-2); stype = PClass::FindClass (scopename); if (stype == NULL) { SC_ScriptError ("%s is an unknown class.", scopename.GetChars()); } if (!stype->IsDescendantOf (RUNTIME_CLASS(AActor))) { SC_ScriptError ("%s is not an actor class, so it has no states.", stype->TypeName.GetChars()); } if (!stype->IsAncestorOf (actor->Class)) { SC_ScriptError ("%s is not derived from %s so cannot access its states.", actor->Class->TypeName.GetChars(), stype->TypeName.GetChars()); } } else { // No class name is stored. This allows 'virtual' jumps to // labels in subclasses. // It also means that the validity of the given state cannot // be checked here. JumpParameters.Push(NAME_None); } TArray<FName> names; MakeStateNameList(statestring, &names); if (stype != NULL) { if (!stype->ActorInfo->FindState(names.Size(), &names[0])) { SC_ScriptError("Jump to unknown state '%s' in class '%s'", statestring.GetChars(), stype->TypeName.GetChars()); } } JumpParameters.Push((ENamedName)names.Size()); for(unsigned i=0;i<names.Size();i++) { JumpParameters.Push(names[i]); } // No offsets here. The point of jumping to labels is to avoid such things! } break; case 'C': case 'c': // Color SC_MustGetString (); if (SC_Compare("none")) { v = -1; } else { int c = V_GetColor (NULL, sc_String); // 0 needs to be the default so we have to mark the color. v = MAKEARGB(1, RPART(c), GPART(c), BPART(c)); } break; case 'X': case 'x': v = ParseExpression (false, bag.Info->Class); break; case 'Y': case 'y': v = ParseExpression (true, bag.Info->Class); break; default: assert(false); v = -1; break; } StateParameters[paramindex++] = v; params++; if (varargs) { StateParameters[paramstart]++; } if (*params) { if (*params == '+') { if (SC_CheckString(")")) { goto endofstate; } params--; v = 0; StateParameters.Push(v); } else if ((islower(*params) || *params=='!') && SC_CheckString(")")) { goto endofstate; } SC_MustGetStringName (","); } } SC_MustGetStringName(")"); } else { SC_MustGetString(); if (SC_Compare("(")) { SC_ScriptError("You cannot pass parameters to '%s'\n",sc_String); } SC_UnGet(); } goto endofstate; } SC_ScriptError("Invalid state parameter %s\n", sc_String); } SC_UnGet(); endofstate: StateArray.Push(state); while (*statestrp) { int frame=((*statestrp++)&223)-'A'; if (frame<0 || frame>28) { SC_ScriptError ("Frames must be A-Z, [, \\, or ]"); frame=0; } state.Frame=(state.Frame&(SF_FULLBRIGHT|SF_BIGTIC))|frame; StateArray.Push(state); count++; } laststate=&StateArray[count]; count++; } } if (count<=minrequiredstate) { SC_ScriptError("A_Jump offset out of range in %s", actor->Class->TypeName.GetChars()); } SC_SetEscape(true); // re-enable escape sequences return count; }
//========================================================================== // // // //========================================================================== void GLWall::DrawDecal(DBaseDecal *decal) { line_t * line=seg->linedef; side_t * side=seg->sidedef; int i; fixed_t zpos; int light; int rel; float a; bool flipx, flipy, loadAlpha; DecalVertex dv[4]; FTextureID decalTile; if (decal->RenderFlags & RF_INVISIBLE) return; if (type==RENDERWALL_FFBLOCK && gltexture->isMasked()) return; // No decals on 3D floors with transparent textures. //if (decal->sprite != 0xffff) { decalTile = decal->PicNum; flipx = !!(decal->RenderFlags & RF_XFLIP); flipy = !!(decal->RenderFlags & RF_YFLIP); } /* else { decalTile = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].lump[0]; flipx = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].flip & 1; } */ FTexture *texture = TexMan[decalTile]; if (texture == NULL) return; FMaterial *tex; if (texture->UseType == FTexture::TEX_MiscPatch) { // We need to create a clone of this texture where we can force the // texture filtering offset in. if (texture->gl_info.DecalTexture == NULL) { texture->gl_info.DecalTexture = new FCloneTexture(texture, FTexture::TEX_Decal); } tex = FMaterial::ValidateTexture(texture->gl_info.DecalTexture); } else tex = FMaterial::ValidateTexture(texture); // the sectors are only used for their texture origin coordinates // so we don't need the fake sectors for deep water etc. // As this is a completely split wall fragment no further splits are // necessary for the decal. sector_t *frontsector; // for 3d-floor segments use the model sector as reference if ((decal->RenderFlags&RF_CLIPMASK)==RF_CLIPMID) frontsector=decal->Sector; else frontsector=seg->frontsector; switch (decal->RenderFlags & RF_RELMASK) { default: // No valid decal can have this type. If one is encountered anyway // it is in some way invalid so skip it. return; //zpos = decal->z; //break; case RF_RELUPPER: if (type!=RENDERWALL_TOP) return; if (line->flags & ML_DONTPEGTOP) { zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling); } else { zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::ceiling); } break; case RF_RELLOWER: if (type!=RENDERWALL_BOTTOM) return; if (line->flags & ML_DONTPEGBOTTOM) { zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling); } else { zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::floor); } break; case RF_RELMID: if (type==RENDERWALL_TOP || type==RENDERWALL_BOTTOM) return; if (line->flags & ML_DONTPEGBOTTOM) { zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::floor); } else { zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling); } } if (decal->RenderFlags & RF_FULLBRIGHT) { light = 255; rel = 0; } else { light = lightlevel; rel = rellight + getExtraLight(); } int r = RPART(decal->AlphaColor); int g = GPART(decal->AlphaColor); int b = BPART(decal->AlphaColor); FColormap p = Colormap; if (glset.nocoloredspritelighting) { int v = (Colormap.LightColor.r * 77 + Colormap.LightColor.g*143 + Colormap.LightColor.b*35)/255; p.LightColor = PalEntry(p.colormap, v, v, v); } float red, green, blue; if (decal->RenderStyle.Flags & STYLEF_RedIsAlpha) { loadAlpha = true; p.colormap=CM_SHADE; if (glset.lightmode != 8) { gl_GetLightColor(light, rel, &p, &red, &green, &blue); } else { gl_GetLightColor(lightlevel, rellight, &p, &red, &green, &blue); } if (gl_lights && GLRenderer->mLightCount && !gl_fixedcolormap && gl_light_sprites) { float result[3]; fixed_t x, y; decal->GetXY(seg->sidedef, x, y); gl_GetSpriteLight(NULL, x, y, zpos, sub, Colormap.colormap-CM_DESAT0, result, line, side == line->sidedef[0]? 0:1); if (glset.lightmode != 8) { red = clamp<float>(result[0]+red, 0, 1.0f); green = clamp<float>(result[1]+green, 0, 1.0f); blue = clamp<float>(result[2]+blue, 0, 1.0f); } else { gl_RenderState.SetDynLight(result[0], result[1], result[2]); } } BYTE R = xs_RoundToInt(r * red); BYTE G = xs_RoundToInt(g * green); BYTE B = xs_RoundToInt(b * blue); gl_ModifyColor(R,G,B, Colormap.colormap); red = R/255.f; green = G/255.f; blue = B/255.f; } else { loadAlpha = false; red = 1.f; green = 1.f; blue = 1.f; } a = FIXED2FLOAT(decal->Alpha); // now clip the decal to the actual polygon float decalwidth = tex->TextureWidth(GLUSE_PATCH) * FIXED2FLOAT(decal->ScaleX); float decalheight= tex->TextureHeight(GLUSE_PATCH) * FIXED2FLOAT(decal->ScaleY); float decallefto = tex->GetLeftOffset(GLUSE_PATCH) * FIXED2FLOAT(decal->ScaleX); float decaltopo = tex->GetTopOffset(GLUSE_PATCH) * FIXED2FLOAT(decal->ScaleY); float leftedge = glseg.fracleft * side->TexelLength; float linelength = glseg.fracright * side->TexelLength - leftedge; // texel index of the decal's left edge float decalpixpos = (float)side->TexelLength * decal->LeftDistance / (1<<30) - (flipx? decalwidth-decallefto : decallefto) - leftedge; float left,right; float lefttex,righttex; // decal is off the left edge if (decalpixpos < 0) { left = 0; lefttex = -decalpixpos; } else { left = decalpixpos; lefttex = 0; } // decal is off the right edge if (decalpixpos + decalwidth > linelength) { right = linelength; righttex = right - decalpixpos; } else { right = decalpixpos + decalwidth; righttex = decalwidth; } if (right<=left) return; // nothing to draw // one texture unit on the wall as vector float vx=(glseg.x2-glseg.x1)/linelength; float vy=(glseg.y2-glseg.y1)/linelength; dv[1].x=dv[0].x=glseg.x1+vx*left; dv[1].y=dv[0].y=glseg.y1+vy*left; dv[3].x=dv[2].x=glseg.x1+vx*right; dv[3].y=dv[2].y=glseg.y1+vy*right; zpos+= FRACUNIT*(flipy? decalheight-decaltopo : decaltopo); tex->BindPatch(p.colormap, decal->Translation); dv[1].z=dv[2].z = FIXED2FLOAT(zpos); dv[0].z=dv[3].z = dv[1].z - decalheight; dv[1].v=dv[2].v = tex->GetVT(); dv[1].u=dv[0].u = tex->GetU(lefttex / FIXED2FLOAT(decal->ScaleX)); dv[3].u=dv[2].u = tex->GetU(righttex / FIXED2FLOAT(decal->ScaleX)); dv[0].v=dv[3].v = tex->GetVB(); // now clip to the top plane float vzt=(ztop[1]-ztop[0])/linelength; float topleft=this->ztop[0]+vzt*left; float topright=this->ztop[0]+vzt*right; // completely below the wall if (topleft<dv[0].z && topright<dv[3].z) return; if (topleft<dv[1].z || topright<dv[2].z) { // decal has to be clipped at the top // let texture clamping handle all extreme cases dv[1].v=(dv[1].z-topleft)/(dv[1].z-dv[0].z)*dv[0].v; dv[2].v=(dv[2].z-topright)/(dv[2].z-dv[3].z)*dv[3].v; dv[1].z=topleft; dv[2].z=topright; } // now clip to the bottom plane float vzb=(zbottom[1]-zbottom[0])/linelength; float bottomleft=this->zbottom[0]+vzb*left; float bottomright=this->zbottom[0]+vzb*right; // completely above the wall if (bottomleft>dv[1].z && bottomright>dv[2].z) return; if (bottomleft>dv[0].z || bottomright>dv[3].z) { // decal has to be clipped at the bottom // let texture clamping handle all extreme cases dv[0].v=(dv[1].z-bottomleft)/(dv[1].z-dv[0].z)*(dv[0].v-dv[1].v) + dv[1].v; dv[3].v=(dv[2].z-bottomright)/(dv[2].z-dv[3].z)*(dv[3].v-dv[2].v) + dv[2].v; dv[0].z=bottomleft; dv[3].z=bottomright; } if (flipx) { float ur = tex->GetUR(); for(i=0;i<4;i++) dv[i].u=ur-dv[i].u; } if (flipy) { float vb = tex->GetVB(); for(i=0;i<4;i++) dv[i].v=vb-dv[i].v; } // fog is set once per wall in the calling function and not per decal! if (loadAlpha) { glColor4f(red, green, blue, a); if (glset.lightmode == 8) { if (gl_fixedcolormap) glVertexAttrib1f(VATTR_LIGHTLEVEL, 1.0); else glVertexAttrib1f(VATTR_LIGHTLEVEL, gl_CalcLightLevel(light, rel, false) / 255.0); } } else { if (glset.lightmode == 8) { gl_SetColor(light, rel, &p, a, extralight); // Korshun. } else { gl_SetColor(light, rel, &p, a); } } PalEntry fc = gl_RenderState.GetFogColor(); if (decal->RenderStyle.BlendOp == STYLEOP_Add && decal->RenderStyle.DestAlpha == STYLEALPHA_One) { gl_RenderState.SetFog(0,-1); } gl_SetRenderStyle(decal->RenderStyle, false, false); // If srcalpha is one it looks better with a higher alpha threshold if (decal->RenderStyle.SrcAlpha == STYLEALPHA_One) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); else gl_RenderState.AlphaFunc(GL_GREATER, 0.f); gl_RenderState.Apply(); glBegin(GL_TRIANGLE_FAN); for(i=0;i<4;i++) { glTexCoord2f(dv[i].u,dv[i].v); glVertex3f(dv[i].x,dv[i].z,dv[i].y); } glEnd(); rendered_decals++; gl_RenderState.SetFog(fc,-1); gl_RenderState.SetDynLight(0,0,0); }