imagedumper_desktop.go (4028B)
1 // Copyright 2018 The Ebiten Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // +build !android 16 // +build !js 17 // +build !ios 18 19 package ebiten 20 21 import ( 22 "fmt" 23 "os" 24 "time" 25 26 "github.com/hajimehoshi/ebiten/v2/internal/shareable" 27 ) 28 29 // availableFilename returns a filename that is valid as a new file or directory. 30 func availableFilename(prefix, postfix string) (string, error) { 31 const datetimeFormat = "20060102030405" 32 33 now := time.Now() 34 name := fmt.Sprintf("%s%s%s", prefix, now.Format(datetimeFormat), postfix) 35 for i := 1; ; i++ { 36 if _, err := os.Stat(name); err != nil { 37 if os.IsNotExist(err) { 38 break 39 } 40 if !os.IsNotExist(err) { 41 return "", err 42 } 43 } 44 name = fmt.Sprintf("%s%s_%d%s", prefix, now.Format(datetimeFormat), i, postfix) 45 } 46 return name, nil 47 } 48 49 func takeScreenshot(screen *Image) error { 50 newname, err := availableFilename("screenshot_", ".png") 51 if err != nil { 52 return err 53 } 54 55 blackbg := !IsScreenTransparent() 56 if err := screen.mipmap.Dump(newname, blackbg); err != nil { 57 return err 58 } 59 60 if _, err := fmt.Fprintf(os.Stderr, "Saved screenshot: %s\n", newname); err != nil { 61 return err 62 } 63 return nil 64 } 65 66 func dumpInternalImages() error { 67 dir, err := availableFilename("internalimages_", "") 68 if err != nil { 69 return err 70 } 71 72 if err := os.Mkdir(dir, 0755); err != nil { 73 return err 74 } 75 76 if err := shareable.DumpImages(dir); err != nil { 77 return err 78 } 79 80 if _, err := fmt.Fprintf(os.Stderr, "Dumped the internal images at: %s\n", dir); err != nil { 81 return err 82 } 83 return nil 84 } 85 86 type imageDumper struct { 87 g Game 88 89 keyState map[Key]int 90 91 hasScreenshotKey bool 92 screenshotKey Key 93 toTakeScreenshot bool 94 95 hasDumpInternalImagesKey bool 96 dumpInternalImagesKey Key 97 toDumpInternalImages bool 98 99 err error 100 } 101 102 func (i *imageDumper) update() error { 103 if i.err != nil { 104 return i.err 105 } 106 107 const ( 108 envScreenshotKey = "EBITEN_SCREENSHOT_KEY" 109 envInternalImagesKey = "EBITEN_INTERNAL_IMAGES_KEY" 110 ) 111 112 if err := i.g.Update(); err != nil { 113 return err 114 } 115 116 // If keyState is nil, all values are not initialized. 117 if i.keyState == nil { 118 i.keyState = map[Key]int{} 119 120 if keyname := os.Getenv(envScreenshotKey); keyname != "" { 121 if key, ok := keyNameToKeyCode(keyname); ok { 122 i.hasScreenshotKey = true 123 i.screenshotKey = key 124 } 125 } 126 127 if keyname := os.Getenv(envInternalImagesKey); keyname != "" { 128 if isDebug() { 129 if key, ok := keyNameToKeyCode(keyname); ok { 130 i.hasDumpInternalImagesKey = true 131 i.dumpInternalImagesKey = key 132 } 133 } else { 134 fmt.Fprintf(os.Stderr, "%s is disabled. Specify a build tag 'ebitendebug' to enable it.\n", envInternalImagesKey) 135 } 136 } 137 } 138 139 keys := map[Key]struct{}{} 140 if i.hasScreenshotKey { 141 keys[i.screenshotKey] = struct{}{} 142 } 143 if i.hasDumpInternalImagesKey { 144 keys[i.dumpInternalImagesKey] = struct{}{} 145 } 146 147 for key := range keys { 148 if IsKeyPressed(key) { 149 i.keyState[key]++ 150 if i.keyState[key] == 1 { 151 if i.hasScreenshotKey && key == i.screenshotKey { 152 i.toTakeScreenshot = true 153 } 154 if i.hasDumpInternalImagesKey && key == i.dumpInternalImagesKey { 155 i.toDumpInternalImages = true 156 } 157 } 158 } else { 159 i.keyState[key] = 0 160 } 161 } 162 return nil 163 } 164 165 func (i *imageDumper) dump(screen *Image) error { 166 if i.toTakeScreenshot { 167 i.toTakeScreenshot = false 168 if err := takeScreenshot(screen); err != nil { 169 return err 170 } 171 } 172 173 if i.toDumpInternalImages { 174 i.toDumpInternalImages = false 175 if err := dumpInternalImages(); err != nil { 176 return err 177 } 178 } 179 180 return nil 181 }