<commit_before>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include <stdio.h>
#include "glsl_parser_extras.h"
#include "glsl_symbol_table.h"
#include "ir.h"
#include "builtin_variables.h"

#ifndef Elements
#define Elements(x) (sizeof(x)/sizeof(*(x)))
#endif

static ir_variable *
add_variable(const char *name, enum ir_variable_mode mode,
	     const glsl_type *type, exec_list *instructions,
		     glsl_symbol_table *symtab)
{
   ir_variable *var = new ir_variable(type, name);

   var->mode = mode;
   switch (var->mode) {
   case ir_var_in:
      var->shader_in = true;
      var->read_only = true;
      break;
   case ir_var_inout:
      var->shader_in = true;
      var->shader_out = true;
      break;
   case ir_var_out:
      var->shader_out = true;
      break;
   case ir_var_uniform:
      var->shader_in = true;
      var->read_only = true;
      break;
   default:
      assert(0);
      break;
   }

   /* Once the variable is created an initialized, add it to the symbol table
    * and add the declaration to the IR stream.
    */
   instructions->push_tail(var);

   symtab->add_variable(var->name, var);
   return var;
}

static void
add_builtin_variable(const builtin_variable *proto, exec_list *instructions,
		     glsl_symbol_table *symtab)
{
   /* Create a new variable declaration from the description supplied by
    * the caller.
    */
   const glsl_type *const type = symtab->get_type(proto->type);

   assert(type != NULL);

   add_variable(proto->name, proto->mode, type, instructions, symtab);
}

static void
generate_110_uniforms(exec_list *instructions,
		      glsl_symbol_table *symtab)
{
   for (unsigned i = 0
	   ; i < Elements(builtin_110_deprecated_uniforms)
	   ; i++) {
      add_builtin_variable(& builtin_110_deprecated_uniforms[i],
			   instructions, symtab);
   }

   /* FINISHME: The size of this array is implementation dependent based on the
    * FINISHME: value of GL_MAX_TEXTURE_COORDS.  GL_MAX_TEXTURE_COORDS must be
    * FINISHME: at least 2, so hard-code 2 for now.
    */
   const glsl_type *const mat4_array_type =
      glsl_type::get_array_instance(glsl_type::mat4_type, 2);

   add_variable("gl_TextureMatrix", ir_var_uniform, mat4_array_type,
		instructions, symtab);

   /* FINISHME: Add support for gl_DepthRangeParameters */
   /* FINISHME: Add support for gl_ClipPlane[] */
   /* FINISHME: Add support for gl_PointParameters */

   /* FINISHME: Add support for gl_MaterialParameters
    * FINISHME: (glFrontMaterial, glBackMaterial)
    */

   /* FINISHME: Add support for gl_LightSource[] */
   /* FINISHME: Add support for gl_LightModel */
   /* FINISHME: Add support for gl_FrontLightProduct[], gl_BackLightProduct[] */
   /* FINISHME: Add support for gl_TextureEnvColor[] */
   /* FINISHME: Add support for gl_ObjectPlane*[], gl_EyePlane*[] */
   /* FINISHME: Add support for gl_Fog */
}

static void
generate_110_vs_variables(exec_list *instructions,
			  glsl_symbol_table *symtab)
{
   for (unsigned i = 0; i < Elements(builtin_core_vs_variables); i++) {
      add_builtin_variable(& builtin_core_vs_variables[i],
			   instructions, symtab);
   }

   for (unsigned i = 0
	   ; i < Elements(builtin_110_deprecated_vs_variables)
	   ; i++) {
      add_builtin_variable(& builtin_110_deprecated_vs_variables[i],
			   instructions, symtab);
   }
   generate_110_uniforms(instructions, symtab);

   /* FINISHME: The size of this array is implementation dependent based on the
    * FINISHME: value of GL_MAX_TEXTURE_COORDS.  GL_MAX_TEXTURE_COORDS must be
    * FINISHME: at least 2, so hard-code 2 for now.
    */
   const glsl_type *const vec4_array_type =
      glsl_type::get_array_instance(glsl_type::vec4_type, 2);

   add_variable("gl_TexCoord", ir_var_out, vec4_array_type, instructions,
		symtab);
}

static void
generate_120_vs_variables(exec_list *instructions,
			  glsl_symbol_table *symtab)
{
   /* GLSL version 1.20 did not add any built-in variables in the vertex
    * shader.
    */
   generate_110_vs_variables(instructions, symtab);
}

static void
generate_130_vs_variables(exec_list *instructions,
			  glsl_symbol_table *symtab)
{
   generate_120_vs_variables(instructions, symtab);

   for (unsigned i = 0; i < Elements(builtin_130_vs_variables); i++) {
      add_builtin_variable(& builtin_130_vs_variables[i],
			   instructions, symtab);
   }

   /* FINISHME: The size of this array is implementation dependent based on
    * FINISHME: the value of GL_MAX_CLIP_DISTANCES.
    */
   const glsl_type *const clip_distance_array_type =
      glsl_type::get_array_instance(glsl_type::float_type, 8);
   add_variable("gl_ClipDistance", ir_var_out, clip_distance_array_type,
		instructions, symtab);

}

static void
initialize_vs_variables(exec_list *instructions,
			struct _mesa_glsl_parse_state *state)
{

   switch (state->language_version) {
   case 110:
      generate_110_vs_variables(instructions, state->symbols);
      break;
   case 120:
      generate_120_vs_variables(instructions, state->symbols);
      break;
   case 130:
      generate_130_vs_variables(instructions, state->symbols);
      break;
   }
}

static void
generate_110_fs_variables(exec_list *instructions,
			  glsl_symbol_table *symtab)
{
   for (unsigned i = 0; i < Elements(builtin_core_fs_variables); i++) {
      add_builtin_variable(& builtin_core_fs_variables[i],
			   instructions, symtab);
   }

   for (unsigned i = 0
	   ; i < Elements(builtin_110_deprecated_fs_variables)
	   ; i++) {
      add_builtin_variable(& builtin_110_deprecated_fs_variables[i],
			   instructions, symtab);
   }
   generate_110_uniforms(instructions, symtab);

   /* FINISHME: The size of this array is implementation dependent based on the
    * FINISHME: value of GL_MAX_TEXTURE_COORDS.  GL_MAX_TEXTURE_COORDS must be
    * FINISHME: at least 2, so hard-code 2 for now.
    */
   const glsl_type *const vec4_array_type =
      glsl_type::get_array_instance(glsl_type::vec4_type, 2);

   add_variable("gl_TexCoord", ir_var_in, vec4_array_type, instructions,
		symtab);
}

static void
generate_ARB_draw_buffers_fs_variables(exec_list *instructions,
				       glsl_symbol_table *symtab, bool warn)
{
   /* FINISHME: The size of this array is implementation dependent based on the
    * FINISHME: value of GL_MAX_DRAW_BUFFERS.  GL_MAX_DRAW_BUFFERS must be
    * FINISHME: at least 1, so hard-code 1 for now.
    */
   const glsl_type *const vec4_array_type =
      glsl_type::get_array_instance(glsl_type::vec4_type, 1);

   ir_variable *const fd =
      add_variable("gl_FragData", ir_var_out, vec4_array_type, instructions,
		   symtab);

   if (warn)
      fd->warn_extension = "GL_ARB_draw_buffers";
}

static void
generate_120_fs_variables(exec_list *instructions,
			  glsl_symbol_table *symtab)
{
   generate_110_fs_variables(instructions, symtab);
   generate_ARB_draw_buffers_fs_variables(instructions, symtab, false);
}

static void
generate_130_fs_variables(exec_list *instructions,
			  glsl_symbol_table *symtab)
{
   generate_120_fs_variables(instructions, symtab);

   /* FINISHME: The size of this array is implementation dependent based on
    * FINISHME: the value of GL_MAX_CLIP_DISTANCES.
    */
   const glsl_type *const clip_distance_array_type =
      glsl_type::get_array_instance(glsl_type::float_type, 8);
   add_variable("gl_ClipDistance", ir_var_in, clip_distance_array_type,
		instructions, symtab);
}

static void
initialize_fs_variables(exec_list *instructions,
			struct _mesa_glsl_parse_state *state)
{

   switch (state->language_version) {
   case 110:
      generate_110_fs_variables(instructions, state->symbols);
      break;
   case 120:
      generate_120_fs_variables(instructions, state->symbols);
      break;
   case 130:
      generate_130_fs_variables(instructions, state->symbols);
      break;
   }

   /* Since GL_ARB_draw_buffers is included in GLSL 1.20 and later, we
    * can basically ignore any extension settings for it.
    */
   if (state->language_version < 120) {
      if (state->ARB_draw_buffers_enable) {
	 generate_ARB_draw_buffers_fs_variables(instructions, state->symbols,
						state->ARB_draw_buffers_warn);
      }
   }
}

void
_mesa_glsl_initialize_variables(exec_list *instructions,
				struct _mesa_glsl_parse_state *state)
{
   switch (state->target) {
   case vertex_shader:
      initialize_vs_variables(instructions, state);
      break;
   case geometry_shader:
      break;
   case fragment_shader:
      initialize_fs_variables(instructions, state);
      break;
   case ir_shader:
      fprintf(stderr, "ir reader has no builtin variables");
      exit(1);
      break;
   }
}
<commit_msg>Add builtin gl_LightSource[].<commit_after>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include <stdio.h>
#include "glsl_parser_extras.h"
#include "glsl_symbol_table.h"
#include "ir.h"
#include "builtin_variables.h"

#ifndef Elements
#define Elements(x) (sizeof(x)/sizeof(*(x)))
#endif

static ir_variable *
add_variable(const char *name, enum ir_variable_mode mode,
	     const glsl_type *type, exec_list *instructions,
		     glsl_symbol_table *symtab)
{
   ir_variable *var = new ir_variable(type, name);

   var->mode = mode;
   switch (var->mode) {
   case ir_var_in:
      var->shader_in = true;
      var->read_only = true;
      break;
   case ir_var_inout:
      var->shader_in = true;
      var->shader_out = true;
      break;
   case ir_var_out:
      var->shader_out = true;
      break;
   case ir_var_uniform:
      var->shader_in = true;
      var->read_only = true;
      break;
   default:
      assert(0);
      break;
   }

   /* Once the variable is created an initialized, add it to the symbol table
    * and add the declaration to the IR stream.
    */
   instructions->push_tail(var);

   symtab->add_variable(var->name, var);
   return var;
}

static void
add_builtin_variable(const builtin_variable *proto, exec_list *instructions,
		     glsl_symbol_table *symtab)
{
   /* Create a new variable declaration from the description supplied by
    * the caller.
    */
   const glsl_type *const type = symtab->get_type(proto->type);

   assert(type != NULL);

   add_variable(proto->name, proto->mode, type, instructions, symtab);
}

