From 0fb9e10a7af80cbe94fe27bc97d4f7b45e456e48 Mon Sep 17 00:00:00 2001 From: requinDr <75610214+requinDr@users.noreply.github.com> Date: Fri, 21 Jun 2024 18:21:21 +0200 Subject: [PATCH] Add a few thumbnails and blur on flowchart --- src/assets/game/scene_attrs.json | 72 +++--- src/components/Flowchart.tsx | 431 ++++++++++++++++--------------- src/styles/flowchart.scss | 112 ++++---- src/styles/gallery.scss | 84 +++--- 4 files changed, 358 insertions(+), 341 deletions(-) diff --git a/src/assets/game/scene_attrs.json b/src/assets/game/scene_attrs.json index 11bb1c3..bcc3ef3 100644 --- a/src/assets/game/scene_attrs.json +++ b/src/assets/game/scene_attrs.json @@ -143,32 +143,32 @@ "s104" : {"r": "ark", "d": "04a", "s": "7", "fc": {"col": 0, "from": ["s102", "s103"], "graph": {"bg": "event/nero_e04"}}}, "s105" : {"r": "ark", "d": "04a", "s": "8a", "fc": {"col": 0, "from": ["s104"], "graph": {"bg": "bg/ima_18"}}}, "s106" : {"r": "ark", "d": "04a", "s": "8b", "fc": {"col": 6, "from": ["s104"], "graph": {"bg": "event/cel_e04"}}}, - "s108" : {"r": "ark", "d": "05a", "s": "1" , "fc": {"col": 0, "from": ["s105"]}}, - "s109" : {"r": "ark", "d": "05a", "s": "2a", "fc": {"col": 0, "from": ["s108"]}}, - "s110" : {"r": "ark", "d": "05a", "s": "2b", "fc": {"col": 1, "from": ["s108"]}}, - "s111" : {"r": "ark", "d": "05a", "s": "2c", "fc": {"col": 2, "from": ["s108"]}}, - "s112" : {"r": "ark", "d": "05a", "s": "3" , "fc": {"col": 0, "from": ["s109", "s110", "s111"]}}, - "s113" : {"r": "ark", "d": "05a", "s": "4a", "fc": {"col": 0, "from": ["s112"]}}, + "s108" : {"r": "ark", "d": "05a", "s": "1" , "fc": {"col": 0, "from": ["s105"], "graph": {"bg": "bg/bg_40e", "c": "tachi/his_t01"}}}, + "s109" : {"r": "ark", "d": "05a", "s": "2a", "fc": {"col": 0, "from": ["s108"], "graph": {"bg": "bg/bg_34a", "c": "tachi/aki_t01a"}}}, + "s110" : {"r": "ark", "d": "05a", "s": "2b", "fc": {"col": 1, "from": ["s108"], "graph": {"bg": "bg/bg_34a", "c": "tachi/aki_t15a"}}}, + "s111" : {"r": "ark", "d": "05a", "s": "2c", "fc": {"col": 2, "from": ["s108"], "graph": {"bg": "bg/bg_34a", "c": "tachi/aki_t10"}}}, + "s112" : {"r": "ark", "d": "05a", "s": "3" , "fc": {"col": 0, "from": ["s109", "s110", "s111"], "graph": {"bg": "bg/bg_34a", "c": "tachi/aki_t01a"}}}, + "s113" : {"r": "ark", "d": "05a", "s": "4a", "fc": {"col": 0, "from": ["s112"], "graph": {"bg": "bg/bg_25a", "c": "tachi/ark_t22"}}}, "s114" : {"r": "ark", "d": "05a", "s": "4b", "fc": {"col": 1, "from": ["s112"]}}, "s115" : {"r": "ark", "d": "05a", "s": "4c", "fc": {"col": 2, "from": ["s112"]}}, - "s116" : {"r": "ark", "d": "05a", "s": "5" , "fc": {"col": 0, "from": ["s113", "s114", "s115"]}}, - "s116a" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "05a", "s": {"flg":"E","0":"6","1":"11"}, "fc": {"col": 0, "from": ["s116", "s233"]}}, - "s118" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "05a", "s": {"flg":"E","0":"7a","1":"12a"}, "fc": {"col": 0, "from": ["s116a"]}, "h": true}, - "s119" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "05a", "s": {"flg":"E","0":"7b","1":"12b"}, "fc": {"col": 1, "from": ["s116a"]}, "h": true}, - "s120" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "05a", "s": {"flg":"E","0":"7c","1":"12c"}, "fc": {"col": 2, "from": ["s116a"]}, "h": true}, - "s121" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "05a", "s": {"flg":"E","0":"7d","1":"12d"}, "fc": {"col": 3, "from": ["s116a"]}, "h": true, "//": "day=6 inside scene"}, - "s122" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "05a", "s": {"flg":"E","0":"7e","1":"12e"}, "fc": {"col": 4, "from": ["s116a"]}, "h": true}, - "s125" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "1a", "fc": {"col": 0, "from": ["s118"]}}, - "s126" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "1b", "fc": {"col": 1, "from": ["s119"]}}, - "s128" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "1c", "fc": {"col": 2, "from": ["s120"]}}, - "s127" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "1d", "fc": {"col": 4, "from": ["s122"]}}, - "s129" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "2" , "fc": {"col": 0, "from": ["s125", "s126", "s128", "s121", "s127"]}}, + "s116" : {"r": "ark", "d": "05a", "s": "5" , "fc": {"col": 0, "from": ["s113", "s114", "s115"], "graph": {"bg": "bg/bg_32b", "c": "tachi/his_t01"}}}, + "s116a" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "05a", "s": {"flg":"E","0":"6","1":"11"}, "fc": {"col": 0, "from": ["s116", "s233"], "graph": {"bg": "#000000"}}}, + "s118" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "05a", "s": {"flg":"E","0":"7a","1":"12a"}, "fc": {"col": 0, "from": ["s116a"], "graph": {"bg": "event/ark_h01"}}, "h": true}, + "s119" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "05a", "s": {"flg":"E","0":"7b","1":"12b"}, "fc": {"col": 1, "from": ["s116a"], "graph": {"bg": "event/cel_h01"}}, "h": true}, + "s120" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "05a", "s": {"flg":"E","0":"7c","1":"12c"}, "fc": {"col": 2, "from": ["s116a"], "graph": {"bg": "event/aki_h15"}}, "h": true}, + "s121" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "05a", "s": {"flg":"E","0":"7d","1":"12d"}, "fc": {"col": 3, "from": ["s116a"], "graph": {"bg": "event/his_h15"}}, "h": true, "//": "day=6 inside scene"}, + "s122" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "05a", "s": {"flg":"E","0":"7e","1":"12e"}, "fc": {"col": 4, "from": ["s116a"], "graph": {"bg": "event/koha_h10"}}, "h": true}, + "s125" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "1a", "fc": {"col": 0, "from": ["s118"], "graph": {"bg": "bg/bg_40a", "c": "tachi/his_t01"}}}, + "s126" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "1b", "fc": {"col": 1, "from": ["s119"], "graph": {"bg": "bg/bg_40a", "c": "tachi/his_t01"}}}, + "s128" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "1c", "fc": {"col": 2, "from": ["s120"], "graph": {"bg": "bg/bg_40a", "c": "tachi/his_t01"}}}, + "s127" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "1d", "fc": {"col": 4, "from": ["s122"], "graph": {"bg": "bg/bg_40a", "c": "tachi/his_t01"}}}, + "s129" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "2" , "fc": {"col": 0, "from": ["s125", "s126", "s128", "s121", "s127"], "graph": {"bg": "bg/bg_01a"}}}, "s130" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "3a", "fc": {"col": 0, "from": ["s129"]}}, "s131" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "3b", "fc": {"col": 1, "from": ["s129"]}}, - "s132" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "3c", "fc": {"col": 2, "from": ["s129"]}}, - "s133" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "4a", "fc": {"col": 0, "from": ["b133"]}}, - "s134" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "4b", "fc": {"col": 1, "from": ["b133"]}}, - "s135" : {"r": "ark", "d": "06a", "s": "5" , "fc": {"col": 0, "from": ["b135"]}}, + "s132" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "3c", "fc": {"col": 2, "from": ["s129"], "graph": {"bg": "bg/bg_11a", "c": "tachi/cel_t06a"}}}, + "s133" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "4a", "fc": {"col": 0, "from": ["b133"], "graph": {"bg": "bg/bg_11a", "c": "tachi/cel_t03"}}}, + "s134" : {"r": {"flg":"E", "0":"ark", "1":"cel"}, "d": "06a", "s": "4b", "fc": {"col": 1, "from": ["b133"], "graph": {"bg": "bg/bg_11a", "c": "tachi/cel_t07a"}}}, + "s135" : {"r": "ark", "d": "06a", "s": "5" , "fc": {"col": 0, "from": ["b135"], "graph": {"bg": "bg/bg_06a", "c": "tachi/ari_t05"}}}, "s138" : {"r": "ark", "d": "06a", "s": "6a", "fc": {"col": 0, "from": ["s135"]}}, "s136" : {"r": "ark", "d": "06a", "s": "6b", "fc": {"col": 1, "from": ["s135"]}}, "s137" : {"r": "ark", "d": "06a", "s": "6c", "fc": {"col": 2, "from": ["s135"]}}, @@ -260,12 +260,12 @@ "s226" : {"r": "cel", "d": "05a", "s": "6a", "fc": {"col": 6, "from": ["s225"]}}, "s227" : {"r": "cel", "d": "05a", "s": "6b", "fc": {"col": 7, "from": ["s225"]}}, "s228" : {"r": "cel", "d": "05a", "s": "7" , "fc": {"col": 6, "from": ["s226", "s227"]}}, - "s229" : {"r": "cel", "d": "05a", "s": "8a", "fc": {"col": 6, "from": ["s228"]}}, + "s229" : {"r": "cel", "d": "05a", "s": "8a", "fc": {"col": 6, "from": ["s228"], "graph": {"bg": "bg/bg_06b", "c": "tachi/cel_t02"}}}, "s230" : {"r": "cel", "d": "05a", "s": "8b", "fc": {"col": 7, "from": ["s228"]}}, "s231" : {"r": "cel", "d": "05a", "s": "9a", "fc": {"col": 7, "from": ["s230"]}}, "s232" : {"r": "cel", "d": "05a", "s": "9b", "fc": {"col": 8, "from": ["s230"]}}, - "s233" : {"r": "cel", "d": "05a", "s": "10", "fc": {"col": 6, "from": ["s229","s231","s232"]}}, - "s244" : {"r": "cel", "d": "06a", "s": "5" , "fc": {"col": 6, "from": ["b135"]}}, + "s233" : {"r": "cel", "d": "05a", "s": "10", "fc": {"col": 6, "from": ["s229","s231","s232"], "graph": {"bg": "bg/bg_32b", "c": "tachi/his_t01"}}}, + "s244" : {"r": "cel", "d": "06a", "s": "5" , "fc": {"col": 6, "from": ["b135"], "graph": {"bg": "bg/bg_06a", "c": "tachi/ari_t05"}}}, "s245" : {"r": "cel", "d": "06a", "s": "6a", "fc": {"col": 6, "from": ["s244"]}}, "s246" : {"r": "cel", "d": "06a", "s": "6b", "fc": {"col": 7, "from": ["s244"]}}, "s247" : {"r": "cel", "d": "06a", "s": "7a", "fc": {"col": 7, "from": ["s246"]}}, @@ -274,13 +274,13 @@ "s250" : {"r": "cel", "d": "06a", "s": "9a", "fc": {"col": 6, "from": ["s249"]}}, "s251" : {"r": "cel", "d": "06a", "s": "9b", "fc": {"col": 7, "from": ["s249"]}}, "s252" : {"r": "cel", "d": "06a", "s": "9c", "fc": {"col": 8, "from": ["s249"]}}, - "s253" : {"r": "cel", "d": "06a", "s": "10", "fc": {"col": 6, "from": ["s250", "s251", "s252"]}}, + "s253" : {"r": "cel", "d": "06a", "s": "10", "fc": {"col": 6, "from": ["s250", "s251", "s252"], "graph": {"bg": "bg/bg_34b", "l": "tachi/koha_t03", "r": "tachi/aki_t04b"}}}, "s254" : {"r": "cel", "d": "06a", "s": "11a", "fc": {"col": 6, "from": ["s253"]}}, "s255" : {"r": "cel", "d": "06a", "s": "11b", "fc": {"col": 7, "from": ["s253"]}}, "s256" : {"r": "cel", "d": "06a", "s": "12", "fc": {"col": 6, "from": ["s254", "s255"]}}, "s257" : {"r": "cel", "d": "06a", "s": "13a", "fc": {"col": 6, "from": ["s256"]}}, "s258" : {"r": "cel", "d": "06a", "s": "13b", "fc": {"col": 7, "from": ["s256"]}}, - "s259" : {"r": "cel", "d": "06a", "s": "14", "fc": {"col": 6, "from": ["s257", "s258"]}}, + "s259" : {"r": "cel", "d": "06a", "s": "14", "fc": {"col": 6, "from": ["s257", "s258"], "graph": {"bg": "bg/bg_52", "c": "tachi/ark_t22"}}}, "s260" : {"r": "cel", "d": "07a", "s": "1" , "fc": {"col": 6, "from": ["s259"]}}, "s261" : {"r": "cel", "d": "07a", "s": "2a", "fc": {"col": 6, "from": ["s260"]}}, "s262" : {"r": "cel", "d": "07a", "s": "2b", "fc": {"col": 7, "from": ["s260"]}}, @@ -291,7 +291,7 @@ "s267" : {"r": "cel", "d": "07a", "s": "4" , "fc": {"col": 6, "from": ["s263", "s264", "s265", "s266"]}}, "s268" : {"r": "cel", "d": "07a", "s": "5a", "fc": {"col": 6, "from": ["s267"]}}, "s269" : {"r": "cel", "d": "07a", "s": "5b", "fc": {"col": 7, "from": ["s267"]}}, - "s270" : {"r": "cel", "d": "07a", "s": "6" , "fc": {"col": 6, "from": ["s268", "s269"]}}, + "s270" : {"r": "cel", "d": "07a", "s": "6" , "fc": {"col": 6, "from": ["s268", "s269"], "graph": {"bg": "bg/bg_25b", "l": "tachi/ark_t05b", "r": "tachi/cel_t07b"}}}, "s271" : {"r": "cel", "d": "08a", "fc": {"col": 6, "from": ["s270"]}, "//" : "day=8 inside scene"}, "s273" : {"r": "cel", "d": "09a", "s": "1" , "fc": {"col": 6, "from": ["s271"]}}, "s274" : {"r": "cel", "d": "09a", "s": "2a", "fc": {"col": 6, "from": ["s273"]}}, @@ -309,7 +309,7 @@ "s284" : {"r": "cel", "d": "10a", "s": "1" , "fc": {"col": 6, "from": ["s283"]}}, "s285" : {"r": "cel", "d": "10a", "s": "2a", "fc": {"col": 6, "from": ["s284"]}}, "s286" : {"r": "cel", "d": "10a", "s": "2b", "fc": {"col": 7, "from": ["s284"]}}, - "s287" : {"r": "cel", "d": "10a", "s": "3" , "fc": {"col": 6, "from": ["s285", "s286"]}}, + "s287" : {"r": "cel", "d": "10a", "s": "3" , "fc": {"col": 6, "from": ["s285", "s286"], "graph": {"bg": "bg/bg_25b"}}}, "s288" : {"r": "cel", "d": "11a", "s": "1" , "fc": {"col": 6, "from": ["s287"]}}, "s289" : {"r": "cel", "d": "11b", "s": "1" , "fc": {"col": 6, "from": ["s288"]}}, "s289a" : {"r": "cel", "d": "11b", "fc": {"col": 6, "from": ["s289", "s296"]}, "deadEnd": true}, @@ -332,7 +332,7 @@ "s307" : {"r": "cel", "d": "12a", "fc": {"col": 6, "from": ["s504", "s505"]}}, "s308" : {"r": "cel", "d": "13b", "fc": {"col": 6, "from": ["s307"]}, "//": "day=13 inside scene"}, "s526" : {"r": "cel", "d": "13b", "osiete": true}, - "s310" : {"r": "cel", "d": "13a", "fc": {"col": 7, "from": ["s307"]}, "//": "day=13 inside scene"}, + "s310" : {"r": "cel", "d": "13a", "fc": {"col": 7, "from": ["s307"], "graph": {"bg": "event/cel_f02"}}, "//": "day=13 inside scene"}, "s527" : {"r": "cel", "d": "13b", "osiete": true}, "s234" : {"r": "aki", "d": "03b", "fc": {"col": 12, "from": ["s211"]}, "deadEnd": true}, @@ -357,7 +357,7 @@ "s317" : {"r": {"flg":"P", "0":"his", "1": "aki"}, "d": "04a", "s": "2", "fc": {"col": 11, "from": ["a305", "s306"]}}, "s320" : {"r": "aki", "d": "04a", "s": "3" , "fc": {"col": 11, "from": ["s317"]}}, "s321" : {"r": {"flg":"P", "0":"his", "1": "aki"}, "d": "04a", "s": "4", "fc": {"col": 11, "from": ["s320", "s318", "s319"]}}, - "s322" : {"r": "aki", "d": "04a", "s": "5" , "fc": {"col": 11, "from": ["s321"]}}, + "s322" : {"r": "aki", "d": "04a", "s": "5" , "fc": {"col": 11, "from": ["s321"], "graph": {"bg": "bg/bg_34c", "c": "tachi/aki_t26"}}}, "s325" : {"r": "aki", "d": "05a", "s": "1a", "fc": {"col": 11, "from": ["s322"]}}, "s303" : {"r": "aki", "d": "05a", "s": "1b", "fc": {"col": 10, "from": ["s305"], "align": "s325"}, "//" : "day=5 inside scene"}, "s326" : {"r": "aki", "d": "05a", "s": "2a", "fc": {"col": 10, "from": ["a303"]}}, @@ -437,13 +437,13 @@ "s318" : {"r": "his", "d": "04a", "s": "3a", "fc": {"col": 11, "from": ["s317"]}}, "s319" : {"r": "his", "d": "04a", "s": "3b", "fc": {"col": 12, "from": ["s317"]}}, "s414" : {"r": "his", "d": "05a", "s": "1a", "fc": {"col": 14, "from": ["b414"], "align": "s323", "cutAt": 1}}, - "s323" : {"r": "his", "d": "05a", "s": "1b", "fc": {"col": 15, "from": ["s321"]}}, - "s324" : {"r": "his", "d": "05a", "s": "1c", "fc": {"col": 17, "from": ["s321"]}}, + "s323" : {"r": "his", "d": "05a", "s": "1b", "fc": {"col": 15, "from": ["s321"], "graph": {"bg": "bg/bg_34b", "c": "tachi/his_t11"}}}, + "s324" : {"r": "his", "d": "05a", "s": "1c", "fc": {"col": 17, "from": ["s321"], "graph": {"bg": "bg/bg_34c", "l": "tachi/koha_t02b" , "r": "tachi/aki_t13b"}}}, "s386" : {"r": "his", "d": "05a", "s": "2" , "fc": {"col": 14, "from": ["s323", "s414"]}}, "s387" : {"r": "his", "d": "05a", "s": "3a", "fc": {"col": 14, "from": ["s386"]}}, "s388" : {"r": "his", "d": "05a", "s": "3b", "fc": {"col": 15, "from": ["s386"]}}, "s389" : {"r": "his", "d": "05a", "s": "3c", "fc": {"col": 16, "from": ["s386"]}}, - "s390" : {"r": "his", "d": "05a", "s": "4" , "fc": {"col": 14, "from": ["s387", "s388", "s389"]}}, + "s390" : {"r": "his", "d": "05a", "s": "4" , "fc": {"col": 14, "from": ["s387", "s388", "s389"], "graph": {"bg": "bg/bg_26a"}}}, "s391" : {"r": "his", "d": "06a", "s": "1" , "fc": {"col": 14, "from": ["s390"]}}, "s392" : {"r": "his", "d": "06a", "s": "2a", "fc": {"col": 14, "from": ["s391"]}}, "s393" : {"r": "his", "d": "06a", "s": "2b", "fc": {"col": 15, "from": ["s391"]}}, @@ -456,7 +456,7 @@ "s399" : {"r": "his", "d": "07a", "s": "1" , "fc": {"col": 14, "from": ["s397", "s398"]}}, "s400" : {"r": "his", "d": "07a", "s": "2a", "fc": {"col": 14, "from": ["s399"]}}, "s401" : {"r": "his", "d": "07a", "s": "2b", "fc": {"col": 15, "from": ["s399"]}}, - "s402" : {"r": "his", "d": "07a", "s": "3" , "fc": {"col": 14, "from": ["s400", "s401"]}, "h": true, "//" : "day=8,9,10,11,12 inside scene"}, + "s402" : {"r": "his", "d": "07a", "s": "3" , "fc": {"col": 14, "from": ["s400", "s401"], "graph": {"bg": "event/his_h14"}}, "h": true, "//" : "day=8,9,10,11,12 inside scene"}, "s404" : {"r": "his", "d": "12a", "s": "4a", "fc": {"col": 14, "from": ["s402"]}, "h": true}, "s403" : {"r": "his", "d": "12a", "s": "4b", "fc": {"col": 15, "from": ["s402"]}}, "s405" : {"r": "his", "d": "07a", "s": "5" , "fc": {"col": 14, "from": ["s403", "s404"]}, "h": true}, @@ -478,7 +478,7 @@ "s419" : {"r": "koha", "d": "07a", "s": "3" , "fc": {"col": 17, "from": ["s417", "s418"]}}, "s420" : {"r": "koha", "d": "07a", "s": "4a", "fc": {"col": 17, "from": ["s419"]}, "//": "day=8 inside scene"}, "s421" : {"r": "koha", "d": "07a", "s": "4b", "fc": {"col": 18, "from": ["s419"]}, "//": "day=8 inside scene"}, - "s422" : {"r": "koha", "d": "08a", "fc": {"col": 17, "from": ["s420", "s421"]}, "h": true, "//": "day=9,10 inside scene"}, + "s422" : {"r": "koha", "d": "08a", "fc": {"col": 17, "from": ["s420", "s421"], "graph": {"bg": "event/aki_h13"}}, "h": true, "//": "day=9,10 inside scene"}, "s423" : {"r": "koha", "d": "10a", "s": "1a", "fc": {"col": 17, "from": ["s422"]}}, "s424" : {"r": "koha", "d": "10a", "s": "1b", "fc": {"col": 18, "from": ["s422"]}}, "s425" : {"r": "koha", "d": "10a", "s": "2", "fc": {"col": 17, "from": ["s423", "s424"]}, "h": true, "//": "day=11 inside scene"}, diff --git a/src/components/Flowchart.tsx b/src/components/Flowchart.tsx index a438e0e..79784dc 100644 --- a/src/components/Flowchart.tsx +++ b/src/components/Flowchart.tsx @@ -7,6 +7,7 @@ import { isScene } from "../utils/scriptUtils" import { settings } from "../utils/settings" import { playScene } from "../utils/savestates" import GraphicsGroup from "./molecules/GraphicsGroup" +import { findImageObjectByName } from "utils/gallery" const SCENE_WIDTH = 27 const SCENE_HEIGHT = 18 @@ -15,241 +16,247 @@ const DY = 3 const OVERLAP_BREAK_LENGTH = 2 const SCENE_RECT_ATTRS = { - width: SCENE_WIDTH, - height: SCENE_HEIGHT, - x: -SCENE_WIDTH/2, - y: -SCENE_HEIGHT/2 + width: SCENE_WIDTH, + height: SCENE_HEIGHT, + x: -SCENE_WIDTH/2, + y: -SCENE_HEIGHT/2 } function getPreviousScenes(tree: Map<string, FcNodeParams|FcNode>, scene: string): string[] { - const currNode = tree.get(scene) - if (!currNode) - throw Error(`unknown flowchart node ${scene}`) - const from = currNode.from - const result = [] - for (const node of from) { - if (node instanceof FcScene) - result.push(node.id) - else if (node instanceof FcNode) - result.push(...getPreviousScenes(tree, node.id)) - else if (isScene(node)) - result.push(node) - else - result.push(...getPreviousScenes(tree, node)) - } - return result - //TODO used to determine if a scene must be displayed (greyed out) if it hasn't been seen yet. (i.e., yes if one of the previous scenes has been seen) + const currNode = tree.get(scene) + if (!currNode) + throw Error(`unknown flowchart node ${scene}`) + const from = currNode.from + const result = [] + for (const node of from) { + if (node instanceof FcScene) + result.push(node.id) + else if (node instanceof FcNode) + result.push(...getPreviousScenes(tree, node.id)) + else if (isScene(node)) + result.push(node) + else + result.push(...getPreviousScenes(tree, node)) + } + return result + //TODO used to determine if a scene must be displayed (greyed out) if it hasn't been seen yet. (i.e., yes if one of the previous scenes has been seen) } class FcNode { - column: number; - y: number; - id: string; - from: FcNode[]; - cutAt?: number - constructor(id: string, column: number, from: FcNode[], alignedNode?: FcNode, cutAt?: number) { - this.id = id - this.column = column - this.from = from - this.y = alignedNode ? alignedNode.top - : from.reduce((yMax, node)=> Math.max(node.bottom, yMax), 0) + DY*2 - this.cutAt = cutAt - } - - get x() { return this.column * COLUMN_WIDTH } - get width() { return 0 } - get height() { return 0 } - get top() { return this.y - this.height/2 } - get bottom() { return this.y + this.height/2 } - get left() { return this.x - this.width/2 } - get right() { return this.x + this.width/2 } - - render(): React.ReactNode { - return this.from.map(node=> { - const id = `${node.id}-${this.id}` - const yStart = node.bottom - const yEnd = this.top - let path = `M ${node.x},${yStart}` - if (node.column == this.column) - path += ` V ${yEnd}` - else if (yStart == yEnd) - path += ` H ${this.x}` - else { - const turnY = yEnd - DY - if (turnY > yStart) - path += ` V ${turnY}` - path +=` H ${this.x} V ${yEnd}` - } - if (this.cutAt != undefined) { - const totalLength = (yEnd - yStart) + Math.abs(this.x - node.x) - const bl = OVERLAP_BREAK_LENGTH - const cutLength = this.cutAt * DY - const lengths = [totalLength - cutLength - bl/2, bl, cutLength - bl/2] - return <path key={id} className="fc-link" id={id} d={path} - style={{strokeDasharray: lengths.join(' ')}}/> - } else { - return <path key={id} className="fc-link" id={id} d={path}/> - } - }) - } + column: number; + y: number; + id: string; + from: FcNode[]; + cutAt?: number + constructor(id: string, column: number, from: FcNode[], alignedNode?: FcNode, cutAt?: number) { + this.id = id + this.column = column + this.from = from + this.y = alignedNode ? alignedNode.top + : from.reduce((yMax, node)=> Math.max(node.bottom, yMax), 0) + DY*2 + this.cutAt = cutAt + } + + get x() { return this.column * COLUMN_WIDTH } + get width() { return 0 } + get height() { return 0 } + get top() { return this.y - this.height/2 } + get bottom() { return this.y + this.height/2 } + get left() { return this.x - this.width/2 } + get right() { return this.x + this.width/2 } + + render(): React.ReactNode { + return this.from.map(node=> { + const id = `${node.id}-${this.id}` + const yStart = node.bottom + const yEnd = this.top + let path = `M ${node.x},${yStart}` + if (node.column == this.column) + path += ` V ${yEnd}` + else if (yStart == yEnd) + path += ` H ${this.x}` + else { + const turnY = yEnd - DY + if (turnY > yStart) + path += ` V ${turnY}` + path +=` H ${this.x} V ${yEnd}` + } + if (this.cutAt != undefined) { + const totalLength = (yEnd - yStart) + Math.abs(this.x - node.x) + const bl = OVERLAP_BREAK_LENGTH + const cutLength = this.cutAt * DY + const lengths = [totalLength - cutLength - bl/2, bl, cutLength - bl/2] + return <path key={id} className="fc-link" id={id} d={path} + style={{strokeDasharray: lengths.join(' ')}}/> + } else { + return <path key={id} className="fc-link" id={id} d={path}/> + } + }) + } } class FcScene extends FcNode { - graph: Graphics|undefined - constructor(id: SceneName, column: number, from: FcNode[], alignedNode?: FcNode, graph ?: Graphics, cutAt?: number) { - super(id, column, from, alignedNode, cutAt) - this.y += SCENE_HEIGHT/2 - this.graph = graph - } - - get width() { return SCENE_WIDTH } - get height() { return SCENE_HEIGHT } - - render() { - let content - let completed = settings.completedScenes.includes(this.id) - if (!completed) - content = <use href="#fc-scene-hidden"/> - else if (!this.graph) - content = <> - <use href="#fc-scene-background" /> - <text className="fc-scene-title">{this.id}</text> - <use href="#fc-scene-outline"/> - </> - else { - content = <> - <foreignObject x={-SCENE_WIDTH/2} y={-SCENE_HEIGHT/2} - width={SCENE_WIDTH} height={SCENE_HEIGHT}> - <GraphicsGroup images={this.graph} resolution="thumb" lazy={true} /> - </foreignObject> - <use href="#fc-scene-outline"/> - </> - } - - return <Fragment key={this.id}> - {super.render()} - <g className="fc-scene" id={this.id} - transform={`translate(${this.x},${this.y})`} - onClick={() => playScene(this.id as LabelName, { continueScript: false })} - // TODO: continueScript = true if using the flowchart to navigate to previous scene (not yet implemented) - clipPath="url(#fc-scene-clip)"> - {content} - </g> - </Fragment> - } + graph: Graphics|undefined + constructor(id: SceneName, column: number, from: FcNode[], alignedNode?: FcNode, graph ?: Graphics, cutAt?: number) { + super(id, column, from, alignedNode, cutAt) + this.y += SCENE_HEIGHT/2 + this.graph = graph + } + + get width() { return SCENE_WIDTH } + get height() { return SCENE_HEIGHT } + + render() { + let content + let completed = settings.completedScenes.includes(this.id) + if (!completed) + content = <use href="#fc-scene-hidden"/> + else if (!this.graph) + content = <> + <use href="#fc-scene-background" /> + <text className="fc-scene-title">{this.id}</text> + <use href="#fc-scene-outline"/> + </> + else { + content = <> + <foreignObject + x={-SCENE_WIDTH/2} y={-SCENE_HEIGHT/2} + width={SCENE_WIDTH} height={SCENE_HEIGHT} + > + <GraphicsGroup images={this.graph} resolution="thumb" lazy={true} /> + </foreignObject> + <use href="#fc-scene-outline"/> + </> + } + + const blur = settings.blurThumbnails && this.graph?.bg && findImageObjectByName(this.graph?.bg)?.sensitive + + return <Fragment key={this.id}> + {super.render()} + + <g className={`fc-scene${blur ? " blur" : ""}`} id={this.id} + transform={`translate(${this.x},${this.y})`} + onClick={() => playScene(this.id as LabelName, { continueScript: false })} + // TODO: continueScript = true if using the flowchart to navigate to previous scene (not yet implemented) + clipPath="url(#fc-scene-clip)"> + <title>{this.id}</title> + {content} + </g> + </Fragment> + } } function getNode(nodes: Map<string, FcNode|FcNodeParams>, id: string) { - let node = nodes.get(id) - if (!node) - throw Error(`unknown node id ${id}`) - if (node instanceof FcNodeParams) { - node.build(nodes) - node = nodes.get(id) - } - return node as FcNode + let node = nodes.get(id) + if (!node) + throw Error(`unknown node id ${id}`) + if (node instanceof FcNodeParams) { + node.build(nodes) + node = nodes.get(id) + } + return node as FcNode } class FcNodeParams { - id: string - column: number - from: string[] - align: string|undefined - cutAt: number|undefined - constructor(id: string, column: number, from: string[], align?: string, cutAt?: number) { - this.id = id - this.column = column - this.from = from - this.align = align - this.cutAt = cutAt - } - build(nodes: Map<string, FcNode|FcNodeParams>) { - const parentNodes = this.from.map(getNode.bind(null, nodes)) - const alignedNode = this.align ? getNode(nodes, this.align) : undefined - nodes.set(this.id, this.construct(parentNodes, alignedNode)) - } - construct(parentNodes: FcNode[], alignedNode: FcNode|undefined) { - return new FcNode(this.id, this.column, parentNodes, alignedNode, this.cutAt) - } + id: string + column: number + from: string[] + align: string|undefined + cutAt: number|undefined + constructor(id: string, column: number, from: string[], align?: string, cutAt?: number) { + this.id = id + this.column = column + this.from = from + this.align = align + this.cutAt = cutAt + } + build(nodes: Map<string, FcNode|FcNodeParams>) { + const parentNodes = this.from.map(getNode.bind(null, nodes)) + const alignedNode = this.align ? getNode(nodes, this.align) : undefined + nodes.set(this.id, this.construct(parentNodes, alignedNode)) + } + construct(parentNodes: FcNode[], alignedNode: FcNode|undefined) { + return new FcNode(this.id, this.column, parentNodes, alignedNode, this.cutAt) + } } class FcSceneParams extends FcNodeParams { - graph: Graphics|undefined - constructor(id: SceneName, column: number, from: string[], align?: string, graph?: Graphics, cutAt?: number) { - super(id, column, from, align, cutAt) - this.graph = graph - } - construct(parentNodes: FcNode[], alignedNode: FcNode|undefined) { - return new FcScene(this.id as SceneName, this.column, parentNodes, alignedNode, this.graph, this.cutAt) - } + graph: Graphics|undefined + constructor(id: SceneName, column: number, from: string[], align?: string, graph?: Graphics, cutAt?: number) { + super(id, column, from, align, cutAt) + this.graph = graph + } + construct(parentNodes: FcNode[], alignedNode: FcNode|undefined) { + return new FcScene(this.id as SceneName, this.column, parentNodes, alignedNode, this.graph, this.cutAt) + } } function createTree() { - let tree = new Map<string, FcNodeParams|FcNode>() - Object.entries(SCENE_ATTRS.scenes).forEach(([id, {fc}])=> { - if (fc) { - let {col, from, align, graph, cutAt} = fc - tree.set(id, new FcSceneParams(id as SceneName, col, from, align, graph, cutAt)) - } - }) - Object.entries(SCENE_ATTRS["fc-nodes"]??{}).forEach(([id, {col, from, align, cutAt}])=> { - tree.set(id, new FcNodeParams(id, col, from, align, cutAt)) - }) - for (const node of tree.values()) { - if (node instanceof FcNodeParams) { - node.build(tree) - } - } - return Array.from(tree.values()) as FcNode[] + let tree = new Map<string, FcNodeParams|FcNode>() + Object.entries(SCENE_ATTRS.scenes).forEach(([id, {fc}])=> { + if (fc) { + let {col, from, align, graph, cutAt} = fc + tree.set(id, new FcSceneParams(id as SceneName, col, from, align, graph, cutAt)) + } + }) + Object.entries(SCENE_ATTRS["fc-nodes"]??{}).forEach(([id, {col, from, align, cutAt}])=> { + tree.set(id, new FcNodeParams(id, col, from, align, cutAt)) + }) + for (const node of tree.values()) { + if (node instanceof FcNodeParams) { + node.build(tree) + } + } + return Array.from(tree.values()) as FcNode[] } type Props = { - back: (sceneLoaded: boolean)=>void + back: (sceneLoaded: boolean)=>void } export const Flowchart = memo(({back}: Props)=> { - const [tree] = useState<FcNode[]>(createTree) - const [left, top, right, bottom] = tree.reduce((vb, node)=> [ - Math.min(vb[0], node.left), - Math.min(vb[1], node.top), - Math.max(vb[2], node.right), - Math.max(vb[3], node.bottom), - ], [Number.MAX_VALUE, Number.MAX_VALUE, 0, 0]) - const width = right - left - const height = bottom - top - const minWidth = `${width/8}rem` - const minHeight = `${height/8}rem` - const maxWidth = `${100 * width / (2 * COLUMN_WIDTH)}%` // minimum 2 scenes visible - const maxHeight = `${100 * height / (4 * (SCENE_HEIGHT + DY*2))}%` // minimum 4 scenes visible - - return ( - <div className="flowchart"> - <svg viewBox={`${left} ${top} ${width} ${height}`} - style={{minWidth: minWidth, maxWidth: maxWidth, - minHeight: minHeight, maxHeight: maxHeight}} - version="1.1" - xmlns="http://www.w3.org/2000/svg"> - <defs> - <radialGradient id="hidden-scene-gradient"> - <stop offset="0%" stopColor="black" /> - <stop offset="50%" stopColor="#111" /> - <stop offset="95%" stopColor="#222" /> - </radialGradient> - <rect id="fc-scene-outline" {...SCENE_RECT_ATTRS} rx={SCENE_HEIGHT/10} /> - <rect id="fc-scene-background" {...SCENE_RECT_ATTRS} /> - <g id="fc-scene-hidden"> - <rect {...SCENE_RECT_ATTRS} rx={SCENE_HEIGHT/10} fill="url(#hidden-scene-gradient)" /> - <line x1={-SCENE_WIDTH/2} y1={-SCENE_HEIGHT/2} stroke="black" - x2={ SCENE_WIDTH/2} y2={ SCENE_HEIGHT/2} strokeWidth={0.4}/> - <line x1={-SCENE_WIDTH/2} y1={ SCENE_HEIGHT/2} stroke="black" - x2={ SCENE_WIDTH/2} y2={-SCENE_HEIGHT/2} strokeWidth={0.4}/> - <rect {...SCENE_RECT_ATTRS} rx={SCENE_HEIGHT/10} /> - </g> - </defs> - <clipPath id="fc-scene-clip"> - <use href="#fc-scene-outline"/> - </clipPath> - {tree.map(node=> node.render())} - </svg> - {/*<FlowchartSVG/>*/} - </div> - ) + const [tree] = useState<FcNode[]>(createTree) + const [left, top, right, bottom] = tree.reduce((vb, node)=> [ + Math.min(vb[0], node.left), + Math.min(vb[1], node.top), + Math.max(vb[2], node.right), + Math.max(vb[3], node.bottom), + ], [Number.MAX_VALUE, Number.MAX_VALUE, 0, 0]) + const width = right - left + const height = bottom - top + const minWidth = `${width/8}rem` + const minHeight = `${height/8}rem` + const maxWidth = `${100 * width / (2 * COLUMN_WIDTH)}%` // minimum 2 scenes visible + const maxHeight = `${100 * height / (4 * (SCENE_HEIGHT + DY*2))}%` // minimum 4 scenes visible + + return ( + <div className="flowchart"> + <svg viewBox={`${left} ${top} ${width} ${height}`} + style={{minWidth: minWidth, maxWidth: maxWidth, + minHeight: minHeight, maxHeight: maxHeight}} + version="1.1" + xmlns="http://www.w3.org/2000/svg"> + <defs> + <radialGradient id="hidden-scene-gradient"> + <stop offset="0%" stopColor="black" /> + <stop offset="50%" stopColor="#111" /> + <stop offset="95%" stopColor="#222" /> + </radialGradient> + <rect id="fc-scene-outline" {...SCENE_RECT_ATTRS} rx={SCENE_HEIGHT/10} /> + <rect id="fc-scene-background" {...SCENE_RECT_ATTRS} /> + <g id="fc-scene-hidden"> + <rect {...SCENE_RECT_ATTRS} rx={SCENE_HEIGHT/10} fill="url(#hidden-scene-gradient)" /> + <line x1={-SCENE_WIDTH/2} y1={-SCENE_HEIGHT/2} stroke="black" + x2={ SCENE_WIDTH/2} y2={ SCENE_HEIGHT/2} strokeWidth={0.4}/> + <line x1={-SCENE_WIDTH/2} y1={ SCENE_HEIGHT/2} stroke="black" + x2={ SCENE_WIDTH/2} y2={-SCENE_HEIGHT/2} strokeWidth={0.4}/> + <rect {...SCENE_RECT_ATTRS} rx={SCENE_HEIGHT/10} /> + </g> + </defs> + <clipPath id="fc-scene-clip"> + <use href="#fc-scene-outline"/> + </clipPath> + {tree.map(node=> node.render())} + </svg> + {/*<FlowchartSVG/>*/} + </div> + ) }) \ No newline at end of file diff --git a/src/styles/flowchart.scss b/src/styles/flowchart.scss index a714feb..97c1368 100644 --- a/src/styles/flowchart.scss +++ b/src/styles/flowchart.scss @@ -1,68 +1,78 @@ #scenes { - overflow: auto; + overflow: auto; - .flowchart { - padding-bottom: 60px; - } - .fc-scene { - .fc-scene-title { - font-size: 3.52777px; - line-height: 1; - text-align: center; - text-anchor: middle; - dominant-baseline: middle; - stroke-width: 0.264583; - stroke-linejoin: round; - fill: rgb(179 179 179); - } + .flowchart { + padding-bottom: 60px; + } + .fc-scene { + &.blur { + filter: blur(.5em); + transition: .2s ease-out; + transition-delay: 0s; - &:hover { - cursor: pointer; - .graphics { - filter: brightness(1.1); - } - } - } - .fc-link { - fill: none; - fill-opacity: 0.246809; - fill-rule: evenodd; - // not unlocked stroke: #1a465d; - stroke: #1187c5; - stroke-width: 0.6px; - stroke-linejoin: round; - stroke-opacity: 1; - paint-order: fill markers stroke; - stop-color: #000000; - } - .day-separator { - stroke: black; - stroke-width: 0.1px; - } - .day-title { - font-size: 3.52777px; - line-height: 1; - text-align: start; - text-anchor: start; - stroke-width: 0.264583; - } + &:hover, &:focus-visible { + filter: blur(0); + transition-delay: .6s; + } + } + .fc-scene-title { + font-size: 3.52777px; + line-height: 1; + text-align: center; + text-anchor: middle; + dominant-baseline: middle; + stroke-width: 0.264583; + stroke-linejoin: round; + fill: rgb(179 179 179); + } + + &:hover { + cursor: pointer; + .graphics { + filter: brightness(1.1); + } + } + } + .fc-link { + fill: none; + fill-opacity: 0.246809; + fill-rule: evenodd; + // not unlocked stroke: #1a465d; + stroke: #1187c5; + stroke-width: 0.6px; + stroke-linejoin: round; + stroke-opacity: 1; + paint-order: fill markers stroke; + stop-color: #000000; + } + .day-separator { + stroke: black; + stroke-width: 0.1px; + } + .day-title { + font-size: 3.52777px; + line-height: 1; + text-align: start; + text-anchor: start; + stroke-width: 0.264583; + } } #fc-scene-outline, #fc-scene-hidden rect:last-of-type { - stroke-width: 0.6; - stroke-linejoin: round; - fill: none; + stroke-width: 0.6; + stroke-linejoin: round; + fill: none; } #fc-scene-hidden rect:last-of-type { - stroke: rgb(115 115 115); + stroke: rgb(115 115 115); } #fc-scene-outline { - stroke: #1187c5; + stroke: #1187c5; } #fc-scene-background { - fill: rgb(67 67 67); + fill: rgb(67 67 67); } \ No newline at end of file diff --git a/src/styles/gallery.scss b/src/styles/gallery.scss index b125f8b..322e2cd 100644 --- a/src/styles/gallery.scss +++ b/src/styles/gallery.scss @@ -1,51 +1,51 @@ @use 'partials/_components'; #gallery { - .gallery-transition { - position: relative; - overflow: hidden; - } + .gallery-transition { + position: relative; + overflow: hidden; + } - .gallery-container { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(min(160px, 100%), 1fr)); - gap: 8px; + .gallery-container { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(min(160px, 100%), 1fr)); + gap: 8px; - @media (max-width: 480px) or (max-height: 480px) { - grid-template-columns: repeat(auto-fill, minmax(min(100px, 100%), 1fr)); - } + @media (max-width: 480px) or (max-height: 480px) { + grid-template-columns: repeat(auto-fill, minmax(min(100px, 100%), 1fr)); + } - a { - overflow: hidden; + a { + overflow: hidden; - &:hover, &:focus-visible { - img { - transform: scale(1.1); - } - } - } - img, .placeholder { - display: block; - aspect-ratio: 4/3; - width: 100%; - } - img { - transition: .2s ease-out; - background-color: #0e98cb59; - } - .placeholder { - border: 1px solid #004f87; - background-color: rgb(0 0 0 / 40%); - } - .blur img { - filter: blur(30px); - transition: .2s ease-out; - transition-delay: 0s; + &:hover, &:focus-visible { + img { + transform: scale(1.1); + } + } + } + img, .placeholder { + display: block; + aspect-ratio: 4/3; + width: 100%; + } + img { + transition: .2s ease-out; + background-color: #0e98cb59; + } + .placeholder { + border: 1px solid #004f87; + background-color: rgb(0 0 0 / 40%); + } + .blur img { + filter: blur(30px); + transition: .2s ease-out; + transition-delay: 0s; - &:hover, &:focus-visible { - filter: blur(0); - transition-delay: .6s; - } - } - } + &:hover, &:focus-visible { + filter: blur(0); + transition-delay: .6s; + } + } + } }