diff --git a/src/cdogs/draw/draw_actor.c b/src/cdogs/draw/draw_actor.c index 69878515f..3694d8837 100644 --- a/src/cdogs/draw/draw_actor.c +++ b/src/cdogs/draw/draw_actor.c @@ -1,50 +1,50 @@ /* - C-Dogs SDL - A port of the legendary (and fun) action/arcade cdogs. - Copyright (C) 1995 Ronny Wester - Copyright (C) 2003 Jeremy Chin - Copyright (C) 2003-2007 Lucas Martin-King - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - This file incorporates work covered by the following copyright and - permission notice: - - Copyright (c) 2013-2019 Cong Xu - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. + C-Dogs SDL + A port of the legendary (and fun) action/arcade cdogs. + Copyright (C) 1995 Ronny Wester + Copyright (C) 2003 Jeremy Chin + Copyright (C) 2003-2007 Lucas Martin-King + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + This file incorporates work covered by the following copyright and + permission notice: + + Copyright (c) 2013-2020 Cong Xu + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. */ #include "draw/draw_actor.h" @@ -163,9 +163,6 @@ ActorPics GetCharacterPicsFromActor(TActor *a) gun->Gun != NULL ? gun->Gun->Sprites : NULL, gun->state, shadowMask, maskP, colors, a->dead); } -static const Pic *GetHairPic( - const Character *c, const direction_e dir, const gunstate_e gunState, - const CharColors *colors); static const Pic *GetBodyPic( PicManager *pm, const CharSprites *cs, const direction_e dir, const ActorAnimation anim, const int frame, const bool isArmed, @@ -238,7 +235,10 @@ ActorPics GetCharacterPics( pics.HeadOffset = GetActorDrawOffset( pics.Head, BODY_PART_HEAD, c->Class->Sprites, anim, frame, dir, gunState); - pics.Hair = GetHairPic(c, headDir, gunState, colors); + if (c->Class->HasHair) + { + pics.Hair = GetHairPic(c->Hair, headDir, gunState, colors); + } pics.HairOffset = GetActorDrawOffset( pics.Hair, BODY_PART_HAIR, c->Class->Sprites, anim, frame, dir, gunState); @@ -432,11 +432,11 @@ const Pic *GetHeadPic( &gPicManager, c->HeadSprites, colors); return CArrayGet(&ns->pics, idx); } -static const Pic *GetHairPic( - const Character *c, const direction_e dir, const gunstate_e gunState, +const Pic *GetHairPic( + const char *hair, const direction_e dir, const gunstate_e gunState, const CharColors *colors) { - if (!c->Class->HasHair || c->Hair == NULL) + if (hair == NULL) { return NULL; } @@ -445,7 +445,7 @@ static const Pic *GetHairPic( const int idx = (int)dir + row * 8; // Get or generate masked sprites char buf[CDOGS_PATH_MAX]; - sprintf(buf, "chars/hairs/%s", c->Hair); + sprintf(buf, "chars/hairs/%s", hair); const NamedSprites *ns = PicManagerGetCharSprites(&gPicManager, buf, colors); return CArrayGet(&ns->pics, idx); @@ -535,12 +535,15 @@ void DrawHead( PicRender( head, renderer, drawPos, mask, 0, svec2_one(), SDL_FLIP_NONE, Rect2iZero()); - const Pic *hair = GetHairPic(c, dir, g, &c->Colors); - if (hair) + if (c->Class->HasHair) { - PicRender( - hair, renderer, drawPos, mask, 0, svec2_one(), SDL_FLIP_NONE, - Rect2iZero()); + const Pic* hair = GetHairPic(c->Hair, dir, g, &c->Colors); + if (hair) + { + PicRender( + hair, renderer, drawPos, mask, 0, svec2_one(), SDL_FLIP_NONE, + Rect2iZero()); + } } } #define DYING_BODY_OFFSET 3 diff --git a/src/cdogs/draw/draw_actor.h b/src/cdogs/draw/draw_actor.h index 248c6a15b..6e5158331 100644 --- a/src/cdogs/draw/draw_actor.h +++ b/src/cdogs/draw/draw_actor.h @@ -85,6 +85,9 @@ void DrawHead( const Pic *GetHeadPic( const CharacterClass *c, const direction_e dir, const gunstate_e gunState, const CharColors *colors); +const Pic* GetHairPic( + const char* hair, const direction_e dir, const gunstate_e gunState, + const CharColors* colors); ActorPics GetCharacterPics( const Character *c, const direction_e dir, const direction_e legDir, const ActorAnimation anim, const int frame, diff --git a/src/cdogs/map_new.c b/src/cdogs/map_new.c index 378e5c22b..de669a108 100644 --- a/src/cdogs/map_new.c +++ b/src/cdogs/map_new.c @@ -1,29 +1,29 @@ /* - C-Dogs SDL - A port of the legendary (and fun) action/arcade cdogs. - Copyright (c) 2014-2017, 2019 Cong Xu - All rights reserved. + C-Dogs SDL + A port of the legendary (and fun) action/arcade cdogs. + Copyright (c) 2014-2017, 2019 Cong Xu + All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. */ #include "map_new.h" @@ -399,16 +399,16 @@ void LoadMissionTileClasses( LoadColor(&altMask, node, "AltMask"); } TileClassInit( - &mtc->Wall, &gPicManager, &gTileWall, wallStyle, NULL, + &mtc->Wall, &gPicManager, &gTileWall, wallStyle, "o", wallMask, altMask); TileClassInit( - &mtc->Floor, &gPicManager, &gTileFloor, floorStyle, NULL, + &mtc->Floor, &gPicManager, &gTileFloor, floorStyle, "normal", floorMask, altMask); TileClassInit( - &mtc->Room, &gPicManager, &gTileRoom, roomStyle, NULL, + &mtc->Room, &gPicManager, &gTileRoom, roomStyle, "normal", roomMask, altMask); TileClassInit( - &mtc->Door, &gPicManager, &gTileDoor, doorStyle, NULL, + &mtc->Door, &gPicManager, &gTileDoor, doorStyle, "normal_h", colorWhite, colorWhite); } else diff --git a/src/cdogs/mission_static.c b/src/cdogs/mission_static.c index f63fe2d6d..693ee0728 100644 --- a/src/cdogs/mission_static.c +++ b/src/cdogs/mission_static.c @@ -209,6 +209,7 @@ static void ConvertOldTile( memcpy(tc, base, sizeof *tc); if (base->Name) CSTRDUP(tc->Name, base->Name); if (base->Style) CSTRDUP(tc->Style, base->Style); + if (base->StyleType) CSTRDUP(tc->StyleType, base->StyleType); tc->Mask = base->Mask; tc->MaskAlt = base->MaskAlt; if (hashmap_put(m->TileClasses, keyBuf, tc) != MAP_OK) diff --git a/src/cdogs/tile_class.c b/src/cdogs/tile_class.c index 4578bd8d0..511d12da1 100644 --- a/src/cdogs/tile_class.c +++ b/src/cdogs/tile_class.c @@ -1,29 +1,29 @@ /* - C-Dogs SDL - A port of the legendary (and fun) action/arcade cdogs. - Copyright (c) 2018-2020 Cong Xu - All rights reserved. + C-Dogs SDL + A port of the legendary (and fun) action/arcade cdogs. + Copyright (c) 2018-2020 Cong Xu + All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. */ #include "tile_class.h" @@ -165,11 +165,14 @@ void TileClassInit( } t->Mask = mask; t->MaskAlt = maskAlt; - // Generate the pic in case it doesn't exist - PicManagerGenerateMaskedStylePic( - pm, t->Name, style, type, mask, maskAlt, false); - t->Pic = TileClassGetPic(pm, t); - CASSERT(t->Pic != NULL, "cannot find tile pic"); + if (t->Name != NULL) + { + // Generate the pic in case it doesn't exist + PicManagerGenerateMaskedStylePic( + pm, t->Name, style, type, mask, maskAlt, false); + t->Pic = TileClassGetPic(pm, t); + CASSERT(t->Pic != NULL, "cannot find tile pic"); + } } const TileClass *TileClassesGetMaskedTile( const TileClass *baseClass, const char *style, const char *type, diff --git a/src/cdogsed/char_editor.c b/src/cdogsed/char_editor.c index d0c5088cb..2e3838281 100644 --- a/src/cdogsed/char_editor.c +++ b/src/cdogsed/char_editor.c @@ -1,7 +1,7 @@ /* C-Dogs SDL A port of the legendary (and fun) action/arcade cdogs. - Copyright (c) 2017-2019 Cong Xu + Copyright (c) 2017-2020 Cong Xu All rights reserved. Redistribution and use in source and binary forms, with or without @@ -42,10 +42,12 @@ typedef struct CampaignSetting *Setting; bool *FileChanged; char *CharacterClassNames; + char *HairNames; char *GunNames; CArray texidsChars; // of GLuint[BODY_PART_COUNT] GLuint texidsPreview[BODY_PART_COUNT]; CArray texIdsCharClasses; // of GLuint + CArray texIdsHairs; // of GLuint CArray texIdsGuns; // of GLuint Animation anim; direction_e previewDir; @@ -55,9 +57,12 @@ typedef struct static char *GetClassNames(const int len, const char *(*indexNameFunc)(int)); static const char *IndexCharacterClassName(const int i); +static const char *IndexHairName(const int i); static int NumCharacterClasses(void); static const char *IndexGunName(const int i); static int NumGuns(void); +static void TexArrayInit(CArray* arr, const int count); +static void TexArrayTerminate(CArray *arr); static int GunIndex(const WeaponClass *wc); static void AddCharacterTextures(EditorContext *ec); static bool Draw(SDL_Window *win, struct nk_context *ctx, void *data); @@ -86,6 +91,8 @@ void CharEditor( ec.FileChanged = fileChanged; ec.CharacterClassNames = GetClassNames( NumCharacterClasses(), IndexCharacterClassName); + ec.HairNames = GetClassNames( + gPicManager.hairstyleNames.size, IndexHairName); ec.GunNames = GetClassNames(NumGuns(), IndexGunName); CArrayInit(&ec.texidsChars, sizeof(GLuint) * BODY_PART_COUNT); @@ -94,23 +101,26 @@ void CharEditor( AddCharacterTextures(&ec); } glGenTextures(BODY_PART_COUNT, ec.texidsPreview); - CArrayInit(&ec.texIdsCharClasses, sizeof(GLuint)); - CArrayResize(&ec.texIdsCharClasses, NumCharacterClasses(), NULL); - glGenTextures(NumCharacterClasses(), (GLuint *)ec.texIdsCharClasses.data); + CharColors cc; cc.Skin = colorSkin; cc.Hair = colorRed; - for (int i = 0; i < NumCharacterClasses(); i++) - { - const GLuint *texid = CArrayGet(&ec.texIdsCharClasses, i); - const CharacterClass *c = IndexCharacterClass(i); + + TexArrayInit(&ec.texIdsCharClasses, NumCharacterClasses()); + CA_FOREACH(const GLuint, texid, ec.texIdsCharClasses) + const CharacterClass *c = IndexCharacterClass(_ca_index); LoadTexFromPic( *texid, GetHeadPic(c, DIRECTION_DOWN, GUNSTATE_READY, &cc)); - // TODO: also get hair pic - } - CArrayInit(&ec.texIdsGuns, sizeof(GLuint)); - CArrayResize(&ec.texIdsGuns, NumGuns(), NULL); - glGenTextures(NumGuns(), (GLuint *)ec.texIdsGuns.data); + CA_FOREACH_END() + + TexArrayInit(&ec.texIdsHairs, gPicManager.hairstyleNames.size); + CA_FOREACH(const GLuint, texid, ec.texIdsHairs) + const char *hair = IndexHairName(_ca_index); + LoadTexFromPic( + *texid, GetHairPic(hair, DIRECTION_DOWN, GUNSTATE_READY, &cc)); + CA_FOREACH_END() + + TexArrayInit(&ec.texIdsGuns, NumGuns()); for (int i = 0; i < NumGuns(); i++) { const GLuint *texid = CArrayGet(&ec.texIdsGuns, i); @@ -127,17 +137,15 @@ void CharEditor( NKWindow(cfg); CFREE(ec.CharacterClassNames); + CFREE(ec.HairNames); CFREE(ec.GunNames); glDeleteTextures( (GLsizei)(BODY_PART_COUNT * ec.texidsChars.size), ec.texidsChars.data); CArrayTerminate(&ec.texidsChars); glDeleteTextures(BODY_PART_COUNT, ec.texidsPreview); - glDeleteTextures( - (GLsizei)ec.texIdsCharClasses.size, - (const GLuint *)ec.texIdsCharClasses.data); - CArrayTerminate(&ec.texIdsCharClasses); - glDeleteTextures((GLsizei)(ec.texIdsGuns.size), (const GLuint *)ec.texIdsGuns.data); - CArrayTerminate(&ec.texIdsGuns); + TexArrayTerminate(&ec.texIdsCharClasses); + TexArrayTerminate(&ec.texIdsHairs); + TexArrayTerminate(&ec.texIdsGuns); } static char *GetClassNames(const int len, const char *(*indexNameFunc)(int)) @@ -170,6 +178,10 @@ static const char *IndexCharacterClassName(const int i) const CharacterClass *c = IndexCharacterClass(i); return c->Name; } +static const char *IndexHairName(const int i) +{ + return *(char **)CArrayGet(&gPicManager.hairstyleNames, i); +} static int NumCharacterClasses(void) { return @@ -226,6 +238,18 @@ static int GunIndex(const WeaponClass *wc) return -1; } +static void TexArrayInit(CArray *arr, const int count) +{ + CArrayInit(arr, sizeof(GLuint)); + CArrayResize(arr, count, NULL); + glGenTextures(count, (GLuint*)arr->data); +} +static void TexArrayTerminate(CArray *arr) +{ + glDeleteTextures((GLsizei)arr->size, (const GLuint*)arr->data); + CArrayTerminate(arr); +} + static void AddCharacter(EditorContext *ec, const int cloneIdx); static int MoveCharacter( EditorContext *ec, const int selectedIndex, const int d); @@ -234,6 +258,7 @@ static int DrawClassSelection( struct nk_context *ctx, EditorContext *ec, const char *label, const GLuint *texids, const char *items, const int selected, const size_t len); +static int HairIndex(const char *hair); static void DrawCharColor( struct nk_context *ctx, EditorContext *ec, const char *label, color_t *c); static void DrawFlag( @@ -363,16 +388,44 @@ static bool Draw(SDL_Window *win, struct nk_context *ctx, void *data) nk_end(ctx); if (nk_begin(ctx, "Appearance", - nk_rect(pad, (float)charStoreSize.y + pad, 260, 225), + nk_rect(pad, (float)charStoreSize.y + pad, 260, 280), NK_WINDOW_BORDER|NK_WINDOW_TITLE)) { nk_layout_row(ctx, NK_DYNAMIC, ROW_HEIGHT, 2, colRatios); + const int selectedClass = DrawClassSelection( ctx, ec, "Class:", ec->texIdsCharClasses.data, ec->CharacterClassNames, (int)CharacterClassIndex(ec->Char->Class), NumCharacterClasses()); ec->Char->Class = IndexCharacterClass(selectedClass); + nk_layout_row_dynamic(ctx, ROW_HEIGHT, 1); + int hasHair = ec->Char->Hair != NULL; + nk_checkbox_label(ctx, "Has Hair", &hasHair); + + if (hasHair) + { + nk_layout_row(ctx, NK_DYNAMIC, ROW_HEIGHT, 2, colRatios); + const int currentHair = (int)HairIndex(ec->Char->Hair); + int selectedHair = DrawClassSelection( + ctx, ec, "Hair:", ec->texIdsHairs.data, + ec->HairNames, currentHair, gPicManager.hairstyleNames.size); + if (selectedHair == -1) + { + selectedHair = 0; + } + if (currentHair != selectedHair) + { + CFREE(ec->Char->Hair); + CSTRDUP(ec->Char->Hair, IndexHairName(selectedHair)); + } + } + else + { + CFREE(ec->Char->Hair); + ec->Char->Hair = NULL; + } + // Character colours nk_layout_row(ctx, NK_DYNAMIC, ROW_HEIGHT, 2, colRatios); DrawCharColor(ctx, ec, "Skin:", &ec->Char->Colors.Skin); @@ -565,6 +618,21 @@ static int DrawClassSelection( return selectedNew; } +static int HairIndex(const char *hair) +{ + if (hair == NULL) + { + return -1; + } + CA_FOREACH(const char *, hairstyleName, gPicManager.hairstyleNames) + if (strcmp(*hairstyleName, hair) == 0) + { + return _ca_index; + } + CA_FOREACH_END() + return -1; +} + static void DrawCharColor( struct nk_context *ctx, EditorContext *ec, const char *label, color_t *c) {