static void
generate_110_uniforms(exec_list *instructions,
		      glsl_symbol_table *symtab)
{
   for (unsigned i = 0
	   ; i < Elements(builtin_110_deprecated_uniforms)
	   ; i++) {
      add_builtin_variable(& builtin_110_deprecated_uniforms[i],
			   instructions, symtab);
   }

   /* FINISHME: The size of this array is implementation dependent based on the
    * FINISHME: value of GL_MAX_TEXTURE_COORDS.  GL_MAX_TEXTURE_COORDS must be
    * FINISHME: at least 2, so hard-code 2 for now.
    */
   const glsl_type *const mat4_array_type =
      glsl_type::get_array_instance(glsl_type::mat4_type, 2);

   add_variable("gl_TextureMatrix", ir_var_uniform, mat4_array_type,
		instructions, symtab);

   /* FINISHME: Add support for gl_DepthRangeParameters */
   /* FINISHME: Add support for gl_ClipPlane[] */
   /* FINISHME: Add support for gl_PointParameters */

   /* FINISHME: Add support for gl_MaterialParameters
    * FINISHME: (glFrontMaterial, glBackMaterial)
    */

   /* FINISHME: The size of this array is implementation dependent based on the
    * FINISHME: value of GL_MAX_TEXTURE_LIGHTS.  GL_MAX_TEXTURE_LIGHTS must be
    * FINISHME: at least 8, so hard-code 8 for now.
    */
   const glsl_type *const light_source_array_type =
      glsl_type::get_array_instance(symtab->get_type("gl_LightSourceParameters"), 8);

   add_variable("gl_LightSource", ir_var_uniform, light_source_array_type,
		instructions, symtab);

   /* FINISHME: Add support for gl_LightModel */
   /* FINISHME: Add support for gl_FrontLightProduct[], gl_BackLightProduct[] */
   /* FINISHME: Add support for gl_TextureEnvColor[] */
   /* FINISHME: Add support for gl_ObjectPlane*[], gl_EyePlane*[] */
   /* FINISHME: Add support for gl_Fog */
}

static void
generate_110_vs_variables(exec_list *instructions,
			  glsl_symbol_table *symtab)
{
   for (unsigned i = 0; i < Elements(builtin_core_vs_variables); i++) {
      add_builtin_variable(& builtin_core_vs_variables[i],
			   instructions, symtab);
   }

   for (unsigned i = 0
	   ; i < Elements(builtin_110_deprecated_vs_variables)
	   ; i++) {
      add_builtin_variable(& builtin_110_deprecated_vs_variables[i],
			   instructions, symtab);
   }
   generate_110_uniforms(instructions, symtab);

   /* FINISHME: The size of this array is implementation dependent based on the
    * FINISHME: value of GL_MAX_TEXTURE_COORDS.  GL_MAX_TEXTURE_COORDS must be
    * FINISHME: at least 2, so hard-code 2 for now.
    */
   const glsl_type *const vec4_array_type =
      glsl_type::get_array_instance(glsl_type::vec4_type, 2);

   add_variable("gl_TexCoord", ir_var_out, vec4_array_type, instructions,
		symtab);
}

static void
generate_120_vs_variables(exec_list *instructions,
			  glsl_symbol_table *symtab)
{
   /* GLSL version 1.20 did not add any built-in variables in the vertex
    * shader.
    */
   generate_110_vs_variables(instructions, symtab);
}

static void
generate_130_vs_variables(exec_list *instructions,
			  glsl_symbol_table *symtab)
{
   generate_120_vs_variables(instructions, symtab);

   for (unsigned i = 0; i < Elements(builtin_130_vs_variables); i++) {
      add_builtin_variable(& builtin_130_vs_variables[i],
			   instructions, symtab);
   }

   /* FINISHME: The size of this array is implementation dependent based on
    * FINISHME: the value of GL_MAX_CLIP_DISTANCES.
    */
   const glsl_type *const clip_distance_array_type =
      glsl_type::get_array_instance(glsl_type::float_type, 8);
   add_variable("gl_ClipDistance", ir_var_out, clip_distance_array_type,
		instructions, symtab);

}

static void
initialize_vs_variables(exec_list *instructions,
			struct _mesa_glsl_parse_state *state)
{

   switch (state->language_version) {
   case 110:
      generate_110_vs_variables(instructions, state->symbols);
      break;
   case 120:
      generate_120_vs_variables(instructions, state->symbols);
      break;
   case 130:
      generate_130_vs_variables(instructions, state->symbols);
      break;
   }
}

static void
generate_110_fs_variables(exec_list *instructions,
			  glsl_symbol_table *symtab)
{
   for (unsigned i = 0; i < Elements(builtin_core_fs_variables); i++) {
      add_builtin_variable(& builtin_core_fs_variables[i],
			   instructions, symtab);
   }

   for (unsigned i = 0
	   ; i < Elements(builtin_110_deprecated_fs_variables)
	   ; i++) {
      add_builtin_variable(& builtin_110_deprecated_fs_variables[i],
			   instructions, symtab);
   }
   generate_110_uniforms(instructions, symtab);

   /* FINISHME: The size of this array is implementation dependent based on the
    * FINISHME: value of GL_MAX_TEXTURE_COORDS.  GL_MAX_TEXTURE_COORDS must be
    * FINISHME: at least 2, so hard-code 2 for now.
    */
   const glsl_type *const vec4_array_type =
      glsl_type::get_array_instance(glsl_type::vec4_type, 2);

   add_variable("gl_TexCoord", ir_var_in, vec4_array_type, instructions,
		symtab);
}

static void
generate_ARB_draw_buffers_fs_variables(exec_list *instructions,
				       glsl_symbol_table *symtab, bool warn)
{
   /* FINISHME: The size of this array is implementation dependent based on the
    * FINISHME: value of GL_MAX_DRAW_BUFFERS.  GL_MAX_DRAW_BUFFERS must be
    * FINISHME: at least 1, so hard-code 1 for now.
    */
   const glsl_type *const vec4_array_type =
      glsl_type::get_array_instance(glsl_type::vec4_type, 1);

   ir_variable *const fd =
      add_variable("gl_FragData", ir_var_out, vec4_array_type, instructions,
		   symtab);

   if (warn)
      fd->warn_extension = "GL_ARB_draw_buffers";
}

static void
generate_120_fs_variables(exec_list *instructions,
			  glsl_symbol_table *symtab)
{
   generate_110_fs_variables(instructions, symtab);
   generate_ARB_draw_buffers_fs_variables(instructions, symtab, false);
}

static void
generate_130_fs_variables(exec_list *instructions,
			  glsl_symbol_table *symtab)
{
   generate_120_fs_variables(instructions, symtab);

   /* FINISHME: The size of this array is implementation dependent based on
    * FINISHME: the value of GL_MAX_CLIP_DISTANCES.
    */
   const glsl_type *const clip_distance_array_type =
      glsl_type::get_array_instance(glsl_type::float_type, 8);
   add_variable("gl_ClipDistance", ir_var_in, clip_distance_array_type,
		instructions, symtab);
}

static void
initialize_fs_variables(exec_list *instructions,
			struct _mesa_glsl_parse_state *state)
{

   switch (state->language_version) {
   case 110:
      generate_110_fs_variables(instructions, state->symbols);
      break;
   case 120:
      generate_120_fs_variables(instructions, state->symbols);
      break;
   case 130:
      generate_130_fs_variables(instructions, state->symbols);
      break;
   }

   /* Since GL_ARB_draw_buffers is included in GLSL 1.20 and later, we
    * can basically ignore any extension settings for it.
    */
   if (state->language_version < 120) {
      if (state->ARB_draw_buffers_enable) {
	 generate_ARB_draw_buffers_fs_variables(instructions, state->symbols,
						state->ARB_draw_buffers_warn);
      }
   }
}

void
_mesa_glsl_initialize_variables(exec_list *instructions,
				struct _mesa_glsl_parse_state *state)
{
   switch (state->target) {
   case vertex_shader:
      initialize_vs_variables(instructions, state);
      break;
   case geometry_shader:
      break;
   case fragment_shader:
      initialize_fs_variables(instructions, state);
      break;
   case ir_shader:
      fprintf(stderr, "ir reader has no builtin variables");
      exit(1);
      break;
   }
}
<|endoftext|>


<commit_before>/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

============================================================================*/

#include "mitkBaseDICOMReaderService.h"

#include <mitkCustomMimeType.h>
#include <mitkIOMimeTypes.h>
#include <mitkDICOMFileReaderSelector.h>
#include <mitkImage.h>
#include <mitkDICOMFilesHelper.h>
#include <mitkDICOMTagsOfInterestHelper.h>
#include <mitkDICOMProperty.h>
#include "legacy/mitkDicomSeriesReader.h"
#include <mitkDICOMDCMTKTagScanner.h>
#include <mitkLocaleSwitch.h>
#include "mitkIPropertyProvider.h"
#include "mitkPropertyNameHelper.h"

#include <iostream>

#include <itksys/SystemTools.hxx>
#include <itksys/Directory.hxx>

namespace mitk {

  BaseDICOMReaderService::BaseDICOMReaderService(const std::string& description)
    : AbstractFileReader(CustomMimeType(IOMimeTypes::DICOM_MIMETYPE()), description)
{
}

  BaseDICOMReaderService::BaseDICOMReaderService(const mitk::CustomMimeType& customType, const std::string& description)
    : AbstractFileReader(customType, description)
  {
  }

std::vector<itk::SmartPointer<BaseData> > BaseDICOMReaderService::Read()
{
  std::vector<BaseData::Pointer> result;

  std::string fileName = this->GetLocalFileName();
  //special handling of Philips 3D US DICOM.
  //Copied from DICOMSeriesReaderService
  if (DicomSeriesReader::IsPhilips3DDicom(fileName))
  {
      MITK_INFO << "it is a Philips3D US Dicom file" << std::endl;
      mitk::LocaleSwitch localeSwitch("C");
      std::locale previousCppLocale(std::cin.getloc());
      std::locale l("C");
      std::cin.imbue(l);

      DataNode::Pointer node = DataNode::New();
      mitk::DicomSeriesReader::StringContainer stringvec;
      stringvec.push_back(fileName);
      if (DicomSeriesReader::LoadDicomSeries(stringvec, *node))
      {
          BaseData::Pointer data = node->GetData();
          StringProperty::Pointer nameProp = StringProperty::New(itksys::SystemTools::GetFilenameName(fileName));
          data->GetPropertyList()->SetProperty("name", nameProp);
          result.push_back(data);
      }
      std::cin.imbue(previousCppLocale);
      return result;
  }

  //Normal DICOM handling (It wasn't a Philips 3D US)
  mitk::StringList relevantFiles = this->GetRelevantFiles();

  // check whether directory or file
  // if directory try to find first file within it instead
  // We only support this for a single directory at once
  if (relevantFiles.empty())
  {
    bool pathIsDirectory = itksys::SystemTools::FileIsDirectory(this->GetLocalFileName());
    if (pathIsDirectory)
    {
      itksys::Directory input;
      input.Load(this->GetLocalFileName().c_str());

      std::vector<std::string> files;
      for (unsigned long idx = 0; idx<input.GetNumberOfFiles(); idx++)
      {
        if (!itksys::SystemTools::FileIsDirectory(input.GetFile(idx)))
        {
          std::string fullpath = this->GetLocalFileName() + "/" + std::string(input.GetFile(idx));
          files.push_back(fullpath.c_str());
        }
      }
      relevantFiles = files;
    }
  }

  if (relevantFiles.empty())
  {
      MITK_INFO << "DICOMReader service found no relevant files in specified location. No data is loaded. Location: "<<fileName;
  }
  else
  {
      mitk::DICOMFileReader::Pointer reader = this->GetReader(relevantFiles);

      if(reader.IsNull())
      {
          MITK_INFO << "DICOMReader service found no suitable reader configuration for relevant files.";
      }
      else
      {
          const unsigned int ntotalfiles = relevantFiles.size();

          for( unsigned int i=0; i< ntotalfiles; i++)
          {
            m_ReadFiles.push_back( relevantFiles.at(i) );
          }

          reader->SetAdditionalTagsOfInterest(mitk::GetCurrentDICOMTagsOfInterest());
          reader->SetTagLookupTableToPropertyFunctor(mitk::GetDICOMPropertyForDICOMValuesFunctor);
          reader->SetInputFiles(relevantFiles);

          mitk::DICOMDCMTKTagScanner::Pointer scanner = mitk::DICOMDCMTKTagScanner::New();
          scanner->AddTagPaths(reader->GetTagsOfInterest());
          scanner->SetInputFiles(relevantFiles);
          scanner->Scan();

          reader->SetTagCache(scanner->GetScanCache());
          reader->AnalyzeInputFiles();
          reader->LoadImages();

          for (unsigned int i = 0; i < reader->GetNumberOfOutputs(); ++i)
          {
            const mitk::DICOMImageBlockDescriptor& desc = reader->GetOutput(i);
            mitk::BaseData::Pointer data = desc.GetMitkImage().GetPointer();

            std::string nodeName = GenerateNameFromDICOMProperties(&desc);

            StringProperty::Pointer nameProp = StringProperty::New(nodeName);
            data->SetProperty("name", nameProp);

            result.push_back(data);
          }
      }
  }

  return result;
}

StringList BaseDICOMReaderService::GetRelevantFiles() const
{
  std::string fileName = this->GetLocalFileName();

  mitk::StringList relevantFiles = mitk::GetDICOMFilesInSameDirectory(fileName);

  return relevantFiles;
}

IFileReader::ConfidenceLevel BaseDICOMReaderService::GetConfidenceLevel() const
{
  IFileReader::ConfidenceLevel abstractConfidence = AbstractFileReader::GetConfidenceLevel();

  if (Unsupported == abstractConfidence)
  {
    if (itksys::SystemTools::FileIsDirectory(this->GetInputLocation().c_str()))
    {
      // In principle we support dicom directories
      return Supported;
    }
  }

  return abstractConfidence;
}

std::string GenerateNameFromDICOMProperties(const mitk::IPropertyProvider* provider)
{
  std::string nodeName = mitk::DataNode::NO_NAME_VALUE();

  auto studyProp = provider->GetConstProperty(mitk::GeneratePropertyNameForDICOMTag(0x0020, 0x000D).c_str());
  if (studyProp.IsNotNull())
  {
    nodeName = studyProp->GetValueAsString();
  }

  auto seriesProp = provider->GetConstProperty(mitk::GeneratePropertyNameForDICOMTag(0x0020, 0x000E).c_str());

  if (seriesProp.IsNotNull())
  {
    if (studyProp.IsNotNull())
    {
      nodeName += " / ";
    }
    nodeName += seriesProp->GetValueAsString();
  }

  return nodeName;
};

}
<commit_msg>Changed name generation to use study and series description again.<commit_after>/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

