int CLayerQuads::BrushGrab(CLayerGroup *pBrush, CUIRect Rect) { // create new layers CLayerQuads *pGrabbed = new CLayerQuads(); pGrabbed->m_pEditor = m_pEditor; pGrabbed->m_Image = m_Image; pBrush->AddLayer(pGrabbed); //dbg_msg("", "%f %f %f %f", rect.x, rect.y, rect.w, rect.h); for(int i = 0; i < m_lQuads.size(); i++) { CQuad *q = &m_lQuads[i]; float px = fx2f(q->m_aPoints[4].x); float py = fx2f(q->m_aPoints[4].y); if(px > Rect.x && px < Rect.x+Rect.w && py > Rect.y && py < Rect.y+Rect.h) { dbg_msg("", "grabbed one"); CQuad n; n = *q; for(int p = 0; p < 5; p++) { n.m_aPoints[p].x -= f2fx(Rect.x); n.m_aPoints[p].y -= f2fx(Rect.y); } pGrabbed->m_lQuads.add(n); } } return pGrabbed->m_lQuads.size()?1:0; }
void CLayerQuads::GetSize(float *w, float *h) { *w = 0; *h = 0; for(int i = 0; i < m_lQuads.size(); i++) { for(int p = 0; p < 5; p++) { *w = max(*w, fx2f(m_lQuads[i].m_aPoints[p].x)); *h = max(*h, fx2f(m_lQuads[i].m_aPoints[p].y)); } } }
void CLayerQuads::BrushRotate(float Amount) { vec2 Center; GetSize(&Center.x, &Center.y); Center.x /= 2; Center.y /= 2; for(int i = 0; i < m_lQuads.size(); i++) { CQuad *q = &m_lQuads[i]; for(int p = 0; p < 5; p++) { vec2 Pos(fx2f(q->m_aPoints[p].x), fx2f(q->m_aPoints[p].y)); Rotate(&Center, &Pos, Amount); q->m_aPoints[p].x = f2fx(Pos.x); q->m_aPoints[p].y = f2fx(Pos.y); } } }
void CRenderTools::RenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags, void (*pfnEval)(float TimeOffset, int Env, float *pChannels, void *pUser), void *pUser) { if(g_Config.m_ClShowEntities && g_Config.m_ClDDRaceCheats) return; Graphics()->QuadsBegin(); float Conv = 1/255.0f; for(int i = 0; i < NumQuads; i++) { CQuad *q = &pQuads[i]; float r=1, g=1, b=1, a=1; if(q->m_ColorEnv >= 0) { float aChannels[4]; pfnEval(q->m_ColorEnvOffset/1000.0f, q->m_ColorEnv, aChannels, pUser); r = aChannels[0]; g = aChannels[1]; b = aChannels[2]; a = aChannels[3]; } bool Opaque = false; if(a < 0.01f || (q->m_aColors[0].a < 0.01f && q->m_aColors[1].a < 0.01f && q->m_aColors[2].a < 0.01f && q->m_aColors[3].a < 0.01f)) Opaque = true; if(Opaque && !(RenderFlags&LAYERRENDERFLAG_OPAQUE)) continue; if(!Opaque && !(RenderFlags&LAYERRENDERFLAG_TRANSPARENT)) continue; Graphics()->QuadsSetSubsetFree( fx2f(q->m_aTexcoords[0].x), fx2f(q->m_aTexcoords[0].y), fx2f(q->m_aTexcoords[1].x), fx2f(q->m_aTexcoords[1].y), fx2f(q->m_aTexcoords[2].x), fx2f(q->m_aTexcoords[2].y), fx2f(q->m_aTexcoords[3].x), fx2f(q->m_aTexcoords[3].y) ); float OffsetX = 0; float OffsetY = 0; float Rot = 0; // TODO: fix this if(q->m_PosEnv >= 0) { float aChannels[4]; pfnEval(q->m_PosEnvOffset/1000.0f, q->m_PosEnv, aChannels, pUser); OffsetX = aChannels[0]; OffsetY = aChannels[1]; Rot = aChannels[2]/360.0f*pi*2; } IGraphics::CColorVertex Array[4] = { IGraphics::CColorVertex(0, q->m_aColors[0].r*Conv*r, q->m_aColors[0].g*Conv*g, q->m_aColors[0].b*Conv*b, q->m_aColors[0].a*Conv*a), IGraphics::CColorVertex(1, q->m_aColors[1].r*Conv*r, q->m_aColors[1].g*Conv*g, q->m_aColors[1].b*Conv*b, q->m_aColors[1].a*Conv*a), IGraphics::CColorVertex(2, q->m_aColors[2].r*Conv*r, q->m_aColors[2].g*Conv*g, q->m_aColors[2].b*Conv*b, q->m_aColors[2].a*Conv*a), IGraphics::CColorVertex(3, q->m_aColors[3].r*Conv*r, q->m_aColors[3].g*Conv*g, q->m_aColors[3].b*Conv*b, q->m_aColors[3].a*Conv*a)}; Graphics()->SetColorVertex(Array, 4); CPoint *pPoints = q->m_aPoints; if(Rot != 0) { static CPoint aRotated[4]; aRotated[0] = q->m_aPoints[0]; aRotated[1] = q->m_aPoints[1]; aRotated[2] = q->m_aPoints[2]; aRotated[3] = q->m_aPoints[3]; pPoints = aRotated; Rotate(&q->m_aPoints[4], &aRotated[0], Rot); Rotate(&q->m_aPoints[4], &aRotated[1], Rot); Rotate(&q->m_aPoints[4], &aRotated[2], Rot); Rotate(&q->m_aPoints[4], &aRotated[3], Rot); } IGraphics::CFreeformItem Freeform( fx2f(pPoints[0].x)+OffsetX, fx2f(pPoints[0].y)+OffsetY, fx2f(pPoints[1].x)+OffsetX, fx2f(pPoints[1].y)+OffsetY, fx2f(pPoints[2].x)+OffsetX, fx2f(pPoints[2].y)+OffsetY, fx2f(pPoints[3].x)+OffsetX, fx2f(pPoints[3].y)+OffsetY); Graphics()->QuadsDrawFreeform(&Freeform, 1); } Graphics()->QuadsEnd(); }
void CRenderTools::RenderEvalEnvelope(CEnvPoint *pPoints, int NumPoints, int Channels, float Time, float *pResult) { if(NumPoints == 0) { pResult[0] = 0; pResult[1] = 0; pResult[2] = 0; pResult[3] = 0; return; } if(NumPoints == 1) { pResult[0] = fx2f(pPoints[0].m_aValues[0]); pResult[1] = fx2f(pPoints[0].m_aValues[1]); pResult[2] = fx2f(pPoints[0].m_aValues[2]); pResult[3] = fx2f(pPoints[0].m_aValues[3]); return; } Time = fmod(Time, pPoints[NumPoints-1].m_Time/1000.0f)*1000.0f; for(int i = 0; i < NumPoints-1; i++) { if(Time >= pPoints[i].m_Time && Time <= pPoints[i+1].m_Time) { float Delta = pPoints[i+1].m_Time-pPoints[i].m_Time; float a = (Time-pPoints[i].m_Time)/Delta; if(pPoints[i].m_Curvetype == CURVETYPE_SMOOTH) a = -2*a*a*a + 3*a*a; // second hermite basis else if(pPoints[i].m_Curvetype == CURVETYPE_SLOW) a = a*a*a; else if(pPoints[i].m_Curvetype == CURVETYPE_FAST) { a = 1-a; a = 1-a*a*a; } else if (pPoints[i].m_Curvetype == CURVETYPE_STEP) a = 0; else { // linear } for(int c = 0; c < Channels; c++) { float v0 = fx2f(pPoints[i].m_aValues[c]); float v1 = fx2f(pPoints[i+1].m_aValues[c]); pResult[c] = v0 + (v1-v0) * a; } return; } } pResult[0] = fx2f(pPoints[NumPoints-1].m_aValues[0]); pResult[1] = fx2f(pPoints[NumPoints-1].m_aValues[1]); pResult[2] = fx2f(pPoints[NumPoints-1].m_aValues[2]); pResult[3] = fx2f(pPoints[NumPoints-1].m_aValues[3]); return; }
int CEditor::PopupPoint(CEditor *pEditor, CUIRect View) { CQuad *pQuad = pEditor->GetSelectedQuad(); enum { PROP_POS_X=0, PROP_POS_Y, PROP_COLOR, PROP_TEX_U, PROP_TEX_V, NUM_PROPS, }; int Color = 0; int x = 0, y = 0; int tu = 0, tv = 0; for(int v = 0; v < 4; v++) { if(pEditor->m_SelectedPoints&(1<<v)) { Color = 0; Color |= pQuad->m_aColors[v].r<<24; Color |= pQuad->m_aColors[v].g<<16; Color |= pQuad->m_aColors[v].b<<8; Color |= pQuad->m_aColors[v].a; x = fx2i(pQuad->m_aPoints[v].x); y = fx2i(pQuad->m_aPoints[v].y); tu = fx2f(pQuad->m_aTexcoords[v].x)*1024; tv = fx2f(pQuad->m_aTexcoords[v].y)*1024; } } CProperty aProps[] = { {"Pos X", x, PROPTYPE_INT_SCROLL, -1000000, 1000000}, {"Pos Y", y, PROPTYPE_INT_SCROLL, -1000000, 1000000}, {"Color", Color, PROPTYPE_COLOR, -1, pEditor->m_Map.m_lEnvelopes.size()}, {"Tex U", tu, PROPTYPE_INT_SCROLL, -1000000, 1000000}, {"Tex V", tv, PROPTYPE_INT_SCROLL, -1000000, 1000000}, {0}, }; static int s_aIds[NUM_PROPS] = {0}; int NewVal = 0; int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal); if(Prop != -1) pEditor->m_Map.m_Modified = true; if(Prop == PROP_POS_X) { for(int v = 0; v < 4; v++) if(pEditor->m_SelectedPoints&(1<<v)) pQuad->m_aPoints[v].x = i2fx(NewVal); } if(Prop == PROP_POS_Y) { for(int v = 0; v < 4; v++) if(pEditor->m_SelectedPoints&(1<<v)) pQuad->m_aPoints[v].y = i2fx(NewVal); } if(Prop == PROP_COLOR) { for(int v = 0; v < 4; v++) { if(pEditor->m_SelectedPoints&(1<<v)) { pQuad->m_aColors[v].r = (NewVal>>24)&0xff; pQuad->m_aColors[v].g = (NewVal>>16)&0xff; pQuad->m_aColors[v].b = (NewVal>>8)&0xff; pQuad->m_aColors[v].a = NewVal&0xff; } } }
void CMapReader::Generate(CGenInfo *pInfo) { m_OverallBenchmark.Unpause(); // create folders char aGeneratedFolder[256]; sprintf(aGeneratedFolder, "%sgenerated/%s", pInfo->m_aCurrentDir, pInfo->m_aMap); char aGeneratedMapresFolder[256]; sprintf(aGeneratedMapresFolder, "%s/mapres", aGeneratedFolder); MakeDir(aGeneratedFolder); MakeDir(aGeneratedMapresFolder); // check map version CMapItemVersion *pVersion = (CMapItemVersion *)m_Reader.FindItem(MAPITEMTYPE_VERSION, 0); if(!pVersion || pVersion->m_Version != 1) return; // create generating file char aGenerating[256]; sprintf(aGenerating, "%s/generating", aGeneratedFolder); FILE *pGeneratingFile = fopen(aGenerating, "wb"); if(pGeneratingFile) fclose(pGeneratingFile); // load images m_ImagesBenchmark.Unpause(); int ImagesStart; int ImagesNum; m_Reader.GetType(MAPITEMTYPE_IMAGE, &ImagesStart, &ImagesNum); CMapItemImage *pImages = NULL; if(ImagesNum > 0) { pImages = new CMapItemImage[ImagesNum]; for(int i = ImagesStart; i < ImagesStart+ImagesNum; i++) { CMapItemImage *pImage = (CMapItemImage *)m_Reader.GetItem(i, NULL, NULL); if(!pImage->m_External && pInfo->m_DumpEmbedded) { const char *pName = (char *)m_Reader.GetData(pImage->m_ImageName); unsigned char *pData = (unsigned char *)m_Reader.GetData(pImage->m_ImageData); char aImageFilename[512]; sprintf(aImageFilename, "%s/%s.png", aGeneratedMapresFolder, pName); CImageWrite Image; Image.Open(aImageFilename, pImage->m_Width, pImage->m_Height); Image.SetPixels(pData); Image.Save(); } pImages[i-ImagesStart] = *pImage; } } m_ImagesBenchmark.Pause(); // load groups and layers int GroupsStart; int GroupsNum; m_Reader.GetType(MAPITEMTYPE_GROUP, &GroupsStart, &GroupsNum); int LayersStart; int LayersNum; m_Reader.GetType(MAPITEMTYPE_LAYER, &LayersStart, &LayersNum); for(int g = GroupsStart; g < GroupsStart+GroupsNum; g++) { CMapItemGroup *pGroup = (CMapItemGroup *)m_Reader.GetItem(g, NULL, NULL); if(pGroup->m_Version < 1 || pGroup->m_Version > 2) continue; for(int l = LayersStart + pGroup->m_StartLayer; l < LayersStart + pGroup->m_StartLayer+pGroup->m_NumLayers; l++) { if(l >= LayersStart+LayersNum) break; CMapItemLayer *pLayer = (CMapItemLayer *)m_Reader.GetItem(l, NULL, NULL); if(pLayer->m_Type == LAYERTYPE_TILES) { m_TilemapsBenchmark.Unpause(); CMapItemLayerTilemap *pTilesLayer = (CMapItemLayerTilemap *)pLayer; bool GameLayer = (pTilesLayer->m_Flags & TILESLAYERFLAG_GAME) ? true : false; if((GameLayer && !pInfo->m_DumpGameTilemap) || (!GameLayer && !pInfo->m_DumpTilemaps)) continue; if(!GameLayer && pTilesLayer->m_Image < 0) continue; CMapItemImage *pImage = NULL; if(!GameLayer) pImage = &pImages[pTilesLayer->m_Image]; const char *pTilesetName; if(GameLayer) pTilesetName = pInfo->m_aEntities; else pTilesetName = (char *)m_Reader.GetData(pImage->m_ImageName); CTileset Src; if(GameLayer || pImage->m_External) { char aTilesetFilename[512]; sprintf(aTilesetFilename, "%smapres/%s.png", pInfo->m_aCurrentDir, pTilesetName); bool Success = Src.Open(aTilesetFilename); if(!Success) continue; } else { bool Success = Src.OpenFromBuffer((unsigned char *)m_Reader.GetData(pImage->m_ImageData), pImage->m_Width, pImage->m_Height); if(!Success) continue; } char aTilemapFilename[512]; if(GameLayer) sprintf(aTilemapFilename, "%s/tiles_game_%d.png", aGeneratedFolder, pTilesLayer->m_Data); else sprintf(aTilemapFilename, "%s/tiles_%d.png", aGeneratedFolder, pTilesLayer->m_Data); CTilemap Dest; bool Success = Dest.Open(aTilemapFilename, pTilesLayer->m_Width, pTilesLayer->m_Height, &Src, pInfo->m_TileSize); if(!Success) continue; CTile *pTilesData = (CTile *)m_Reader.GetData(pTilesLayer->m_Data); for(int x = 0; x < pTilesLayer->m_Width; x++) { for(int y = 0; y < pTilesLayer->m_Height; y++) { CTile *pTile = &pTilesData[y*pTilesLayer->m_Width + x]; if(pTile->m_Index == 0) continue; Dest.SetTile(x, y, pTile->m_Index, pTile->m_Flags); } } Dest.Colorize(&pTilesLayer->m_Color); Dest.Save(); Src.Close(); m_TilemapsBenchmark.Pause(); } else if(pLayer->m_Type == LAYERTYPE_QUADS) { m_QuadsBenchmark.Unpause(); CMapItemLayerQuads *pQuadsLayer = (CMapItemLayerQuads *)pLayer; if(!pInfo->m_DumpQuads) continue; CImageRead Src; CMapItemImage *pImage = NULL; if(pQuadsLayer->m_Image >= 0) pImage = &pImages[pQuadsLayer->m_Image]; if(pQuadsLayer->m_Image >= 0) { const char *pImageName = (char *)m_Reader.GetData(pImage->m_ImageName); if(pImage->m_External) { char aImageFilename[512]; sprintf(aImageFilename, "%smapres/%s.png", pInfo->m_aCurrentDir, pImageName); bool Success = Src.Open(aImageFilename); if(!Success) continue; } else { bool Success = Src.OpenFromBuffer((unsigned char *)m_Reader.GetData(pImage->m_ImageData), pImage->m_Width, pImage->m_Height); if(!Success) continue; } } CQuad *pQuadsData = (CQuad *)m_Reader.GetData(pQuadsLayer->m_Data); for(int q = 0; q < pQuadsLayer->m_NumQuads; q++) { CQuad *pQuad = &pQuadsData[q]; int MinX = min(min(min(pQuad->m_aPoints[0].x, pQuad->m_aPoints[1].x), pQuad->m_aPoints[2].x), pQuad->m_aPoints[3].x) / 1024; int MinY = min(min(min(pQuad->m_aPoints[0].y, pQuad->m_aPoints[1].y), pQuad->m_aPoints[2].y), pQuad->m_aPoints[3].y) / 1024; int MaxX = max(max(max(pQuad->m_aPoints[0].x, pQuad->m_aPoints[1].x), pQuad->m_aPoints[2].x), pQuad->m_aPoints[3].x) / 1024; int MaxY = max(max(max(pQuad->m_aPoints[0].y, pQuad->m_aPoints[1].y), pQuad->m_aPoints[2].y), pQuad->m_aPoints[3].y) / 1024; int Width = MaxX-MinX; int Height = MaxY-MinY; if(Width <= 0 || Height <= 0) continue; char aQuadsFilename[512]; sprintf(aQuadsFilename, "%s/quads_%d_%d.png", aGeneratedFolder, pQuadsLayer->m_Data, q); CQuads Dest; bool Success = Dest.Open(aQuadsFilename, Width, Height, pInfo->m_TileSize); if(!Success) continue; if(pQuadsLayer->m_Image < 0) Dest.FillWhite(); else Dest.DrawImage(&Src); Dest.DrawGradient(pQuad->m_aColors); Dest.Save(); } m_QuadsBenchmark.Pause(); } } } // dump metadata if(pInfo->m_DumpMetadata) { m_MetadataBenchmark.Unpause(); CXMLDocument Doc; CXMLItem *pMainItem = Doc.Open("map"); pMainItem->AddAttributeInt("version", pVersion->m_Version); for(int i = 0; i < ImagesNum; i++) { const char *pName = (char *)m_Reader.GetData(pImages[i].m_ImageName); CXMLItem *pImageItem = pMainItem->AddChild("image"); pImageItem->AddAttributeInt("version", pImages[i].m_Version); pImageItem->AddAttributeInt("width", pImages[i].m_Width); pImageItem->AddAttributeInt("height", pImages[i].m_Height); pImageItem->AddAttributeBool("external", pImages[i].m_External); pImageItem->AddAttributeStr("name", pName); } for(int g = GroupsStart; g < GroupsStart+GroupsNum; g++) { CMapItemGroup *pGroup = (CMapItemGroup *)m_Reader.GetItem(g, NULL, NULL); CXMLItem *pGroupItem = pMainItem->AddChild("group"); pGroupItem->AddAttributeInt("version", pGroup->m_Version); pGroupItem->AddAttributeInt("offset_x", pGroup->m_OffsetX); pGroupItem->AddAttributeInt("offset_y", pGroup->m_OffsetY); pGroupItem->AddAttributeInt("parallax_x", pGroup->m_ParallaxX); pGroupItem->AddAttributeInt("parallax_y", pGroup->m_ParallaxY); if(pGroup->m_Version >= 2) { pGroupItem->AddAttributeBool("use_clipping", pGroup->m_UseClipping); pGroupItem->AddAttributeInt("clip_x", pGroup->m_ClipX); pGroupItem->AddAttributeInt("clip_y", pGroup->m_ClipY); pGroupItem->AddAttributeInt("clip_w", pGroup->m_ClipW); pGroupItem->AddAttributeInt("clip_h", pGroup->m_ClipH); } for(int l = LayersStart + pGroup->m_StartLayer; l < LayersStart + pGroup->m_StartLayer+pGroup->m_NumLayers; l++) { if(l >= LayersStart+LayersNum) break; CMapItemLayer *pLayer = (CMapItemLayer *)m_Reader.GetItem(l, NULL, NULL); CXMLItem *pLayerItem = pGroupItem->AddChild("layer"); if(pLayer->m_Type == LAYERTYPE_TILES) pLayerItem->AddAttributeStr("type", "tiles"); else if(pLayer->m_Type == LAYERTYPE_QUADS) pLayerItem->AddAttributeStr("type", "quads"); else pLayerItem->AddAttributeStr("type", "invalid"); pLayerItem->AddAttributeBool("detail", pLayer->m_Flags&TILESLAYERFLAG_GAME); if(pLayer->m_Type == LAYERTYPE_TILES) { CMapItemLayerTilemap *pTilesLayer = (CMapItemLayerTilemap *)pLayer; const char *pImageName = ""; if(pTilesLayer->m_Image >= 0 && pTilesLayer->m_Image < ImagesNum) pImageName = (char *)m_Reader.GetData(pImages[pTilesLayer->m_Image].m_ImageName); pLayerItem->AddAttributeInt("version", pTilesLayer->m_Version); pLayerItem->AddAttributeInt("width", pTilesLayer->m_Width); pLayerItem->AddAttributeInt("height", pTilesLayer->m_Height); pLayerItem->AddAttributeBool("game", pTilesLayer->m_Flags&TILESLAYERFLAG_GAME); pLayerItem->AddAttributeInt("color_env", pTilesLayer->m_ColorEnv); pLayerItem->AddAttributeInt("color_env_offset", pTilesLayer->m_ColorEnvOffset); pLayerItem->AddAttributeStr("image", pImageName); pLayerItem->AddAttributeInt("data", pTilesLayer->m_Data); CXMLItem *pColorItem = pLayerItem->AddChild("color"); pColorItem->AddAttributeInt("r", pTilesLayer->m_Color.r); pColorItem->AddAttributeInt("g", pTilesLayer->m_Color.g); pColorItem->AddAttributeInt("b", pTilesLayer->m_Color.b); pColorItem->AddAttributeInt("a", pTilesLayer->m_Color.a); } else if(pLayer->m_Type == LAYERTYPE_QUADS) { CMapItemLayerQuads *pQuadsLayer = (CMapItemLayerQuads *)pLayer; const char *pImageName = ""; if(pQuadsLayer->m_Image >= 0 && pQuadsLayer->m_Image < ImagesNum) pImageName = (char *)m_Reader.GetData(pImages[pQuadsLayer->m_Image].m_ImageName); pLayerItem->AddAttributeInt("version", pQuadsLayer->m_Version); pLayerItem->AddAttributeStr("image", pImageName); pLayerItem->AddAttributeInt("data", pQuadsLayer->m_Data); CQuad *pQuadsData = (CQuad *)m_Reader.GetData(pQuadsLayer->m_Data); for(int q = 0; q < pQuadsLayer->m_NumQuads; q++) { CQuad *pQuad = &pQuadsData[q]; CXMLItem *pQuadItem = pLayerItem->AddChild("quad"); pQuadItem->AddAttributeInt("pos_env", pQuad->m_PosEnv); pQuadItem->AddAttributeInt("pos_env_offset", pQuad->m_PosEnvOffset); pQuadItem->AddAttributeInt("color_env", pQuad->m_ColorEnv); pQuadItem->AddAttributeInt("color_env_offset", pQuad->m_ColorEnvOffset); pQuadItem->AddAttributeInt("data", q); for(int k = 0; k < 5; k++) { CXMLItem *pPointItem = pQuadItem->AddChild("point"); pPointItem->AddAttributeInt("x", fx2f(pQuad->m_aPoints[k].x)); pPointItem->AddAttributeInt("y", fx2f(pQuad->m_aPoints[k].y)); } for(int k = 0; k < 4; k++) { CXMLItem *pColorItem = pQuadItem->AddChild("color"); pColorItem->AddAttributeInt("r", pQuad->m_aColors[k].r); pColorItem->AddAttributeInt("g", pQuad->m_aColors[k].g); pColorItem->AddAttributeInt("b", pQuad->m_aColors[k].b); pColorItem->AddAttributeInt("a", pQuad->m_aColors[k].a); } for(int k = 0; k < 4; k++) { CXMLItem *pTexcoordItem = pQuadItem->AddChild("texcoord"); pTexcoordItem->AddAttributeInt("x", fx2f(pQuad->m_aTexcoords[k].x)); pTexcoordItem->AddAttributeInt("y", fx2f(pQuad->m_aTexcoords[k].y)); } } } } } int EnvPointsStart; int EnvPointsNum; m_Reader.GetType(MAPITEMTYPE_ENVPOINTS, &EnvPointsStart, &EnvPointsNum); CEnvPoint *pPoints = 0; if(EnvPointsNum) pPoints = (CEnvPoint *)m_Reader.GetItem(EnvPointsStart, NULL, NULL); int EnvStart; int EnvNum; m_Reader.GetType(MAPITEMTYPE_ENVELOPE, &EnvStart, &EnvNum); for(int e = EnvStart; e < EnvStart+EnvNum; e++) { CMapItemEnvelope *pEnv = (CMapItemEnvelope *)m_Reader.GetItem(e, NULL, NULL); CXMLItem *pEnvItem = pMainItem->AddChild("envelope"); pEnvItem->AddAttributeInt("version", pEnv->m_Version); if(pEnv->m_Channels == 3) pEnvItem->AddAttributeStr("type", "pos"); else if(pEnv->m_Channels == 4) pEnvItem->AddAttributeStr("type", "color"); else pEnvItem->AddAttributeStr("type", "invalid"); if(pEnv->m_aName[0] != -1) { char aEnvName[64]; IntsToStr(pEnv->m_aName, sizeof(pEnv->m_aName)/sizeof(int), aEnvName); pEnvItem->AddAttributeStr("name", aEnvName); } for(int p = pEnv->m_StartPoint; p < pEnv->m_StartPoint+pEnv->m_NumPoints; p++) { CXMLItem *pEnvPointItem = pEnvItem->AddChild("envpoint"); pEnvPointItem->AddAttributeInt("time", pPoints[p].m_Time); if(p != pEnv->m_StartPoint+pEnv->m_NumPoints -1) { if(pPoints[p].m_Curvetype == CURVETYPE_STEP) pEnvPointItem->AddAttributeStr("curvetype", "step"); else if(pPoints[p].m_Curvetype == CURVETYPE_LINEAR) pEnvPointItem->AddAttributeStr("curvetype", "linear"); else if(pPoints[p].m_Curvetype == CURVETYPE_SLOW) pEnvPointItem->AddAttributeStr("curvetype", "slow"); else if(pPoints[p].m_Curvetype == CURVETYPE_FAST) pEnvPointItem->AddAttributeStr("curvetype", "fast"); else if(pPoints[p].m_Curvetype == CURVETYPE_SMOOTH) pEnvPointItem->AddAttributeStr("curvetype", "smooth"); else pEnvPointItem->AddAttributeStr("curvetype", "invalid"); } if(pEnv->m_Channels == 3) { pEnvPointItem->AddAttributeInt("x", fx2f(pPoints[p].m_aValues[0])); pEnvPointItem->AddAttributeInt("y", fx2f(pPoints[p].m_aValues[1])); pEnvPointItem->AddAttributeInt("r", fx2f(pPoints[p].m_aValues[2])); } else if(pEnv->m_Channels == 4) { pEnvPointItem->AddAttributeInt("r", fx2f(pPoints[p].m_aValues[0])*255); pEnvPointItem->AddAttributeInt("g", fx2f(pPoints[p].m_aValues[1])*255); pEnvPointItem->AddAttributeInt("b", fx2f(pPoints[p].m_aValues[2])*255); pEnvPointItem->AddAttributeInt("a", fx2f(pPoints[p].m_aValues[3])*255); } } } char aMetadataFilename[512]; sprintf(aMetadataFilename, "%s/metadata.xml", aGeneratedFolder); Doc.Save(aMetadataFilename); Doc.Close(); m_MetadataBenchmark.Pause(); } if(ImagesNum > 0) delete pImages; remove(aGenerating); m_OverallBenchmark.Pause(); if(pInfo->m_ShowBenchmark) { printf("Benchmark results:\n"); printf(" Images dumping:\t%dms\n", m_ImagesBenchmark.GetTime()); printf(" Tilemaps dumping:\t%dms\n", m_TilemapsBenchmark.GetTime()); printf(" Quads dumping:\t%dms\n", m_QuadsBenchmark.GetTime()); printf(" Metadata dumping:\t%dms\n", m_MetadataBenchmark.GetTime()); printf(" Overall:\t\t%dms\n", m_OverallBenchmark.GetTime()); } }
void CRenderTools::RenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags, ENVELOPE_EVAL pfnEval, void *pUser) { Graphics()->QuadsBegin(); float Conv = 1/255.0f; for(int i = 0; i < NumQuads; i++) { CQuad *q = &pQuads[i]; float r=1, g=1, b=1, a=1; if(q->m_ColorEnv >= 0) { float aChannels[4]; pfnEval(q->m_ColorEnvOffset/1000.0f, q->m_ColorEnv, aChannels, pUser); r = aChannels[0]; g = aChannels[1]; b = aChannels[2]; a = aChannels[3]; } /*bool Opaque = false; TODO: Analyze quadtexture if(a < 0.01f || (q->m_aColors[0].a < 0.01f && q->m_aColors[1].a < 0.01f && q->m_aColors[2].a < 0.01f && q->m_aColors[3].a < 0.01f)) Opaque = true; if(Opaque && !(RenderFlags&LAYERRENDERFLAG_OPAQUE)) continue; if(!Opaque && !(RenderFlags&LAYERRENDERFLAG_TRANSPARENT)) continue; */ vec2 aTexCoords[4]; for(int k = 0; k < 4; k++) { aTexCoords[k].x = fx2f(q->m_aTexcoords[k].x); aTexCoords[k].y = fx2f(q->m_aTexcoords[k].y); } // Check if we want to repeat the texture // Otherwise clamp to the edge to prevent texture bleeding bool RepeatU = false, RepeatV = false; for(int k = 0; k < 4; k++) { if(aTexCoords[k].x < 0.0f || aTexCoords[k].x > 1.0f) RepeatU = true; if(aTexCoords[k].y < 0.0f || aTexCoords[k].y > 1.0f) RepeatV = true; } Graphics()->WrapMode( RepeatU ? IGraphics::WRAP_REPEAT : IGraphics::WRAP_CLAMP, RepeatV ? IGraphics::WRAP_REPEAT : IGraphics::WRAP_CLAMP); Graphics()->QuadsSetSubsetFree( aTexCoords[0].x, aTexCoords[0].y, aTexCoords[1].x, aTexCoords[1].y, aTexCoords[2].x, aTexCoords[2].y, aTexCoords[3].x, aTexCoords[3].y); float OffsetX = 0; float OffsetY = 0; float Rot = 0; // TODO: fix this if(q->m_PosEnv >= 0) { float aChannels[4]; pfnEval(q->m_PosEnvOffset/1000.0f, q->m_PosEnv, aChannels, pUser); OffsetX = aChannels[0]; OffsetY = aChannels[1]; Rot = aChannels[2]/360.0f*pi*2; } IGraphics::CColorVertex Array[4] = { IGraphics::CColorVertex(0, q->m_aColors[0].r*Conv*r*q->m_aColors[0].a*Conv*a, q->m_aColors[0].g*Conv*g*q->m_aColors[0].a*Conv*a, q->m_aColors[0].b*Conv*b*q->m_aColors[0].a*Conv*a, q->m_aColors[0].a*Conv*a), IGraphics::CColorVertex(1, q->m_aColors[1].r*Conv*r*q->m_aColors[1].a*Conv*a, q->m_aColors[1].g*Conv*g*q->m_aColors[1].a*Conv*a, q->m_aColors[1].b*Conv*b*q->m_aColors[1].a*Conv*a, q->m_aColors[1].a*Conv*a), IGraphics::CColorVertex(2, q->m_aColors[2].r*Conv*r*q->m_aColors[2].a*Conv*a, q->m_aColors[2].g*Conv*g*q->m_aColors[2].a*Conv*a, q->m_aColors[2].b*Conv*b*q->m_aColors[2].a*Conv*a, q->m_aColors[2].a*Conv*a), IGraphics::CColorVertex(3, q->m_aColors[3].r*Conv*r*q->m_aColors[3].a*Conv*a, q->m_aColors[3].g*Conv*g*q->m_aColors[3].a*Conv*a, q->m_aColors[3].b*Conv*b*q->m_aColors[3].a*Conv*a, q->m_aColors[3].a*Conv*a)}; Graphics()->SetColorVertex(Array, 4); CPoint *pPoints = q->m_aPoints; if(Rot != 0) { static CPoint aRotated[4]; aRotated[0] = q->m_aPoints[0]; aRotated[1] = q->m_aPoints[1]; aRotated[2] = q->m_aPoints[2]; aRotated[3] = q->m_aPoints[3]; pPoints = aRotated; Rotate(&q->m_aPoints[4], &aRotated[0], Rot); Rotate(&q->m_aPoints[4], &aRotated[1], Rot); Rotate(&q->m_aPoints[4], &aRotated[2], Rot); Rotate(&q->m_aPoints[4], &aRotated[3], Rot); } IGraphics::CFreeformItem Freeform( fx2f(pPoints[0].x)+OffsetX, fx2f(pPoints[0].y)+OffsetY, fx2f(pPoints[1].x)+OffsetX, fx2f(pPoints[1].y)+OffsetY, fx2f(pPoints[2].x)+OffsetX, fx2f(pPoints[2].y)+OffsetY, fx2f(pPoints[3].x)+OffsetX, fx2f(pPoints[3].y)+OffsetY); Graphics()->QuadsDrawFreeform(&Freeform, 1); } Graphics()->QuadsEnd(); Graphics()->WrapNormal(); }
void CRenderTools::RenderEvalEnvelope(CEnvPoint *pPoints, int NumPoints, int Channels, float Time, float *pResult) { if(NumPoints == 0) { pResult[0] = 0; pResult[1] = 0; pResult[2] = 0; pResult[3] = 0; return; } if(NumPoints == 1) { pResult[0] = fx2f(pPoints[0].m_aValues[0]); pResult[1] = fx2f(pPoints[0].m_aValues[1]); pResult[2] = fx2f(pPoints[0].m_aValues[2]); pResult[3] = fx2f(pPoints[0].m_aValues[3]); return; } Time = fmod(Time, pPoints[NumPoints-1].m_Time/1000.0f)*1000.0f; for(int i = 0; i < NumPoints-1; i++) { if(Time >= pPoints[i].m_Time && Time <= pPoints[i+1].m_Time) { float Delta = pPoints[i+1].m_Time-pPoints[i].m_Time; float a = (Time-pPoints[i].m_Time)/Delta; switch(pPoints[i].m_Curvetype) { case CURVETYPE_STEP: a = 0; break; case CURVETYPE_SMOOTH: a = -2*a*a*a + 3*a*a; // second hermite basis break; case CURVETYPE_SLOW: a = a*a*a; break; case CURVETYPE_FAST: a = 1-a; a = 1-a*a*a; break; case CURVETYPE_BEZIER: for(int c = 0; c < Channels; c++) { // monotonic 2d cubic bezier curve vec2 p0, p1, p2, p3; vec2 inTang, outTang; p0 = vec2(pPoints[i].m_Time/1000.0f, fx2f(pPoints[i].m_aValues[c])); p3 = vec2(pPoints[i+1].m_Time/1000.0f, fx2f(pPoints[i+1].m_aValues[c])); outTang = vec2(pPoints[i].m_aOutTangentdx[c]/1000.0f, fx2f(pPoints[i].m_aOutTangentdy[c])); inTang = -vec2(pPoints[i+1].m_aInTangentdx[c]/1000.0f, fx2f(pPoints[i+1].m_aInTangentdy[c])); p1 = p0 + outTang; p2 = p3 - inTang; // validate bezier curve ValidateFCurve(p0, p1, p2, p3); // solve x(a) = time for a a = clamp(SolveBezier(Time/1000.0f, p0.x, p1.x, p2.x, p3.x), 0.0f, 1.0f); // value = y(t) pResult[c] = bezier(p0.y, p1.y, p2.y, p3.y, a); } return; case CURVETYPE_LINEAR: break; } for(int c = 0; c < Channels; c++) { float v0 = fx2f(pPoints[i].m_aValues[c]); float v1 = fx2f(pPoints[i+1].m_aValues[c]); pResult[c] = mix(v0, v1, a); } return; } } pResult[0] = fx2f(pPoints[NumPoints-1].m_aValues[0]); pResult[1] = fx2f(pPoints[NumPoints-1].m_aValues[1]); pResult[2] = fx2f(pPoints[NumPoints-1].m_aValues[2]); pResult[3] = fx2f(pPoints[NumPoints-1].m_aValues[3]); return; }