From 411c5a8e210b5cbca330a5438e2406dbe1ffecab Mon Sep 17 00:00:00 2001 From: Treeki Date: Thu, 27 Sep 2012 04:40:34 +0200 Subject: made world changes work, and HUD colourising and other fun things --- src/koopatlas/hud.cpp | 158 ++++++++++++++++++++++++++++++++++++++++-- src/koopatlas/hud.h | 21 +++++- src/koopatlas/mapdata.cpp | 2 +- src/koopatlas/pathmanager.cpp | 11 +-- 4 files changed, 177 insertions(+), 15 deletions(-) (limited to 'src/koopatlas') diff --git a/src/koopatlas/hud.cpp b/src/koopatlas/hud.cpp index 4f4ce2f..84329bf 100644 --- a/src/koopatlas/hud.cpp +++ b/src/koopatlas/hud.cpp @@ -1,5 +1,146 @@ #include "koopatlas/hud.h" + +dTexMapColouriser_c::dTexMapColouriser_c() { + texmap = 0; + original = 0; + mine = 0; +} + +void *EGG__Heap__alloc(unsigned long size, int unk, void *heap); +void EGG__Heap__free(void *ptr, void *heap); + +dTexMapColouriser_c::~dTexMapColouriser_c() { + resetAndClear(); +} + +void dTexMapColouriser_c::resetAndClear() { + texmap = 0; + if (mine) { + EGG__Heap__free(mine, 0); + mine = 0; + } +} + +void dTexMapColouriser_c::setTexMap(nw4r::lyt::TexMap *tm) { + OSReport("Colourising TexMap: %p (w:%d h:%d)\n", tm, tm->width, tm->height); + if (texmap) + resetAndClear(); + + if (tm->mBits.textureFormat != GX_TF_IA8) { + OSReport("Warning: Trying to colourise image whose format is %d not GX_TF_IA8\n", tm->mBits.textureFormat); + } + + texmap = tm; + original = (u16*)tm->image; + mine = (u16*)EGG__Heap__alloc(tm->width * tm->height * 4, 0x20, mHeap::gameHeaps[2]); + tm->image = mine; + tm->mBits.textureFormat = GX_TF_RGBA8; +} + +void dTexMapColouriser_c::applyAlso(nw4r::lyt::TexMap *tm) { + if (!texmap) { + setTexMap(tm); + } else { + tm->image = mine; + tm->mBits.textureFormat = GX_TF_RGBA8; + } +} + +inline static float hslValue(float n1, float n2, float hue) { + if (hue > 6.0f) + hue -= 6.0f; + else if (hue < 0.0f) + hue += 6.0f; + + if (hue < 1.0f) + return n1 + (n1 - n1) * hue; + else if (hue < 3.0f) + return n2; + else if (hue < 4.0f) + return n1 + (n2 - n1) * (4.0f - hue); + else + return n1; +} + +void dTexMapColouriser_c::colourise(int h, int s, int l) { + if (!mine) + return; + + int width = texmap->width, height = texmap->height; + int texelW = width / 4, texelH = height / 4; + + u16 *source = original, *dest = mine; + + float hueParam = h / 360.0f; + float satParam = s / 100.0f; + float lumParam = l / 100.0f; + + for (int texelY = 0; texelY < texelH; texelY++) { + for (int texelX = 0; texelX < texelW; texelX++) { + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 4; x++) { + u8 intensity = *source & 0xFF; + u8 alpha = *source >> 8; + + u8 r, g, b; + + // This is a hack + if (alpha < 250) { + r = g = b = intensity; + } else { + // converting from GIMP's colourise code... + // h and s are always the same + // l is the only thing we need to touch: + // we get the luminance from the source pixel + // (which, conveniently, is the intensity) + // manipulate it using the passed l and then + // convert the whole thing to RGB + + float lum = intensity / 255.0f; + + // manipulate it + if (l > 0) { + lum = lum * (1.0f - lumParam); + lum += (1.0f - (1.0f - lumParam)); + } else if (l < 0) { + lum = lum * (lumParam + 1.0f); + } + + // make it RGB + + if (s == 0) { + r = g = b = lum*255.0f; + } else { + float m1, m2; + if (lum <= 0.5f) + m2 = lum * (1.0f + satParam); + else + m2 = lum + satParam - lum * satParam; + + m1 = 2.0f * lum - m2; + + r = hslValue(m1, m2, hueParam * 6.0f + 2.0) * 255.0f; + g = hslValue(m1, m2, hueParam * 6.0f) * 255.0f; + b = hslValue(m1, m2, hueParam * 6.0f - 2.0) * 255.0f; + } + } + + // now write it + dest[0] = (alpha<<8)|r; + dest[16] = (g<<8)|b; + + source++; + dest++; + } + } + + dest += 16; + } + } +} + + dWMHud_c *dWMHud_c::instance = 0; dWMHud_c *dWMHud_c::build() { @@ -63,13 +204,13 @@ int dWMHud_c::onCreate() { layout.getPanes(paneNames, &N_IconPosXP_00[0], 4); static const char *pictureNames[] = { - "Header_Centre", "Header_Right", + "Header_Centre", "Header_Right", "Footer", "NormalExitFlag", "SecretExitFlag", "StarCoinOn0", "StarCoinOn1", "StarCoinOn2", "P_marioFace_00", "P_luigiFace_00", "P_BkinoFace_00", "P_YkinoFace_00" }; - layout.getPictures(pictureNames, &Header_Centre, 11); + layout.getPictures(pictureNames, &Header_Centre, 12); static const char *textBoxNames[] = { "LevelName", "LevelNameS", @@ -81,6 +222,10 @@ int dWMHud_c::onCreate() { }; layout.getTextBoxes(textBoxNames, &LevelName, 11); + headerCol.setTexMap(Header_Right->material->texMaps); + headerCol.applyAlso(Header_Centre->material->texMaps); + footerCol.setTexMap(Footer->material->texMaps); + layoutLoaded = true; willShowHeader = false; @@ -228,6 +373,9 @@ void dWMHud_c::loadHeaderInfo() { totalWidth = 270.0f; Header_Centre->size.x = totalWidth; Header_Right->trans.x = totalWidth; + + SaveBlock *save = GetSaveFile()->GetBlock(-1); + headerCol.colourise(save->hudHintH, save->hudHintS, save->hudHintL); } @@ -246,8 +394,10 @@ void dWMHud_c::loadFooterInfo() { WorldName->SetString(convertedWorldName); WorldNameS->SetString(convertedWorldName); - WorldName->colour1 = save->hudTextColour[0]; - WorldName->colour2 = save->hudTextColour[1]; + WorldName->colour1 = save->hudTextColours[0]; + WorldName->colour2 = save->hudTextColours[1]; + + footerCol.colourise(save->hudHintH, save->hudHintS, save->hudHintL); } diff --git a/src/koopatlas/hud.h b/src/koopatlas/hud.h index deac84f..c0079af 100644 --- a/src/koopatlas/hud.h +++ b/src/koopatlas/hud.h @@ -3,6 +3,23 @@ #include "koopatlas/core.h" +// Colourises an IA8 texture +class dTexMapColouriser_c { + public: + dTexMapColouriser_c(); + ~dTexMapColouriser_c(); + + void resetAndClear(); + void setTexMap(nw4r::lyt::TexMap *tm); + void applyAlso(nw4r::lyt::TexMap *tm); + void colourise(int h, int s, int l); + + private: + nw4r::lyt::TexMap *texmap; + u16 *original; + u16 *mine; +}; + class dWMHud_c : public dBase_c { public: dWMHud_c(); @@ -39,12 +56,14 @@ class dWMHud_c : public dBase_c { void loadFooterInfo(); bool willShowFooter; + dTexMapColouriser_c headerCol, footerCol; + nw4r::lyt::Pane *N_IconPosXP_00[4]; nw4r::lyt::Picture - *Header_Centre, *Header_Right, + *Header_Centre, *Header_Right, *Footer, *NormalExitFlag, *SecretExitFlag, *StarCoinOn[3], *P_marioFace_00, *P_luigiFace_00, diff --git a/src/koopatlas/mapdata.cpp b/src/koopatlas/mapdata.cpp index 29c6a23..d4f9d0c 100644 --- a/src/koopatlas/mapdata.cpp +++ b/src/koopatlas/mapdata.cpp @@ -286,7 +286,7 @@ void dKPMapData_c::fixup() { } -const dKPWorldDef_s *dKPMapData_c::findWorldDef(int id) { +const dKPWorldDef_s *dKPMapData_c::findWorldDef(int id) const { for (int i = 0; i < data->worldCount; i++) { if (data->worlds[i].key == id) return &data->worlds[i]; diff --git a/src/koopatlas/pathmanager.cpp b/src/koopatlas/pathmanager.cpp index 2401e04..896707a 100644 --- a/src/koopatlas/pathmanager.cpp +++ b/src/koopatlas/pathmanager.cpp @@ -566,7 +566,7 @@ void dWMPathManager_c::moveThroughPath() { isJumping = false; timer = 0.0; - SpammyReport("reached path end (%p)\n", to); + SpammyReport("reached path end (%p) with type %d\n", to, to->type); bool reallyStop = false; @@ -595,7 +595,7 @@ void dWMPathManager_c::moveThroughPath() { SaveBlock *save = GetSaveFile()->GetBlock(-1); OSReport("Activating world change %d\n", to->worldID); - dKPWorldDef_s *world = dScKoopatlas_c::instance->mapData.findWorldDef(to->worldID); + const dKPWorldDef_s *world = dScKoopatlas_c::instance->mapData.findWorldDef(to->worldID); if (world) { OSReport("Found!\n"); strncpy(save->newerWorldName, world->name, 36); @@ -653,13 +653,6 @@ void dWMPathManager_c::moveThroughPath() { save->current_path_node = pathLayer->findNodeID(to); if (!calledEnteredNode) dWMHud_c::instance->enteredNode(); - - if (to->type == dKPNode_s::LEVEL) { - NWRWorld nWorld = NewerWorldForLevelID(to->levelNumber[0], to->levelNumber[1]); - if (nWorld != UNKNOWN_WORLD) { - save->currentNewerWorld = (u8)nWorld; - } - } } else { startMovementTo(to->getOppositeAvailableExitTo(currentPath)); SpammyReport("passthrough node, continuing to next path\n"); -- cgit v1.2.3