============================================================================*/

#include "mitkBaseDICOMReaderService.h"

#include <mitkCustomMimeType.h>
#include <mitkIOMimeTypes.h>
#include <mitkDICOMFileReaderSelector.h>
#include <mitkImage.h>
#include <mitkDICOMFilesHelper.h>
#include <mitkDICOMTagsOfInterestHelper.h>
#include <mitkDICOMProperty.h>
#include "legacy/mitkDicomSeriesReader.h"
#include <mitkDICOMDCMTKTagScanner.h>
#include <mitkLocaleSwitch.h>
#include "mitkIPropertyProvider.h"
#include "mitkPropertyNameHelper.h"

#include <iostream>

#include <itksys/SystemTools.hxx>
#include <itksys/Directory.hxx>

namespace mitk {

  BaseDICOMReaderService::BaseDICOMReaderService(const std::string& description)
    : AbstractFileReader(CustomMimeType(IOMimeTypes::DICOM_MIMETYPE()), description)
{
}

  BaseDICOMReaderService::BaseDICOMReaderService(const mitk::CustomMimeType& customType, const std::string& description)
    : AbstractFileReader(customType, description)
  {
  }

std::vector<itk::SmartPointer<BaseData> > BaseDICOMReaderService::Read()
{
  std::vector<BaseData::Pointer> result;

  std::string fileName = this->GetLocalFileName();
  //special handling of Philips 3D US DICOM.
  //Copied from DICOMSeriesReaderService
  if (DicomSeriesReader::IsPhilips3DDicom(fileName))
  {
      MITK_INFO << "it is a Philips3D US Dicom file" << std::endl;
      mitk::LocaleSwitch localeSwitch("C");
      std::locale previousCppLocale(std::cin.getloc());
      std::locale l("C");
      std::cin.imbue(l);

      DataNode::Pointer node = DataNode::New();
      mitk::DicomSeriesReader::StringContainer stringvec;
      stringvec.push_back(fileName);
      if (DicomSeriesReader::LoadDicomSeries(stringvec, *node))
      {
          BaseData::Pointer data = node->GetData();
          StringProperty::Pointer nameProp = StringProperty::New(itksys::SystemTools::GetFilenameName(fileName));
          data->GetPropertyList()->SetProperty("name", nameProp);
          result.push_back(data);
      }
      std::cin.imbue(previousCppLocale);
      return result;
  }

  //Normal DICOM handling (It wasn't a Philips 3D US)
  mitk::StringList relevantFiles = this->GetRelevantFiles();

  // check whether directory or file
  // if directory try to find first file within it instead
  // We only support this for a single directory at once
  if (relevantFiles.empty())
  {
    bool pathIsDirectory = itksys::SystemTools::FileIsDirectory(this->GetLocalFileName());
    if (pathIsDirectory)
    {
      itksys::Directory input;
      input.Load(this->GetLocalFileName().c_str());

      std::vector<std::string> files;
      for (unsigned long idx = 0; idx<input.GetNumberOfFiles(); idx++)
      {
        if (!itksys::SystemTools::FileIsDirectory(input.GetFile(idx)))
        {
          std::string fullpath = this->GetLocalFileName() + "/" + std::string(input.GetFile(idx));
          files.push_back(fullpath.c_str());
        }
      }
      relevantFiles = files;
    }
  }

  if (relevantFiles.empty())
  {
      MITK_INFO << "DICOMReader service found no relevant files in specified location. No data is loaded. Location: "<<fileName;
  }
  else
  {
      mitk::DICOMFileReader::Pointer reader = this->GetReader(relevantFiles);

      if(reader.IsNull())
      {
          MITK_INFO << "DICOMReader service found no suitable reader configuration for relevant files.";
      }
      else
      {
          const unsigned int ntotalfiles = relevantFiles.size();

          for( unsigned int i=0; i< ntotalfiles; i++)
          {
            m_ReadFiles.push_back( relevantFiles.at(i) );
          }

          reader->SetAdditionalTagsOfInterest(mitk::GetCurrentDICOMTagsOfInterest());
          reader->SetTagLookupTableToPropertyFunctor(mitk::GetDICOMPropertyForDICOMValuesFunctor);
          reader->SetInputFiles(relevantFiles);

          mitk::DICOMDCMTKTagScanner::Pointer scanner = mitk::DICOMDCMTKTagScanner::New();
          scanner->AddTagPaths(reader->GetTagsOfInterest());
          scanner->SetInputFiles(relevantFiles);
          scanner->Scan();

          reader->SetTagCache(scanner->GetScanCache());
          reader->AnalyzeInputFiles();
          reader->LoadImages();

          for (unsigned int i = 0; i < reader->GetNumberOfOutputs(); ++i)
          {
            const mitk::DICOMImageBlockDescriptor& desc = reader->GetOutput(i);
            mitk::BaseData::Pointer data = desc.GetMitkImage().GetPointer();

            std::string nodeName = GenerateNameFromDICOMProperties(&desc);

            StringProperty::Pointer nameProp = StringProperty::New(nodeName);
            data->SetProperty("name", nameProp);

            result.push_back(data);
          }
      }
  }

  return result;
}

StringList BaseDICOMReaderService::GetRelevantFiles() const
{
  std::string fileName = this->GetLocalFileName();

  mitk::StringList relevantFiles = mitk::GetDICOMFilesInSameDirectory(fileName);

  return relevantFiles;
}

IFileReader::ConfidenceLevel BaseDICOMReaderService::GetConfidenceLevel() const
{
  IFileReader::ConfidenceLevel abstractConfidence = AbstractFileReader::GetConfidenceLevel();

  if (Unsupported == abstractConfidence)
  {
    if (itksys::SystemTools::FileIsDirectory(this->GetInputLocation().c_str()))
    {
      // In principle we support dicom directories
      return Supported;
    }
  }

  return abstractConfidence;
}

std::string GenerateNameFromDICOMProperties(const mitk::IPropertyProvider* provider)
{
  std::string nodeName = mitk::DataNode::NO_NAME_VALUE();

  auto studyProp = provider->GetConstProperty(mitk::GeneratePropertyNameForDICOMTag(0x0008, 0x1030).c_str());
  if (studyProp.IsNotNull())
  {
    nodeName = studyProp->GetValueAsString();
  }

  auto seriesProp = provider->GetConstProperty(mitk::GeneratePropertyNameForDICOMTag(0x0008, 0x103E).c_str());

  if (seriesProp.IsNotNull())
  {
    if (studyProp.IsNotNull())
    {
      nodeName += " / ";
    }
    else
    {
      nodeName = "";

    }
    nodeName += seriesProp->GetValueAsString();
  }

  return nodeName;
};

}
<|endoftext|>


<commit_before>#include "Plater/Plate2D.hpp"

// libslic3r includes
#include "Geometry.hpp"
#include "Point.hpp"
#include "Log.hpp"
#include "ClipperUtils.hpp"

// wx includes
#include <wx/colour.h>
#include <wx/dcbuffer.h>

