imagedumper_desktop.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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. // +build !android
  15. // +build !js
  16. // +build !ios
  17. package ebiten
  18. import (
  19. "fmt"
  20. "os"
  21. "time"
  22. "github.com/hajimehoshi/ebiten/v2/internal/atlas"
  23. )
  24. // availableFilename returns a filename that is valid as a new file or directory.
  25. func availableFilename(prefix, postfix string) (string, error) {
  26. const datetimeFormat = "20060102030405"
  27. now := time.Now()
  28. name := fmt.Sprintf("%s%s%s", prefix, now.Format(datetimeFormat), postfix)
  29. for i := 1; ; i++ {
  30. if _, err := os.Stat(name); err != nil {
  31. if os.IsNotExist(err) {
  32. break
  33. }
  34. if !os.IsNotExist(err) {
  35. return "", err
  36. }
  37. }
  38. name = fmt.Sprintf("%s%s_%d%s", prefix, now.Format(datetimeFormat), i, postfix)
  39. }
  40. return name, nil
  41. }
  42. func takeScreenshot(screen *Image) error {
  43. newname, err := availableFilename("screenshot_", ".png")
  44. if err != nil {
  45. return err
  46. }
  47. blackbg := !IsScreenTransparent()
  48. if err := screen.mipmap.Dump(newname, blackbg); err != nil {
  49. return err
  50. }
  51. if _, err := fmt.Fprintf(os.Stderr, "Saved screenshot: %s\n", newname); err != nil {
  52. return err
  53. }
  54. return nil
  55. }
  56. func dumpInternalImages() error {
  57. dir, err := availableFilename("internalimages_", "")
  58. if err != nil {
  59. return err
  60. }
  61. if err := os.Mkdir(dir, 0755); err != nil {
  62. return err
  63. }
  64. if err := atlas.DumpImages(dir); err != nil {
  65. return err
  66. }
  67. if _, err := fmt.Fprintf(os.Stderr, "Dumped the internal images at: %s\n", dir); err != nil {
  68. return err
  69. }
  70. return nil
  71. }
  72. type imageDumper struct {
  73. g Game
  74. keyState map[Key]int
  75. hasScreenshotKey bool
  76. screenshotKey Key
  77. toTakeScreenshot bool
  78. hasDumpInternalImagesKey bool
  79. dumpInternalImagesKey Key
  80. toDumpInternalImages bool
  81. err error
  82. }
  83. func (i *imageDumper) update() error {
  84. if i.err != nil {
  85. return i.err
  86. }
  87. const (
  88. envScreenshotKey = "EBITEN_SCREENSHOT_KEY"
  89. envInternalImagesKey = "EBITEN_INTERNAL_IMAGES_KEY"
  90. )
  91. if err := i.g.Update(); err != nil {
  92. return err
  93. }
  94. // If keyState is nil, all values are not initialized.
  95. if i.keyState == nil {
  96. i.keyState = map[Key]int{}
  97. if keyname := os.Getenv(envScreenshotKey); keyname != "" {
  98. if key, ok := keyNameToKeyCode(keyname); ok {
  99. i.hasScreenshotKey = true
  100. i.screenshotKey = key
  101. }
  102. }
  103. if keyname := os.Getenv(envInternalImagesKey); keyname != "" {
  104. if isDebug() {
  105. if key, ok := keyNameToKeyCode(keyname); ok {
  106. i.hasDumpInternalImagesKey = true
  107. i.dumpInternalImagesKey = key
  108. }
  109. } else {
  110. fmt.Fprintf(os.Stderr, "%s is disabled. Specify a build tag 'ebitendebug' to enable it.\n", envInternalImagesKey)
  111. }
  112. }
  113. }
  114. keys := map[Key]struct{}{}
  115. if i.hasScreenshotKey {
  116. keys[i.screenshotKey] = struct{}{}
  117. }
  118. if i.hasDumpInternalImagesKey {
  119. keys[i.dumpInternalImagesKey] = struct{}{}
  120. }
  121. for key := range keys {
  122. if IsKeyPressed(key) {
  123. i.keyState[key]++
  124. if i.keyState[key] == 1 {
  125. if i.hasScreenshotKey && key == i.screenshotKey {
  126. i.toTakeScreenshot = true
  127. }
  128. if i.hasDumpInternalImagesKey && key == i.dumpInternalImagesKey {
  129. i.toDumpInternalImages = true
  130. }
  131. }
  132. } else {
  133. i.keyState[key] = 0
  134. }
  135. }
  136. return nil
  137. }
  138. func (i *imageDumper) dump(screen *Image) error {
  139. if i.toTakeScreenshot {
  140. i.toTakeScreenshot = false
  141. if err := takeScreenshot(screen); err != nil {
  142. return err
  143. }
  144. }
  145. if i.toDumpInternalImages {
  146. i.toDumpInternalImages = false
  147. if err := dumpInternalImages(); err != nil {
  148. return err
  149. }
  150. }
  151. return nil
  152. }