namespace Slic3r { namespace GUI {

Plate2D::Plate2D(wxWindow* parent, const wxSize& size, std::vector<PlaterObject>& _objects, std::shared_ptr<Model> _model, std::shared_ptr<Config> _config, std::shared_ptr<Settings> _settings) :
    wxPanel(parent, wxID_ANY, wxDefaultPosition, size, wxTAB_TRAVERSAL), objects(_objects), model(_model), config(_config), settings(_settings)
{

    this->Bind(wxEVT_PAINT, [=](wxPaintEvent &e) { this->repaint(e); });
    this->Bind(wxEVT_MOTION, [=](wxMouseEvent &e) { this->mouse_drag(e); });
    this->Bind(wxEVT_LEFT_DOWN, [=](wxMouseEvent &e) { this->mouse_down(e); });
    this->Bind(wxEVT_LEFT_UP, [=](wxMouseEvent &e) { this->mouse_up(e); });
    this->Bind(wxEVT_LEFT_DCLICK, [=](wxMouseEvent &e) { this->mouse_dclick(e); });

    if (user_drawn_background) {
        this->Bind(wxEVT_ERASE_BACKGROUND, [=](wxEraseEvent& e){ });
    }

    this->Bind(wxEVT_SIZE, [=](wxSizeEvent &e) { this->update_bed_size(); this->Refresh(); });

    // Bind the varying mouse events

    // Set the brushes
    set_colors();
    this->SetBackgroundStyle(wxBG_STYLE_PAINT);

}

void Plate2D::repaint(wxPaintEvent& e) {

    // Need focus to catch keyboard events.
    this->SetFocus();

    auto dc {new wxAutoBufferedPaintDC(this)};
    const auto& size {wxSize(this->GetSize().GetWidth(), this->GetSize().GetHeight())};

    if (this->user_drawn_background) {
        // On all systems the AutoBufferedPaintDC() achieves double buffering.
        // On MacOS the background is erased, on Windows the background is not erased
        // and on Linux/GTK the background is erased to gray color.
        // Fill DC with the background on Windows & Linux/GTK.
        const auto& brush_background {wxBrush(this->settings->color->BACKGROUND255(), wxBRUSHSTYLE_SOLID)};
        const auto& pen_background {wxPen(this->settings->color->BACKGROUND255(), 1, wxPENSTYLE_SOLID)};
        dc->SetPen(pen_background);
        dc->SetBrush(brush_background);
        const auto& rect {this->GetUpdateRegion().GetBox()};
        dc->DrawRectangle(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
    }

    // Draw bed
    {
        dc->SetPen(this->print_center_pen);
        dc->SetBrush(this->bed_brush);
        auto tmp {scaled_points_to_pixel(this->bed_polygon, true)};
        dc->DrawPolygon(this->bed_polygon.points.size(), tmp.data(), 0, 0);
    }

    // draw print center
    {
        if (this->objects.size() > 0 && settings->autocenter) {
            const auto center = this->unscaled_point_to_pixel(this->print_center);
            dc->SetPen(print_center_pen);
            dc->DrawLine(center.x, 0, center.x, size.y);
            dc->DrawLine(0, center.y, size.x, center.y);
            dc->SetTextForeground(wxColor(0,0,0));
            dc->SetFont(wxFont(10, wxFONTFAMILY_ROMAN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));

            dc->DrawLabel(wxString::Format("X = %.0f", this->print_center.x), wxRect(0,0, center.x*2, this->GetSize().GetHeight()), wxALIGN_CENTER_HORIZONTAL | wxALIGN_BOTTOM);
            dc->DrawRotatedText(wxString::Format("Y = %.0f", this->print_center.y), 0, center.y + 15, 90);
        }
    }

    // draw text if plate is empty
    if (this->objects.size() == 0) {
        dc->SetTextForeground(settings->color->BED_OBJECTS());
        dc->SetFont(wxFont(14, wxFONTFAMILY_ROMAN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
        dc->DrawLabel(CANVAS_TEXT, wxRect(0,0, this->GetSize().GetWidth(), this->GetSize().GetHeight()), wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL);
    } else {
        // draw grid
        dc->SetPen(grid_pen);
        // Assumption: grid of lines is arranged
        // as adjacent pairs of wxPoints
        for (auto i = 0U; i < grid.size(); i+=2) {
            dc->DrawLine(grid[i], grid[i+1]);
        }
    }

    // Draw thumbnails

    dc->SetPen(dark_pen);
    this->clean_instance_thumbnails();
    for (auto& obj : this->objects) {
        auto model_object {this->model->objects.at(obj.identifier)};
        if (obj.thumbnail.expolygons.size() == 0)
            continue; // if there's no thumbnail move on
        for (size_t instance_idx = 0U; instance_idx < model_object->instances.size(); instance_idx++) {
            auto& instance {model_object->instances.at(instance_idx)};
            if (obj.transformed_thumbnail.expolygons.size()) continue;
            auto thumbnail {obj.transformed_thumbnail}; // starts in unscaled model coords

            thumbnail.translate(Point::new_scale(instance->offset));

            obj.instance_thumbnails.emplace_back(thumbnail);

            if (0) { // object is dragged
                dc->SetBrush(dragged_brush);
            } else if (0) {
                dc->SetBrush(instance_brush);
            } else if (0) {
                dc->SetBrush(selected_brush);
            } else {
                dc->SetBrush(objects_brush);
            }
            // porting notes: perl here seems to be making a single-item array of the
            // thumbnail set.
            // no idea why. It doesn't look necessary, so skip the outer layer
            // and draw the contained expolygons
            for (const auto& points : obj.instance_thumbnails.back().expolygons) {
                auto poly { this->scaled_points_to_pixel(Polygon(points), 1) };
                dc->DrawPolygon(poly.size(), poly.data(), 0, 0);
            }
        }
    }
    e.Skip();
}

void Plate2D::clean_instance_thumbnails() {
    for (auto& obj : this->objects) {
        obj.instance_thumbnails.clear();
    }
}

void Plate2D::mouse_drag(wxMouseEvent& e) {
    const auto pos {e.GetPosition()};
    const auto& point {this->point_to_model_units(e.GetPosition())};
    if (e.Dragging()) {
        Slic3r::Log::info(LogChannel, L"Mouse dragging");
    } else {
        auto cursor = wxSTANDARD_CURSOR;
        /*
        if (find_first_of(this->objects.begin(), this->objects.end(); [=](const PlaterObject& o) { return o.contour->contains_point(point);} ) == this->object.end()) {
            cursor = wxCursor(wxCURSOR_HAND);
        }
        */
        this->SetCursor(*cursor);
    }
}

void Plate2D::mouse_down(wxMouseEvent& e) {
}
void Plate2D::mouse_up(wxMouseEvent& e) {
}
void Plate2D::mouse_dclick(wxMouseEvent& e) {
}

void Plate2D::set_colors() {

    this->SetBackgroundColour(settings->color->BACKGROUND255());

    this->objects_brush.SetColour(settings->color->BED_OBJECTS());
    this->objects_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->instance_brush.SetColour(settings->color->BED_INSTANCE());
    this->instance_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->selected_brush.SetColour(settings->color->BED_SELECTED());
    this->selected_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->dragged_brush.SetColour(settings->color->BED_DRAGGED());
    this->dragged_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->bed_brush.SetColour(settings->color->BED_COLOR());
    this->bed_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->transparent_brush.SetColour(wxColour(0,0,0));
    this->transparent_brush.SetStyle(wxBRUSHSTYLE_TRANSPARENT);

    this->grid_pen.SetColour(settings->color->BED_GRID());
    this->grid_pen.SetWidth(1);
    this->grid_pen.SetStyle(wxPENSTYLE_SOLID);
    this->print_center_pen.SetColour(settings->color->BED_CENTER());
    this->print_center_pen.SetWidth(1);
    this->print_center_pen.SetStyle(wxPENSTYLE_SOLID);
    this->clearance_pen.SetColour(settings->color->BED_CLEARANCE());
    this->clearance_pen.SetWidth(1);
    this->clearance_pen.SetStyle(wxPENSTYLE_SOLID);
    this->skirt_pen.SetColour(settings->color->BED_SKIRT());
    this->skirt_pen.SetWidth(1);
    this->skirt_pen.SetStyle(wxPENSTYLE_SOLID);
    this->dark_pen.SetColour(settings->color->BED_DARK());
    this->dark_pen.SetWidth(1);
    this->dark_pen.SetStyle(wxPENSTYLE_SOLID);

}

void Plate2D::nudge_key(wxKeyEvent& e) {
    const auto key = e.GetKeyCode();

    switch( key ) {
        case WXK_LEFT:
            this->nudge(MoveDirection::Left);
        case WXK_RIGHT:
            this->nudge(MoveDirection::Right);
        case WXK_DOWN:
            this->nudge(MoveDirection::Down);
        case WXK_UP:
            this->nudge(MoveDirection::Up);
        default:
            break; // do nothing
    }

}

void Plate2D::nudge(MoveDirection dir) {
    if (this->selected_instance < this->objects.size()) {
        auto i = 0U;
        for (auto& obj : this->objects) {
            if (obj.selected) {
                if (obj.selected_instance != -1) {
                }
            }
            i++;
        }
    }
    if (selected_instance >= this->objects.size()) {
        Slic3r::Log::warn(LogChannel, L"Nudge failed because there is no selected instance.");
        return; // Abort
    }
}

void Plate2D::update_bed_size() {
    const auto& canvas_size {this->GetSize()};
    const auto& canvas_w {canvas_size.GetWidth()};
    const auto& canvas_h {canvas_size.GetHeight()};
    if (canvas_w == 0) return; // Abort early if we haven't drawn canvas yet.

    this->bed_polygon = Slic3r::Polygon(scale(dynamic_cast<ConfigOptionPoints*>(config->optptr("bed_shape"))->values));

    const auto& polygon = bed_polygon;

    const auto& bb = bed_polygon.bounding_box();
    const auto& size = bb.size();

    this->scaling_factor = std::min(static_cast<double>(canvas_w) / unscale(size.x), static_cast<double>(canvas_h) / unscale(size.y));
    this->bed_origin = wxPoint(
        canvas_w / 2.0 - (unscale(bb.max.x + bb.min.x)/2.0 * this->scaling_factor),
        canvas_h - (canvas_h / 2.0 - (unscale(bb.max.y + bb.min.y)/2.0 * this->scaling_factor))
    );

    const auto& center = bb.center();
    this->print_center = wxPoint(unscale(center.x), unscale(center.y));

    // Cache bed contours and grid
    {
        const auto& step { scale_(10.0) }; // want a 10mm step for the lines
        auto grid {Polylines()};

        for (coord_t x = (bb.min.x - (bb.min.x % step) + step); x < bb.max.x; x += step) {
            grid.push_back(Polyline());
            grid.back().append(Point(x, bb.min.y));
            grid.back().append(Point(x, bb.max.y));
        };

        for (coord_t y = (bb.min.y - (bb.min.y % step) + step); y < bb.max.y; y += step) {
            grid.push_back(Polyline());
            grid.back().append(Point(bb.min.x, y));
            grid.back().append(Point(bb.max.x, y));
        };

        grid = intersection_pl(grid, polygon);
        for (auto& i : grid) {
            const auto& tmpline { this->scaled_points_to_pixel(i, 1) };
            this->grid.insert(this->grid.end(), tmpline.begin(), tmpline.end());
        }
    }
}

std::vector<wxPoint> Plate2D::scaled_points_to_pixel(const Slic3r::Polygon& poly, bool unscale) {
    return this->scaled_points_to_pixel(Polyline(poly),  unscale);
}

std::vector<wxPoint> Plate2D::scaled_points_to_pixel(const Slic3r::Polyline& poly, bool _unscale) {
    std::vector<wxPoint> result;
    for (const auto& pt : poly.points) {
        const auto x {_unscale ? Slic3r::unscale(pt.x) : pt.x};
        const auto y {_unscale ? Slic3r::unscale(pt.y) : pt.y};
        result.push_back(wxPoint(x, y));
    }
    return result;
}

wxPoint Plate2D::unscaled_point_to_pixel(const wxPoint& in) {
    const auto& canvas_height {this->GetSize().GetHeight()};
    const auto& zero = this->bed_origin;
    return wxPoint(in.x * this->scaling_factor + zero.x,
            in.y * this->scaling_factor + (zero.y - canvas_height));
}

} } // Namespace Slic3r::GUI
<commit_msg>Pass bool when we mean bool, not int.<commit_after>#include "Plater/Plate2D.hpp"

// libslic3r includes
#include "Geometry.hpp"
#include "Point.hpp"
#include "Log.hpp"
#include "ClipperUtils.hpp"

// wx includes
#include <wx/colour.h>
#include <wx/dcbuffer.h>

namespace Slic3r { namespace GUI {

Plate2D::Plate2D(wxWindow* parent, const wxSize& size, std::vector<PlaterObject>& _objects, std::shared_ptr<Model> _model, std::shared_ptr<Config> _config, std::shared_ptr<Settings> _settings) :
    wxPanel(parent, wxID_ANY, wxDefaultPosition, size, wxTAB_TRAVERSAL), objects(_objects), model(_model), config(_config), settings(_settings)
{

    this->Bind(wxEVT_PAINT, [=](wxPaintEvent &e) { this->repaint(e); });
    this->Bind(wxEVT_MOTION, [=](wxMouseEvent &e) { this->mouse_drag(e); });
    this->Bind(wxEVT_LEFT_DOWN, [=](wxMouseEvent &e) { this->mouse_down(e); });
    this->Bind(wxEVT_LEFT_UP, [=](wxMouseEvent &e) { this->mouse_up(e); });
    this->Bind(wxEVT_LEFT_DCLICK, [=](wxMouseEvent &e) { this->mouse_dclick(e); });

    if (user_drawn_background) {
        this->Bind(wxEVT_ERASE_BACKGROUND, [=](wxEraseEvent& e){ });
    }

    this->Bind(wxEVT_SIZE, [=](wxSizeEvent &e) { this->update_bed_size(); this->Refresh(); });

    // Bind the varying mouse events

    // Set the brushes
    set_colors();
    this->SetBackgroundStyle(wxBG_STYLE_PAINT);

}

void Plate2D::repaint(wxPaintEvent& e) {

    // Need focus to catch keyboard events.
    this->SetFocus();

    auto dc {new wxAutoBufferedPaintDC(this)};
    const auto& size {wxSize(this->GetSize().GetWidth(), this->GetSize().GetHeight())};

    if (this->user_drawn_background) {
        // On all systems the AutoBufferedPaintDC() achieves double buffering.
        // On MacOS the background is erased, on Windows the background is not erased
        // and on Linux/GTK the background is erased to gray color.
        // Fill DC with the background on Windows & Linux/GTK.
        const auto& brush_background {wxBrush(this->settings->color->BACKGROUND255(), wxBRUSHSTYLE_SOLID)};
        const auto& pen_background {wxPen(this->settings->color->BACKGROUND255(), 1, wxPENSTYLE_SOLID)};
        dc->SetPen(pen_background);
        dc->SetBrush(brush_background);
        const auto& rect {this->GetUpdateRegion().GetBox()};
        dc->DrawRectangle(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
    }

    // Draw bed
    {
        dc->SetPen(this->print_center_pen);
        dc->SetBrush(this->bed_brush);
        auto tmp {scaled_points_to_pixel(this->bed_polygon, true)};
        dc->DrawPolygon(this->bed_polygon.points.size(), tmp.data(), 0, 0);
    }

    // draw print center
    {
        if (this->objects.size() > 0 && settings->autocenter) {
            const auto center = this->unscaled_point_to_pixel(this->print_center);
            dc->SetPen(print_center_pen);
            dc->DrawLine(center.x, 0, center.x, size.y);
            dc->DrawLine(0, center.y, size.x, center.y);
            dc->SetTextForeground(wxColor(0,0,0));
            dc->SetFont(wxFont(10, wxFONTFAMILY_ROMAN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));

            dc->DrawLabel(wxString::Format("X = %.0f", this->print_center.x), wxRect(0,0, center.x*2, this->GetSize().GetHeight()), wxALIGN_CENTER_HORIZONTAL | wxALIGN_BOTTOM);
            dc->DrawRotatedText(wxString::Format("Y = %.0f", this->print_center.y), 0, center.y + 15, 90);
        }
    }

    // draw text if plate is empty
    if (this->objects.size() == 0) {
        dc->SetTextForeground(settings->color->BED_OBJECTS());
        dc->SetFont(wxFont(14, wxFONTFAMILY_ROMAN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
        dc->DrawLabel(CANVAS_TEXT, wxRect(0,0, this->GetSize().GetWidth(), this->GetSize().GetHeight()), wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL);
    } else {
        // draw grid
        dc->SetPen(grid_pen);
        // Assumption: grid of lines is arranged
        // as adjacent pairs of wxPoints
        for (auto i = 0U; i < grid.size(); i+=2) {
            dc->DrawLine(grid[i], grid[i+1]);
        }
    }

    // Draw thumbnails

    dc->SetPen(dark_pen);
    this->clean_instance_thumbnails();
    for (auto& obj : this->objects) {
        auto model_object {this->model->objects.at(obj.identifier)};
        if (obj.thumbnail.expolygons.size() == 0)
            continue; // if there's no thumbnail move on
        for (size_t instance_idx = 0U; instance_idx < model_object->instances.size(); instance_idx++) {
            auto& instance {model_object->instances.at(instance_idx)};
            if (obj.transformed_thumbnail.expolygons.size()) continue;
            auto thumbnail {obj.transformed_thumbnail}; // starts in unscaled model coords

            thumbnail.translate(Point::new_scale(instance->offset));

            obj.instance_thumbnails.emplace_back(thumbnail);

            if (0) { // object is dragged
                dc->SetBrush(dragged_brush);
            } else if (0) {
                dc->SetBrush(instance_brush);
            } else if (0) {
                dc->SetBrush(selected_brush);
            } else {
                dc->SetBrush(objects_brush);
            }
            // porting notes: perl here seems to be making a single-item array of the
            // thumbnail set.
            // no idea why. It doesn't look necessary, so skip the outer layer
            // and draw the contained expolygons
            for (const auto& points : obj.instance_thumbnails.back().expolygons) {
                auto poly { this->scaled_points_to_pixel(Polygon(points), true) };
                dc->DrawPolygon(poly.size(), poly.data(), 0, 0);
            }
        }
    }
    e.Skip();
}

void Plate2D::clean_instance_thumbnails() {
    for (auto& obj : this->objects) {
        obj.instance_thumbnails.clear();
    }
}

void Plate2D::mouse_drag(wxMouseEvent& e) {
    const auto pos {e.GetPosition()};
    const auto& point {this->point_to_model_units(e.GetPosition())};
    if (e.Dragging()) {
        Slic3r::Log::info(LogChannel, L"Mouse dragging");
    } else {
        auto cursor = wxSTANDARD_CURSOR;
        /*
        if (find_first_of(this->objects.begin(), this->objects.end(); [=](const PlaterObject& o) { return o.contour->contains_point(point);} ) == this->object.end()) {
            cursor = wxCursor(wxCURSOR_HAND);
        }
        */
        this->SetCursor(*cursor);
    }
}

void Plate2D::mouse_down(wxMouseEvent& e) {
}
void Plate2D::mouse_up(wxMouseEvent& e) {
}
void Plate2D::mouse_dclick(wxMouseEvent& e) {
}

void Plate2D::set_colors() {

    this->SetBackgroundColour(settings->color->BACKGROUND255());

    this->objects_brush.SetColour(settings->color->BED_OBJECTS());
    this->objects_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->instance_brush.SetColour(settings->color->BED_INSTANCE());
    this->instance_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->selected_brush.SetColour(settings->color->BED_SELECTED());
    this->selected_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->dragged_brush.SetColour(settings->color->BED_DRAGGED());
    this->dragged_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->bed_brush.SetColour(settings->color->BED_COLOR());
    this->bed_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->transparent_brush.SetColour(wxColour(0,0,0));
    this->transparent_brush.SetStyle(wxBRUSHSTYLE_TRANSPARENT);

    this->grid_pen.SetColour(settings->color->BED_GRID());
    this->grid_pen.SetWidth(1);
    this->grid_pen.SetStyle(wxPENSTYLE_SOLID);
    this->print_center_pen.SetColour(settings->color->BED_CENTER());
    this->print_center_pen.SetWidth(1);
    this->print_center_pen.SetStyle(wxPENSTYLE_SOLID);
    this->clearance_pen.SetColour(settings->color->BED_CLEARANCE());
    this->clearance_pen.SetWidth(1);
    this->clearance_pen.SetStyle(wxPENSTYLE_SOLID);
    this->skirt_pen.SetColour(settings->color->BED_SKIRT());
    this->skirt_pen.SetWidth(1);
    this->skirt_pen.SetStyle(wxPENSTYLE_SOLID);
    this->dark_pen.SetColour(settings->color->BED_DARK());
    this->dark_pen.SetWidth(1);
    this->dark_pen.SetStyle(wxPENSTYLE_SOLID);

}

void Plate2D::nudge_key(wxKeyEvent& e) {
    const auto key = e.GetKeyCode();

    switch( key ) {
        case WXK_LEFT:
            this->nudge(MoveDirection::Left);
        case WXK_RIGHT:
            this->nudge(MoveDirection::Right);
        case WXK_DOWN:
            this->nudge(MoveDirection::Down);
        case WXK_UP:
            this->nudge(MoveDirection::Up);
        default:
            break; // do nothing
    }

}

void Plate2D::nudge(MoveDirection dir) {
    if (this->selected_instance < this->objects.size()) {
        auto i = 0U;
        for (auto& obj : this->objects) {
            if (obj.selected) {
                if (obj.selected_instance != -1) {
                }
            }
            i++;
        }
    }
    if (selected_instance >= this->objects.size()) {
        Slic3r::Log::warn(LogChannel, L"Nudge failed because there is no selected instance.");
        return; // Abort
    }
}

void Plate2D::update_bed_size() {
    const auto& canvas_size {this->GetSize()};
    const auto& canvas_w {canvas_size.GetWidth()};
    const auto& canvas_h {canvas_size.GetHeight()};
    if (canvas_w == 0) return; // Abort early if we haven't drawn canvas yet.

    this->bed_polygon = Slic3r::Polygon(scale(dynamic_cast<ConfigOptionPoints*>(config->optptr("bed_shape"))->values));

    const auto& polygon = bed_polygon;

    const auto& bb = bed_polygon.bounding_box();
    const auto& size = bb.size();

    this->scaling_factor = std::min(static_cast<double>(canvas_w) / unscale(size.x), static_cast<double>(canvas_h) / unscale(size.y));
    this->bed_origin = wxPoint(
        canvas_w / 2.0 - (unscale(bb.max.x + bb.min.x)/2.0 * this->scaling_factor),
        canvas_h - (canvas_h / 2.0 - (unscale(bb.max.y + bb.min.y)/2.0 * this->scaling_factor))
    );

    const auto& center = bb.center();
    this->print_center = wxPoint(unscale(center.x), unscale(center.y));

    // Cache bed contours and grid
    {
        const auto& step { scale_(10.0) }; // want a 10mm step for the lines
        auto grid {Polylines()};

        for (coord_t x = (bb.min.x - (bb.min.x % step) + step); x < bb.max.x; x += step) {
            grid.push_back(Polyline());
            grid.back().append(Point(x, bb.min.y));
            grid.back().append(Point(x, bb.max.y));
        };

        for (coord_t y = (bb.min.y - (bb.min.y % step) + step); y < bb.max.y; y += step) {
            grid.push_back(Polyline());
            grid.back().append(Point(bb.min.x, y));
            grid.back().append(Point(bb.max.x, y));
        };

        grid = intersection_pl(grid, polygon);
        for (auto& i : grid) {
            const auto& tmpline { this->scaled_points_to_pixel(i, 1) };
            this->grid.insert(this->grid.end(), tmpline.begin(), tmpline.end());
        }
    }
}

std::vector<wxPoint> Plate2D::scaled_points_to_pixel(const Slic3r::Polygon& poly, bool unscale) {
    return this->scaled_points_to_pixel(Polyline(poly),  unscale);
}

std::vector<wxPoint> Plate2D::scaled_points_to_pixel(const Slic3r::Polyline& poly, bool _unscale) {
    std::vector<wxPoint> result;
    for (const auto& pt : poly.points) {
        const auto x {_unscale ? Slic3r::unscale(pt.x) : pt.x};
        const auto y {_unscale ? Slic3r::unscale(pt.y) : pt.y};
        result.push_back(wxPoint(x, y));
    }
    return result;
}

wxPoint Plate2D::unscaled_point_to_pixel(const wxPoint& in) {
    const auto& canvas_height {this->GetSize().GetHeight()};
    const auto& zero = this->bed_origin;
    return wxPoint(in.x * this->scaling_factor + zero.x,
            in.y * this->scaling_factor + (zero.y - canvas_height));
}

} } // Namespace Slic3r::GUI
<|endoftext|>


<commit_before>#include <TGUI/TGUI.hpp>
#include <vili/Vili.hpp>

#include "System/Window.hpp"
#include <Editor/MapEditor.hpp>
#include <Modes/Game.hpp>
#include <Modes/Menu.hpp>
#include <Modes/Toolkit.hpp>
#include <System/Config.hpp>
#include <System/Loaders.hpp>
#include <System/Path.hpp>
#include <Utils/StringUtils.hpp>
#include <thread>

namespace obe::Modes
{
    void scrollPanel(tgui::Panel::Ptr panel, tgui::Scrollbar::Ptr scrollbar)
    {
        static int previousScrolbarValue = 0;
        const int distanceToMove =
            previousScrolbarValue - scrollbar->getValue();

        for (auto& widget : panel->getWidgets())
            widget->setPosition(widget->getPosition().x,
                                widget->getPosition().y + distanceToMove);

        previousScrolbarValue = scrollbar->getValue();
    }

    void chooseMapAddMaps(tgui::Panel::Ptr middlePanel,
                          tgui::Scrollbar::Ptr scrollbar,
                          tgui::Theme& baseTheme, std::string& currentMap)
    {
        int scrollBoxSize = 0;

        scrollbar->setLowValue(middlePanel->getSize().y);
        scrollbar->setMaximum(scrollBoxSize);

        middlePanel->removeAllWidgets();

        std::vector<std::string> allMapsTemp;
        System::Path("Data/Maps")
            .loadAll(System::Loaders::filePathLoader, allMapsTemp);
        std::vector<std::string> allMaps;
        for (int i = 0; i < allMapsTemp.size(); i++)
        {
            if (Utils::String::endsWith(allMapsTemp[i], ".map.vili"))
                allMaps.push_back(allMapsTemp[i]);
        }
        for (int i = 0; i < allMaps.size(); i++)
        {
            vili::ViliParser mapInfoParser;
            mapInfoParser.setQuickLookAttributes({"Meta"});
            System::Path("Data/Maps")
                .add(allMaps[i])
                .load(System::Loaders::dataLoader, mapInfoParser);
            const std::string filename = allMaps[i];
            std::string levelName = "???";

            if (mapInfoParser->contains(vili::NodeType::ComplexNode, "Meta"))
            {
                if (mapInfoParser.at("Meta").contains(vili::NodeType::DataNode,
                                                      "name"))
                    levelName = mapInfoParser.at("Meta")
                                    .getDataNode("name")
                                    .get<std::string>();
            }

            tgui::Button::Ptr selectMapButton = tgui::Button::create();
            selectMapButton->setText(
                levelName + " (" +
                filename.substr(0, allMapsTemp[i].size() - 9) + ")");
            selectMapButton->setRenderer(
                baseTheme.getRenderer("MapSelectButton"));
            selectMapButton->setSize("100%", "20%");
            selectMapButton->setPosition("0", i * selectMapButton->getSize().y);
            selectMapButton->connect(
                "pressed", [&currentMap, filename] { currentMap = filename; });
            middlePanel->add(selectMapButton);
            scrollBoxSize += selectMapButton->getSize().y - 1;
        }
        scrollbar->setLowValue(middlePanel->getSize().y);
        scrollbar->setMaximum(scrollBoxSize);
    }

    void createLevel(tgui::EditBox::Ptr input)
    {
        const std::string newLevelName = input->getText();
        if (newLevelName != "")
        {
            if (!Utils::File::fileExists(System::Path("Data/Maps")
                                             .add(newLevelName + ".map.vili")
                                             .getPath(0)
                                             .toString()))
            {
                Debug::Log->info(
                    "<Menu:createLevel> Creating new Map file : '{0}'",
                    newLevelName);
                vili::ViliParser newFileParser;
                newFileParser.addFlag("Map");
                newFileParser.addFlag("Lock");
                newFileParser.includeFile("Obe");
                newFileParser->createComplexNode("Meta");
                newFileParser.at("Meta").createDataNode("name", newLevelName);
                newFileParser->createComplexNode("View");
                newFileParser.at("View").createComplexNode("pos");
                newFileParser.at("View", "pos")
                    .createDataNode("unit", "SceneUnits");
                newFileParser.at("View", "pos").createDataNode("x", 0);
                newFileParser.at("View", "pos").createDataNode("y", 0);
                newFileParser.at("View", "pos")
                    .useTemplate(
                        newFileParser.getTemplate("Vector2<SceneUnits>"));
                newFileParser.at("View").createDataNode("size", 1);
                newFileParser.writeFile(System::Path("Data/Maps")
                                            .add(newLevelName + ".map.vili")
                                            .getPath(0)
                                            .toString(),
                                        true);
                input->setText("");
            }
            else
                Debug::Log->warn("<Menu:createLevel> Map file : '{0}' already "
                                 "exists, cancelling operation",
                                 newLevelName);
        }
    }

    std::string chooseMapMenu()
    {
        unsigned windowSize = sf::VideoMode::getDesktopMode().height / 1.5;
        sf::RenderWindow window({windowSize, windowSize}, "ObEngine Map Selector",
                                sf::Style::None);

        tgui::Gui gui(window);
        gui.setFont("Data/Fonts/weblysleekuil.ttf");
        tgui::Theme baseTheme;
        baseTheme.load("Data/GUI/obe.style");
        std::string currentMap;

        tgui::Panel::Ptr topPanel = tgui::Panel::create();
        tgui::Panel::Ptr bottomPanel = tgui::Panel::create();
        tgui::Panel::Ptr middlePanel = tgui::Panel::create();
        tgui::Scrollbar::Ptr scrollbar = tgui::Scrollbar::create();
        tgui::Label::Ptr titleLabel = tgui::Label::create();
        tgui::Label::Ptr mapEditorLabel = tgui::Label::create();
        tgui::Button::Ptr closeButton = tgui::Button::create();
        tgui::Label::Ptr createMapLabel = tgui::Label::create();
        tgui::Button::Ptr createMapButton = tgui::Button::create();
        tgui::EditBox::Ptr createMapInput = tgui::EditBox::create();

        topPanel->setRenderer(baseTheme.getRenderer("Panel"));
        topPanel->setSize("100%", "10%");
        topPanel->setPosition("0", "0");

        bottomPanel->setRenderer(baseTheme.getRenderer("Panel"));
        bottomPanel->setSize("100%", "10%");
        bottomPanel->setPosition("0", "90%");

        middlePanel->setRenderer(baseTheme.getRenderer("LightPanel"));
        middlePanel->setSize("100%", "80%");
        middlePanel->setPosition("0", "10%");

        scrollbar->setPosition("620", "10% - 1");
        scrollbar->setSize("16", "80% + 1");
        scrollbar->connect("ValueChanged", scrollPanel, middlePanel, scrollbar);

        titleLabel->setRenderer(baseTheme.getRenderer("Label"));
        titleLabel->setText("ObEngine");
        titleLabel->setTextSize(windowSize * 0.06);
        titleLabel->setPosition("2.5%", "15=5%");

        mapEditorLabel->setRenderer(baseTheme.getRenderer("Label"));
        mapEditorLabel->setText("<Map Editor>");
        mapEditorLabel->setTextSize(windowSize * 0.035);
        mapEditorLabel->setPosition(tgui::bindRight(titleLabel) + 20, "40%");

        closeButton->setRenderer(baseTheme.getRenderer("CloseButton"));
        closeButton->setSize("height", "50%");
        closeButton->setPosition("92%", "25%");
        closeButton->connect("pressed", [&window]() { window.close(); });

        createMapLabel->setRenderer(baseTheme.getRenderer("Label"));
        createMapLabel->setText("Create Level : ");
        createMapLabel->setTextSize(windowSize * 0.045);
        createMapLabel->setPosition("2.5%", "20%");

        auto createMapLambda = [createMapInput, middlePanel, scrollbar,
                                &baseTheme, &currentMap]() {
            createLevel(createMapInput);
            chooseMapAddMaps(middlePanel, scrollbar, baseTheme, currentMap);
        };

        createMapButton->setRenderer(baseTheme.getRenderer("AddButton"));
        createMapButton->setSize("height", "50%");
        createMapButton->setPosition("90%", "25%");
        createMapButton->connect("pressed", createMapLambda);

        createMapInput->setRenderer(baseTheme.getRenderer("TextBox"));
        createMapInput->setSize("47%", "50%");
        createMapInput->setPosition("35%", "25%");
        createMapInput->connect("returnkeypressed", createMapLambda);

        gui.add(topPanel);
        gui.add(bottomPanel);
        gui.add(middlePanel);
        gui.add(scrollbar);
        topPanel->add(closeButton);
        topPanel->add(titleLabel);
        topPanel->add(mapEditorLabel);
        bottomPanel->add(createMapButton);
        bottomPanel->add(createMapLabel);
        bottomPanel->add(createMapInput);

        sf::Vector2i grabbedOffset;
        bool grabbedWindow = false;

        chooseMapAddMaps(middlePanel, scrollbar, baseTheme, currentMap);

        while (window.isOpen() && currentMap == "")
        {
            sf::Event event;
            while (window.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                    window.close();
                else if (event.type == sf::Event::MouseButtonPressed)
                {
                    if (sf::Mouse::getPosition().y - window.getPosition().y <
                            60 &&
                        sf::Mouse::getPosition().x - window.getPosition().x <
                            580)
                    {
                        if (event.mouseButton.button == sf::Mouse::Left)
                        {
                            grabbedOffset =
                                window.getPosition() - sf::Mouse::getPosition();
                            grabbedWindow = true;
                        }
                    }
                }
                else if (event.type == sf::Event::MouseButtonReleased)
                {
                    if (event.mouseButton.button == sf::Mouse::Left)
                        grabbedWindow = false;
                }
                else if (event.type == sf::Event::MouseWheelScrolled)
                {
                    scrollbar->mouseWheelScrolled(
                        event.mouseWheelScroll.delta * 30, sf::Vector2f(0, 0));
                }
                else if (event.type == sf::Event::MouseMoved)
                {
                    if (grabbedWindow)
                        window.setPosition(sf::Mouse::getPosition() +
                                           grabbedOffset);
                }
                gui.handleEvent(event);
            }

            window.clear();
            gui.draw();
            window.display();
        }

        return currentMap;
    }

    void startDevMenu()
    {
        unsigned windowSize = sf::VideoMode::getDesktopMode().height / 1.5;
        sf::RenderWindow window({ windowSize, windowSize },
            "ObEngine Development Window",
                                sf::Style::None);

        tgui::Gui gui(window);
        gui.setFont("Data/Fonts/weblysleekuil.ttf");
        tgui::Theme baseTheme;
        baseTheme.load("Data/GUI/obe.style");

        tgui::Panel::Ptr topPanel = tgui::Panel::create();
        tgui::Panel::Ptr middlePanel = tgui::Panel::create();
        tgui::Label::Ptr titleLabel = tgui::Label::create();
        tgui::Button::Ptr closeButton = tgui::Button::create();
        tgui::Button::Ptr playButton = tgui::Button::create();
        tgui::Button::Ptr editButton = tgui::Button::create();
        tgui::Button::Ptr toolkitButton = tgui::Button::create();
        tgui::Button::Ptr helpButton = tgui::Button::create();

        topPanel->setRenderer(baseTheme.getRenderer("Panel"));
        topPanel->setSize("100%", "10%");
        topPanel->setPosition("0", "0");

        middlePanel->setRenderer(baseTheme.getRenderer("LightPanel"));
        middlePanel->setSize("100%", "90%");
        middlePanel->setPosition("0", "10%");

        titleLabel->setRenderer(baseTheme.getRenderer("Label"));
        titleLabel->setText("ObEngine Development Menu");
        titleLabel->setTextSize(float(windowSize) * 0.06);
        titleLabel->setPosition("2.5%", "15%");

        closeButton->setRenderer(baseTheme.getRenderer("CloseButton"));
        closeButton->setSize("height", "50%");
        closeButton->setPosition("92%", "25%");
        closeButton->connect("pressed", [&window]() { window.close(); });

        auto checkBootFile = [playButton]() {
            if (System::Path("boot.lua").find() == "")
            {
                playButton->disable();
            }
            else
            {
                playButton->enable();
            }
        };

        auto checkMapFolder = [editButton]() {
            if (System::Path("Data/Maps").find(System::PathType::Directory) ==
                "")
            {
                editButton->disable();
            }
            else
            {
                editButton->enable();
            }
        };

        checkBootFile();
        checkMapFolder();

        playButton->setRenderer(baseTheme.getRenderer("PlaySquareButton"));
        playButton->setSize("50%", "50%");
        playButton->setPosition("0", "0");
        playButton->connect("pressed", [&checkBootFile, &checkMapFolder]() {
            startGame();
            checkBootFile();
            checkMapFolder();
        });

        editButton->setRenderer(baseTheme.getRenderer("EditSquareButton"));
        editButton->setSize("50%", "50%");
        editButton->setPosition(tgui::bindRight(playButton), "0");
        editButton->connect("pressed", [&checkBootFile, &checkMapFolder]() {
            std::string editMapName = chooseMapMenu();
            if (editMapName != "")
                Editor::editMap(editMapName);
            checkBootFile();
            checkMapFolder();
        });

        toolkitButton->setRenderer(
            baseTheme.getRenderer("ToolkitSquareButton"));
        toolkitButton->setSize("50%", "50%");
        toolkitButton->setPosition("0", tgui::bindBottom(playButton));
        toolkitButton->connect("pressed",
                               [&window, &checkBootFile, &checkMapFolder]() {
                                   startToolkitMode();
                                   checkBootFile();
                                   checkMapFolder();
                                   System::InitConfiguration();
                               });

        helpButton->setRenderer(baseTheme.getRenderer("HelpSquareButton"));
        helpButton->setSize("50%", "50%");
        helpButton->setPosition(tgui::bindLeft(editButton),
                                tgui::bindBottom(playButton));
        // helpButton->connect("pressed", [&window]()

        gui.add(topPanel);
        gui.add(middlePanel);
        topPanel->add(closeButton);
        topPanel->add(titleLabel);
        middlePanel->add(playButton);
        middlePanel->add(editButton);
        middlePanel->add(toolkitButton);
        middlePanel->add(helpButton);

        sf::Vector2i grabbedOffset;
        bool grabbedWindow = false;

        while (window.isOpen())
        {
            sf::Event event;
            while (window.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                    window.close();
                else if (event.type == sf::Event::MouseButtonPressed)
                {
                    if (sf::Mouse::getPosition().y - window.getPosition().y <
                            60 &&
                        sf::Mouse::getPosition().x - window.getPosition().x <
                            580)
                    {
                        if (event.mouseButton.button == sf::Mouse::Left)
                        {
                            grabbedOffset =
                                window.getPosition() - sf::Mouse::getPosition();
                            grabbedWindow = true;
                        }
                    }
                }
                else if (event.type == sf::Event::MouseButtonReleased)
                {
                    if (event.mouseButton.button == sf::Mouse::Left)
                        grabbedWindow = false;
                }
                else if (event.type == sf::Event::MouseMoved)
                {
                    if (grabbedWindow)
                    {
                        window.setPosition(sf::Mouse::getPosition() +
                                           grabbedOffset);
                    }
                }
                gui.handleEvent(event);
            }

            window.clear();
            gui.draw();
            window.display();
        }
    }
} // namespace obe::Modes
<commit_msg>fix display of maps list<commit_after>#include <TGUI/TGUI.hpp>
#include <vili/Vili.hpp>

#include "System/Window.hpp"
#include <Editor/MapEditor.hpp>
#include <Modes/Game.hpp>
#include <Modes/Menu.hpp>
#include <Modes/Toolkit.hpp>
#include <System/Config.hpp>
#include <System/Loaders.hpp>
#include <System/Path.hpp>
#include <Utils/StringUtils.hpp>
#include <thread>

namespace obe::Modes
{
    void scrollPanel(tgui::Panel::Ptr panel, tgui::Scrollbar::Ptr scrollbar)
    {
        static int previousScrolbarValue = 0;
        const int distanceToMove =
            previousScrolbarValue - scrollbar->getValue();

        for (auto& widget : panel->getWidgets())
            widget->setPosition(widget->getPosition().x,
                                widget->getPosition().y + distanceToMove);

        previousScrolbarValue = scrollbar->getValue();
    }

    void chooseMapAddMaps(tgui::Panel::Ptr middlePanel,
                          tgui::Scrollbar::Ptr scrollbar,
                          tgui::Theme& baseTheme, std::string& currentMap)
    {
        int scrollBoxSize = 0;

        scrollbar->setLowValue(middlePanel->getSize().y);
        scrollbar->setMaximum(scrollBoxSize);

        middlePanel->removeAllWidgets();

        std::vector<std::string> allMapsTemp;
        System::Path("Data/Maps")
            .loadAll(System::Loaders::filePathLoader, allMapsTemp);
        std::vector<std::string> allMaps;
        for (int i = 0; i < allMapsTemp.size(); i++)
        {
            if (Utils::String::endsWith(allMapsTemp[i], ".map.vili"))
                allMaps.push_back(allMapsTemp[i]);
        }
        for (int i = 0; i < allMaps.size(); i++)
        {
            vili::ViliParser mapInfoParser;
            mapInfoParser.setQuickLookAttributes({"Meta"});
            System::Path("Data/Maps")
                .add(allMaps[i])
                .load(System::Loaders::dataLoader, mapInfoParser);
            const std::string filename = allMaps[i];
            std::string levelName = "???";

            if (mapInfoParser->contains(vili::NodeType::ComplexNode, "Meta"))
            {
                if (mapInfoParser.at("Meta").contains(vili::NodeType::DataNode,
                                                      "name"))
                    levelName = mapInfoParser.at("Meta")
                                    .getDataNode("name")
                                    .get<std::string>();
            }

            tgui::Button::Ptr selectMapButton = tgui::Button::create();
            middlePanel->add(selectMapButton);
            selectMapButton->setText(
                levelName + " (" +
                filename.substr(0, allMapsTemp[i].size() - 9) + ")");
            selectMapButton->setRenderer(
                baseTheme.getRenderer("MapSelectButton"));
            selectMapButton->setSize("100%", "20%");
            selectMapButton->setPosition("0", i * selectMapButton->getSize().y);
            selectMapButton->connect(
                "pressed", [&currentMap, filename] { currentMap = filename; });
            scrollBoxSize += selectMapButton->getSize().y - 1;
        }
        scrollbar->setLowValue(middlePanel->getSize().y);
        scrollbar->setMaximum(scrollBoxSize);
    }

    void createLevel(tgui::EditBox::Ptr input)
    {
        const std::string newLevelName = input->getText();
        if (newLevelName != "")
        {
            if (!Utils::File::fileExists(System::Path("Data/Maps")
                                             .add(newLevelName + ".map.vili")
                                             .getPath(0)
                                             .toString()))
            {
                Debug::Log->info(
                    "<Menu:createLevel> Creating new Map file : '{0}'",
                    newLevelName);
                vili::ViliParser newFileParser;
                newFileParser.addFlag("Map");
                newFileParser.addFlag("Lock");
                newFileParser.includeFile("Obe");
                newFileParser->createComplexNode("Meta");
                newFileParser.at("Meta").createDataNode("name", newLevelName);
                newFileParser->createComplexNode("View");
                newFileParser.at("View").createComplexNode("pos");
                newFileParser.at("View", "pos")
                    .createDataNode("unit", "SceneUnits");
                newFileParser.at("View", "pos").createDataNode("x", 0);
                newFileParser.at("View", "pos").createDataNode("y", 0);
                newFileParser.at("View", "pos")
                    .useTemplate(
                        newFileParser.getTemplate("Vector2<SceneUnits>"));
                newFileParser.at("View").createDataNode("size", 1);
                newFileParser.writeFile(System::Path("Data/Maps")
                                            .add(newLevelName + ".map.vili")
                                            .getPath(0)
                                            .toString(),
                                        true);
                input->setText("");
            }
            else
                Debug::Log->warn("<Menu:createLevel> Map file : '{0}' already "
                                 "exists, cancelling operation",
                                 newLevelName);
        }
    }

    std::string chooseMapMenu()
    {
        unsigned windowSize = sf::VideoMode::getDesktopMode().height / 1.5;
        sf::RenderWindow window({windowSize, windowSize}, "ObEngine Map Selector",
                                sf::Style::None);

        tgui::Gui gui(window);
        gui.setFont("Data/Fonts/weblysleekuil.ttf");
        tgui::Theme baseTheme;
        baseTheme.load("Data/GUI/obe.style");
        std::string currentMap;

        tgui::Panel::Ptr topPanel = tgui::Panel::create();
        tgui::Panel::Ptr bottomPanel = tgui::Panel::create();
        tgui::Panel::Ptr middlePanel = tgui::Panel::create();
        tgui::Scrollbar::Ptr scrollbar = tgui::Scrollbar::create();
        tgui::Label::Ptr titleLabel = tgui::Label::create();
        tgui::Label::Ptr mapEditorLabel = tgui::Label::create();
        tgui::Button::Ptr closeButton = tgui::Button::create();
        tgui::Label::Ptr createMapLabel = tgui::Label::create();
        tgui::Button::Ptr createMapButton = tgui::Button::create();
        tgui::EditBox::Ptr createMapInput = tgui::EditBox::create();

        topPanel->setRenderer(baseTheme.getRenderer("Panel"));
        topPanel->setSize("100%", "10%");
        topPanel->setPosition("0", "0");

        bottomPanel->setRenderer(baseTheme.getRenderer("Panel"));
        bottomPanel->setSize("100%", "10%");
        bottomPanel->setPosition("0", "90%");

        middlePanel->setRenderer(baseTheme.getRenderer("LightPanel"));
        middlePanel->setSize("100%", "80%");
        middlePanel->setPosition("0", "10%");

        scrollbar->setPosition("620", "10% - 1");
        scrollbar->setSize("16", "80% + 1");
        scrollbar->connect("ValueChanged", scrollPanel, middlePanel, scrollbar);

        titleLabel->setRenderer(baseTheme.getRenderer("Label"));
        titleLabel->setText("ObEngine");
        titleLabel->setTextSize(windowSize * 0.06);
        titleLabel->setPosition("2.5%", "15=5%");

        mapEditorLabel->setRenderer(baseTheme.getRenderer("Label"));
        mapEditorLabel->setText("<Map Editor>");
        mapEditorLabel->setTextSize(windowSize * 0.035);
        mapEditorLabel->setPosition(tgui::bindRight(titleLabel) + 20, "40%");

        closeButton->setRenderer(baseTheme.getRenderer("CloseButton"));
        closeButton->setSize("height", "50%");
        closeButton->setPosition("92%", "25%");
        closeButton->connect("pressed", [&window]() { window.close(); });

        createMapLabel->setRenderer(baseTheme.getRenderer("Label"));
        createMapLabel->setText("Create Level : ");
        createMapLabel->setTextSize(windowSize * 0.045);
        createMapLabel->setPosition("2.5%", "20%");

        auto createMapLambda = [createMapInput, middlePanel, scrollbar,
                                &baseTheme, &currentMap]() {
            createLevel(createMapInput);
            chooseMapAddMaps(middlePanel, scrollbar, baseTheme, currentMap);
        };

        createMapButton->setRenderer(baseTheme.getRenderer("AddButton"));
        createMapButton->setSize("height", "50%");
        createMapButton->setPosition("90%", "25%");
        createMapButton->connect("pressed", createMapLambda);

        createMapInput->setRenderer(baseTheme.getRenderer("TextBox"));
        createMapInput->setSize("47%", "50%");
        createMapInput->setPosition("35%", "25%");
        createMapInput->connect("returnkeypressed", createMapLambda);

        gui.add(topPanel);
        gui.add(bottomPanel);
        gui.add(middlePanel);
        gui.add(scrollbar);
        topPanel->add(closeButton);
        topPanel->add(titleLabel);
        topPanel->add(mapEditorLabel);
        bottomPanel->add(createMapButton);
        bottomPanel->add(createMapLabel);
        bottomPanel->add(createMapInput);

        sf::Vector2i grabbedOffset;
        bool grabbedWindow = false;

        chooseMapAddMaps(middlePanel, scrollbar, baseTheme, currentMap);

        while (window.isOpen() && currentMap == "")
        {
            sf::Event event;
            while (window.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                    window.close();
                else if (event.type == sf::Event::MouseButtonPressed)
                {
                    if (sf::Mouse::getPosition().y - window.getPosition().y <
                            60 &&
                        sf::Mouse::getPosition().x - window.getPosition().x <
                            580)
                    {
                        if (event.mouseButton.button == sf::Mouse::Left)
                        {
                            grabbedOffset =
                                window.getPosition() - sf::Mouse::getPosition();
                            grabbedWindow = true;
                        }
                    }
                }
                else if (event.type == sf::Event::MouseButtonReleased)
                {
                    if (event.mouseButton.button == sf::Mouse::Left)
                        grabbedWindow = false;
                }
                else if (event.type == sf::Event::MouseWheelScrolled)
                {
                    scrollbar->mouseWheelScrolled(
                        event.mouseWheelScroll.delta * 30, sf::Vector2f(0, 0));
                }
                else if (event.type == sf::Event::MouseMoved)
                {
                    if (grabbedWindow)
                        window.setPosition(sf::Mouse::getPosition() +
                                           grabbedOffset);
                }
                gui.handleEvent(event);
            }

            window.clear();
            gui.draw();
            window.display();
        }

        return currentMap;
    }

    void startDevMenu()
    {
        unsigned windowSize = sf::VideoMode::getDesktopMode().height / 1.5;
        sf::RenderWindow window({ windowSize, windowSize },
            "ObEngine Development Window",
                                sf::Style::None);

        tgui::Gui gui(window);
        gui.setFont("Data/Fonts/weblysleekuil.ttf");
        tgui::Theme baseTheme;
        baseTheme.load("Data/GUI/obe.style");

        tgui::Panel::Ptr topPanel = tgui::Panel::create();
        tgui::Panel::Ptr middlePanel = tgui::Panel::create();
        tgui::Label::Ptr titleLabel = tgui::Label::create();
        tgui::Button::Ptr closeButton = tgui::Button::create();
        tgui::Button::Ptr playButton = tgui::Button::create();
        tgui::Button::Ptr editButton = tgui::Button::create();
        tgui::Button::Ptr toolkitButton = tgui::Button::create();
        tgui::Button::Ptr helpButton = tgui::Button::create();

        topPanel->setRenderer(baseTheme.getRenderer("Panel"));
        topPanel->setSize("100%", "10%");
        topPanel->setPosition("0", "0");

        middlePanel->setRenderer(baseTheme.getRenderer("LightPanel"));
        middlePanel->setSize("100%", "90%");
        middlePanel->setPosition("0", "10%");

        titleLabel->setRenderer(baseTheme.getRenderer("Label"));
        titleLabel->setText("ObEngine Development Menu");
        titleLabel->setTextSize(float(windowSize) * 0.06);
        titleLabel->setPosition("2.5%", "15%");

        closeButton->setRenderer(baseTheme.getRenderer("CloseButton"));
        closeButton->setSize("height", "50%");
        closeButton->setPosition("92%", "25%");
        closeButton->connect("pressed", [&window]() { window.close(); });

        auto checkBootFile = [playButton]() {
            if (System::Path("boot.lua").find() == "")
            {
                playButton->disable();
            }
            else
            {
                playButton->enable();
            }
        };

        auto checkMapFolder = [editButton]() {
            if (System::Path("Data/Maps").find(System::PathType::Directory) ==
                "")
            {
                editButton->disable();
            }
            else
            {
                editButton->enable();
            }
        };

        checkBootFile();
        checkMapFolder();

        playButton->setRenderer(baseTheme.getRenderer("PlaySquareButton"));
        playButton->setSize("50%", "50%");
        playButton->setPosition("0", "0");
        playButton->connect("pressed", [&checkBootFile, &checkMapFolder]() {
            startGame();
            checkBootFile();
            checkMapFolder();
        });

        editButton->setRenderer(baseTheme.getRenderer("EditSquareButton"));
        editButton->setSize("50%", "50%");
        editButton->setPosition(tgui::bindRight(playButton), "0");
        editButton->connect("pressed", [&checkBootFile, &checkMapFolder]() {
            std::string editMapName = chooseMapMenu();
            if (editMapName != "")
                Editor::editMap(editMapName);
            checkBootFile();
            checkMapFolder();
        });

        toolkitButton->setRenderer(
            baseTheme.getRenderer("ToolkitSquareButton"));
        toolkitButton->setSize("50%", "50%");
        toolkitButton->setPosition("0", tgui::bindBottom(playButton));
        toolkitButton->connect("pressed",
                               [&window, &checkBootFile, &checkMapFolder]() {
                                   startToolkitMode();
                                   checkBootFile();
                                   checkMapFolder();
                                   System::InitConfiguration();
                               });

        helpButton->setRenderer(baseTheme.getRenderer("HelpSquareButton"));
        helpButton->setSize("50%", "50%");
        helpButton->setPosition(tgui::bindLeft(editButton),
                                tgui::bindBottom(playButton));
        // helpButton->connect("pressed", [&window]()

        gui.add(topPanel);
        gui.add(middlePanel);
        topPanel->add(closeButton);
        topPanel->add(titleLabel);
        middlePanel->add(playButton);
        middlePanel->add(editButton);
        middlePanel->add(toolkitButton);
        middlePanel->add(helpButton);

        sf::Vector2i grabbedOffset;
        bool grabbedWindow = false;

        while (window.isOpen())
        {
            sf::Event event;
            while (window.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                    window.close();
                else if (event.type == sf::Event::MouseButtonPressed)
                {
                    if (sf::Mouse::getPosition().y - window.getPosition().y <
                            60 &&
                        sf::Mouse::getPosition().x - window.getPosition().x <
                            580)
                    {
                        if (event.mouseButton.button == sf::Mouse::Left)
                        {
                            grabbedOffset =
                                window.getPosition() - sf::Mouse::getPosition();
                            grabbedWindow = true;
                        }
                    }
                }
                else if (event.type == sf::Event::MouseButtonReleased)
                {
                    if (event.mouseButton.button == sf::Mouse::Left)
                        grabbedWindow = false;
                }
                else if (event.type == sf::Event::MouseMoved)
                {
                    if (grabbedWindow)
                    {
                        window.setPosition(sf::Mouse::getPosition() +
                                           grabbedOffset);
                    }
                }
                gui.handleEvent(event);
            }

            window.clear();
            gui.draw();
            window.display();
        }
    }
} // namespace obe::Modes
<|endoftext|>


<commit_before>#include	"GL/gl.h"

#include	"FTTextureGlyph.h"
#include	"FTGL.h"

int FTTextureGlyph::activeTextureID = 0;

FTTextureGlyph::FTTextureGlyph( FT_Glyph glyph, int id, unsigned char* data, int stride, int height, float u, float v)
:	FTGlyph(),
	destWidth(0),
	destHeight(0),
	numGreys(0),
	glTextureID(id)
{
	// This function will always fail if the glyph's format isn't scalable????
	err = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1);
	if( err || glyph->format != ft_glyph_format_bitmap)
	{ return;}

	FT_BitmapGlyph  bitmap = ( FT_BitmapGlyph)glyph;
	FT_Bitmap*      source = &bitmap->bitmap;

	//check the pixel mode
	//ft_pixel_mode_grays

	int srcWidth = source->width;
	int srcHeight = source->rows;
	int srcPitch = source->pitch;

	numGreys = source->num_grays;
	advance = glyph->advance.x >> 16; // this is 6 in the freetype docs!!!!!!

 	pos.x = bitmap->left;
	pos.y = bitmap->top;

    destWidth = srcWidth;
    destHeight = srcHeight;

    for(int y = 0; y < srcHeight; ++y)
    {
    	for(int x = 0; x < srcWidth; ++x)
    	{
			*( data + ( y * stride  + x)) = *( source->buffer + ( y * srcPitch) + x);
    	}
    }

//		0
//		+----+
//		|    |
//		|    |
//		|    |
//		+----+
//		     1

	uv[0].x = u;
	uv[0].y = v;
	uv[1].x = uv[0].x + ( (float)destWidth / (float)stride);
	uv[1].y = uv[0].y + ( (float)destHeight / (float)height);

	// discard glyph image (bitmap or not)
	// Is this the right place to do this?
	FT_Done_Glyph( glyph);
}

FTTextureGlyph::~FTTextureGlyph()
{

}

float FTTextureGlyph::Render( const FT_Vector& pen)
{
	// This could be really ugly!!
	if( activeTextureID != glTextureID)
	{
		glEnd();
		glBindTexture( GL_TEXTURE_2D, (GLuint)glTextureID);
		activeTextureID = glTextureID;
		glBegin( GL_QUADS);
	}

	glTexCoord2f( uv[0].x, uv[0].y); glVertex2f( pen.x + pos.x,				pen.y + pos.y);
	glTexCoord2f( uv[1].x, uv[0].y); glVertex2f( pen.x + destWidth + pos.x,	pen.y + pos.y);
	glTexCoord2f( uv[1].x, uv[1].y); glVertex2f( pen.x + destWidth + pos.x,	pen.y + pos.y - destHeight);
	glTexCoord2f( uv[0].x, uv[1].y); glVertex2f( pen.x + pos.x,				pen.y + pos.y - destHeight);

	return advance;
}
<commit_msg>Minor changes<commit_after>#include	"GL/gl.h"

#include	"FTTextureGlyph.h"
#include	"FTGL.h"

int FTTextureGlyph::activeTextureID = 0;

FTTextureGlyph::FTTextureGlyph( FT_Glyph glyph, int id, unsigned char* data, int stride, int height, float u, float v)
:	FTGlyph(),
	destWidth(0),
	destHeight(0),
	numGreys(0),
	glTextureID(id)
{
	// This function will always fail if the glyph's format isn't scalable????
	err = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1);
	if( err || glyph->format != ft_glyph_format_bitmap)
	{
		return;
	}

	FT_BitmapGlyph  bitmap = ( FT_BitmapGlyph)glyph;
	FT_Bitmap*      source = &bitmap->bitmap;

	//check the pixel mode
	//ft_pixel_mode_grays

	int srcWidth = source->width;
	int srcHeight = source->rows;
	int srcPitch = source->pitch;

	numGreys = source->num_grays;
	advance = glyph->advance.x >> 16;

 	pos.x = bitmap->left;
	pos.y = bitmap->top;

    destWidth = srcWidth;
    destHeight = srcHeight;

    for(int y = 0; y < srcHeight; ++y)
    {
    	for(int x = 0; x < srcWidth; ++x)
    	{
			*( data + ( y * stride  + x)) = *( source->buffer + ( y * srcPitch) + x);
    	}
    }

//		0
//		+----+
//		|    |
//		|    |
//		|    |
//		+----+
//		     1

	uv[0].x = u;
	uv[0].y = v;
	uv[1].x = uv[0].x + ( (float)destWidth / (float)stride);
	uv[1].y = uv[0].y + ( (float)destHeight / (float)height);

	// discard glyph image (bitmap or not)
	// Is this the right place to do this?
	FT_Done_Glyph( glyph);
}

FTTextureGlyph::~FTTextureGlyph()
{

}

float FTTextureGlyph::Render( const FT_Vector& pen)
{
	// This could be really ugly!!
	if( activeTextureID != glTextureID)
	{
		glEnd();
		glBindTexture( GL_TEXTURE_2D, (GLuint)glTextureID);
		activeTextureID = glTextureID;
		glBegin( GL_QUADS);
	}

	glTexCoord2f( uv[0].x, uv[0].y); glVertex2f( pen.x + pos.x,				pen.y + pos.y);
	glTexCoord2f( uv[1].x, uv[0].y); glVertex2f( pen.x + destWidth + pos.x,	pen.y + pos.y);
	glTexCoord2f( uv[1].x, uv[1].y); glVertex2f( pen.x + destWidth + pos.x,	pen.y + pos.y - destHeight);
	glTexCoord2f( uv[0].x, uv[1].y); glVertex2f( pen.x + pos.x,				pen.y + pos.y - destHeight);

	return advance;
}
<|endoftext|>